Completed
Push — master ( 2bf15e...34716f )
by Morris
24:46 queued 11:25
created

OC_User::getLogoutUrl()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 1
dl 0
loc 15
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
	 * @suppress PhanDeprecatedFunction
82
	 */
83
	public static function useBackend($backend = 'database') {
84
		if ($backend instanceof \OCP\UserInterface) {
85
			self::$_usedBackends[get_class($backend)] = $backend;
86
			\OC::$server->getUserManager()->registerBackend($backend);
87
		} else {
88
			// You'll never know what happens
89
			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...
90
				$backend = 'database';
91
			}
92
93
			// Load backend
94
			switch ($backend) {
95
				case 'database':
96
				case 'mysql':
97
				case 'sqlite':
98
					\OCP\Util::writeLog('core', 'Adding user backend ' . $backend . '.', \OCP\Util::DEBUG);
99
					self::$_usedBackends[$backend] = new \OC\User\Database();
100
					\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
101
					break;
102
				case 'dummy':
103
					self::$_usedBackends[$backend] = new \Test\Util\User\Dummy();
104
					\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
105
					break;
106
				default:
107
					\OCP\Util::writeLog('core', 'Adding default user backend ' . $backend . '.', \OCP\Util::DEBUG);
108
					$className = 'OC_USER_' . strtoupper($backend);
109
					self::$_usedBackends[$backend] = new $className();
110
					\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
111
					break;
112
			}
113
		}
114
		return true;
115
	}
116
117
	/**
118
	 * remove all used backends
119
	 */
120
	public static function clearBackends() {
121
		self::$_usedBackends = array();
122
		\OC::$server->getUserManager()->clearBackends();
123
	}
124
125
	/**
126
	 * setup the configured backends in config.php
127
	 * @suppress PhanDeprecatedFunction
128
	 */
129
	public static function setupBackends() {
130
		OC_App::loadApps(['prelogin']);
131
		$backends = \OC::$server->getSystemConfig()->getValue('user_backends', []);
132
		if (isset($backends['default']) && !$backends['default']) {
133
			// clear default backends
134
			self::clearBackends();
135
		}
136
		foreach ($backends as $i => $config) {
137
			if (!is_array($config)) {
138
				continue;
139
			}
140
			$class = $config['class'];
141
			$arguments = $config['arguments'];
142
			if (class_exists($class)) {
143
				if (array_search($i, self::$_setupedBackends) === false) {
144
					// make a reflection object
145
					$reflectionObj = new ReflectionClass($class);
146
147
					// use Reflection to create a new instance, using the $args
148
					$backend = $reflectionObj->newInstanceArgs($arguments);
149
					self::useBackend($backend);
150
					self::$_setupedBackends[] = $i;
151
				} else {
152
					\OCP\Util::writeLog('core', 'User backend ' . $class . ' already initialized.', \OCP\Util::DEBUG);
153
				}
154
			} else {
155
				\OCP\Util::writeLog('core', 'User backend ' . $class . ' not found.', \OCP\Util::ERROR);
156
			}
157
		}
158
	}
159
160
	/**
161
	 * Try to login a user, assuming authentication
162
	 * has already happened (e.g. via Single Sign On).
163
	 *
164
	 * Log in a user and regenerate a new session.
165
	 *
166
	 * @param \OCP\Authentication\IApacheBackend $backend
167
	 * @return bool
168
	 */
169
	public static function loginWithApache(\OCP\Authentication\IApacheBackend $backend) {
170
171
		$uid = $backend->getCurrentUserId();
172
		$run = true;
173
		OC_Hook::emit("OC_User", "pre_login", array("run" => &$run, "uid" => $uid));
174
175
		if ($uid) {
176
			if (self::getUser() !== $uid) {
177
				self::setUserId($uid);
178
				$userSession = self::getUserSession();
179
				$userSession->setLoginName($uid);
180
				$request = OC::$server->getRequest();
181
				$userSession->createSessionToken($request, $uid, $uid);
182
				// setup the filesystem
183
				OC_Util::setupFS($uid);
184
				// first call the post_login hooks, the login-process needs to be
185
				// completed before we can safely create the users folder.
186
				// For example encryption needs to initialize the users keys first
187
				// before we can create the user folder with the skeleton files
188
				OC_Hook::emit("OC_User", "post_login", array("uid" => $uid, 'password' => ''));
189
				//trigger creation of user home and /files folder
190
				\OC::$server->getUserFolder($uid);
191
			}
192
			return true;
193
		}
194
		return false;
195
	}
196
197
	/**
198
	 * Verify with Apache whether user is authenticated.
199
	 *
200
	 * @return boolean|null
201
	 *          true: authenticated
202
	 *          false: not authenticated
203
	 *          null: not handled / no backend available
204
	 */
205
	public static function handleApacheAuth() {
206
		$backend = self::findFirstActiveUsedBackend();
207
		if ($backend) {
208
			OC_App::loadApps();
209
210
			//setup extra user backends
211
			self::setupBackends();
212
			self::getUserSession()->unsetMagicInCookie();
213
214
			return self::loginWithApache($backend);
215
		}
216
217
		return null;
218
	}
219
220
221
	/**
222
	 * Sets user id for session and triggers emit
223
	 *
224
	 * @param string $uid
225
	 */
226
	public static function setUserId($uid) {
227
		$userSession = \OC::$server->getUserSession();
228
		$userManager = \OC::$server->getUserManager();
229
		if ($user = $userManager->get($uid)) {
230
			$userSession->setUser($user);
231
		} else {
232
			\OC::$server->getSession()->set('user_id', $uid);
233
		}
234
	}
235
236
	/**
237
	 * Sets user display name for session
238
	 *
239
	 * @param string $uid
240
	 * @param string $displayName
241
	 * @return bool Whether the display name could get set
242
	 */
243 View Code Duplication
	public static function setDisplayName($uid, $displayName = null) {
244
		if (is_null($displayName)) {
245
			$displayName = $uid;
246
		}
247
		$user = \OC::$server->getUserManager()->get($uid);
248
		if ($user) {
249
			return $user->setDisplayName($displayName);
250
		} else {
251
			return false;
252
		}
253
	}
254
255
	/**
256
	 * Check if the user is logged in, considers also the HTTP basic credentials
257
	 *
258
	 * @deprecated use \OC::$server->getUserSession()->isLoggedIn()
259
	 * @return bool
260
	 */
261
	public static function isLoggedIn() {
262
		return \OC::$server->getUserSession()->isLoggedIn();
263
	}
264
265
	/**
266
	 * set incognito mode, e.g. if a user wants to open a public link
267
	 *
268
	 * @param bool $status
269
	 */
270
	public static function setIncognitoMode($status) {
271
		self::$incognitoMode = $status;
272
	}
273
274
	/**
275
	 * get incognito mode status
276
	 *
277
	 * @return bool
278
	 */
279
	public static function isIncognitoMode() {
280
		return self::$incognitoMode;
281
	}
282
283
	/**
284
	 * Returns the current logout URL valid for the currently logged-in user
285
	 *
286
	 * @param \OCP\IURLGenerator $urlGenerator
287
	 * @return string
288
	 */
289
	public static function getLogoutUrl(\OCP\IURLGenerator $urlGenerator) {
290
		$backend = self::findFirstActiveUsedBackend();
291
		if ($backend) {
292
			return $backend->getLogoutUrl();
293
		}
294
295
		$logoutUrl = $urlGenerator->linkToRouteAbsolute(
296
			'core.login.logout',
297
			[
298
				'requesttoken' => \OCP\Util::callRegister(),
299
			]
300
		);
301
302
		return $logoutUrl;
303
	}
304
305
	/**
306
	 * Check if the user is an admin user
307
	 *
308
	 * @param string $uid uid of the admin
309
	 * @return bool
310
	 */
311
	public static function isAdminUser($uid) {
312
		$group = \OC::$server->getGroupManager()->get('admin');
313
		$user = \OC::$server->getUserManager()->get($uid);
314
		if ($group && $user && $group->inGroup($user) && self::$incognitoMode === false) {
315
			return true;
316
		}
317
		return false;
318
	}
319
320
321
	/**
322
	 * get the user id of the user currently logged in.
323
	 *
324
	 * @return string|bool uid or false
325
	 */
326
	public static function getUser() {
327
		$uid = \OC::$server->getSession() ? \OC::$server->getSession()->get('user_id') : null;
328
		if (!is_null($uid) && self::$incognitoMode === false) {
329
			return $uid;
330
		} else {
331
			return false;
332
		}
333
	}
334
335
	/**
336
	 * get the display name of the user currently logged in.
337
	 *
338
	 * @param string $uid
339
	 * @return string|bool uid or false
340
	 */
341
	public static function getDisplayName($uid = null) {
342
		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...
343
			$user = \OC::$server->getUserManager()->get($uid);
344
			if ($user) {
345
				return $user->getDisplayName();
346
			} else {
347
				return $uid;
348
			}
349
		} else {
350
			$user = self::getUserSession()->getUser();
351
			if ($user) {
352
				return $user->getDisplayName();
353
			} else {
354
				return false;
355
			}
356
		}
357
	}
358
359
	/**
360
	 * Set password
361
	 *
362
	 * @param string $uid The username
363
	 * @param string $password The new password
364
	 * @param string $recoveryPassword for the encryption app to reset encryption keys
365
	 * @return bool
366
	 *
367
	 * Change the password of a user
368
	 */
369
	public static function setPassword($uid, $password, $recoveryPassword = null) {
370
		$user = \OC::$server->getUserManager()->get($uid);
371
		if ($user) {
372
			return $user->setPassword($password, $recoveryPassword);
373
		} else {
374
			return false;
375
		}
376
	}
377
378
	/**
379
	 * Check if the password is correct
380
	 *
381
	 * @param string $uid The username
382
	 * @param string $password The password
383
	 * @return string|false user id a string on success, false otherwise
384
	 *
385
	 * Check if the password is correct without logging in the user
386
	 * returns the user id or false
387
	 */
388 View Code Duplication
	public static function checkPassword($uid, $password) {
389
		$manager = \OC::$server->getUserManager();
390
		$username = $manager->checkPassword($uid, $password);
391
		if ($username !== false) {
392
			return $username->getUID();
393
		}
394
		return false;
395
	}
396
397
	/**
398
	 * @param string $uid The username
399
	 * @return string
400
	 *
401
	 * returns the path to the users home directory
402
	 * @deprecated Use \OC::$server->getUserManager->getHome()
403
	 */
404
	public static function getHome($uid) {
405
		$user = \OC::$server->getUserManager()->get($uid);
406
		if ($user) {
407
			return $user->getHome();
408
		} else {
409
			return \OC::$server->getSystemConfig()->getValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $uid;
410
		}
411
	}
412
413
	/**
414
	 * Get a list of all users
415
	 *
416
	 * @return array an array of all uids
417
	 *
418
	 * Get a list of all users.
419
	 * @param string $search
420
	 * @param integer $limit
421
	 * @param integer $offset
422
	 */
423 View Code Duplication
	public static function getUsers($search = '', $limit = null, $offset = null) {
424
		$users = \OC::$server->getUserManager()->search($search, $limit, $offset);
425
		$uids = array();
426
		foreach ($users as $user) {
427
			$uids[] = $user->getUID();
428
		}
429
		return $uids;
430
	}
431
432
	/**
433
	 * Get a list of all users display name
434
	 *
435
	 * @param string $search
436
	 * @param int $limit
437
	 * @param int $offset
438
	 * @return array associative array with all display names (value) and corresponding uids (key)
439
	 *
440
	 * Get a list of all display names and user ids.
441
	 * @deprecated Use \OC::$server->getUserManager->searchDisplayName($search, $limit, $offset) instead.
442
	 */
443 View Code Duplication
	public static function getDisplayNames($search = '', $limit = null, $offset = null) {
444
		$displayNames = array();
445
		$users = \OC::$server->getUserManager()->searchDisplayName($search, $limit, $offset);
446
		foreach ($users as $user) {
447
			$displayNames[$user->getUID()] = $user->getDisplayName();
448
		}
449
		return $displayNames;
450
	}
451
452
	/**
453
	 * check if a user exists
454
	 *
455
	 * @param string $uid the username
456
	 * @return boolean
457
	 */
458
	public static function userExists($uid) {
459
		return \OC::$server->getUserManager()->userExists($uid);
460
	}
461
462
	/**
463
	 * checks if a user is enabled
464
	 *
465
	 * @param string $uid
466
	 * @return bool
467
	 */
468
	public static function isEnabled($uid) {
469
		$user = \OC::$server->getUserManager()->get($uid);
470
		if ($user) {
471
			return $user->isEnabled();
472
		} else {
473
			return false;
474
		}
475
	}
476
477
	/**
478
	 * Returns the first active backend from self::$_usedBackends.
479
	 *
480
	 * @return OCP\Authentication\IApacheBackend|null if no backend active, otherwise OCP\Authentication\IApacheBackend
481
	 */
482
	private static function findFirstActiveUsedBackend() {
483
		foreach (self::$_usedBackends as $backend) {
484
			if ($backend instanceof OCP\Authentication\IApacheBackend) {
485
				if ($backend->isSessionActive()) {
486
					return $backend;
487
				}
488
			}
489
		}
490
491
		return null;
492
	}
493
}
494