http://phing.info/

Source Code Coverage

Designed for use with PHPUnit2, Xdebug and Phing.

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


Report generated at 2010-10-18T17:19:48-04:00