Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100755 313 lines (219 sloc) 12.784 kb
a14c28f @josegonzalez Minor readme updates
authored
1 # Sanction Plugin for CakePHP
2
3 Centralize all of those permissions in a single file using the Sanction plugin.
4
5 ## Background
6
7 Sanction is the culmination of lots of auth work on CakePackages. I was using the [CakePHP Authsome](https://github.com/felixge/cakephp-authsome) plugin for application authentication, but needed something similar to Auth for Authorization. I could have used Auth component, but that felt both hacky and sometimes tricky to use. Rather than spread the permissions across several controllers with complex rules in various places, I created the PermitComponent to centralize all of this into one `permit.php` file.
8
9 ## Requirements
10
11 * CakeSession-accessible User session
12 * CakePHP 2.x
13
14 ## Installation
15
16 For 1.3 support, please see the [1.3 branch](https://github.com/josegonzalez/sanction/tree/1.3).
17
18 _[Manual]_
19
20 * Download this: [https://github.com/josegonzalez/sanction/zipball/master](https://github.com/josegonzalez/sanction/zipball/master)
21 * Unzip that download.
22 * Copy the resulting folder to `app/Plugin`
23 * Rename the folder you just copied to `Sanction`
24
25 _[GIT Submodule]_
26
27 In your app directory type:
28
29 git submodule add git://github.com/josegonzalez/sanction.git Plugin/Sanction
30 git submodule init
31 git submodule update
32
33 _[GIT Clone]_
34
35 In your plugin directory type
36
37 git clone git://github.com/josegonzalez/sanction.git Sanction
38
39 ### Enable plugin
40
41 In 2.0 you need to enable the plugin your `app/Config/bootstrap.php` file:
42
43 CakePlugin::load('Sanction');
44
45 If you are already using `CakePlugin::loadAll();`, then this is not necessary.
46
47 ## Usage
48
49 ### PermitComponent Setup
50
51 Install the SanctionPlugin in your `app/Plugin/` folder under the `Sanction` folder.
52
53 If you want to use the `PermitComponent` to block user access to controllers/actions, add the following to your `AppController` or a specific Controller:
54
55 /**
56 * the 'path' key defines the Session key which holds user information (default Auth.User)
57 * the 'check' key defined the subfield of the path, used to verify only that someone is logged in (default: id)
58 */
59
60
61 // Example for default AuthComponent Configuration (with associated models)
62 public $components = array('Sanction.Permit' => array(
63 'path' => 'Auth',
64 'check' => 'Auth.id'
65 ));
66
67 // Example for default AuthComponent Configuration (no associated models, restricted to just looking at the User model)
68 public $components = array('Sanction.Permit' => array(
69 'path' => 'Auth.User'
70 ));
71
72 // Example for default AuthsomeComponent Configuration (with associated models)
73 public $components = array('Sanction.Permit' => array(
74 'path' => 'User',
75 'check' => 'User.id'
76 ));
77
78 // Example for default AuthsomeComponent Configuration (no associated models, restricted to just looking at the User model)
79 public $components = array('Sanction.Permit' => array(
80 'path' => 'User.User'
81 ));
82
83 // Example for customized AuthsomeComponent Configuration (with associated models)
84 public $components = array(
85 'Authsome.Authsome' => array(
86 'model' => 'Member',
87 'configureKey' => 'MemberAuth',
88 'sessionKey' => 'MemberAuth',
89 'cookieKey' => 'MemberAuth',
90 ),
91 'Sanction.Permit' => array('path' => 'MemberAuth')
92 );
93
94 // NOTE: you can also configure the settings in the permit.php file (below) in which case, just include the component by itself (this way the configuration is available to the debug_kit panel)
95 public $components = array('Sanction.Permit');
96
97 Then you will want to setup some permissions...
98
99 Create a file called `permit.php` in your `app/Config/` folder. You'll need to do the following:
100
101 * Add `App::uses('Permit', 'Sanction.Controller/Component');`
102 * Define some rules - these will be outlined below - using `Permit::access();`
103
104 You can test those rules by browsing to the url you are protecting.
105
106 ### ClearanceHelper Setup
107
108 Install the SanctionPlugin in your `app/Plugin/` folder under the `Sanction` folder.
109
110 If you want to use the ClearanceHelper to block user access to controllers/actions, add the following to your AppController or a specific Controller:
111
112 // Example (use the same {{$PATH}} as in the component)
113 var $helpers = array('Sanction.Clearance' => array('path' => '{{$PATH}}'));
114
115 Then you will want to setup some permissions...
116
117 Create a file called `permit.php` in your `app/Config/` folder. You'll need to do the following:
118
119 * Add `App::uses('Permit', 'Sanction.Controller/Component');`
120 * Define some rules (these will be outlined below)
121
122 Then create links in your views using `$this->Clearance->link()` instead of `$this->Html->link()`. If the currently logged in user (or not logged in user) has access as defined by the `app/config/permit.php` file, then the link will appear in whatever view the ClearanceHelper was created in.
123
124 Note that checking against the `app/Config/permit.php` file is an expensive operation (for now!), so you might want to use this on links that will actually vary when displayed to different users, as opposed to all links in your application.
125
126 ### DebugKit Panel
127
128 Included in the Sanction plugin is a `debug_kit` panel (as of commit fb061e57) which displays not only the currently matched access rule, but also all rules that you have defined for the application. Useful information if only so you can see whether the current request even went through a rule.
129
130 To use it, add the following to your AppController:
131
132
133 // Example of how to implement the Sanction pannel
134 var $components = array(
135 'DebugKit.Toolbar' => array('panels' => array('Sanction.permit')),
136 );
137
138 In the future, it will also keep a history of past requests, as well as highlighting explicitly which access rule was used.
139
140 ### Rules
141
142 Rules are defined by `Permit::access();` and can contain 3 arrays:
143
144 * Array of rules upon which we will control access
145 * Array of rules by which the User's session must be defined by
8604a6e @josegonzalez Minor readme updates
authored
146 * If you restrict to a single model and don't use associated data, you can enter just the fieldname to match on in the Auth array
147 * If you use associated models, you need to specify a `Set::extract()` path as the fieldname
a14c28f @josegonzalez Minor readme updates
authored
148 * Array of extra parameters, such as where to redirect, the flash message, etc.
149
150 An example `app/Config/permit.php`:
151
152 App::uses('Permit', 'Sanction.Controller/Component');
153
154 // no associated model, example: looks for $sessionUser['group'] == 'admin'
155 Permit::access(
156 array('controller' => 'posts', 'action' => array('add', 'edit', 'delete')),
157 array('auth' => array('group' => 'admin')),
158 array('redirect' => array('controller' => 'users', 'action' => 'login'))
159 );
160
161 // with associated model, example: looks for in_array('admin',set::extract('/Group/name',$sessionUser))
162 Permit::access(
163 array('controller' => 'posts', 'action' => array('add', 'edit', 'delete')),
164 array('auth' => array('Group.name' => 'admin')),
165 array('redirect' => array('controller' => 'users', 'action' => 'login'))
166 );
167
168 For the above, the following actions will be affected:
169
170 * `/posts/add/*`
171 * `/posts/edit/*`
172 * `/posts/delete/*`
173
174 The user must have be in the `admin` group (first example as a field on the user model, second as an assocaited Group model), and if they are not, they will be redirected to `/users/login`.
175
176 App::uses('Permit', 'Sanction.Controller/Component');
177
178 // no associated model, example: looks for $sessionUser['group'] == 'admin'
179 Permit::access(
180 array('controller' => 'comments', 'action' => array('edit', 'delete')),
181 array('auth' => array('group' => 'admin')),
182 array(
183 'element' => 'comment',
184 'key' => 'flash',
185 'message' => __('You must be logged in to comment', true),
186 'redirect' => array('controller' => 'users', 'action' => 'login')
187 )
188 );
189
190 For the above, the following actions will be affected:
191
192 * `/comments/edit/*`
193 * `/comments/delete/*`
194
195 The user must have a field 'group' with a value of `admin`, and if they do not, they will be redirected to `/users/login`. A flash message at the key `flash` using the `comment` element will also be displayed, which will contain the message '`You must be logged in to comment`'.
196
197 App::uses('Permit', 'Sanction.Controller/Component');
198
199 Permit::access(
200 array('controller' => array('comments'), 'action' => array('add')),
201 array('auth' => true),
202 array(
203 'message' => __('You must be logged in to comment', true),
204 'redirect' => array('controller' => 'users', 'action' => 'login')
205 )
206 );
207
208 For the above, the following actions will be affected:
209
210 * `/comments/add/*`
211
212 The user must authenticated, and if they are not, they will be redirected to `/users/login`. A flash message will also be presented to them which will contain the message '`You must be logged in to comment`'.
213
214 App::uses('Permit', 'Sanction.Controller/Component');
215
216 // no associated model, example: looks for $sessionUser['group'] == 'admin'
217 Permit::access(
218 array('prefix' => 'admin'),
219 array('auth' => array('group' => 'admin')),
220 array('redirect' => array('admin' => false, 'controller' => 'users', 'action' => 'login')));
221
222 // with associated model, example: looks for in_array('admin',set::extract('/Group/name',$sessionUser))
223 Permit::access(
224 array('prefix' => 'admin'),
225 array('auth' => array('Group.name' => 'admin')),
226 array('redirect' => array('admin' => false, 'controller' => 'users', 'action' => 'login'))
227 );
228
229 For the above, any route with an admin prefix would be affected.
230
231 The user must be in the group `admin`, and if they are not, they will be redirected to `/users/login`.
232
63bc509 @josegonzalez Minor readme updates
authored
233 #### Rules Specificity
234
235 As with routes, all rules must be specified in order of most specific to least specific. The following two examples will illustrate this:
236
237 // If this access declaration comes first, this will be the
238 // ONLY declaration that Sanction uses. Once this fails,
239 // Sanction will not continue on to other rules
240 Permit::access(
241 array('controller' => array('posts', 'categories', 'comments'),
242 array('auth' => array('User.role' => array('admin'))),
243 array('redirect' => array('controller' => 'users', 'action' => 'account')
244 );
245
246 // So this declaration will be effectively useless.
247 Permit::access(
248 array('controller' => array('posts'), 'action' => array('edit'),
249 array('auth' => array('User.role' => array('manager', 'admin'))),
250 array('redirect' => array('controller' => 'users', 'action' => 'account')
251 );
252
253 In order to specify the rules such that an admin user can edit posts, the rules would need to be switched. The most restrictive rule - i.e. the one that limits the controller AND action, as opposed to just the controller - should come first. The following will work as expected:
254
255 Permit::access(
256 array('controller' => array('posts'), 'action' => array('edit'),
257 array('auth' => array('User.role' => array('manager', 'admin'))),
258 array('redirect' => array('controller' => 'users', 'action' => 'account')
259 );
260
261 Permit::access(
262 array('controller' => array('posts', 'configs', 'comments'),
263 array('auth' => array('User.role' => array('admin'))),
264 array('redirect' => array('controller' => 'users', 'action' => 'account')
265 );
266
ab42076 @josegonzalez More permission examples. Closes #15
authored
267 #### Example Rules
268
269 Allowing anonymous access:
270
271 Permit::access(
272 array('controller' => array('posts'), 'action' => array('index')),
273 array(),
274 array()
275 );
276
277 Allowing access to multiple roles:
278
279 Permit::access(
280 array('controller' => array('posts'), 'action' => array('add', 'delete')),
281 array('auth' => array('User.role' => array('user', 'admin'))),
282 array('redirect' => array('controller' => 'posts', 'action' => 'index'),
283 'message' => 'You are not authorized to perform the requested action.'
284 )
285 );
286
a14c28f @josegonzalez Minor readme updates
authored
287 ## Todo
288
289 * More Unit Tests
290 * Document the Access Plugin
291 * Support yaml/db-backed Permit Component permission loading
292
293 ## License
294
295 Copyright (c) 2010-2012 Jose Diaz-Gonzalez
296
297 Permission is hereby granted, free of charge, to any person obtaining a copy
298 of this software and associated documentation files (the "Software"), to deal
299 in the Software without restriction, including without limitation the rights
300 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
301 copies of the Software, and to permit persons to whom the Software is
302 furnished to do so, subject to the following conditions:
303
304 The above copyright notice and this permission notice shall be included in
305 all copies or substantial portions of the Software.
306
307 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
308 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
309 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
310 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
311 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
312 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
313 THE SOFTWARE.
Something went wrong with that request. Please try again.