DefaultPermissionManager.php
1 <?php
2 /**
3  * wCMF - wemove Content Management Framework
4  * Copyright (C) 2005-2020 wemove digital solutions GmbH
5  *
6  * Licensed under the terms of the MIT License.
7  *
8  * See the LICENSE file distributed with this work for
9  * additional information.
10  */
11 namespace wcmf\lib\security\impl;
12 
24 
25 /**
26  * DefaultPermissionManager retrieves authorization rules the storage.
27  * It is configured with an entity type that stores permissions and must
28  * have the values 'resource', 'context', 'action', 'roles'.
29  *
30  * @author ingo herwig <ingo@wemove.com>
31  */
33 
34  private $permissionType = null;
35  private $actionKeyProvider = null;
36 
37  private static $logger = null;
38 
39  /**
40  * Constructor
41  * @param $persistenceFacade
42  * @param $session
43  */
45  Session $session) {
46  parent::__construct($persistenceFacade, $session);
47  if (self::$logger == null) {
48  self::$logger = LogManager::getLogger(__CLASS__);
49  }
50  $this->actionKeyProvider = new PersistenceActionKeyProvider();
51  $this->actionKeyProvider->setValueMap([
52  'resource' => 'resource',
53  'context' => 'context',
54  'action' => 'action',
55  'value' => 'roles',
56  ]);
57  }
58 
59  /**
60  * Set the entity type name of Permission instances.
61  * @param $permissionType String
62  */
63  public function setPermissionType($permissionType) {
64  $this->permissionType = $permissionType;
65  $this->actionKeyProvider->setEntityType($this->permissionType);
66  }
67 
68  /**
69  * @see PermissionManager::getPermissions()
70  */
71  public function getPermissions($resource, $context, $action) {
72  $result = null;
73  $actionKey = ActionKey::getBestMatch($this->actionKeyProvider, $resource, $context, $action);
74  if (strlen($actionKey) > 0) {
75  $result = $this->deserializePermissions($this->actionKeyProvider->getKeyValue($actionKey));
76  }
77  if (self::$logger->isDebugEnabled()) {
78  self::$logger->debug("Permissions for $resource?$context?$action (->$actionKey): ".trim(StringUtil::getDump($result)));
79  }
80  return $result;
81  }
82 
83  /**
84  * @see PermissionManager::setPermissions()
85  */
86  public function setPermissions($resource, $context, $action, $permissions) {
87  $permissionInstance = $this->getPermissionInstance($resource, $context, $action);
88  $isChanged = false;
89 
90  if ($permissions != null) {
91  // set permissions
92  $rolesStr = $this->serializePermissions($permissions);
93  if (strlen($rolesStr)) {
94  if (!$permissionInstance) {
95  $this->createPermissionObject($resource, $context, $action, $rolesStr);
96  }
97  else {
98  $permissionInstance->setValue('roles', $rolesStr);
99  }
100  $isChanged = true;
101  }
102  }
103  else {
104  // delete permissions
105  if ($permissionInstance) {
106  $permissionInstance->delete();
107  $isChanged = true;
108  }
109  }
110  }
111 
112  /**
113  * @see PermissionManager::createPermission()
114  */
115  public function createPermission($resource, $context, $action, $role, $modifier) {
116  return self::modifyPermission($resource, $context, $action, $role, $modifier);
117  }
118 
119  /**
120  * @see PermissionManager::removePermission()
121  */
122  public function removePermission($resource, $context, $action, $role) {
123  return self::modifyPermission($resource, $context, $action, $role, null);
124  }
125 
126  /**
127  * Modify a permission for the given role.
128  * @param $resource The resource (e.g. class name of the Controller or object id).
129  * @param $context The context in which the action takes place.
130  * @param $action The action to process.
131  * @param $role The role to authorize.
132  * @param $modifier One of the PERMISSION_MODIFIER_ constants, null, if the permission
133  * should be removed.
134  * @return boolean
135  */
136  protected function modifyPermission($resource, $context, $action, $role, $modifier) {
137  // define roles value (empty if no modifier is given)
138  $permVal = $modifier != null ? $modifier.$role : '';
139 
140  // check for existing permission
141  $permission = $this->getPermissionInstance($resource, $context, $action);
142  if (!$permission && $modifier != null) {
143  // create the permission, if it does not exist yet
144  $permission = $this->createPermissionObject($resource, $context, $action, $permVal);
145  }
146  elseif ($permission) {
147  $value = $permission->getValue('roles');
148  // remove role from value
149  $newValue = preg_replace('/ +/', ' ', str_replace([PermissionManager::PERMISSION_MODIFIER_ALLOW.$role,
150  PermissionManager::PERMISSION_MODIFIER_DENY.$role], "", $value));
151  if (strlen($newValue) > 0) {
152  $permission->setValue('roles', trim($newValue." ".$permVal));
153  }
154  else {
155  $permission->delete();
156  }
157  }
158  return true;
159  }
160 
161  /**
162  * Get the permission object that matches the given parameters
163  * @param $resource Resource
164  * @param $context Context
165  * @param $action Action
166  * @return Instance of _permissionType or null
167  */
168  protected function getPermissionInstance($resource, $context, $action) {
169  $query = new ObjectQuery($this->permissionType, __CLASS__.__METHOD__);
170  $tpl = $query->getObjectTemplate($this->permissionType);
171  $tpl->setValue('resource', Criteria::asValue('=', $resource));
172  $tpl->setValue('context', Criteria::asValue('=', $context));
173  $tpl->setValue('action', Criteria::asValue('=', $action));
174  $permissions = $query->execute(BuildDepth::SINGLE);
175  return (sizeof($permissions) > 0) ? $permissions[0] : null;
176  }
177 
178  /**
179  * Create a permission object with the given parameters
180  * @param $resource Resource
181  * @param $context Context
182  * @param $action Action
183  * @param $roles String representing the permissions as returned from serializePermissions()
184  * @return Instance of _permissionType
185  */
186  protected function createPermissionObject($resource, $context, $action, $roles) {
187  $permission = $this->persistenceFacade->create($this->permissionType);
188  $permission->setValue('resource', $resource);
189  $permission->setValue('context', $context);
190  $permission->setValue('action', $action);
191  $permission->setValue('roles', $roles);
192  return $permission;
193  }
194 }
195 ?>
Session is the interface for session implementations and defines access to session variables.
Definition: Session.php:19
static getDump($variable, $strlen=100, $width=25, $depth=10, $i=0, &$objects=[])
Get the dump of a variable as string.
Definition: StringUtil.php:29
PersistenceActionKeyProvider searches for action keys in the application storage.
modifyPermission($resource, $context, $action, $role, $modifier)
Modify a permission for the given role.
static getBestMatch(ActionKeyProvider $actionKeyProvider, $resource, $context, $action)
Get an action key that matches a given combination of resource, context, action best.
Definition: ActionKey.php:55
setPermissions($resource, $context, $action, $permissions)
static asValue($operator, $value)
Factory method for constructing a Criteria that may be used as value on a PersistentObject's attribut...
Definition: Criteria.php:58
StringUtil provides support for string manipulation.
Definition: StringUtil.php:18
removePermission($resource, $context, $action, $role)
Criteria defines a condition on a PersistentObject's attribute used to select specific instances.
Definition: Criteria.php:21
DefaultPermissionManager retrieves authorization rules the storage.
getPermissionInstance($resource, $context, $action)
Get the permission object that matches the given parameters.
BuildDepth values are used to define the depth when loading object trees.
Definition: BuildDepth.php:19
createPermissionObject($resource, $context, $action, $roles)
Create a permission object with the given parameters.
PersistenceFacade defines the interface for PersistenceFacade implementations.
deserializePermissions($value)
Parse a permissions string and return an associative array with the keys 'default',...
static getLogger($name)
Get the logger with the given name.
Definition: LogManager.php:37
createPermission($resource, $context, $action, $role, $modifier)
__construct(PersistenceFacade $persistenceFacade, Session $session)
Constructor.
An action key is a combination of a resource, context and action that is represented as a string.
Definition: ActionKey.php:22
AbstractPermissionManager is the base class for concrete PermissionManager implementations.
PermissionManager implementations are used to handle all authorization requests.
LogManager is used to retrieve Logger instances.
Definition: LogManager.php:20
serializePermissions($permissions)
Convert an associative permissions array with keys 'default', 'allow', 'deny' into a string.
setPermissionType($permissionType)
Set the entity type name of Permission instances.
ObjectQuery implements a template based object query.