Skip to content

Commit

Permalink
Merge pull request #4 from mr-luke/feature/multiscopes
Browse files Browse the repository at this point in the history
added multiscopes and dynamis scopes
  • Loading branch information
hsmusz committed Nov 21, 2019
2 parents 182bdfc + ee040b0 commit bfc4a1b
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 57 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ node_modules/
.DS_Store
composer.lock
npm-debug.log
.idea/
6 changes: 3 additions & 3 deletions src/Detector.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class Detector
/**
* Scope name.
*
* @var string
* @var string|array
*/
protected $scope;

Expand Down Expand Up @@ -177,10 +177,10 @@ public function ownerOrLevel(Model $model, int $min, string $foreign = null)
/**
* Set scope that is checking.
*
* @param string $scope
* @param string|array $scope
* @return self
*/
public function scope(string $scope): self
public function scope($scope): self
{
$this->scope = $scope;

Expand Down
6 changes: 3 additions & 3 deletions src/Extentions/Authorizable.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ public function assignRole($role): void
/**
* Return permission level based on personal's & role's permission.
*
* @param string $scope
* @param string|array $scopes
* @return int
*/
public function considerPermission(string $scope): int
public function considerPermission($scopes): int
{
return Manager::considerPermission($this, $scope);
return Manager::considerPermission($this, $scopes);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Facades/Detector.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* @method static mixed level(int $min)
* @method static mixed owner(Model $model, string $foreign = null)
* @method static mixed ownerOrLevel(Model $model, int $min, string $foreign = null)
* @method static self scope(string $scope)
* @method static self scope($scope)
* @method static mixed share(Model $model, string $modelRelation, string $relation)
* @method static self subject(Authorizable $auth)
*/
Expand Down
2 changes: 1 addition & 1 deletion src/Facades/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

/**
* @method static void assignRole(Authorizable $auth, $role)
* @method static int considerPermission(Authorizable $auth, string $scope)
* @method static int considerPermission(Authorizable $auth, $scope)
* @method static array considerRestriction(Authorizable $auth)
* @method static mixed detectScope(string $model)
* @method static string getAuthorizableModel()
Expand Down
128 changes: 79 additions & 49 deletions src/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

namespace Mrluke\Privileges;

use InvalidArgumentException;
use Illuminate\Database\Eloquent\Model;
use InvalidArgumentException;
use Mrluke\Configuration\Contracts\ArrayHost as Host;
use Mrluke\Configuration\Exceptions\ConfigurationException;
use Mrluke\Privileges\Contracts\Authorizable;
use Mrluke\Privileges\Contracts\Permission;
use Mrluke\Privileges\Contracts\Permitable;
use Mrluke\Privileges\Contracts\Role;

Expand All @@ -23,9 +22,9 @@
* @license MIT
* @version 1.0.0
*
* @property mixed $allowed_value
* @property mixed $allowed_value
* @property string $authKeyName
* @property mixed $denied_value
* @property mixed $denied_value
*/
class Manager
{
Expand Down Expand Up @@ -65,8 +64,9 @@ public function __construct(Host $config)
/**
* Assign Authorizable to given role.
*
* @param \Mrluke\Privileges\Contracts\Authorizable $auth
* @param mixed $role
* @param \Mrluke\Privileges\Contracts\Authorizable $auth
* @param mixed $role
*
* @return void
*/
public function assignRole(Authorizable $auth, $role): void
Expand All @@ -87,32 +87,47 @@ public function assignRole(Authorizable $auth, $role): void
/**
* Return permission level based on personal's & role's permission.
*
* @param \Mrluke\Privileges\Contracts\Authorizable $auth
* @param string $scope
* @param \Mrluke\Privileges\Contracts\Authorizable $auth
* @param string|array $scopes
*
* @return int
*
* @throws \InvalidArgumentException
*/
public function considerPermission(Authorizable $auth, string $scope): int
public function considerPermission(Authorizable $auth, $scopes): int
{
if ($personal = $this->getPermission($auth, $scope)) {
// Personal permissions has priority
// over role's ones.
//
return $personal->level;
if (!is_array($scopes)) {
$scopes = [$scopes];
}

// Validate scopes ahead of all conditions
//
foreach ($scopes as $scope) {
$this->checkScope($scope);
}

foreach ($scopes as $scope) {
if ($personal = $this->getPermission($auth, $scope, false)) {
// Personal permissions has priority
// over role's ones.
//
return $personal->level;
}
}

$general = 0;
if (! $auth->relationLoaded('roles')) {
if (!$auth->relationLoaded('roles')) {
$auth->load('roles.permissions');
}

foreach ($auth->roles as $r) {
// Let's check if there's a given scope defined
// as a permission in any of Authorizable roles.
//
if ($p = $this->getPermission($r, $scope)) {
($p->level < $general) ?: $general = $p->level;
foreach ($scopes as $scope) {
foreach ($auth->roles as $r) {
// Let's check if there's a given scope defined
// as a permission in any of Authorizable roles.
//
if ($p = $this->getPermission($r, $scope, false)) {
($p->level < $general) ?: $general = $p->level;
}
}
}

Expand All @@ -122,7 +137,8 @@ public function considerPermission(Authorizable $auth, string $scope): int
/**
* Return restrictions based on roles.
*
* @param \Mrluke\Privileges\Contracts\Authorizable $auth
* @param \Mrluke\Privileges\Contracts\Authorizable $auth
*
* @return array
*
* @throws \InvalidArgumentException
Expand All @@ -132,7 +148,7 @@ public function considerRestriction(Authorizable $auth): array
$restrictions = [];
$level = 0;

if (! $auth->relationLoaded('roles')) {
if (!$auth->relationLoaded('roles')) {
$auth->load('roles.permissions');
}

Expand All @@ -147,13 +163,14 @@ public function considerRestriction(Authorizable $auth): array
/**
* Detect which scope should be applied for given model.
*
* @param string $model
* @param string $model
*
* @return string|null
*/
public function detectScope(string $model)
{
return $this->config->get(
'mapping.'.$model,
'mapping.' . $model,
$this->config->get('mapping_default')
);
}
Expand All @@ -177,7 +194,7 @@ public function getAuthorizableMigration(): array
{
if (is_null($this->authKeyName)) {
$authorizableClass = $this->config->get('authorizable');
$instance = new $authorizableClass;
$instance = new $authorizableClass;

if (!$instance instanceof Model) {
throw new ConfigurationException(
Expand All @@ -193,32 +210,36 @@ public function getAuthorizableMigration(): array
return [
'key' => $this->authKeyName,
'type' => $this->authKeyType,
'table' => $this->authTable
'table' => $this->authTable,
];
}

/**
* Return Permission for given scope.
*
* @param \Mrluke\Privileges\Contracts\Permitable $subject
* @param string $scope
* @param \Mrluke\Privileges\Contracts\Permitable $subject
* @param string $scope
* @param bool $checkScope
*
* @return \Mrluke\Privileges\Contracts\Permission|null
*
* @throws \InvalidArgumentException
*/
public function getPermission(Permitable $subject, string $scope)
public function getPermission(Permitable $subject, string $scope, bool $checkScope = true)
{
$this->checkScope($scope);
if($checkScope) {
$this->checkScope($scope);
}

return $subject->permissions->where('scope', $scope)->first();
}

/**
* Grant or update premission for a Permitable.
*
* @param \Mrluke\Privileges\Contracts\Permitable $subject
* @param string $scope
* @param int $level
* @param \Mrluke\Privileges\Contracts\Permitable $subject
* @param string $scope
* @param int $level
*
* @return void
*
* @throws \InvalidArgumentException
Expand All @@ -231,15 +252,16 @@ public function grantPermission(Permitable $subject, string $scope, int $level):

$permission ? $permission->update(['level' => $level]) : $subject->permissions()->create([
'scope' => $scope,
'level' => $level
'level' => $level,
]);
}

/**
* Determine if there's a given scope Permission for a Permitable.
*
* @param \Mrluke\Privileges\Contracts\Permitable $subject
* @param string $scope
* @param \Mrluke\Privileges\Contracts\Permitable $subject
* @param string $scope
*
* @return bool
*
* @throws \InvalidArgumentException
Expand All @@ -254,8 +276,9 @@ public function hasPermission(Permitable $subject, string $scope): bool
/**
* Determine if Permitable has given Role assigned.
*
* @param \Mrluke\Privileges\Contracts\Permitable $subject
* @param mixed $role
* @param \Mrluke\Privileges\Contracts\Permitable $subject
* @param mixed $role
*
* @return bool
*/
public function hasRole(Permitable $subject, $role): bool
Expand All @@ -266,8 +289,9 @@ public function hasRole(Permitable $subject, $role): bool
/**
* Regain permission for a Permitable.
*
* @param \Mrluke\Privileges\Contracts\Permitable $subject
* @param string $scope
* @param \Mrluke\Privileges\Contracts\Permitable $subject
* @param string $scope
*
* @return void
*
* @throws \InvalidArgumentException
Expand All @@ -282,8 +306,9 @@ public function regainPermission(Permitable $subject, string $scope): void
/**
* Remove Authorizable's role.
*
* @param \Mrluke\Privileges\Contracts\Authorizable $auth
* @param mixed $role
* @param \Mrluke\Privileges\Contracts\Authorizable $auth
* @param mixed $role
*
* @return void
*/
public function removeRole(Authorizable $auth, $role): void
Expand All @@ -302,7 +327,8 @@ public function removeRole(Authorizable $auth, $role): void
/**
* Return class attributes or setting.
*
* @param string $name
* @param string $name
*
* @return mixed
*/
public function __get(string $name)
Expand All @@ -321,23 +347,27 @@ public function __get(string $name)
/**
* Check if the scope value.
*
* @param string $scope
* @param string $scope
*
* @return void
*
* @throws \InvalidArgumentException
*/
private function checkScope(string $scope): void
{
if (!in_array($scope, $this->config->get('scopes'))) {
$scope = explode(':', $scope);

if (!in_array($scope[0], $this->config->get('scopes'))) {
throw new InvalidArgumentException('Given [scope] is not allowed.');
}
}

/**
* Check if the scope & level values.
*
* @param string $scope
* @param int $level
* @param string $scope
* @param int $level
*
* @return void
*
* @throws \InvalidArgumentException
Expand Down

0 comments on commit bfc4a1b

Please sign in to comment.