AbstractUser.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  */
12 
19 
20 /**
21  * Default implementation of a user that is persistent.
22  *
23  * @author ingo herwig <ingo@wemove.com>
24  */
25 abstract class AbstractUser extends Node implements User {
26 
27  private $roles = null;
28 
29  private static $roleConfig = null;
30 
31  /**
32  * @see User::setLogin()
33  */
34  public function setLogin($login) {
35  $this->setValue('login', $login);
36  }
37 
38  /**
39  * @see User::getLogin()
40  */
41  public function getLogin() {
42  return $this->getValue('login');
43  }
44 
45  /**
46  * @see User::setPassword()
47  */
48  public function setPassword($password) {
49  $this->setValue('password', $password);
50  }
51 
52  /**
53  * @see User::getPassword()
54  */
55  public function getPassword() {
56  return $this->getValue('password');
57  }
58 
59  /**
60  * @see User::verifyPassword()
61  */
62  public function verifyPassword($password) {
63  return PasswordService::verify($password, $this->getPassword());
64  }
65 
66  /**
67  * @see User::setIsActive()
68  */
69  public function setIsActive($isActive) {
70  $this->setValue('active', $isActive);
71  }
72 
73  /**
74  * @see User::isActive()
75  */
76  public function isActive() {
77  return intval($this->getValue('active')) === 1;
78  }
79 
80  /**
81  * @see User::setIsSuperUser()
82  */
83  public function setIsSuperUser($isSuperUser) {
84  $this->setValue('super_user', $isSuperUser);
85  }
86 
87  /**
88  * @see User::isSuperUser()
89  */
90  public function isSuperUser() {
91  return intval($this->getValue('super_user')) === 1;
92  }
93 
94  /**
95  * @see User::setConfig()
96  */
97  public function setConfig($config) {
98  $this->setValue('config', $config);
99  }
100 
101  /**
102  * @see User::getConfig()
103  */
104  public function getConfig() {
105  return $this->getValue('config');
106  }
107 
108  /**
109  * @see User::hasRole()
110  */
111  public function hasRole($roleName) {
112  $roles = $this->getRoles();
113  for ($i=0, $count=sizeof($roles); $i<$count; $i++) {
114  if ($roles[$i]->getName() == $roleName) {
115  return true;
116  }
117  }
118  return false;
119  }
120 
121  /**
122  * @see User::getRoles()
123  */
124  public function getRoles() {
125  if (!$this->roles) {
126  $principalFactory = ObjectFactory::getInstance('principalFactory');
127  $this->roles = $principalFactory->getUserRoles($this, true);
128  }
129  return $this->roles;
130  }
131 
132  /**
133  * @see PersistentObject::beforeInsert()
134  */
135  public function beforeInsert() {
136  $this->ensureHashedPassword();
137  }
138 
139  /**
140  * @see PersistentObject::beforeUpdate()
141  */
142  public function beforeUpdate() {
143  $this->ensureHashedPassword();
144  $this->setRoleConfig();
145  }
146 
147  /**
148  * @see PersistentObject::beforeDelete()
149  */
150  public function beforeDelete() {
151  if ($this->isSuperUser()) {
152  $message = ObjectFactory::getInstance("message");
153  throw new \Exception($message->getText("Super users cannot be deleted"));
154  }
155  }
156 
157  /**
158  * Hash password property if not done already.
159  */
160  protected function ensureHashedPassword() {
161  // the password is expected to be stored in the 'password' value
162  $password = $this->getValue('password');
163  if (strlen($password) > 0 && !PasswordService::isHashed($password)) {
164  $this->setValue('password', PasswordService::hash($password));
165  }
166  }
167 
168  /**
169  * Set the configuration of the currently associated role, if no
170  * configuration is set already.
171  */
172  protected function setRoleConfig() {
173  if (strlen($this->getConfig()) == 0) {
174  // check added nodes for Role instances
175  foreach ($this->getAddedNodes() as $relationName => $nodes) {
176  foreach ($nodes as $node) {
177  if ($node instanceof Role) {
178  $roleName = $node->getName();
179  $roleConfigs = self::getRoleConfigs();
180  if (isset($roleConfigs[$roleName])) {
181  $this->setConfig($roleConfigs[$roleName]);
182  break;
183  }
184  }
185  }
186  }
187  }
188  }
189 
190  /**
191  * @see PersistentObject::setValue()
192  */
193  public function setValue($name, $value, $forceSet=false, $trackChange=true) {
194  // prevent overwriting the password with an empty value
195  // the password is expected to be stored in the 'password' value
196  if (!($name == 'password' && strlen(trim($value)) == 0)) {
197  parent::setValue($name, $value, $forceSet, $trackChange);
198  }
199  }
200 
201  /**
202  * @see PersistentObject::validateValue()
203  */
204  public function validateValue($name, $value) {
205  parent::validateValue($name, $value);
206  $message = ObjectFactory::getInstance('message');
207 
208  // validate the login property
209  if ($name == 'login') {
210  if (strlen(trim($value)) == 0) {
211  throw new ValidationException($name, $value, $message->getText("The user requires a login name"));
212  }
213  if ($value == AnonymousUser::USER_GROUP_NAME) {
214  throw new ValidationException($name, $value, $message->getText("The login '%0%' is not allowed",
216  }
217  $principalFactory = ObjectFactory::getInstance('principalFactory');
218  $user = $principalFactory->getUser($value);
219  if ($user != null && $user->getLogin() == $value && $user->getOID() != $this->getOID()) {
220  throw new ValidationException($name, $value, $message->getText("The login '%0%' already exists", [$value]));
221  }
222  }
223 
224  // validate the password property if the user is newly created
225  if ($name == 'password') {
226  if ($this->getState() == self::STATE_NEW && strlen(trim($value)) == 0) {
227  throw new ValidationException($name, $value, $message->getText("The password can't be empty"));
228  }
229  }
230  }
231 
232  /**
233  * Get the role configurations from the application configuration
234  * @return Array with role names as keys and config file names as values
235  */
236  protected static function getRoleConfigs() {
237  if (self::$roleConfig == null) {
238  // load role config if existing
239  $config = ObjectFactory::getInstance('configuration');
240  if (($roleConfig = $config->getSection('roleconfig')) !== false) {
241  self::$roleConfig = $roleConfig;
242  }
243  }
244  return self::$roleConfig;
245  }
246 
247  /**
248  * Get the currently authenticated user
249  * @return User
250  */
251  protected function getAuthUser() {
252  $principalFactory = ObjectFactory::getInstance('principalFactory');
253  $session = ObjectFactory::getInstance('session');
254  return $principalFactory->getUser($session->getAuthUser());
255  }
256 }
257 ?>
static hash($password)
Hash the given cleartext password.
ValidationException signals an exception in validation.
getAuthUser()
Get the currently authenticated user.
static isHashed($password)
Check if the given password is hashed.
ensureHashedPassword()
Hash password property if not done already.
getValue($name)
Definition: Node.php:97
The PasswordService class provides services for password handling.
static verify($password, $passwordHash)
Check if the given hash represents the given password.
Role is the interface for user roles.
Definition: Role.php:18
static getRoleConfigs()
Get the role configurations from the application configuration.
Node adds the concept of relations to PersistentObject.
Definition: Node.php:34
static getInstance($name, $dynamicConfiguration=[])
setRoleConfig()
Set the configuration of the currently associated role, if no configuration is set already.
Default implementation of a user that is persistent.
getAddedNodes()
Get the object ids of the nodes that were added since the node was loaded.
Definition: Node.php:378
ObjectFactory implements the service locator pattern by wrapping a Factory instance and providing sta...
User is the interface for users.
Definition: User.php:18
setValue($name, $value, $forceSet=false, $trackChange=true)