使用策略限制操作

In my Laravel application, a User can have a Profile which they or a user with privileges can update.

The relation for these two models is defined in this method:

/**
 * Get the profile associated with this user
 */
public function profile()
{
    return $this->hasOne(Profile::class, 'user_username', 'username');
}

This is the method for updating a user profile:

/**
 * Update the specified resource in storage.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \App\Profile  $profile
 * @return \Illuminate\Http\Response
 */
public function update(UpdateProfile $request, User $user)
{
    if ($user) {
        // Only proceed if there is a logged in user
        $profile = $user->profile;

        // If there is no profile, create one for this user as they'll need one.
        if (!empty(request()->get('background'))) {
            $profile->background = clean($request->get('background'));
        }

        if (!empty(request()->get('skills'))) {
            $profile->skills = clean($request->get('skills'));
        }

        if (!empty(request()->get('filepath'))) {
            $profile->displayPicture = $request->get('filepath');
        }

        if (!empty(request()->get('linkedInUrl'))) {
            $socialProfilesDecoded = json_decode($user->profile->socialProfiles, true);
            $socialProfilesDecoded["LinkedIn"] = $request->get('linkedInUrl');
            $profile->socialProfiles = json_encode($socialProfilesDecoded);
        }

        if (!empty(request()->get('twitterUrl'))) {
            $socialProfilesDecoded = json_decode($user->profile->socialProfiles, true);
            $socialProfilesDecoded["Twitter"] = $request->get('twitterUrl');
            $profile->socialProfiles = json_encode($socialProfilesDecoded);
        }

        $user->profile()->save($profile);

        return redirect()->back()->withSuccess('Your profile has been successfully updated');
    }
}

The route for updating a profile is:

Route::post('profile/{user}', 'ProfileController@update');

It came to my attention that exposing the username presents a vulnerability as if you're able to grab the request with a web proxy you can just change the username and update another user's profile.

Without changing the URL could I put a Policy in place to check that:

  1. The user has permission to update said profile
  2. The profile being updated is the correct profile (and the request wasn't tampered with.

Or, should I change the URL and have a way to edit profiles in an admin area only?

Also, as a Profile is associated with a User, how could a privileged user access another user's profile?

Maybe a hidden input?

Update:

if ($request->is('admin/*')) {
    //
}

Could I check if this matches the POST request?

Update 2

Added a simple check to ensure the logged in user had permissions to update a Profile.

/**
 * Update the specified resource in storage.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \App\Profile  $profile
 * @return \Illuminate\Http\Response
 */
public function update(UpdateProfile $request, User $user)
{
    // Check this user
    if(auth()->user() == $user || auth()->user()->can('Approve user profile')){
        if ($user) {
            // Only proceed if there is a logged in user
            $profile = $user->profile;

            // If there is no profile, create one for this user as they'll need one.
            if (!empty(request()->get('background'))) {
                $profile->background = clean($request->get('background'));
            }

            if (!empty(request()->get('skills'))) {
                $profile->skills = clean($request->get('skills'));
            }

            if (!empty(request()->get('filepath'))) {
                $profile->displayPicture = $request->get('filepath');
            }

            if (!empty(request()->get('linkedInUrl'))) {
                $socialProfilesDecoded = json_decode($user->profile->socialProfiles, true);
                $socialProfilesDecoded["LinkedIn"] = $request->get('linkedInUrl');
                $profile->socialProfiles = json_encode($socialProfilesDecoded);
            }

            if (!empty(request()->get('twitterUrl'))) {
                $socialProfilesDecoded = json_decode($user->profile->socialProfiles, true);
                $socialProfilesDecoded["Twitter"] = $request->get('twitterUrl');
                $profile->socialProfiles = json_encode($socialProfilesDecoded);
            }

            $user->profile()->save($profile);

            return redirect()->back()->withSuccess('Your profile has been successfully updated');
        }
    }
}