├── .gitignore ├── LICENSE ├── README.markdown ├── config └── autoload.php ├── helpers └── authority_helper.php ├── libraries ├── Authority.php └── authority │ ├── ability.php │ └── rule.php └── spark.info /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.swp 3 | *.swo 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2011 by Matthew Machuga 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE ORnse, and/or sell 19 | copies of the Software, an 20 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | Authority Authorization for Codeigniter 2 | ======================================= 3 | 4 | Authority is an authorization library inspired by, and largely based off, Ryan 5 | Bates' CanCan gem for Ruby on Rails. It is not a 1:1 port, but the essentials 6 | are available. Please check out his work at http://github.com/ryanb/cancan/. 7 | 8 | Usage 9 | ----- 10 | 11 | Authority uses the `can()` function to check if the current user has permission 12 | to access a certain portion of the site or application. This function is an 13 | alias to the `Authority::can()` method, for convenience. The `cannot()` 14 | function is simply a negation of `can()`. 15 | 16 | ### can() ### 17 | 18 | `can()` is a function that accepts two parameters. The first parameter should 19 | be the action the current user is trying to perform, such as `read`, `create`, 20 | `delete`. The second parameter may be either an object or a class name for the 21 | resource the current user wants to access, such as `Post`, or `Comment`. 22 | Authority knows who the current user is internally upon instantiation of the 23 | library via default or custom configuration. 24 | 25 | In CodeIgniter, `can()` is available in both Views and Controllers. This means 26 | you may restrict accessibility to entire controller actions or certain functionality on a 27 | page (generally in conjunction with each other). 28 | 29 | An example of this use in a PHP view: 30 | 31 | ```php 32 |

Here is my awesome text blah blah blah

33 | 34 | 35 | 36 |

message ?>

37 | 38 | 39 | 40 |

id}", 'Click to edit an awesome secret') ?>

41 | 42 | ``` 43 | 44 | ### Authority::allow() ### 45 | 46 | `Authority::allow()` is a method that accepts up to three arguments. It is used 47 | to grant access to various elements of an application. It's counterpart, 48 | `Authority::deny()` accepts the same number of arguments, but will deny access 49 | to various elements of the application. The method signature is: 50 | 51 | `allow($action, $resource, \Closure $callback = null)` 52 | 53 | Like the `can()` helper, `$action` is the action the current user is trying to 54 | perform, and `$resource` is the object or class name for the resource the 55 | current user is trying to access. An anonymous function may be passed in as 56 | the third argument if finer grained control is desired (restrict editability 57 | to a resource to only the owner). `Authority::deny()` shares the same 58 | signature. Examples are below within the Configuration section. 59 | 60 | 61 | Configuration 62 | ------------- 63 | 64 | Inside `./application/sparks/authority/0.0.1/libraries/Authority.php` 65 | 66 | If using Authentic authentication lib, `Authority::current_user()` method may 67 | be left alone; otherwise, change it to fit your needs. 68 | 69 | Authority is fairly configuration agnostic (and at it's core it is framework 70 | agnostic), so your setup may very. All configuration should take place inside 71 | of the the `Authority::initialize() method. An example configuration: 72 | 73 | ```php 74 | public static function initialize($user) 75 | { 76 | // Set any aliased actions you may want to simplify your use 77 | // Here, 'manage' will cover basic crud 78 | Authority::action_alias('manage', array('create', 'read', 'update', 'delete')); 79 | 80 | // Next, we check if there is a user or not. You may setup rules for a 81 | // guest user, or simply ignore them. Here, no permissions are given. 82 | if ( ! $user || ! $user->role) return false; 83 | 84 | // If the current user is an admin, setup permissions 85 | // Note: You may check on any attribute, class type, etc 86 | if ($user->role == 'admin') 87 | { 88 | // Authority::allow() will grant permission for the current user to 89 | // perform that particular action. The first parameter is the 90 | // action, the second parameter is the resource the user is trying 91 | // to access. 'all' is a default wildcard. 92 | Authority::allow('manage', 'all'); 93 | 94 | // The last rule will always take precedence, so if we want our 95 | // admin to be able to manage users, but not delete them (unless 96 | // that user is him/herself, we will deny this ability.) As seen 97 | // below, a third closure parameter may be passed in to define 98 | // finer-grain permissions. 99 | Authority::deny('delete', 'User', function ($a_user) use ($user) { 100 | return $a_user->id !== $user->id; 101 | }); 102 | } 103 | 104 | // We will give a typical member read-access to everything. 105 | if ($user->role == 'member') 106 | { 107 | Authority::allow('read', 'all'); 108 | } 109 | 110 | } 111 | ``` 112 | 113 | Caveats 114 | ------- 115 | 116 | Currently, a resource must be a string or an object. If a callback is to be 117 | used on a resource, it must be an object. The class type will be determined 118 | when rule matching takes place. Additionally, while not necessary, this 119 | plugin works well with PHPActiveRecord and likely most other ORMs. 120 | 121 | Notes 122 | ----- 123 | 124 | This library was created and is maintained by Matthew Machuga, is hosted on 125 | GitHub, and is made possible by the GetSparks team. Please support their 126 | efforts! 127 | 128 | If you have any questions, feel free to send me a message! 129 | 130 | Twitter: @machuga 131 | -------------------------------------------------------------------------------- /config/autoload.php: -------------------------------------------------------------------------------- 1 | role) return false; 36 | 37 | if ($user->role == 'admin') 38 | { 39 | Authority::allow('manage', 'all'); 40 | Authority::deny('update', 'User', function ($a_user) use ($user) { 41 | return $a_user->id !== $user->id; 42 | }); 43 | } 44 | 45 | if ($user->role == 'member') 46 | { 47 | 48 | Authority::allow('manage', 'Project'); 49 | Authority::allow('manage', 'User', function($a_user) use ($user) { 50 | return $user->id == $a_user->id; 51 | }); 52 | } 53 | 54 | if ($user->role == 'client') 55 | { 56 | Authority::allow('read', 'Project', function($project) use ($user) { 57 | return $user->company_id == $project->company_id; 58 | }); 59 | } 60 | */ 61 | } 62 | 63 | protected static function current_user() 64 | { 65 | return parent::current_user(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /libraries/authority/ability.php: -------------------------------------------------------------------------------- 1 | role) return false; 34 | 35 | if ($user->role == 'admin') 36 | { 37 | static::allow('manage', 'all'); 38 | } 39 | } 40 | 41 | public static function can($action, $resource, $resource_val = null) 42 | { 43 | if ( empty(static::$_rules)) { 44 | static::initialize(static::current_user()); 45 | } 46 | 47 | // See if the action has been aliased to somethign else 48 | $true_action = static::determine_action($action); 49 | 50 | $matches = static::find_matches($true_action, $resource); 51 | 52 | if ($matches && ! empty($matches)) 53 | { 54 | $results = array(); 55 | $resource_value = ($resource_val) ?: $resource; 56 | 57 | foreach ($matches as $matched_rule) 58 | { 59 | $results[] = !($matched_rule->callback($resource_value) xor $matched_rule->allowed()); 60 | } 61 | 62 | // Last rule overrides others 63 | return $results[count($results)-1]; 64 | } 65 | else 66 | { 67 | return false; 68 | } 69 | } 70 | 71 | public static function cannot($action, $resource, $resource_val = null) 72 | { 73 | return ! static::can($action, $resource, $resource_val); 74 | } 75 | 76 | public static function allow($action, $resource, \Closure $callback = null) 77 | { 78 | static::$_rules[] = new Rule(true, $action, $resource, $callback); 79 | } 80 | 81 | public static function deny($action, $resource, \Closure $callback = null) 82 | { 83 | static::$_rules[] = new Rule(false, $action, $resource, $callback); 84 | } 85 | 86 | public static function action_alias($action, Array $aliases) 87 | { 88 | static::$_action_aliases[$action] = $aliases; 89 | } 90 | 91 | public static function dealias($action) 92 | { 93 | return static::$_action_aliases[$action] ?: $action; 94 | } 95 | 96 | protected static function determine_action($action) 97 | { 98 | $actions = array(); 99 | if ( ! empty(static::$_action_aliases)) 100 | { 101 | foreach (static::$_action_aliases as $aliased_action => $aliases) 102 | { 103 | if ( ! empty($aliases) && in_array($action, $aliases)) 104 | { 105 | $actions[] = $aliased_action; 106 | } 107 | } 108 | } 109 | 110 | if (empty($actions)) 111 | { 112 | return $action; 113 | } 114 | else 115 | { 116 | $actions[] = $action; 117 | return $actions; 118 | } 119 | } 120 | 121 | protected static function find_matches($action, $resource) 122 | { 123 | $matches = array(); 124 | if (!empty(static::$_rules)) 125 | { 126 | foreach(static::$_rules as $rule) 127 | { 128 | if ($rule->relevant($action, $resource)) 129 | { 130 | $matches[] = $rule; 131 | } 132 | } 133 | } 134 | return $matches; 135 | } 136 | 137 | public function __construct() 138 | { 139 | static::initialize(static::current_user()); 140 | } 141 | 142 | protected static function current_user() 143 | { 144 | $ci = get_instance(); 145 | if (isset($ci->authentic)) { 146 | // using authentic library 147 | return $ci->authentic->current_user() ?: new \User; 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /libraries/authority/rule.php: -------------------------------------------------------------------------------- 1 | _allowed = $allowed; 38 | $this->_action = $action; 39 | $this->_resource = $resource; 40 | $this->_callback = $callback; 41 | } 42 | 43 | public function allowed() 44 | { 45 | return $this->_allowed; 46 | } 47 | 48 | public function matches_action($action) 49 | { 50 | return is_array($action) ? in_array($this->_action, $action) 51 | : $this->_action === $action; 52 | } 53 | 54 | public function matches_resource($resource) 55 | { 56 | $resource = is_object($resource) ? get_class($resource) : $resource; 57 | return $this->_resource === $resource || $this->_resource === 'all'; 58 | } 59 | 60 | public function relevant($action, $resource) 61 | { 62 | return $this->matches_action($action) && $this->matches_resource($resource); 63 | } 64 | 65 | public function callback($resource) 66 | { 67 | if (isset($this->_callback) && is_string($resource)) { 68 | return false; 69 | } 70 | return (isset($this->_callback)) ? $this->_callback($resource) : true; 71 | } 72 | 73 | // Allow callbacks to be called 74 | public function __call($method, $args) 75 | { 76 | return (isset($this->$method)) ? call_user_func_array($this->$method, $args) : true; 77 | } 78 | 79 | } 80 | 81 | -------------------------------------------------------------------------------- /spark.info: -------------------------------------------------------------------------------- 1 | name: authority 2 | version: 0.0.3 3 | compatibility: 2.0.1 4 | 5 | tags: ["authorization"] 6 | --------------------------------------------------------------------------------