http://phing.info/

Source Code Coverage

Designed for use with PHPUnit2, Xdebug and Phing.

Methods: 15 LOC: 396 Statements: 105

Source file Statements Methods Total coverage
Acl.php 98.1% 100.0% 98.3%
   
1
<?php
2
/**
3
 * Xyster Framework
4
 *
5
 * This source file is subject to the new BSD license that is bundled
6
 * with this package in the file LICENSE.txt.
7
 * It is also available through the world-wide-web at this URL:
8
 * http://www.opensource.org/licenses/bsd-license.php
9
 *
10
 * @category  Xyster
11
 * @package   Xyster_Controller
12
 * @subpackage Plugins
13
 * @copyright Copyright (c) 2007-2008 Irrational Logic (http://irrationallogic.net)
14
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
15
 * @version   $Id: Acl.php 202 2008-01-20 16:20:09Z doublecompile $
16
 */
17
/**
18
 * Zend_Controller_Plugin_Abstract
19
 */
20 1
require_once 'Zend/Controller/Plugin/Abstract.php';
21
/**
22
 * @see Xyster_Controller_Request_Resource
23
 */
24 1
require_once 'Xyster/Controller/Request/Resource.php';
25
/**
26
 * Zend_Auth
27
 */
28 1
require_once 'Zend/Auth.php';
29
/**
30
 * Zend_Acl
31
 */
32 1
require_once 'Zend/Acl.php';
33
/**
34
 * Authorization plugin
35
 *
36
 * @category  Xyster
37
 * @package   Xyster_Controller
38
 * @subpackage Plugins
39
 * @copyright Copyright (c) 2007-2008 Irrational Logic (http://irrationallogic.net)
40
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
41
 */
42
class Xyster_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
43
{
44
    /**
45
     * The acl
46
     *
47
     * @var Zend_Acl
48
     */
49
    protected $_acl;
50
51
    /**
52
     * Action to use for errors; defaults to 'error'
53
     * @var string
54
     */
55
    protected $_deniedAction = 'error';
56
57
    /**
58
     * Controller to use for errors; defaults to 'error'
59
     * @var string
60
     */
61
    protected $_deniedController = 'error';
62
63
    /**
64
     * Module to use for errors; defaults to default module in dispatcher
65
     * @var string
66
     */
67
    protected $_deniedModule;
68
69
    /**
70
     * Action to use for login; defaults to 'index'
71
     * @var string
72
     */
73
    protected $_loginAction = 'index';
74
75
    /**
76
     * Controller to use for login; defaults to 'login'
77
     * @var string
78
     */
79
    protected $_loginController = 'login';
80
81
    /**
82
     * Module to use for login; defaults to default module in dispatcher
83
     * @var string
84
     */
85
    protected $_loginModule;
86
87
    /**
88
     * Holds the rules passed to 'setRules' until dispatchLoopStartup
89
     *
90
     * @var array
91
     */
92
    protected $_rules = array();
93
94
    /**
95
     * Creates a new acl plugin
96
     *
97
     * @param Zend_Acl $acl
98
     */
99
    public function __construct( Zend_Acl $acl )
100
    {
101 7
        $this->_acl = $acl;
102
    }
103
104
    /**
105
     * Allows access to an action by a role
106
     *
107
     * Passing null for the role will allow all users to access the action.
108
     *
109
     * Passing null for the module will allow the role access to all actions in
110
     * all controllers in all modules.  Specifying a module but leaving
111
     * controller and action null will allow access to all actions in all
112
     * controllers in the specified module.  Specifying a module and a
113
     * controller but leaving action null will allow access to all actions in
114
     * the specified controller.
115
     *
116
     * @param Zend_Acl_Role_Interface|string $role
117
     * @param string $module The module name
118
     * @param string $controller The controller name
119
     * @param string $action The action name
120
     * @return Xyster_Controller_Action_Helper_Acl provides a fluent interface
121
     */
122
    public function allow( $role, $module = null, $controller = null, $action = null )
123
    {
124 2
        $resource = $this->_getResource($module, $controller, $action);
125 2
        $this->_acl->allow($role, $resource);
126 2
        return $this;
127
    }
128
129
    /**
130
     * Denies access to an action by a role
131
     *
132
     * Passing null for the role will deny all users access to the action.
133
     *
134
     * Passing null for the module will deny everything to the role supplied.
135
     * Specifying a module but leaving controller and action null will deny
136
     * access to all controllers in the specified module.  Specifying a module
137
     * and a controller but leaving action null will deny access to all actions
138
     * in the specified controller.
139
     *
140
     * @param Zend_Acl_Role_Interface|string $role
141
     * @param string $module The module name
142
     * @param string $controller The controller name
143
     * @param string $action The action name
144
     * @return Xyster_Controller_Action_Helper_Acl provides a fluent interface
145
     */
146
    public function deny( $role, $module = null, $controller = null, $action = null )
147
    {
148 2
        $resource = $this->_getResource($module, $controller, $action);
149 2
        $this->_acl->deny($role, $resource);
150 2
        return $this;
151
    }
152
153
    /**
154
     * Called before Zend_Controller_Front enters its dispatch loop
155
     *
156
     * @param  Zend_Controller_Request_Abstract $request
157
     */
158
    public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
159
    {
160 1
        foreach( $this->_rules as $rule ) {
161 1
            $role = isset($rule['role']) ? $rule['role'] : null;
162 1
            $module = isset($rule['module']) ? $rule['module'] : null;
163 1
            $controller = isset($rule['controller']) ? $rule['controller'] : null;
164 1
            $action = isset($rule['action']) ? $rule['action'] : null;
165
166 1
            if ( isset($rule['type']) && $rule['type'] == Zend_Acl::TYPE_DENY ) {
167 1
                $this->deny($role, $module, $controller, $action);
168 1
            } else {
169 1
                $this->allow($role, $module, $controller, $action);
170
            }
171 1
        }
172
    }
173
174
    /**
175
     * Retrieve the current acl plugin action
176
     *
177
     * @return string
178
     */
179
    public function getAccessDeniedAction()
180
    {
181 4
        return $this->_deniedAction;
182
    }
183
184
    /**
185
     * Retrieve the current acl plugin controller
186
     *
187
     * @return string
188
     */
189
    public function getAccessDeniedController()
190
    {
191 4
        return $this->_deniedController;
192
    }
193
194
    /**
195
     * Retrieve the current acl plugin module
196
     *
197
     * @return string
198
     */
199
    public function getAccessDeniedModule()
200
    {
201 4
        if (null === $this->_deniedModule) {
202 3
            require_once 'Zend/Controller/Front.php';
203 3
            $this->_deniedModule = Zend_Controller_Front::getInstance()->getDispatcher()->getDefaultModule();
204 3
        }
205 4
        return $this->_deniedModule;
206
    }
207
208
    /**
209
     * Retrieve the current not-authenticated action
210
     *
211
     * @return string
212
     */
213
    public function getLoginAction()
214
    {
215 2
        return $this->_loginAction;
216
    }
217
218
    /**
219
     * Retrieve the current not-authenticated controller
220
     *
221
     * @return string
222
     */
223
    public function getLoginController()
224
    {
225 2
        return $this->_loginController;
226
    }
227
228
    /**
229
     * Retrieve the current not-authenticated module
230
     *
231
     * @return string
232
     */
233
    public function getLoginModule()
234
    {
235 2
        if (null === $this->_loginModule) {
236 1
            require_once 'Zend/Controller/Front.php';
237 1
            $this->_loginModule = Zend_Controller_Front::getInstance()->getDispatcher()->getDefaultModule();
238 1
        }
239 2
        return $this->_loginModule;
240
    }
241
242
    /**
243
     * Called before an action is dispatched by Zend_Controller_Dispatcher.
244
     *
245
     * @param  Zend_Controller_Request_Abstract $request
246
     */
247
    public function preDispatch(Zend_Controller_Request_Abstract $request)
248
    {
249 5
        $request = $this->getRequest();
250 5
        $auth = Zend_Auth::getInstance();
251 5
        $role = $auth->getIdentity();
252 5
        $resource = $this->_getResource($request->getModuleName(),
253 5
            $request->getControllerName(), $request->getActionName());
254
255 5
        $isAllowed = $this->_acl->isAllowed($role, $resource);
256
257 5
        if ( !$isAllowed && !$auth->hasIdentity() ) {
258
            // they should be allowed access to the login form
259 1
            $this->_acl->allow(null,
260 1
                $this->_getResource($this->getLoginModule(),
261 1
                $this->getLoginController(),
262 1
                $this->getLoginAction()));
263
264
            // Forward to the login form
265 1
            $request->setModuleName($this->getLoginModule())
266 1
                ->setControllerName($this->getLoginController())
267 1
                ->setActionName($this->getLoginAction())
268 1
                ->setDispatched(false);
269 1
            return;
270 0
        }
271
272
        try {
273 4
            if ( !$isAllowed ) {
274 3
                $msg = 'Insufficient permissions: ';
275 3
        		$msg .= $role . ' -> ' . $resource->getResourceId();
276 3
        		require_once 'Zend/Acl/Exception.php';
277 3
                throw new Zend_Acl_Exception($msg);
278 0
            }
279 4
        } catch ( Zend_Acl_Exception $thrown ) {
280 3
            $error = new ArrayObject(array(), ArrayObject::ARRAY_AS_PROPS);
281 3
            $error->exception = $thrown;
282 3
            $error->type = 'EXCEPTION_OTHER';
283
284
            // Keep a copy of the original request
285 3
            $error->request = clone $request;
286
287
            // they should be allowed access to the error display screen, duh
288 3
            $this->_acl->allow(null,
289 3
                $this->_getResource($this->getAccessDeniedModule(),
290 3
                $this->getAccessDeniedController(),
291 3
                $this->getAccessDeniedAction()));
292
293
            // Forward to the error handler
294 3
            $request->setParam('error_handler', $error)
295 3
                ->setModuleName($this->getAccessDeniedModule())
296 3
                ->setControllerName($this->getAccessDeniedController())
297 3
                ->setActionName($this->getAccessDeniedAction())
298 3
                ->setDispatched(false);
299
        }
300
    }
301
302
    /**
303
     * Setup the dispatch location for access denied errors
304
     *
305
     * @param string $module
306
     * @param string $controller
307
     * @param string $action
308
     * @return Xyster_Controller_Plugin_Acl provides a fluent interface
309
     */
310
    public function setAccessDenied( $module, $controller, $action )
311
    {
312 1
        $this->_deniedModule = (string) $module;
313 1
        $this->_deniedController = (string) $controller;
314 1
        $this->_deniedAction = (string) $action;
315
316 1
        return $this;
317
    }
318
319
    /**
320
     * Setup the dispatch location for unauthenticated users
321
     *
322
     * @param string $module
323
     * @param string $controller
324
     * @param string $action
325
     * @return Xyster_Controller_Plugin_Acl provides a fluent interface
326
     */
327
    public function setLogin( $module, $controller, $action )
328
    {
329 1
        $this->_loginModule = (string) $module;
330 1
        $this->_loginController = (string) $controller;
331 1
        $this->_loginAction = (string) $action;
332
333 1
        return $this;
334
    }
335
336
    /**
337
     * Sets multiple rules simultaneously
338
     *
339
     * Each element in the $rules array should be itself an associative array
340
     * containing the following keys:
341
     *  - type : either Zend_Acl::TYPE_ALLOW or Zend_Acl::TYPE_DENY
342
     *  - role : the string role ID
343
     *  - module : the module name
344
     *  - controller : the controller name
345
     *  - action : the action name
346
     *
347
     * If 'type' is omitted or is null, Zend_Acl::TYPE_ALLOW is assumed.  If any
348
     * of the other keys are omitted, null is assumed.  See {@link allow} and
349
     * {@link deny} for the behavior when null is specified for these values.
350
     *
351
     * @param array $rules
352
     * @return Xyster_Controller_Plugin_Acl provides a fluent interface
353
     */
354
    public function setRules( array $rules )
355
    {
356 1
        $this->_rules = $rules;
357 1
        return $this;
358
    }
359
360
    /**
361
     * Gets the resource object
362
     *
363
     * @param string $module
364
     * @param string $controller
365
     * @param string $action
366
     * @return Xyster_Controller_Request_Resource
367
     */
368
    protected function _getResource( $module, $controller, $action )
369
    {
370 5
        $resource = null;
371
372 5
        if ( $module ) {
373 5
            $moduleResource = new Xyster_Controller_Request_Resource($module);
374 5
            if ( !$this->_acl->has($moduleResource) ) {
375 5
                $this->_acl->add($moduleResource);
376 5
            }
377 5
            $resource = $moduleResource;
378 5
        }
379 5
        if ( $module && $controller ) {
380 5
            $controllerResource = new Xyster_Controller_Request_Resource($module, $controller);
381 5
            if ( !$this->_acl->has($controllerResource) ) {
382 5
                $this->_acl->add($controllerResource, $moduleResource);
383 5
            }
384 5
            $resource = $controllerResource;
385 5
        }
386 5
        if ( $module && $controller && $action ) {
387 5
            $actionResource = new Xyster_Controller_Request_Resource($module, $controller, $action);
388 5
            if ( !$this->_acl->has($actionResource) ) {
389 5
                $this->_acl->add($actionResource, $controllerResource);
390 5
            }
391 5
            $resource = $actionResource;
392 5
        }
393
394 5
        return $resource;
395
    }
396
}


Report generated at 2008-03-05T18:27:43-05:00