2017 © Pedro Peláez
 

library permissions

image

damejidlo/permissions

  • Sunday, November 27, 2016
  • by Achse
  • Repository
  • 10 Watchers
  • 11 Stars
  • 3,460 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 0 Forks
  • 0 Open issues
  • 3 Versions
  • 2 % Grown

The README.md

Downloads this Month Latest Stable Version , (*1)

Motivation

Purpose of this library is to add User specific data to isAllowed evaluation. Assertion callback got IUser directly as first argument., (*2)

This solves biggest "problem" of native ACL in Nette such is:, (*3)

    $callback = function (IUser $user, $queriedRole, $queriedResource) {
        return $user->getEntity()->getId() === $queriedResource->getEntity()->getCreatorId();
    };

    // god can destroy world, but only the one he created
    $authorizator->allow('god', 'world', 'destroy', $callback);

Another aspect of this library is separating Authorizator from Nette\Security\User as it's definitely not users responsibility to provide this functionality., (*4)

Disclaimer

This library is written to be as much as possible similar to Permission class in Nette. However evaluation of rules is written from scratch., (*5)

And therefore: * does not implement Nette\Security\IAuthorizator (it can't due to different isAllowed method API), * can be significantly slower (but is written nicely), * there is no guarantee that behaves 100% same way., (*6)

Installation

composer require damejidlo/permission

Configuration

AccessList and Neon

Example implementation of your own AccessList service., (*7)

class AccessList extends Authorizator
{
    /**
     * @param string[][] $roles
     */
    public function addRoles(array $roles)
    {
        foreach ($roles as $role => $parentRoles) {
            $this->addRole($role, $parentRoles);
        }
    }

    /**
     * @param @param string[] $resources
     */
    public function addResources(array $resources)
    {
        foreach ($resources as $resource) {
            $this->addResource($resource);
        }
    }

    /**
     * @param string[][][] $directives
     */
    public function addDirectives(array $directives)
    {
        foreach ($directives as $resource => $resourceDirectives) {
            foreach ($resourceDirectives as $privilege => $privilegeDirectives) {
                foreach ($privilegeDirectives as $roleIdentifier => $directiveType) {
                    $this->createDirective($directiveType, $roleIdentifier, $resource, $privilege);
                }
            }
        }
    }

    public function someStuff()
    {
        $callback = function (IUser $user, $queriedRole, $queriedResource) {
            return $user->getEntity()->getId() === $queriedResource->getEntity()->getCreatorId();
        };

        // god can destroy world, but only the one he created
        $authorizator->allow('god', 'world', 'destroy', $callback);
    }
}

Then just add to your config.neon, (*8)

parameters:
    acl:
        roles:
            writer: []
            reviewer: [writer]

        resources:
            - article

        directives:
            article:
                create:
                    writer: allow
                publish:
                    reviewer: allow

services:
    acl:
        class: YourProject\Security\AccessList
        setup:
            - addRoles(%acl.roles%)
            - addResources(%acl.resources%)
            - addDirectives(%acl.directives%)
            - someStuff() # here we can do some "cool stuff"

Create your AclUser

class AclUser extends Object implements IUser
{
    // Implement `getRoles` method
}

Creating your own Nette\Security\User

You need to create your own User service, (*9)

class MyLoggedUser extends \Nette\Security\User
{
    /**
     * @param IUserStorage $storage
     * @param IAuthenticator|NULL $authenticator
     */
    public function __construct(IUserStorage $storage, IAuthenticator $authenticator = NULL)
    {
        parent::__construct($storage, $authenticator); // No IAuthorizator here !!!
    }

    /**
     * @inheritdoc
     */
    public function isAllowed($resource = IAuthorizator::ALL, $privilege = IAuthorizator::ALL)
    {
        throw new LogicException('Use Damejidlo\ACL\Authorizator directly. User shouldn\'t have such a responsibility');
    }

    /**
     * @inheritdoc
     */
    public function isInRole($role)
    {
        throw new LogicException('Use Damejidlo\ACL\Authorizator directly. User shouldn\'t have such a responsibility');
    }

    /**
     * @return AclUser
     */
    public function getAclUser()
    {
        $entity = $this->getEntity(); // depens on your implementation
        return new AclUser($entity, $this->getRoles());
    }
}

```yaml services: user: Some\Namespace\MyLoggedUser, (*10)


## Load your Authorizator into template Best way is to create your own `TemplateFactory`. And in `createTemplate` method just call: ```php /** * @param Control|NULL $control * @return Template */ public function createTemplate(Control $control = NULL) { $template = parent::createTemplate($control); // Some stuff (helper registration, etc...) $template->setParameters([ 'authorizator' => $this->authorizator, ]); return $template; }

Usage

And now, profit!, (*11)

    // In some Presenter

    public function handleDestroy($worldId)
    {
        $world = $this->worldFinder->findWorld($worldId);
        $resource = new WorldResource($world);
        $permission = 'destroy';

        if (!$this->authorizator->isAllowed($this->user->getAclUser(), $resource, $permission) {
            throw new NotAllowedException($resource, $permission);
        }
    }

The Versions

27/11 2016

dev-master

9999999-dev

  Sources   Download

MIT

The Requires

 

The Development Requires

acl security nette permission

27/11 2016

1.1

1.1.0.0

  Sources   Download

MIT

The Requires

 

The Development Requires

acl security nette permission

25/03 2016

1.0.0

1.0.0.0

  Sources   Download

MIT

The Requires

 

The Development Requires

acl security nette permission