FrazeColder's avatar

Laravel FormRequest validation gets User model and sometimes directly the name

Hi,

I am using Laravel 8 and validate my requests with the form request validation. However, I have a strange problem. Before I am going to describe my problem I will paste my routes and my validation class here:

routes:

Route::post('users', ['as' => 'user.search', 'uses' => 'UserController@indexSearch']);

Route::post('user/name', ['as' => 'user.name.exists', 'uses' => 'UserController@nameExists']);

Route::post('user/email', ['as' => 'user.email.exists', 'uses' => 'UserController@emailExists']);

Route::post('user/email/check', ['as' => 'user.email.check', 'uses' => 'UserController@emailCheck']);

Route::get('user/{user:name}', ['as' => 'user.show', 'uses' => 'UserController@show']);

Route::get('user/{user:name}/einstellungen', ['as' => 'user.settings', 'uses' => 'UserController@showSettings']);

Route::get('user/{user:name}/produkte', ['as' => 'user.products', 'uses' => 'UserController@userProducts']);

Route::post('user/{user:name}/produkte', ['as' => 'user.products.post', 'uses' => 'UserController@userProducts']);

Route::get('user/{user:name}/saved/produkte', ['as' => 'user.marked.products', 'uses' => 'UserController@userMarkedProducts']);

Route::post('user/{user:name}/saved/produkte', ['as' => 'user.marked.products.post', 'uses' => 'UserController@userMarkedProducts']);

Route::post('user/{user:name}/avatar/upload', ['as' => 'user.avatar.update', 'uses' => 'UserController@update']);

Route::post('user/{user:name}/avatar/valid', ['as' => 'user.avatar.valid', 'uses' => 'UserController@validAvatar']);

Route::post('user/{user:name}/avatar/löschen', ['as' => 'user.avatar.delete', 'uses' => 'UserController@deleteAvatar']);

Route::post('user/{user:name}/update/password', ['as' => 'user.password.change', 'uses' => 'UserController@updatePassword']);

Route::post('user/{user:name}/validate/password', ['as' => 'user.password.validate', 'uses' => 'UserController@validatePassword']);

This is my FormRequest validation which checks if the user is authorized to perform this request and if the given data are valid. As you can see, I check if the Auth::user()->name is the same as the requested user ($this->user->name) to change the image. Because only the owner of his profile image should be allowed to change is profile image.

class UserAvatarUpdateRequest extends FormRequest
{
    public function authorize()
    {
        dump(array('auth' => Auth::user()->name, 'requested' => $this->user));     

        if(Auth::check() && Auth::user()->name == $this->user->name){
            return true;
        }

        return false;
    }
    
    public function rules()
    {
        return [
            'avatar' => [
                'required',
                'image',
                'max:5000',
                'mimes:jpeg,png,jpg',
                Rule::dimensions()->minWidth(200)->minHeight(200)->ratio(1)
            ],
        ];
    }

}

Now I will come to the problem. As you can see I have several routes for my user and there is one route called user.avatar.valid and another route called user.avatar.update.

Both routes, user.avatar.valid and user.avatar.update are using the FormRequest validation class I have pasted above. Basically user.avatar.valid is being called before the user submits the form to check if the uploaded image is valid. I know, I also could do this in one request but that's not possible because I am using vee-validate for Vuejs to validate if the form is valid.

However, thats not the probleme here. The problem is that when calling the user.avatar.valid route my dump echos for the key requested the name of the requested user. But, when performing a request for user.avatar.update I don't get the name of the user but rather the user object which contains the id, name, email and so on.

But exactly this is the point... when trying to call user.avatar.update I get a 403 error (forbidden) because $this->user is not equal to Auth::user()->name. Obviously it is not the same when I compare a string (name) to the user object.

However, when calling user.avatar.valid it passes because here I get the name when calling $this->user and not the user object.

But why is that?

When I change $this->user to $this->user->name I get the actual name for the user when calling the user.avatar.update route but on the other side I get a 500 error when calling the user.avatar.valid route because it says Trying to get property 'name' of non-object...

Does anybody has an idea where the problem here is and how to fix this?

Kind regards and thank you!

0 likes
3 replies
MichalOravec's avatar

Don't use $this->user->name but $this->route('user')->name. If you have input with name user then you have problem. Everytime when you want to access data from route use $this->route()

And use two different form requests which you can inherit and just replace what you need.

1 like
FrazeColder's avatar

Thanks for your answer!

However, I have exactly the same problem as written above just not with $this->user or $this->user->name but with $this->route('user') or $this->route('user')->name...

Why does it either return the user object or cannot access the property name?

FrazeColder's avatar
FrazeColder
OP
Best Answer
Level 1

If anybody else is facing this problem, I found the solution. Well, at least I found the problem I have:

I did forget to pass the User $user to my validate function... Check your function parameters!

Please or to participate in this conversation.