http://phing.info/

Source Code Coverage

Designed for use with PHPUnit2, Xdebug and Phing.

Methods: 15 LOC: 401 Statements: 105

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


Report generated at 2007-11-05T09:09:01-05:00