Skip to content

Commit

Permalink
[5.x] Prevent duplicate roles & groups (#11270)
Browse files Browse the repository at this point in the history
  • Loading branch information
duncanmcclean authored Dec 20, 2024
1 parent 33ba7cc commit 460ab09
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 8 deletions.
22 changes: 14 additions & 8 deletions src/Auth/File/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,14 @@ public function explicitRoles($roles = null)

public function assignRole($role)
{
$roles = collect(Arr::wrap($role))->map(function ($role) {
return is_string($role) ? $role : $role->handle();
})->all();
$roles = collect($this->get('roles', []))
->merge(Arr::wrap($role))
->map(fn ($role) => is_string($role) ? $role : $role->handle())
->unique()
->values()
->all();

$this->set('roles', array_merge($this->get('roles', []), $roles));
$this->set('roles', $roles);

return $this;
}
Expand All @@ -198,11 +201,14 @@ public function removeRole($role)

public function addToGroup($group)
{
$groups = collect(Arr::wrap($group))->map(function ($group) {
return is_string($group) ? $group : $group->handle();
})->all();
$groups = collect($this->get('groups', []))
->merge(Arr::wrap($group))
->map(fn ($group) => is_string($group) ? $group : $group->handle())
->unique()
->values()
->all();

$this->set('groups', array_merge($this->get('groups', []), $groups));
$this->set('groups', $groups);

return $this;
}
Expand Down
45 changes: 45 additions & 0 deletions tests/Auth/FileUserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
use Statamic\Contracts\Auth\Role as RoleContract;
use Statamic\Contracts\Auth\UserGroup as UserGroupContract;
use Statamic\Facades\Role;
use Statamic\Facades\Role as RoleAPI;
use Statamic\Facades\UserGroup;
use Statamic\Facades\UserGroup as UserGroupAPI;
use Statamic\Support\Arr;
use Tests\PreventSavingStacheItemsToDisk;
use Tests\TestCase;
Expand Down Expand Up @@ -123,4 +125,47 @@ public function it_gets_permissions_from_a_cache()
// Doing it a second time should give the same result but without multiple calls.
$this->assertEquals($expectedPermissions, $user->permissions()->all());
}

#[Test]
public function it_prevents_saving_duplicate_roles()
{
$roleA = (new \Statamic\Auth\File\Role)->handle('a');
$roleB = (new \Statamic\Auth\File\Role)->handle('b');
$roleC = (new \Statamic\Auth\File\Role)->handle('c');

RoleAPI::shouldReceive('find')->with('a')->andReturn($roleA);
RoleAPI::shouldReceive('find')->with('b')->andReturn($roleB);
RoleAPI::shouldReceive('find')->with('c')->andReturn($roleC);
RoleAPI::shouldReceive('all')->andReturn(collect([$roleA, $roleB])); // the stache calls this when getting a user. unrelated to test.

$user = $this->createPermissible();
$user->assignRole('a');

$this->assertEquals(['a'], $user->get('roles'));

$user->assignRole(['a', 'b', 'c']);

$this->assertEquals(['a', 'b', 'c'], $user->get('roles'));
}

#[Test]
public function it_prevents_saving_duplicate_groups()
{
$groupA = (new \Statamic\Auth\File\UserGroup)->handle('a');
$groupB = (new \Statamic\Auth\File\UserGroup)->handle('b');
$groupC = (new \Statamic\Auth\File\UserGroup)->handle('c');

UserGroupAPI::shouldReceive('find')->with('a')->andReturn($groupA);
UserGroupAPI::shouldReceive('find')->with('b')->andReturn($groupB);
UserGroupAPI::shouldReceive('find')->with('c')->andReturn($groupC);

$user = $this->createPermissible();
$user->addToGroup('a');

$this->assertEquals(['a'], $user->get('groups'));

$user->addToGroup(['a', 'b', 'c']);

$this->assertEquals(['a', 'b', 'c'], $user->get('groups'));
}
}

0 comments on commit 460ab09

Please sign in to comment.