laravelmiddlewarerestrict

Restrict page if Auth::user()->id != user_id using middleware


i use middleware to restrict the admin page from non-admins, and i can restrict pages with a list of "patients" from other users by using a policy, but if i use a policy. I have to repeat the code can() method in every function. If i use middleware to check if the user_id in the url == Auth::user()->id. I do not need to repeat this, but how do i get the user_id from the url in my middleware?

the route

Route::get('/patients/{patient}', 'PatientController@edit')

What i have now

PatientPolicy

public function view(User $user, Patient $patient)
    {
        // does this patient belong to user
        return $user->id == $patient->user_id;
    }

PatientController

public function edit(Patient $patient)
    {
        // authenticate logged in user
        $user = auth()->user();

        // can the loged in user do this?(policy)
        if($user->can('update', $patient)){
            return view('patient.edit-patient', compact('patient', 'user'));
        }
        return view('403');
    }

what i should have in a middleware

UserMiddleware

/**
 * @param $request
 * @param Closure $next
 * @return mixed
 */
public static function handle($request, Closure $next)
{
    if (Auth::check() && Auth::user()->id == User::patients()->user_id) {
        return $next($request);
    } else {
        return redirect()->route('login');
    }
}

Does somebody know how to check if the {patient} in the routes user_id == the logged in user()->id?


Solution

  • Since you have Illuminate\Http\Request object injected into handle function in middleware this is pretty straight forward to get patient id from url:

    /**
     * @param $request
     * @param Closure $next
     * @return mixed
     */
    public static function handle($request, Closure $next)
    {
        $patientId = $request->patient; // patient id from url!
    
        $patient = Patient::find($patientId);
    
        if (!$patient) {
            return redirect()->back()->with(['message' => 'Patient not found!']);
        }
    
        if (Auth::check() && (int) Auth::user()->id === (int) $patient->id) {
            return $next($request);
        } else {
            return redirect()->route('login');
        }
    }