diff --git a/composer.json b/composer.json index af4082d..d697fa1 100644 --- a/composer.json +++ b/composer.json @@ -1,16 +1,16 @@ { - "name": "wesleywillians/acl", + "name": "esilvajr/acl", "license": "MIT", "authors": [ { - "name": "Wesley Willians", - "email": "wesleywillians@gmail.com" + "name": "Edison Silva Jr", + "email": "edison.junior@s2it.com.br" } ], "require": {}, "autoload": { "psr-4": { - "CodeEdu\\Acl\\": "src/" + "\\Acl\\": "src/" } } } diff --git a/public/Example.php b/public/Example.php new file mode 100644 index 0000000..9bdb292 --- /dev/null +++ b/public/Example.php @@ -0,0 +1,230 @@ +role($role); + } + + public function role(\Acl\Contracts\Role $role = null) : \Acl\Contracts\Role + { + if (!is_null($role)) + $this->role = $role; + return $this->role; + } +} + +/** + * Administrator class + * @implements \Acl\Contracts\User + */ +class Administrator implements \Acl\Contracts\User +{ + private $role; + + public function __construct(\Acl\Contracts\Role $role = null) + { + $this->role($role); + } + + public function role(\Acl\Contracts\Role $role = null) : \Acl\Contracts\Role + { + if (!is_null($role)) + $this->role = $role; + return $this->role; + } +} + +/** + * User class + * @implements \Acl\Contracts\User + */ +class Users implements \Acl\Contracts\User +{ + private $role; + + public function __construct(\Acl\Contracts\Role $role = null) + { + $this->role($role); + } + + public function role(\Acl\Contracts\Role $role = null) : \Acl\Contracts\Role + { + if (!is_null($role)) + $this->role = $role; + return $this->role; + } +} + +/* + * ------------------------------------------------------------------------------- + * Creating new FACTORIES + * ------------------------------------------------------------------------------- + * The factories are used to create and configure a Role or a Resource + */ + +/* + * ------------------------------------------------------------------------------- + * Sample 1 - Full straight way + * Create a new \Acl\Factory\Role()y() object, + * after that call resouces passing by a instance of \Acl\Entity\Role() + * and finally call add to set one or many \Acl\Entity\Resouce() + * ------------------------------------------------------------------------------- + */ + +//Create new \Acl\Source\Models\Role\Factory() Object +$roleFactory = new \Acl\Factory\Role(); + +//Call permissions passing by a instance of \Acl\Source\Entity\Role() to add permissions. +$roleFactory->resources($roleFactory->add(new \Acl\Entity\Role(OWNER))->get()) + ->add(new \Acl\Entity\Resource('ALL')) + ->add(new \Acl\Entity\Resource('ALL_GRANTED')) + ->add(new \Acl\Entity\Resource('ALL_VIEW')); + +/* + * ------------------------------------------------------------------------------ + * Sample 2 - By step way + * Create a new \Acl\Factory\Role() object + * after that add all roles for this factory + * after that call resouces passing a role by param + * and finally call add to set one or many \Acl\Entity\Resouce() that + * belongs to an role + * @todo We need to set up permissions for all roles individually + * ------------------------------------------------------------------------------ + */ + +//Create new \Acl\Factory\Role() Object +$roleFactory = new \Acl\Factory\Role(); + +//Add a new \Acl\Entity\Role() of OWNER type; +$owner = $roleFactory->add(new \Acl\Entity\Role(OWNER)); +//Add a new \Acl\Entity\Role() of ADMIN type; +$admin = $roleFactory->add(new \Acl\Entity\Role(ADMIN)); +//Add a new \Acl\Entity\Role() of USER type; +$users = $roleFactory->add(new \Acl\Entity\Role(USER)); + +//Add resources that belongs to "Owner" role +$roleFactory->resources($owner->get())->add(new \Acl\Entity\Resource(ALL)); + +//Add resources that belongs to "Admin" role +$roleFactory->resources($admin->get()) + ->add(new \Acl\Entity\Resource(EDITOR)) + ->add(new \Acl\Entity\Resource(WEBSERVICE)); + +//Add resouces that belongs to "Users" role +$roleFactory->resources($users->get())->add(new \Acl\Entity\Resource(CONTRIBUTOR)); + +/* + * ------------------------------------------------------------------------------ + * Creating users of type: + * Owner::class, + * Administator::class + * and Users::class. + * Passing a role by param. + * ----------------------------------------------------------------------------- + */ + +$owner = new Owner($roleFactory->get(OWNER)); +$administrator = new Administrator($roleFactory->get(ADMIN)); +$users = new Users($roleFactory->get(OWNER)); + +/* + * ------------------------------------------------------------------------------ + * Create a new \Acl\Source\Acl() object, + * This constructor set up a new FactoryInterface object + * ------------------------------------------------------------------------------ + */ +$acl = new \Acl\Acl($roleFactory); + + +/* + * ------------------------------------------------------------------------------ + * Sample 1 - Setting a user for acl + * as we need a user we can set like in example 1 or direcly + * ------------------------------------------------------------------------------ + */ +$acl->user($owner); //or $acl->user($owner)->method(); +/* + * ------------------------------------------------------------------------------ + * Sample 2 - Has role? + * ------------------------------------------------------------------------------ + */ +$acl->user($owner)->hasRole('owner'); //or $acl->hasRole('ALL') if user already set + +/* + * ------------------------------------------------------------------------------ + * Sample 3 - Has resource? + * ------------------------------------------------------------------------------ + */ +$acl->user($owner)->hasResource($roleFactory->get(OWNER)->get(), 'ALL'); + +/* + * ------------------------------------------------------------------------------ + * Sample 4 - Can and Cannot + * ------------------------------------------------------------------------------ + */ +$acl->user($owner)->can(ALL); +$acl->user($owner)->cannot(ALL); + +/* + * ------------------------------------------------------------------------------ + * Sample 4 - Have a Incident + * ------------------------------------------------------------------------------ + */ +//Set new incident +$incident = new \Acl\Entity\Incident('Coke'); +$incident->owner($owner); +//Verify if owns +$acl->owns($incident, $owner); diff --git a/src/Acl.php b/src/Acl.php deleted file mode 100644 index 8fb4722..0000000 --- a/src/Acl.php +++ /dev/null @@ -1,132 +0,0 @@ -roles = $roles; - - foreach($resources as $resource) { - if(!$resource instanceof Resource) { - throw new \InvalidArgumentException("Invalid Resource"); - } - } - $this->resources = $resources; - } - - /** - * @param UserAcl $user - * @return Acl - */ - public function setUser(UserAcl $user): Acl - { - $this->user = $user; - return $this; - } - - /** - * @param string $role - * @return bool - */ - public function hasRole(string $role): bool - { - foreach ($this->roles as $r) { - if($r->getName() == $role) { - return true; - } - } - return false; - } - - /** - * @param string $role - * @param string $permission - * @return bool - */ - public function hasPermission(string $role, string $permission): bool - { - foreach($this->roles as $r) { - if($r->getName() == $role) { - foreach($r->getPermissions() as $p) { - if($p->getName() == $permission) { - return true; - } - } - } - } - return false; - } - - /** - * @param string $permission - * @param UserAcl|null $user - * @return bool - */ - public function can(string $permission, UserAcl $user = null): bool - { - if($user) { - return $this->hasPermission($user->getRole(), $permission); - } - - if($this->user) { - return $this->hasPermission($this->user->getRole(), $permission); - } - - return false; - } - - /** - * @param string $permission - * @param UserAcl|null $user - * @return bool - */ - public function cannot(string $permission, UserAcl $user = null): bool - { - return !$this->can($permission, $user); - } - - /** - * @param $resource - * @param UserAcl|null $user - * @return bool - */ - public function isOwner($resource, UserAcl $user = null): bool - { - if($user) { - $this->setUser($user); - } - - foreach($this->resources as $r) { - if(is_a($resource, $r->getName())) { - if($user) { - return $resource->{$r->getOwnerField()}() == $user->getId(); - } - - return $resource->{$r->getOwnerField()}() == $this->user->getId(); - - } - } - return false; - } -} \ No newline at end of file diff --git a/src/Contracts/UserAcl.php b/src/Contracts/UserAcl.php deleted file mode 100644 index be76a54..0000000 --- a/src/Contracts/UserAcl.php +++ /dev/null @@ -1,10 +0,0 @@ -name = $name; - } - - /** - * @return string - */ - public function getName(): string - { - return $this->name; - } - - /** - * @param string $name - * @return Permission - */ - public function setName(string $name): Permission - { - $this->name = $name; - return $this; - } - - - -} \ No newline at end of file diff --git a/src/Entities/Resource.php b/src/Entities/Resource.php deleted file mode 100644 index 622b3fe..0000000 --- a/src/Entities/Resource.php +++ /dev/null @@ -1,53 +0,0 @@ -name = $name; - $this->ownerField = $ownerField; - } - - /** - * @return string - */ - public function getName(): string - { - return $this->name; - } - - /** - * @param string $name - * @return Resource - */ - public function setName(string $name):Resource - { - $this->name = $name; - return $this; - } - - /** - * @return string - */ - public function getOwnerField():string - { - return $this->ownerField; - } - - /** - * @param string $ownerField - * @return Resource - */ - public function setOwnerField(string $ownerField): Resource - { - $this->ownerField = $ownerField; - return $this; - } -} \ No newline at end of file diff --git a/src/Entities/Role.php b/src/Entities/Role.php deleted file mode 100644 index eef613c..0000000 --- a/src/Entities/Role.php +++ /dev/null @@ -1,57 +0,0 @@ -name = $name; - $this->permissions = []; - } - - /** - * @return string - */ - public function getName(): string - { - return $this->name; - } - - /** - * @param string $name - * @return Role - */ - public function setName(string $name): Role - { - $this->name = $name; - return $this; - } - - /** - * @return array - */ - public function getPermissions(): array - { - return $this->permissions; - } - - /** - * @param Permission $permission - * @return Role - */ - public function addPermission(Permission $permission): Role - { - $this->permissions[] = $permission; - return $this; - } - - - -} \ No newline at end of file diff --git a/src/src/Acl.php b/src/src/Acl.php new file mode 100644 index 0000000..c66aa8f --- /dev/null +++ b/src/src/Acl.php @@ -0,0 +1,76 @@ +all()); + if ($roles instanceof Traversable) { + foreach($roles as $role) { + $this->roles[$role->get()] = $role; + } + $this->roles = new \ArrayObject($this->roles); + } + } + + + public function user(\Acl\Contracts\User $user): Acl + { + $this->user = $user; + return $this; + } + + public function hasRole(string $find): bool + { + if ($this->roles->offsetExists($find)) { + return true; + } + return false; + } + + public function hasResource(string $role, string $resource): bool + { + if ($this->hasRole($role)) { + $resources = new \ArrayObject($this->roles->offsetGet($role)->resources()->get()); + if ($resources->offsetExists($resource)) { + return true; + } + } + return false; + } + + public function can(string $resource): bool + { + if (!isset($this->user)) + throw new \InvalidArgumentException(\Acl\i18n\Translate::ACL_EMPTY_USER[LANG]); + + return $this->hasPermission($this->user->role()->get(), $resource); + } + + /** + * @param string $permission + * @param UserAcl|null $user + * @return bool + */ + public function cannot(string $resource): bool + { + return !$this->can($resource); + } + + public function owns(\Acl\Contracts\Incident $incident, \Acl\Contracts\User $user): bool + { + if ($incident->owner() == $user) + return true; + return false; + } +} \ No newline at end of file diff --git a/src/src/Contracts/Factory.php b/src/src/Contracts/Factory.php new file mode 100644 index 0000000..983b612 --- /dev/null +++ b/src/src/Contracts/Factory.php @@ -0,0 +1,28 @@ +identifier = $identifier; + } + + /** + * @return string + */ + public function get(): string + { + return $this->identifier; + } + + /** + * @param string $identifier + * @return Resource + */ + public function set(string $identifier): Resource + { + $this->identifier = $identifier; + return $this; + } + + /** + * @param \Acl\Contracts\User|null $owner + * @return \Acl\Contracts\User + */ + public function owner(\Acl\Contracts\User $owner = null) : \Acl\Contracts\User + { + if (!is_null($owner)) + $this->owner = $owner; + + return $this->owner; + } + +} \ No newline at end of file diff --git a/src/src/Entity/Resource.php b/src/src/Entity/Resource.php new file mode 100644 index 0000000..e778d35 --- /dev/null +++ b/src/src/Entity/Resource.php @@ -0,0 +1,45 @@ +identifier = $identifier; + } + + /** + * @return string + */ + public function get(): string + { + return $this->identifier; + } + + /** + * @param string $identifier + * @return Resource + */ + public function set(string $identifier): Resource + { + $this->identifier = $identifier; + return $this; + } + +} \ No newline at end of file diff --git a/src/src/Entity/Role.php b/src/src/Entity/Role.php new file mode 100644 index 0000000..5aaa01b --- /dev/null +++ b/src/src/Entity/Role.php @@ -0,0 +1,61 @@ +identifier = $identifier; + } + + /** + * @return string + */ + public function get(): string + { + return $this->identifier; + } + + /** + * @param string $identifier + * @return Role + */ + public function set(string $identifier): Role + { + $this->identifier = $identifier; + return $this; + } + + /** + * @param \Acl\Factory\Resource|null $resource + * @return mixed + */ + public function resources(\Acl\Factory\Resource $resource = null) + {; + if (is_null($resource)) + return $this->resource; + + $this->resource = $resource; + } + +} \ No newline at end of file diff --git a/src/src/Factory/Resource.php b/src/src/Factory/Resource.php new file mode 100644 index 0000000..e16e05a --- /dev/null +++ b/src/src/Factory/Resource.php @@ -0,0 +1,75 @@ +resources; + } + + /** + * @param \Acl\Contracts\Role $resouce + * @return Resource + */ + public function add(\Acl\Contracts\Role $resouce) : Resource + { + $identifier = $resouce->get(); + if ($this->has($identifier)) { + throw new \InvalidArgumentException(sprintf( + 'Permission "%s" already exists in the registry', + $identifier + )); + } + $this->resources[$identifier] = $resouce; + return $this; + + } + + /** + * @param $resource + * @return Resource + */ + public function remove($resource) : Resource + { + try { + $resource = $this->get($resource)->get(); + } catch (\Exception $e) { + throw new \InvalidArgumentException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + if (array_key_exists($resource, $this->resources)) + unset($this->resources[$resource]); + return $this; + } + + /** + * @param $resource + * @return bool + */ + public function has($resource) : bool + { + if ($resource instanceof \Acl\Entity\Resource) { + $resource = $resource->get(); + } else { + $resource = (string) $resource; + } + return isset($this->resources[$resource]); + } +} \ No newline at end of file diff --git a/src/src/Factory/Role.php b/src/src/Factory/Role.php new file mode 100644 index 0000000..6c83644 --- /dev/null +++ b/src/src/Factory/Role.php @@ -0,0 +1,96 @@ +roles; + } + + /** + * @param $role + * @return mixed + */ + public function get($role) + { + return $this->roles[$role]; + } + + /** + * @param \Acl\Contracts\Role $role + * @return \Acl\Contracts\Role + */ + public function add(\Acl\Contracts\Role $role) : \Acl\Contracts\Role + { + $identifier = $role->get(); + if ($this->has($identifier)) { + throw new \InvalidArgumentException( + sprintf( + \Acl\i18n\Translate::ROLE_ALREADY_EXISTS[LANG], + $identifier + ) + ); + } + $this->roles[$identifier] = $role; + return $role; + } + + /** + * @param $role + * @return Role + */ + public function remove($role) : Role + { + try { + $role = $this->get($role)->get(); + } catch (\Exception $e) { + throw new \InvalidArgumentException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + if (array_key_exists($role, $this->roles)) + unset($this->roles[$role]); + return $this; + } + + /** + * @param $role + * @return bool + */ + public function has($role) : bool + { + if ($role instanceof \Acl\Contracts\Factory) { + $role = $role->get(); + } else { + $role = (string) $role; + } + return isset($this->roles[$role]); + } + + /** + * @param $role + * @return mixed + */ + public function resources($role) + { + $this->roles[$role]->resources(new \Acl\Factory\Resource()); + return $this->roles[$role]->resources(); + } +} \ No newline at end of file diff --git a/src/src/i18n/Translate.php b/src/src/i18n/Translate.php new file mode 100644 index 0000000..6eb98fd --- /dev/null +++ b/src/src/i18n/Translate.php @@ -0,0 +1,18 @@ + 'Role "%s" already exists in the registry.', + self::BR => 'O papel "%s" já existe nos registros.' + ]; + const ACL_EMPTY_USER = [ + self::EN => 'User is not set.', + self::BR => 'Usuário não configurado.' + ]; +}