1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
abstract class Ajde_Acl_Controller extends Ajde_User_Controller |
4
|
|
|
{ |
5
|
|
|
protected $_allowedActions = []; |
6
|
|
|
|
7
|
|
|
/* ACL sets this to true or false to grant/prevent access in beforeInvoke() */ |
8
|
|
|
private $_hasAccess; |
9
|
|
|
|
10
|
|
|
public function beforeInvoke($allowed = []) |
11
|
|
|
{ |
12
|
|
|
if (!in_array($this->getAction(), |
13
|
|
|
array_merge($this->_allowedActions, $allowed)) && $this->hasAccess() === false |
14
|
|
|
) { |
15
|
|
|
Ajde_Log::_('ACL firewall hit', Ajde_Log::CHANNEL_SECURITY, Ajde_Log::LEVEL_INFORMATIONAL, |
16
|
|
|
implode(PHP_EOL, Ajde_Acl::$log)); |
17
|
|
|
Ajde::app()->getRequest()->set('message', trans('You may not have the required permission to view this page')); |
18
|
|
|
Ajde::app()->getResponse()->dieOnCode(Ajde_Http_Response::RESPONSE_TYPE_UNAUTHORIZED); |
19
|
|
|
} else { |
20
|
|
|
return true; |
21
|
|
|
} |
22
|
|
|
} |
23
|
|
|
|
24
|
|
|
protected function getOwnerId() |
25
|
|
|
{ |
26
|
|
|
return false; |
27
|
|
|
} |
28
|
|
|
|
29
|
|
|
protected function getAclParam() |
30
|
|
|
{ |
31
|
|
|
return parent::getAclParam(); |
|
|
|
|
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
protected function setAclParam($param) |
35
|
|
|
{ |
36
|
|
|
parent::setAclParam($param); |
|
|
|
|
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
private function getAclConditions() |
40
|
|
|
{ |
41
|
|
|
$module = $this->getModule(); |
42
|
|
|
$action = $this->getAction(); |
43
|
|
|
$param = $this->hasAclParam() ? $this->getAclParam() : ''; |
|
|
|
|
44
|
|
|
$controller = $this->getRoute()->hasController() ? $this->getRoute()->getController() : ''; |
|
|
|
|
45
|
|
|
$extra = $controller.($controller && $param ? ':' : '').$param; |
46
|
|
|
|
47
|
|
|
return ['module' => $module, 'action' => $action, 'extra' => $extra]; |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
public function validateAccess($conditions = null) |
51
|
|
|
{ |
52
|
|
|
if (!isset($conditions)) { |
53
|
|
|
$conditions = $this->getAclConditions(); |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
return Ajde_Acl::validateController($conditions['module'], $conditions['action'], $conditions['extra']); |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
protected function hasAccess() |
60
|
|
|
{ |
61
|
|
|
if (!isset($this->_hasAccess)) { |
62
|
|
|
$conditions = $this->getAclConditions(); |
63
|
|
|
$aclTimer = Ajde::app()->addTimer('<i>ACL validation for '.implode('/', $conditions).'</i>'); |
64
|
|
|
$this->_hasAccess = $this->validateAccess($conditions); |
65
|
|
|
Ajde::app()->endTimer($aclTimer); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
return $this->_hasAccess; |
69
|
|
|
} |
70
|
|
|
} |
71
|
|
|
|
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the parent class: