-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Open
Description
Description
If you setup your roles()
relationship to use a custom Pivot model and you have teams enabled, then the removeRole()
method fails to include the team scope because InteractsWithPivotTable::detach()
doesn't run a single query to detach the pivot records, rather it uses the function InteractsWithPivotTable::detachUsingCustomClass()
which runs InteractsWithPivotTable::getCurrentlyAttachedPivotsForIds()
and then iterates over the result and deletes each model.
For whatever reason the scoping applied when teams is enabled doesn't get applied when InteractsWithPivotTable::detachUsingCustomClass()
is used.
Steps To Reproduce
works with teams:
use HasRoles {
roles as traitRoles;
}
public function roles(): BelongsToMany
{
// We're adding timestamps so we know when a role was added and/or updated.
// And we always want the vessel_id even if we disable laravel-permissions teams support
return $this->traitRoles()
->withPivot('vessel_id')
->withTimestamps();
//->using(UserRole::class);
}
does not work with teams
use HasRoles {
roles as traitRoles;
}
public function roles(): BelongsToMany
{
// We're adding timestamps so we know when a role was added and/or updated.
// And we always want the vessel_id even if we disable laravel-permissions teams support
return $this->traitRoles()
->withPivot('vessel_id')
->withTimestamps();
->using(UserRole::class);
}
Test case:
<?php
use App\Models\Role;
use App\Models\User;
use App\Models\Vessel;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;
uses(TestCase::class);
uses(DatabaseTransactions::class);
test('Can sync or remove roles without detach on different teams', function () {
app(\Spatie\Permission\PermissionRegistrar::class)->teams = true;
$vessel1 = Vessel::factory()->create();
$vessel2 = Vessel::factory()->create();
Role::create(['name' => 'testRole', 'guard_name' => 'api']);
Role::create(['name' => 'testRole2', 'guard_name' => 'api']);
Role::create(['name' => 'testRole3', 'guard_name' => 'api']);
$testUser = User::factory()->create();
// For Vessel 1 attached testRole and testRole2
setPermissionsTeamId($vessel1);
$testUser->unsetRelation('roles');
$testUser->syncRoles('testRole', 'testRole2');
Log::debug('Vessel 1 Attached Roles', $testUser->roles->pluck('name')->toArray());
// For Vessel 2 attached testRole and testRole3
setPermissionsTeamId($vessel2);
$testUser->unsetRelation('roles');
$testUser->syncRoles('testRole', 'testRole3');
Log::debug('Vessel 2 Attached Roles', $testUser->roles->pluck('name')->toArray());
// Test Vessel 1 only has testRole and testRole2, and that testRole3 didn't get added or testRole2 removed in the syncRoles on Vessel 2
setPermissionsTeamId($vessel1);
$testUser->unsetRelation('roles');
$this->assertEquals(
collect(['testRole', 'testRole2']),
$testUser->getRoleNames()->sort()->values()
);
// For Vessel 1 remove testRole and confirm the user only has testRole2 attached
$testUser->removeRole('testRole');
Log::debug('Vessel 1 Attached Roles', $testUser->roles->pluck('name')->toArray());
$this->assertEquals(
collect(['testRole2']),
$testUser->getRoleNames()->sort()->values()
);
// For Vessel 2, confirm it still has testRole and testRole3, i.e. testRole wasn't incorrectly moved when it was removed from Vessel 1
setPermissionsTeamId($vessel2);
$testUser->unsetRelation('roles');
Log::debug('Vessel 2 Attached Roles', $testUser->roles->pluck('name')->toArray());
$this->assertEquals(
collect(['testRole', 'testRole3']),
$testUser->getRoleNames()->sort()->values()
);
});
Example Application
No response
Version of spatie/laravel-permission package:
6.21.0
Version of laravel/framework package:
12.21.0
PHP version:
8.2
Database engine and version:
No response
OS: Windows/Mac/Linux version:
No response
Metadata
Metadata
Assignees
Labels
No labels