php - Laravel 8.x: How do I prevent users from accessing Projects they aren't permitted to?

one text

I'm currently making a Laravel project where a logged in user can select roles and projects they've been assigned using a Postgres Database. After logging in the HomeController passes the roles and projects to projectroles.blade.php which utilises Vue.js to display the necessary data.

I've then got a GET route set up /map/{role}/{project} where after a user selects the role and project from projectroles.blade.php where it passes it to MapController which then gets data relevant to the project chosen to welcome.blade.php.

However, I've noticed an issue with my route. Modifying the URL to change the role and project IDs a user could in theory access a project that a user doesn't have the permission to access.

I have two ideas but don't know which one would be best practice or which one would give the desired effect.

  1. I add the same code I used in the HomeController into the MapController and check if the user is permitted to see the role/project that they're attempting to access. Obviously I know this isn't the best practice since it's the repetition of code but if it's the only thing I can do, is there anything I can add to make it more simplistic/efficient.
...
        $user = Auth::user() ?? 'null';
        $layers = array();

        $roles = DB::table('users')
          ->join('user_roles', 'users.id', '=', 'user_roles.user_id')
          ->join('roles', 'roles.id', '=', 'user_roles.role_id')
          ->select('roles.*')
          ->where('users.id', '=', $user->id)
          ->get();
        $roleprojects = array();

        foreach ($roles as $role)
        {
          $roleproject = array(
              'role' => $role->id,
              'projects' => DB::table('roles')
          ->join('role_projects', 'roles.id', '=', 'role_projects.role_id')
          ->join('projects', 'projects.id', '=', 'role_projects.project_id')
          ->select('projects.*')
          ->where('roles.id', '=', $role->id)
          ->get()
          );

          array_push($roleprojects, $roleproject);
        }
...
  1. I change the route to a POST instead of a GET. I've attempted this but unfortunately, this doesn't seem to work. It does come back with a 200 response but doesn't change the view. I'm not sure if this is due to the fact that I'm using an Axios POST to make the call to the controller.

ProjectRoles.vue

...
axios.post('/map/' + this.selectedRole.id+ "/" + this.selectedProject.id).then((response) => {
 console.log(response);
}, (xhr) => {
 console.log(xhr);
});
...

Mapcontroller.php

index($role, $$project){
 ...
 return View::make('welcome.blade.php');
}

Source