Skip to content
This repository has been archived by the owner on Sep 19, 2019. It is now read-only.

Commit

Permalink
Work towards better scope support & docs. Laravel ServiceProvider and…
Browse files Browse the repository at this point in the history
… Facade
  • Loading branch information
deefour committed May 14, 2014
1 parent 019332f commit 3e770f2
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 3 deletions.
72 changes: 70 additions & 2 deletions docs/authorization.rst
Expand Up @@ -40,8 +40,47 @@ When generating a policy class for an object via Aide's helpers, the following a
2. The first argument is the user to authorize for the action. When using Aide's helpers, this requires you create a `currentUser` method on the class using :class:`Deefour\\Aide\\Authorization\\PolicyTrait`.
3. The second argument is the object you wish to check the authorization against.

An Example
----------
Scopes
------

Aide's authorization also provides support for policy scopes. A policy scope will generate an iterable collection of objects the current user is able to see or work with. For example

.. code-block:: php
use Deefour\Aide\Authorization\AbstractScope;
class ArticleScope extends AbstractScope {
public function resolve() {
if ($this->user->isAdmin()) {
return $this->scope->all();
} else {
return $this->scope->where('published', true)->get();
}
}
}
When a policy scope is instantiated through Aide, the current `$user` and a `$scope` object are passed into the derived policy scope. By default, the policy scope is determined based on the name of the `$scope` object.

.. code-block:: php
$user = User::find(1);
$policyScope = new ArticleScope($user, Article::newQuery());
$articles = $policyScope->resolve(); // collection of Articles
Assumptions
^^^^^^^^^^^

When generating a policy scope via Aide's helpers, the following assumptions are made.

1. The policy scope has the same name as the object being authorized, suffixed with `"Scope"` *(though this can be overridden)*
2. The first argument is the user to filter the scope for. When using Aide's helpers, this requires you create a `currentUser` method on the class using :class:`Deefour\\Aide\\Authorization\\PolicyTrait`.
3. The second argument is the scope object you wish to modify based on the state/details of the `$user`.

A Policy Example
----------------

Using Laravel, the following could be added to the `BaseController`.

Expand Down Expand Up @@ -71,6 +110,35 @@ Now, for some `ArticleController`, to authorize the current user against the abi
The `$this->authorize($article);` line will generate a fresh `ArticlePolicy` instance through Aide, passing the current user and the fetched `$article` into it. The `ArticlePolicy::edit()` method will be called, and if the user is authorized to edit the article, the view for the action will render as expected.

Facade for Laravel
------------------

In Laravel's `app/config/app.php` file, a new alias for the class:`Deefour\\Aide\\Authorization\\Policy` class can be added

.. code-block:: php
'aliases' => array(
// ...
'Policy' => 'Deefour\Aide\Authorization\PolicyFacade',
),
// ...
This prevents the need for the `use Deefour\Aide\Authorization\Policy` statement in every file throughout the application, and makes interacting with policies and scopes within views easy.

For example, to conditionally show an 'Edit' link for a specific `$article` based on the current user's ability to edit that article, the following could be used in a view

.. code-block:: php
@if (Policy::policy($article)->edit())
<a href="{{ URL::route('articles.edit', [ 'id' => $article->id ]) }}">Edit</a>
@endif
.. note:: The facade takes care of finding the current user and injecting it into the derived policy. There is no need to pass the current user into the facade methods.

Handling Unauthorized Exceptions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
23 changes: 22 additions & 1 deletion src/Authorization/AbstractPolicy.php
@@ -1,13 +1,34 @@
<?php namespace Deefour\Aide\Authorization;

/**
* Base policy class all application policies are encouraged to extend. Aide
* expects to pass a user as the first argument to a new policy and the record
* to authorize against as the second argument.
*/
abstract class AbstractPolicy {

/**
* The user to be authorized
*
* @var mixed
*/
protected $user;

/**
* The record/object to authorize against
*
* @var mixed
*/
protected $record;



/**
* Sets expectations for dependencies on the policy class and stores references
* to them locally.
*
* @param mixed $user
* @param mixed $record
*/
public function __construct($user, $record) {
$this->user = $user;
$this->record = $record;
Expand Down
34 changes: 34 additions & 0 deletions src/Authorization/AbstractScope.php
@@ -1,7 +1,41 @@
<?php namespace Deefour\Aide\Authorization;

/**
* Base scope class all application scopes are encouraged to extend. Aide
* expects a `resolve` method to be present on the scope
*/
abstract class AbstractScope {

/**
* The user
*
* @var mixed
*/
protected $user;

/**
* The
*
* @var mixed
*/
protected $scope;


/**
* Sets expectations for dependencies on the policy class and stores references
* to them locally.
*
* @param mixed $user
* @param mixed $scope
*/
public function __construct($user, $scope) {
$this->user = $user;
$this->scope = $scope;
}

/**
*
*/
abstract public function resolve();

}
Empty file.

0 comments on commit 3e770f2

Please sign in to comment.