Skip to content

Commit

Permalink
Allow syncing abilities by map
Browse files Browse the repository at this point in the history
  • Loading branch information
JosephSilber committed Sep 1, 2017
1 parent d6b4073 commit bb10eb0
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 46 deletions.
2 changes: 1 addition & 1 deletion src/Conductors/Concerns/FindsAndCreatesAbilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ trait FindsAndCreatesAbilities
* @param array $attributes
* @return array
*/
protected function getAbilityIds($abilities, $model, array $attributes)
protected function getAbilityIds($abilities, $model = null, array $attributes = [])
{
if ($abilities instanceof Model) {
return [$abilities->getKey()];
Expand Down
52 changes: 8 additions & 44 deletions src/Conductors/SyncsRolesAndAbilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

class SyncsRolesAndAbilities
{
use Concerns\FindsAndCreatesAbilities;

/**
* The authority for whom to sync roles/abilities.
*
Expand Down Expand Up @@ -70,11 +72,10 @@ public function forbiddenAbilities($abilities)
*/
protected function syncAbilities($abilities, $options = ['forbidden' => false])
{
$keyName = Models::ability()->getKeyName();

$abilityKeys = $this->getAbilityIds($abilities, $keyName);
$abilityKeys = $this->getAbilityIds($abilities);

$this->authority->abilities()
->whereNotIn($this->getAbilitiesQualifiedKeyName(), $abilityKeys)
->wherePivot('forbidden', $options['forbidden'])
->detach();

Expand All @@ -86,51 +87,14 @@ protected function syncAbilities($abilities, $options = ['forbidden' => false])
}

/**
* Get the IDs of the given abilities, creating new ones for the missing names.
* Get the fully qualified column name for the abilities table's primary key.
*
* @param iterable $abilities
* @param string $keyName
* @return array
* @return string
*/
protected function getAbilityIds($abilities, $keyName)
protected function getAbilitiesQualifiedKeyName()
{
$abilities = Helpers::groupModelsAndIdentifiersByType($abilities);

$abilities['strings'] = $this->findAbilityKeysOrCreate(
$abilities['strings'], $keyName
);

$abilities['models'] = Arr::pluck($abilities['models'], $keyName);

return Arr::collapse($abilities);
}

/**
* Find the IDs of the given ability names, creating the ones that are missing.
*
* @param iterable $names
* @param string $keyName
* @return array
*/
protected function findAbilityKeysOrCreate($names, $keyName)
{
if (empty($names)) {
return [];
}

$model = Models::ability();

$existing = $model->simpleAbility()
->whereIn('name', $names)
->get([$keyName, 'name'])
->pluck('name', $keyName);

$creating = (new Collection($names))->diff($existing);

$created = $creating->map(function ($name) use ($model) {
return $model->create(compact('name'))->getKey();
});

return $created->merge($existing->keys())->all();
return $model->getTable().'.'.$model->getKeyName();
}
}
2 changes: 1 addition & 1 deletion src/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public static function fillMissingKeys($array, $value, $keys)
public static function groupModelsAndIdentifiersByType($models)
{
$groups = (new Collection($models))->groupBy(function ($model) {
if (is_int($model)) {
if (is_numeric($model)) {
return 'integers';
} else if (is_string($model)) {
return 'strings';
Expand Down
25 changes: 25 additions & 0 deletions tests/SyncTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,31 @@ public function test_syncing_abilities()
$this->assertTrue($bouncer->allows('access-dashboard'));
}

public function test_syncing_abilities_With_a_map()
{
$bouncer = $this->bouncer($user = User::create())->dontCache();

$deleteUser = Ability::createForModel($user, 'delete');
$createAccounts = Ability::createForModel(Account::class, 'create');

$bouncer->allow($user)->to([$deleteUser, $createAccounts]);

$this->assertTrue($bouncer->allows('delete', $user));
$this->assertTrue($bouncer->allows('create', Account::class));

$bouncer->sync($user)->abilities([
'access-dashboard',
'create' => Account::class,
'view' => $user,
]);

$this->assertTrue($bouncer->denies('delete', $user));
$this->assertTrue($bouncer->denies('view', User::class));
$this->assertTrue($bouncer->allows('create', Account::class));
$this->assertTrue($bouncer->allows('view', $user));
$this->assertTrue($bouncer->allows('access-dashboard'));
}

public function test_syncing_forbidden_abilities()
{
$bouncer = $this->bouncer($user = User::create())->dontCache();
Expand Down

0 comments on commit bb10eb0

Please sign in to comment.