Completed
Push — master ( 63676d...3faef6 )
by Lukas
28:10 queued 12:28
created

OC_User::enableUser()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Aldo "xoen" Giambelluca <[email protected]>
6
 * @author Andreas Fischer <[email protected]>
7
 * @author Arthur Schiwon <[email protected]>
8
 * @author Bartek Przybylski <[email protected]>
9
 * @author Bart Visscher <[email protected]>
10
 * @author Björn Schießle <[email protected]>
11
 * @author Christoph Wurst <[email protected]>
12
 * @author Georg Ehrke <[email protected]>
13
 * @author Jakob Sack <[email protected]>
14
 * @author Jörn Friedrich Dreyer <[email protected]>
15
 * @author Lukas Reschke <[email protected]>
16
 * @author Morris Jobke <[email protected]>
17
 * @author Robin Appelman <[email protected]>
18
 * @author Robin McCorkell <[email protected]>
19
 * @author Roeland Jago Douma <[email protected]>
20
 * @author shkdee <[email protected]>
21
 * @author Thomas Müller <[email protected]>
22
 * @author Tom Needham <[email protected]>
23
 *
24
 * @license AGPL-3.0
25
 *
26
 * This code is free software: you can redistribute it and/or modify
27
 * it under the terms of the GNU Affero General Public License, version 3,
28
 * as published by the Free Software Foundation.
29
 *
30
 * This program is distributed in the hope that it will be useful,
31
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33
 * GNU Affero General Public License for more details.
34
 *
35
 * You should have received a copy of the GNU Affero General Public License, version 3,
36
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
37
 *
38
 */
39
40
/**
41
 * This class provides wrapper methods for user management. Multiple backends are
42
 * supported. User management operations are delegated to the configured backend for
43
 * execution.
44
 *
45
 * Note that &run is deprecated and won't work anymore.
46
 *
47
 * Hooks provided:
48
 *   pre_createUser(&run, uid, password)
49
 *   post_createUser(uid, password)
50
 *   pre_deleteUser(&run, uid)
51
 *   post_deleteUser(uid)
52
 *   pre_setPassword(&run, uid, password, recoveryPassword)
53
 *   post_setPassword(uid, password, recoveryPassword)
54
 *   pre_login(&run, uid, password)
55
 *   post_login(uid)
56
 *   logout()
57
 */
58
class OC_User {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
59
60
	/**
61
	 * @return \OC\User\Session
62
	 */
63
	public static function getUserSession() {
64
		return OC::$server->getUserSession();
65
	}
66
67
	private static $_usedBackends = array();
68
69
	private static $_setupedBackends = array();
70
71
	// bool, stores if a user want to access a resource anonymously, e.g if they open a public link
72
	private static $incognitoMode = false;
73
74
	/**
75
	 * Adds the backend to the list of used backends
76
	 *
77
	 * @param string|\OCP\UserInterface $backend default: database The backend to use for user management
78
	 * @return bool
79
	 *
80
	 * Set the User Authentication Module
81
	 */
82
	public static function useBackend($backend = 'database') {
83
		if ($backend instanceof \OCP\UserInterface) {
84
			self::$_usedBackends[get_class($backend)] = $backend;
85
			\OC::$server->getUserManager()->registerBackend($backend);
86
		} else {
87
			// You'll never know what happens
88
			if (null === $backend OR !is_string($backend)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
89
				$backend = 'database';
90
			}
91
92
			// Load backend
93
			switch ($backend) {
94
				case 'database':
95
				case 'mysql':
96
				case 'sqlite':
97
					\OCP\Util::writeLog('core', 'Adding user backend ' . $backend . '.', \OCP\Util::DEBUG);
98
					self::$_usedBackends[$backend] = new \OC\User\Database();
99
					\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
100
					break;
101
				case 'dummy':
102
					self::$_usedBackends[$backend] = new \Test\Util\User\Dummy();
103
					\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
104
					break;
105
				default:
106
					\OCP\Util::writeLog('core', 'Adding default user backend ' . $backend . '.', \OCP\Util::DEBUG);
107
					$className = 'OC_USER_' . strtoupper($backend);
108
					self::$_usedBackends[$backend] = new $className();
109
					\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
110
					break;
111
			}
112
		}
113
		return true;
114
	}
115
116
	/**
117
	 * remove all used backends
118
	 */
119
	public static function clearBackends() {
120
		self::$_usedBackends = array();
121
		\OC::$server->getUserManager()->clearBackends();
122
	}
123
124
	/**
125
	 * setup the configured backends in config.php
126
	 */
127
	public static function setupBackends() {
128
		OC_App::loadApps(['prelogin']);
129
		$backends = \OC::$server->getSystemConfig()->getValue('user_backends', []);
130
		if (isset($backends['default']) && !$backends['default']) {
131
			// clear default backends
132
			self::clearBackends();
133
		}
134
		foreach ($backends as $i => $config) {
135
			if (!is_array($config)) {
136
				continue;
137
			}
138
			$class = $config['class'];
139
			$arguments = $config['arguments'];
140
			if (class_exists($class)) {
141
				if (array_search($i, self::$_setupedBackends) === false) {
142
					// make a reflection object
143
					$reflectionObj = new ReflectionClass($class);
144
145
					// use Reflection to create a new instance, using the $args
146
					$backend = $reflectionObj->newInstanceArgs($arguments);
147
					self::useBackend($backend);
148
					self::$_setupedBackends[] = $i;
149
				} else {
150
					\OCP\Util::writeLog('core', 'User backend ' . $class . ' already initialized.', \OCP\Util::DEBUG);
151
				}
152
			} else {
153
				\OCP\Util::writeLog('core', 'User backend ' . $class . ' not found.', \OCP\Util::ERROR);
154
			}
155
		}
156
	}
157
158
	/**
159
	 * Try to login a user, assuming authentication
160
	 * has already happened (e.g. via Single Sign On).
161
	 *
162
	 * Log in a user and regenerate a new session.
163
	 *
164
	 * @param \OCP\Authentication\IApacheBackend $backend
165
	 * @return bool
166
	 */
167
	public static function loginWithApache(\OCP\Authentication\IApacheBackend $backend) {
168
169
		$uid = $backend->getCurrentUserId();
170
		$run = true;
171
		OC_Hook::emit("OC_User", "pre_login", array("run" => &$run, "uid" => $uid));
172
173
		if ($uid) {
174
			if (self::getUser() !== $uid) {
175
				self::setUserId($uid);
176
				$setUidAsDisplayName = true;
177
				if($backend instanceof \OCP\UserInterface
178
					&& $backend->implementsActions(\OC\User\Backend::GET_DISPLAYNAME)) {
179
180
					$backendDisplayName = $backend->getDisplayName($uid);
181
					if(is_string($backendDisplayName) && trim($backendDisplayName) !== '') {
182
						$setUidAsDisplayName = false;
183
					}
184
				}
185
				if($setUidAsDisplayName) {
186
					self::setDisplayName($uid);
187
				}
188
				$userSession = self::getUserSession();
189
				$userSession->setLoginName($uid);
190
				$request = OC::$server->getRequest();
191
				$userSession->createSessionToken($request, $uid, $uid);
192
				// setup the filesystem
193
				OC_Util::setupFS($uid);
194
				// first call the post_login hooks, the login-process needs to be
195
				// completed before we can safely create the users folder.
196
				// For example encryption needs to initialize the users keys first
197
				// before we can create the user folder with the skeleton files
198
				OC_Hook::emit("OC_User", "post_login", array("uid" => $uid, 'password' => ''));
199
				//trigger creation of user home and /files folder
200
				\OC::$server->getUserFolder($uid);
201
			}
202
			return true;
203
		}
204
		return false;
205
	}
206
207
	/**
208
	 * Verify with Apache whether user is authenticated.
209
	 *
210
	 * @return boolean|null
211
	 *          true: authenticated
212
	 *          false: not authenticated
213
	 *          null: not handled / no backend available
214
	 */
215
	public static function handleApacheAuth() {
216
		$backend = self::findFirstActiveUsedBackend();
217
		if ($backend) {
218
			OC_App::loadApps();
219
220
			//setup extra user backends
221
			self::setupBackends();
222
			self::getUserSession()->unsetMagicInCookie();
223
224
			return self::loginWithApache($backend);
225
		}
226
227
		return null;
228
	}
229
230
231
	/**
232
	 * Sets user id for session and triggers emit
233
	 *
234
	 * @param string $uid
235
	 */
236
	public static function setUserId($uid) {
237
		$userSession = \OC::$server->getUserSession();
238
		$userManager = \OC::$server->getUserManager();
239
		if ($user = $userManager->get($uid)) {
240
			$userSession->setUser($user);
241
		} else {
242
			\OC::$server->getSession()->set('user_id', $uid);
243
		}
244
	}
245
246
	/**
247
	 * Sets user display name for session
248
	 *
249
	 * @param string $uid
250
	 * @param string $displayName
251
	 * @return bool Whether the display name could get set
252
	 */
253 View Code Duplication
	public static function setDisplayName($uid, $displayName = null) {
254
		if (is_null($displayName)) {
255
			$displayName = $uid;
256
		}
257
		$user = \OC::$server->getUserManager()->get($uid);
258
		if ($user) {
259
			return $user->setDisplayName($displayName);
260
		} else {
261
			return false;
262
		}
263
	}
264
265
	/**
266
	 * Check if the user is logged in, considers also the HTTP basic credentials
267
	 *
268
	 * @deprecated use \OC::$server->getUserSession()->isLoggedIn()
269
	 * @return bool
270
	 */
271
	public static function isLoggedIn() {
272
		return \OC::$server->getUserSession()->isLoggedIn();
273
	}
274
275
	/**
276
	 * set incognito mode, e.g. if a user wants to open a public link
277
	 *
278
	 * @param bool $status
279
	 */
280
	public static function setIncognitoMode($status) {
281
		self::$incognitoMode = $status;
282
	}
283
284
	/**
285
	 * get incognito mode status
286
	 *
287
	 * @return bool
288
	 */
289
	public static function isIncognitoMode() {
290
		return self::$incognitoMode;
291
	}
292
293
	/**
294
	 * Supplies an attribute to the logout hyperlink. The default behaviour
295
	 * is to return an href with '?logout=true' appended. However, it can
296
	 * supply any attribute(s) which are valid for <a>.
297
	 *
298
	 * @return string with one or more HTML attributes.
299
	 */
300
	public static function getLogoutAttribute() {
301
		$backend = self::findFirstActiveUsedBackend();
302
		if ($backend) {
303
			return $backend->getLogoutAttribute();
304
		}
305
306
		$logoutUrl = \OC::$server->getURLGenerator()->linkToRouteAbsolute(
307
			'core.login.logout',
308
			[
309
				'requesttoken' => \OCP\Util::callRegister(),
310
			]
311
		);
312
313
		return 'href="'.$logoutUrl.'"';
314
	}
315
316
	/**
317
	 * Check if the user is an admin user
318
	 *
319
	 * @param string $uid uid of the admin
320
	 * @return bool
321
	 */
322
	public static function isAdminUser($uid) {
323
		$group = \OC::$server->getGroupManager()->get('admin');
324
		$user = \OC::$server->getUserManager()->get($uid);
325
		if ($group && $user && $group->inGroup($user) && self::$incognitoMode === false) {
326
			return true;
327
		}
328
		return false;
329
	}
330
331
332
	/**
333
	 * get the user id of the user currently logged in.
334
	 *
335
	 * @return string|bool uid or false
336
	 */
337
	public static function getUser() {
338
		$uid = \OC::$server->getSession() ? \OC::$server->getSession()->get('user_id') : null;
339
		if (!is_null($uid) && self::$incognitoMode === false) {
340
			return $uid;
341
		} else {
342
			return false;
343
		}
344
	}
345
346
	/**
347
	 * get the display name of the user currently logged in.
348
	 *
349
	 * @param string $uid
350
	 * @return string uid or false
351
	 */
352
	public static function getDisplayName($uid = null) {
353
		if ($uid) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $uid of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
354
			$user = \OC::$server->getUserManager()->get($uid);
355
			if ($user) {
356
				return $user->getDisplayName();
357
			} else {
358
				return $uid;
359
			}
360
		} else {
361
			$user = self::getUserSession()->getUser();
362
			if ($user) {
363
				return $user->getDisplayName();
364
			} else {
365
				return false;
366
			}
367
		}
368
	}
369
370
	/**
371
	 * Set password
372
	 *
373
	 * @param string $uid The username
374
	 * @param string $password The new password
375
	 * @param string $recoveryPassword for the encryption app to reset encryption keys
376
	 * @return bool
377
	 *
378
	 * Change the password of a user
379
	 */
380
	public static function setPassword($uid, $password, $recoveryPassword = null) {
381
		$user = \OC::$server->getUserManager()->get($uid);
382
		if ($user) {
383
			return $user->setPassword($password, $recoveryPassword);
384
		} else {
385
			return false;
386
		}
387
	}
388
389
	/**
390
	 * Check if the password is correct
391
	 *
392
	 * @param string $uid The username
393
	 * @param string $password The password
394
	 * @return string|false user id a string on success, false otherwise
395
	 *
396
	 * Check if the password is correct without logging in the user
397
	 * returns the user id or false
398
	 */
399 View Code Duplication
	public static function checkPassword($uid, $password) {
400
		$manager = \OC::$server->getUserManager();
401
		$username = $manager->checkPassword($uid, $password);
402
		if ($username !== false) {
403
			return $username->getUID();
404
		}
405
		return false;
406
	}
407
408
	/**
409
	 * @param string $uid The username
410
	 * @return string
411
	 *
412
	 * returns the path to the users home directory
413
	 * @deprecated Use \OC::$server->getUserManager->getHome()
414
	 */
415
	public static function getHome($uid) {
416
		$user = \OC::$server->getUserManager()->get($uid);
417
		if ($user) {
418
			return $user->getHome();
419
		} else {
420
			return \OC::$server->getSystemConfig()->getValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $uid;
421
		}
422
	}
423
424
	/**
425
	 * Get a list of all users
426
	 *
427
	 * @return array an array of all uids
428
	 *
429
	 * Get a list of all users.
430
	 * @param string $search
431
	 * @param integer $limit
432
	 * @param integer $offset
433
	 */
434 View Code Duplication
	public static function getUsers($search = '', $limit = null, $offset = null) {
435
		$users = \OC::$server->getUserManager()->search($search, $limit, $offset);
436
		$uids = array();
437
		foreach ($users as $user) {
438
			$uids[] = $user->getUID();
439
		}
440
		return $uids;
441
	}
442
443
	/**
444
	 * Get a list of all users display name
445
	 *
446
	 * @param string $search
447
	 * @param int $limit
448
	 * @param int $offset
449
	 * @return array associative array with all display names (value) and corresponding uids (key)
450
	 *
451
	 * Get a list of all display names and user ids.
452
	 * @deprecated Use \OC::$server->getUserManager->searchDisplayName($search, $limit, $offset) instead.
453
	 */
454 View Code Duplication
	public static function getDisplayNames($search = '', $limit = null, $offset = null) {
455
		$displayNames = array();
456
		$users = \OC::$server->getUserManager()->searchDisplayName($search, $limit, $offset);
457
		foreach ($users as $user) {
458
			$displayNames[$user->getUID()] = $user->getDisplayName();
459
		}
460
		return $displayNames;
461
	}
462
463
	/**
464
	 * check if a user exists
465
	 *
466
	 * @param string $uid the username
467
	 * @return boolean
468
	 */
469
	public static function userExists($uid) {
470
		return \OC::$server->getUserManager()->userExists($uid);
471
	}
472
473
	/**
474
	 * checks if a user is enabled
475
	 *
476
	 * @param string $uid
477
	 * @return bool
478
	 */
479
	public static function isEnabled($uid) {
480
		$user = \OC::$server->getUserManager()->get($uid);
481
		if ($user) {
482
			return $user->isEnabled();
483
		} else {
484
			return false;
485
		}
486
	}
487
488
	/**
489
	 * Returns the first active backend from self::$_usedBackends.
490
	 *
491
	 * @return OCP\Authentication\IApacheBackend|null if no backend active, otherwise OCP\Authentication\IApacheBackend
492
	 */
493
	private static function findFirstActiveUsedBackend() {
494
		foreach (self::$_usedBackends as $backend) {
495
			if ($backend instanceof OCP\Authentication\IApacheBackend) {
496
				if ($backend->isSessionActive()) {
497
					return $backend;
498
				}
499
			}
500
		}
501
502
		return null;
503
	}
504
}
505