Laravel-permission: RoleDoesNotExist in migrations

Created on 25 Apr 2017  路  17Comments  路  Source: spatie/laravel-permission

I have migration file in which I like to assign role to existing user in my DB.
Code fail when try to assign role viewer on user.

I have in my database:

ID | name   | guard_name
1  | viewer | api

This is my code in migration file:

foreach (User::all() as $user) {
    $user->assignRole('viewer');
}

Can I force some guard or maybe there is some other solution about this problem ?

Most helpful comment

@sebastiandedeyne I think we've made a step forward. I can now assign role to a user in this way:

$user->assignRole(Role::findByName('composer', 'api'));

I don't know if it is the correct way to assign an actual object with assignRole.

All 17 comments

Could you try clearing you cache between creating and assigning the role?

If you're using the default guard, you don't need to worry about that.

@sebastiandedeyne I try to clear cache but problem still here.
My default guard is web but my role viewer has guard_name = api . Maybe this is the problem but this must be like this because I have users on production and all must have viewer role.

Since you're dealing with multiple guards, instead of passing a string try to assign an actual object with assignRole ($user->assignRole($viewerRole))

Error: The given role or permission should use guardwebinstead ofapi.

viewer role has quard_name = api, but my default guard is set to web. I think that there is the problem...

You can't "share" roles between different guards. Different guards require different roles. If you need need one for two guards, create a second role with the same name.

@sebastiandedeyne I don't not quite understand assignRole($user->assignRole($viewerRole)) you said. I have two different guards, web and api. So how shall I assign a role whose guard_name = api to a registered user?

// register
$user = User::create($inputList);
$user->assignRole($user->assignRole('composer', 'api'));    // error

Thanks!

Could you share the configuration of your guards in config/auth.php?

@sebastiandedeyne Here is my config/auth.php

<?php

return [
    'defaults' => [
        // 'guard' => 'web',
        'guard' => 'api',
        'passwords' => 'users',
    ],

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            // 'driver' => 'token',
            // 'driver' => 'passport',
            'driver' => 'jwt',
            'provider' => 'users',
        ],
    ],

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],
    ],
];

Think something's wrong on our end here. Created a new issue (#294) to follow this up, I'll try to get to this soon.

@wyudong Could you require in dev-master and see if your issue is resolved?

@sebastiandedeyne I think we've made a step forward. I can now assign role to a user in this way:

$user->assignRole(Role::findByName('composer', 'api'));

I don't know if it is the correct way to assign an actual object with assignRole.

No that's perfect!

If you're using multiple guards, I recommend using objects over strings, otherwise the package needs to guess with role/permission you want to use in the case of having two roles/permissions with the same names and different guards.

I just released these changes in 2.5.1.

@sebastiandedeyne I just released these changes in 2.5.1.

馃槙 The latest version available at the moment is 2.4.2:

I meant 2.1.5 apparently, so this should be resolved!

Still not working for $user->syncRoles('Administrator'). By using @wyudong workaround (Role::findByName('Administrator', 'api')) seems to work, but it does not when I use string.

Extended example of @wyudong answer

public function update(UpdateUserRequest $request, $id)
    {
        $user = $this->user->findOrFailUuid($id);

        $user->fill($request->all());

        $user->save();

        //sync roles

        if ($request->filled('roles')) {

            $roles = [];

            foreach ($request->roles as $role_name) {

                $role = Role::findByName($role_name, 'api');

                if ($role) {
                    $roles[] = $role;
                }
            }

            if (!empty($roles)) {
                $user->syncRoles($roles);
            }
        }

        return new UserResource($user->load('roles'));
    }

I had the same issue and I solved it by using the Model which is assigned as the provider and in this case its User::class model

'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ],

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ergonomicus picture ergonomicus  路  3Comments

notflip picture notflip  路  3Comments

younus93 picture younus93  路  4Comments

tripex picture tripex  路  3Comments

Dreambox13 picture Dreambox13  路  3Comments