spatie/laravel-permission

for v6 - There is no role with ID `org_uuid` for guard `api`

bilginnet opened this issue · 2 comments

Versions

  • spatie/laravel-permission package version: v6
  • laravel/framework package v10

PHP version: 8.1
Database version: mysql latest

changed migration file:

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        $teams = config('permission.teams');
        $tableNames = config('permission.table_names');
        $columnNames = config('permission.column_names');
        $pivotRole = $columnNames['role_pivot_key'] ?? 'role_id';
        $pivotPermission = $columnNames['permission_pivot_key'] ?? 'permission_id';

        if (empty($tableNames)) {
            throw new \Exception('Error: config/permission.php not loaded. Run [php artisan config:clear] and try again.');
        }
        if ($teams && empty($columnNames['team_foreign_key'] ?? null)) {
            throw new \Exception('Error: team_foreign_key on config/permission.php not loaded. Run [php artisan config:clear] and try again.');
        }

        Schema::create($tableNames['permissions'], function (Blueprint $table) {
            $table->uuid('id')->primary()->unique(); // permission id
            $table->string('name');       // For MySQL 8.0 use string('name', 125);
            $table->string('guard_name'); // For MySQL 8.0 use string('guard_name', 125);
            $table->timestamps();

            $table->unique(['name', 'guard_name']);
        });

        Schema::create($tableNames['roles'], function (Blueprint $table) use ($teams, $columnNames) {
            $table->uuid('id')->primary()->unique(); // role id
            if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing
                $table->uuid($columnNames['team_foreign_key'])->nullable();
                $table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index');
            }
            $table->string('name');       // For MySQL 8.0 use string('name', 125);
            $table->string('guard_name'); // For MySQL 8.0 use string('guard_name', 125);
            $table->timestamps();
            if ($teams || config('permission.testing')) {
                $table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']);
            } else {
                $table->unique(['name', 'guard_name']);
            }
        });

        Schema::create($tableNames['model_has_permissions'], function (Blueprint $table) use ($tableNames, $columnNames, $pivotPermission, $teams) {
            $table->uuid($pivotPermission);

            $table->string('model_type');
            $table->uuid($columnNames['model_morph_key']);
            $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index');

            $table->foreign($pivotPermission)
                ->references('id') // permission id
                ->on($tableNames['permissions'])
                ->onDelete('cascade');
            if ($teams) {
                $table->uuid($columnNames['team_foreign_key'])->nullable();
                $table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index');

                $table->primary([/*$columnNames['team_foreign_key'], */ $pivotPermission, $columnNames['model_morph_key'], 'model_type'],
                    'model_has_permissions_permission_model_type_primary');
            } else {
                $table->primary([$pivotPermission, $columnNames['model_morph_key'], 'model_type'],
                    'model_has_permissions_permission_model_type_primary');
            }

        });

        Schema::create($tableNames['model_has_roles'], function (Blueprint $table) use ($tableNames, $columnNames, $pivotRole, $teams) {
            $table->uuid($pivotRole);

            $table->string('model_type');
            $table->uuid($columnNames['model_morph_key']);
            $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index');

            $table->foreign($pivotRole)
                ->references('id') // role id
                ->on($tableNames['roles'])
                ->onDelete('cascade');
            if ($teams) {
                $table->uuid($columnNames['team_foreign_key'])->nullable();
                $table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index');

                $table->primary([/*$columnNames['team_foreign_key'], */ $pivotRole, $columnNames['model_morph_key'], 'model_type'],
                    'model_has_roles_role_model_type_primary');
            } else {
                $table->primary([$pivotRole, $columnNames['model_morph_key'], 'model_type'],
                    'model_has_roles_role_model_type_primary');
            }
        });

        Schema::create($tableNames['role_has_permissions'], function (Blueprint $table) use ($tableNames, $pivotRole, $pivotPermission) {
            $table->uuid($pivotPermission);
            $table->uuid($pivotRole);

            $table->foreign($pivotPermission)
                ->references('id') // permission id
                ->on($tableNames['permissions'])
                ->onDelete('cascade');

            $table->foreign($pivotRole)
                ->references('id') // role id
                ->on($tableNames['roles'])
                ->onDelete('cascade');

            $table->primary([$pivotPermission, $pivotRole], 'role_has_permissions_permission_id_role_id_primary');
        });

        app('cache')
            ->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null)
            ->forget(config('permission.cache.key'));
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        $tableNames = config('permission.table_names');

        if (empty($tableNames)) {
            throw new \Exception('Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.');
        }

        Schema::drop($tableNames['role_has_permissions']);
        Schema::drop($tableNames['model_has_roles']);
        Schema::drop($tableNames['model_has_permissions']);
        Schema::drop($tableNames['roles']);
        Schema::drop($tableNames['permissions']);
    }
};

Enum class:

namespace App\Enums;

enum RolesEnum: string
{
    case SUPER_ADMIN = 'super-admin';
    case ADMIN = 'admin';
    case VIEWER = 'viewer';
    case ORG_MANAGER = 'org-manager';
    case ORG_USER = 'org-user';

    public function label(): string
    {
        return match ($this) {
            self::SUPER_ADMIN => 'Super Admins',
            self::ADMIN => 'Admins',
            self::VIEWER => 'Viewers',
            self::ORG_MANAGER => 'Organization Managers',
            self::ORG_USER => 'Organization Users',
        };
    }
}

and Seeder file:

            $userOrgManager = User::factory()->create();
            $userOrgUser = User::factory()->create();

            $organization = Organization::factory()->owner($userOrgManager->id)->create();
            $organization->users()->sync([$userOrgManager->id, $userOrgUser->id]);

            // also tried without organization_id . got same error. there is no role for "uuid"
            $roleOrgManager = Role::query()->firstOrCreate(['name' => RolesEnum::ORG_MANAGER->value, 'organization_id' => $organization->id]);
            $roleOrgUser = Role::query()->firstOrCreate(['name' => RolesEnum::ORG_USER->value, 'organization_id' => $organization->id]);


            $userOrgManager->assignRole([$roleOrgManager->id => ['organization_id' => $organization->id]]);
            $userOrgUser->assignRole([$roleOrgUser->id => ['organization_id' => $organization->id]]);

and i got this error - There is no role with ID org_uuid for guard api

already checked .. this role created on the roles table with guard api .

i tried to create roles without organization id but i got same error again.

why i need to fill team_id (it set required and primary in migration file) on the roles table when set teams => true in the permissions.php (config)

It seems to me that you made some mistake in the configuration. Upload a demo repo with the code showing the problem
https://spatie.be/laravel-permission/creating-a-demo-app

  1. The "there is no role with ID x" error is thrown by Role::findById(), which is called from getStoredRole(), which is called by collectRoles(), which is called by assignRole().

  2. Your posted assignRole() call looks strange. Why are you passing a nested array?

When reformatting your posted code of:
$userOrgManager->assignRole([$roleOrgManager->id => ['organization_id' => $organization->id]]);
it looks like this:

$userOrgManager->assignRole([
    $roleOrgManager->id => [
        'organization_id' => $organization->id
        ]
    ]);

That's not the kind of array that assignRole() accepts. assignRole() accepts a one-dimensional array of role ids or role objects/records or role names.

  1. It should never be looking for a role with an ID of uuid (or org_uuid) ... that's part of the schema, not a valid record id. (If you were giving a role name of uuid, then perhaps "uuid" might be acceptable, but if it gave an error related to such a name, then it would say that it couldn't find a role with that name, not "ID".)
    Thus, as parallels999 mentioned, something is wrong in your code or your configuration.
    We need to see your complete code related to this. As mentioned, please create a fresh repository for a basic app which recreates this exact problem.