Passed
Push — master ( f350f2...411d2d )
by Morris
12:45
created

User::canChangeAvatar()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Bart Visscher <[email protected]>
7
 * @author Björn Schießle <[email protected]>
8
 * @author Joas Schilling <[email protected]>
9
 * @author Jörn Friedrich Dreyer <[email protected]>
10
 * @author Lukas Reschke <[email protected]>
11
 * @author Morris Jobke <[email protected]>
12
 * @author Robin Appelman <[email protected]>
13
 * @author Thomas Müller <[email protected]>
14
 * @author Vincent Petry <[email protected]>
15
 *
16
 * @license AGPL-3.0
17
 *
18
 * This code is free software: you can redistribute it and/or modify
19
 * it under the terms of the GNU Affero General Public License, version 3,
20
 * as published by the Free Software Foundation.
21
 *
22
 * This program is distributed in the hope that it will be useful,
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
 * GNU Affero General Public License for more details.
26
 *
27
 * You should have received a copy of the GNU Affero General Public License, version 3,
28
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
29
 *
30
 */
31
32
namespace OC\User;
33
34
use OC\Accounts\AccountManager;
35
use OC\Files\Cache\Storage;
36
use OC\Hooks\Emitter;
37
use OC_Helper;
38
use OCP\IAvatarManager;
39
use OCP\IImage;
40
use OCP\IURLGenerator;
41
use OCP\IUser;
42
use OCP\IConfig;
43
use OCP\UserInterface;
44
use \OCP\IUserBackend;
45
46
class User implements IUser {
47
	/** @var string $uid */
48
	private $uid;
49
50
	/** @var string $displayName */
51
	private $displayName;
52
53
	/** @var UserInterface $backend */
54
	private $backend;
55
56
	/** @var bool $enabled */
57
	private $enabled;
58
59
	/** @var Emitter|Manager $emitter */
60
	private $emitter;
61
62
	/** @var string $home */
63
	private $home;
64
65
	/** @var int $lastLogin */
66
	private $lastLogin;
67
68
	/** @var \OCP\IConfig $config */
69
	private $config;
70
71
	/** @var IAvatarManager */
72
	private $avatarManager;
73
74
	/** @var IURLGenerator */
75
	private $urlGenerator;
76
77
	/**
78
	 * @param string $uid
79
	 * @param UserInterface $backend
80
	 * @param \OC\Hooks\Emitter $emitter
81
	 * @param IConfig|null $config
82
	 * @param IURLGenerator $urlGenerator
83
	 */
84
	public function __construct($uid, $backend, $emitter = null, IConfig $config = null, $urlGenerator = null) {
85
		$this->uid = $uid;
86
		$this->backend = $backend;
87
		$this->emitter = $emitter;
88
		if(is_null($config)) {
89
			$config = \OC::$server->getConfig();
90
		}
91
		$this->config = $config;
92
		$this->urlGenerator = $urlGenerator;
93
		$enabled = $this->config->getUserValue($uid, 'core', 'enabled', 'true');
94
		$this->enabled = ($enabled === 'true');
95
		$this->lastLogin = $this->config->getUserValue($uid, 'login', 'lastLogin', 0);
0 ignored issues
show
Documentation Bug introduced by
The property $lastLogin was declared of type integer, but $this->config->getUserVa...login', 'lastLogin', 0) is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
96
		if (is_null($this->urlGenerator)) {
97
			$this->urlGenerator = \OC::$server->getURLGenerator();
98
		}
99
	}
100
101
	/**
102
	 * get the user id
103
	 *
104
	 * @return string
105
	 */
106
	public function getUID() {
107
		return $this->uid;
108
	}
109
110
	/**
111
	 * get the display name for the user, if no specific display name is set it will fallback to the user id
112
	 *
113
	 * @return string
114
	 */
115
	public function getDisplayName() {
116
		if (!isset($this->displayName)) {
117
			$displayName = '';
118
			if ($this->backend and $this->backend->implementsActions(Backend::GET_DISPLAYNAME)) {
0 ignored issues
show
Deprecated Code introduced by
The function OCP\UserInterface::implementsActions() has been deprecated: 14.0.0 Switch to the interfaces from OCP\User\Backend ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

118
			if ($this->backend and /** @scrutinizer ignore-deprecated */ $this->backend->implementsActions(Backend::GET_DISPLAYNAME)) {

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
119
				// get display name and strip whitespace from the beginning and end of it
120
				$backendDisplayName = $this->backend->getDisplayName($this->uid);
121
				if (is_string($backendDisplayName)) {
0 ignored issues
show
introduced by
The condition is_string($backendDisplayName) is always true.
Loading history...
122
					$displayName = trim($backendDisplayName);
123
				}
124
			}
125
126
			if (!empty($displayName)) {
127
				$this->displayName = $displayName;
128
			} else {
129
				$this->displayName = $this->uid;
130
			}
131
		}
132
		return $this->displayName;
133
	}
134
135
	/**
136
	 * set the displayname for the user
137
	 *
138
	 * @param string $displayName
139
	 * @return bool
140
	 */
141
	public function setDisplayName($displayName) {
142
		$displayName = trim($displayName);
143
		if ($this->backend->implementsActions(Backend::SET_DISPLAYNAME) && !empty($displayName)) {
0 ignored issues
show
Deprecated Code introduced by
The function OCP\UserInterface::implementsActions() has been deprecated: 14.0.0 Switch to the interfaces from OCP\User\Backend ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

143
		if (/** @scrutinizer ignore-deprecated */ $this->backend->implementsActions(Backend::SET_DISPLAYNAME) && !empty($displayName)) {

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
144
			$result = $this->backend->setDisplayName($this->uid, $displayName);
0 ignored issues
show
Bug introduced by
The method setDisplayName() does not exist on OCP\UserInterface. It seems like you code against a sub-type of said class. However, the method does not exist in OC\User\Backend or OCP\User\Backend\ABackend. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

144
			/** @scrutinizer ignore-call */ 
145
   $result = $this->backend->setDisplayName($this->uid, $displayName);
Loading history...
145
			if ($result) {
146
				$this->displayName = $displayName;
147
				$this->triggerChange('displayName', $displayName);
148
			}
149
			return $result !== false;
150
		} else {
151
			return false;
152
		}
153
	}
154
155
	/**
156
	 * set the email address of the user
157
	 *
158
	 * @param string|null $mailAddress
159
	 * @return void
160
	 * @since 9.0.0
161
	 */
162
	public function setEMailAddress($mailAddress) {
163
		$oldMailAddress = $this->getEMailAddress();
164
		if($mailAddress === '') {
165
			$this->config->deleteUserValue($this->uid, 'settings', 'email');
166
		} else {
167
			$this->config->setUserValue($this->uid, 'settings', 'email', $mailAddress);
168
		}
169
		if($oldMailAddress !== $mailAddress) {
170
			$this->triggerChange('eMailAddress', $mailAddress, $oldMailAddress);
171
		}
172
	}
173
174
	/**
175
	 * returns the timestamp of the user's last login or 0 if the user did never
176
	 * login
177
	 *
178
	 * @return int
179
	 */
180
	public function getLastLogin() {
181
		return $this->lastLogin;
182
	}
183
184
	/**
185
	 * updates the timestamp of the most recent login of this user
186
	 */
187
	public function updateLastLoginTimestamp() {
188
		$firstTimeLogin = ($this->lastLogin === 0);
189
		$this->lastLogin = time();
190
		$this->config->setUserValue(
191
			$this->uid, 'login', 'lastLogin', $this->lastLogin);
192
193
		return $firstTimeLogin;
194
	}
195
196
	/**
197
	 * Delete the user
198
	 *
199
	 * @return bool
200
	 */
201
	public function delete() {
202
		if ($this->emitter) {
203
			$this->emitter->emit('\OC\User', 'preDelete', array($this));
0 ignored issues
show
Bug introduced by
The method emit() does not exist on OC\Hooks\Emitter. It seems like you code against a sub-type of said class. However, the method does not exist in OCP\Files\IRootFolder or OC\User\Session. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

203
			$this->emitter->/** @scrutinizer ignore-call */ 
204
                   emit('\OC\User', 'preDelete', array($this));
Loading history...
204
		}
205
		// get the home now because it won't return it after user deletion
206
		$homePath = $this->getHome();
207
		$result = $this->backend->deleteUser($this->uid);
208
		if ($result) {
209
210
			// FIXME: Feels like an hack - suggestions?
211
212
			$groupManager = \OC::$server->getGroupManager();
213
			// We have to delete the user from all groups
214
			foreach ($groupManager->getUserGroupIds($this) as $groupId) {
215
				$group = $groupManager->get($groupId);
216
				if ($group) {
217
					\OC_Hook::emit("OC_Group", "pre_removeFromGroup", ["run" => true, "uid" => $this->uid, "gid" => $groupId]);
218
					$group->removeUser($this);
219
					\OC_Hook::emit("OC_User", "post_removeFromGroup", ["uid" => $this->uid, "gid" => $groupId]);
220
				}
221
			}
222
			// Delete the user's keys in preferences
223
			\OC::$server->getConfig()->deleteAllUserValues($this->uid);
224
225
			// Delete user files in /data/
226
			if ($homePath !== false) {
0 ignored issues
show
introduced by
The condition $homePath !== false is always true.
Loading history...
227
				// FIXME: this operates directly on FS, should use View instead...
228
				// also this is not testable/mockable...
229
				\OC_Helper::rmdirr($homePath);
230
			}
231
232
			// Delete the users entry in the storage table
233
			Storage::remove('home::' . $this->uid);
234
235
			\OC::$server->getCommentsManager()->deleteReferencesOfActor('users', $this->uid);
236
			\OC::$server->getCommentsManager()->deleteReadMarksFromUser($this);
237
238
			$notification = \OC::$server->getNotificationManager()->createNotification();
239
			$notification->setUser($this->uid);
240
			\OC::$server->getNotificationManager()->markProcessed($notification);
241
242
			/** @var AccountManager $accountManager */
243
			$accountManager = \OC::$server->query(AccountManager::class);
244
			$accountManager->deleteUser($this);
245
246
			if ($this->emitter) {
247
				$this->emitter->emit('\OC\User', 'postDelete', array($this));
248
			}
249
		}
250
		return !($result === false);
251
	}
252
253
	/**
254
	 * Set the password of the user
255
	 *
256
	 * @param string $password
257
	 * @param string $recoveryPassword for the encryption app to reset encryption keys
258
	 * @return bool
259
	 */
260
	public function setPassword($password, $recoveryPassword = null) {
261
		if ($this->emitter) {
262
			$this->emitter->emit('\OC\User', 'preSetPassword', array($this, $password, $recoveryPassword));
263
		}
264
		if ($this->backend->implementsActions(Backend::SET_PASSWORD)) {
0 ignored issues
show
Deprecated Code introduced by
The function OCP\UserInterface::implementsActions() has been deprecated: 14.0.0 Switch to the interfaces from OCP\User\Backend ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

264
		if (/** @scrutinizer ignore-deprecated */ $this->backend->implementsActions(Backend::SET_PASSWORD)) {

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
265
			$result = $this->backend->setPassword($this->uid, $password);
0 ignored issues
show
Bug introduced by
The method setPassword() does not exist on OCP\UserInterface. It seems like you code against a sub-type of said class. However, the method does not exist in OC\User\Backend or OCP\User\Backend\ABackend. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

265
			/** @scrutinizer ignore-call */ 
266
   $result = $this->backend->setPassword($this->uid, $password);
Loading history...
266
			if ($this->emitter) {
267
				$this->emitter->emit('\OC\User', 'postSetPassword', array($this, $password, $recoveryPassword));
268
			}
269
			return !($result === false);
270
		} else {
271
			return false;
272
		}
273
	}
274
275
	/**
276
	 * get the users home folder to mount
277
	 *
278
	 * @return string
279
	 */
280
	public function getHome() {
281
		if (!$this->home) {
282
			if ($this->backend->implementsActions(Backend::GET_HOME) and $home = $this->backend->getHome($this->uid)) {
0 ignored issues
show
Deprecated Code introduced by
The function OCP\UserInterface::implementsActions() has been deprecated: 14.0.0 Switch to the interfaces from OCP\User\Backend ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

282
			if (/** @scrutinizer ignore-deprecated */ $this->backend->implementsActions(Backend::GET_HOME) and $home = $this->backend->getHome($this->uid)) {

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
Bug introduced by
The method getHome() does not exist on OCP\UserInterface. It seems like you code against a sub-type of said class. However, the method does not exist in OCP\User\Backend\ABackend. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

282
			if ($this->backend->implementsActions(Backend::GET_HOME) and $home = $this->backend->/** @scrutinizer ignore-call */ getHome($this->uid)) {
Loading history...
283
				$this->home = $home;
284
			} elseif ($this->config) {
285
				$this->home = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/' . $this->uid;
286
			} else {
287
				$this->home = \OC::$SERVERROOT . '/data/' . $this->uid;
288
			}
289
		}
290
		return $this->home;
291
	}
292
293
	/**
294
	 * Get the name of the backend class the user is connected with
295
	 *
296
	 * @return string
297
	 */
298
	public function getBackendClassName() {
299
		if($this->backend instanceof IUserBackend) {
300
			return $this->backend->getBackendName();
301
		}
302
		return get_class($this->backend);
303
	}
304
305
	public function getBackend() {
306
		return $this->backend;
307
	}
308
309
	/**
310
	 * check if the backend allows the user to change his avatar on Personal page
311
	 *
312
	 * @return bool
313
	 */
314
	public function canChangeAvatar() {
315
		if ($this->backend->implementsActions(Backend::PROVIDE_AVATAR)) {
0 ignored issues
show
Deprecated Code introduced by
The function OCP\UserInterface::implementsActions() has been deprecated: 14.0.0 Switch to the interfaces from OCP\User\Backend ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

315
		if (/** @scrutinizer ignore-deprecated */ $this->backend->implementsActions(Backend::PROVIDE_AVATAR)) {

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
316
			return $this->backend->canChangeAvatar($this->uid);
0 ignored issues
show
Bug introduced by
The method canChangeAvatar() does not exist on OCP\UserInterface. It seems like you code against a sub-type of OCP\UserInterface such as OCA\User_LDAP\User_Proxy or OCA\User_LDAP\User_LDAP. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

316
			return $this->backend->/** @scrutinizer ignore-call */ canChangeAvatar($this->uid);
Loading history...
317
		}
318
		return true;
319
	}
320
321
	/**
322
	 * check if the backend supports changing passwords
323
	 *
324
	 * @return bool
325
	 */
326
	public function canChangePassword() {
327
		return $this->backend->implementsActions(Backend::SET_PASSWORD);
0 ignored issues
show
Deprecated Code introduced by
The function OCP\UserInterface::implementsActions() has been deprecated: 14.0.0 Switch to the interfaces from OCP\User\Backend ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

327
		return /** @scrutinizer ignore-deprecated */ $this->backend->implementsActions(Backend::SET_PASSWORD);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
328
	}
329
330
	/**
331
	 * check if the backend supports changing display names
332
	 *
333
	 * @return bool
334
	 */
335
	public function canChangeDisplayName() {
336
		if ($this->config->getSystemValue('allow_user_to_change_display_name') === false) {
337
			return false;
338
		}
339
		return $this->backend->implementsActions(Backend::SET_DISPLAYNAME);
0 ignored issues
show
Deprecated Code introduced by
The function OCP\UserInterface::implementsActions() has been deprecated: 14.0.0 Switch to the interfaces from OCP\User\Backend ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

339
		return /** @scrutinizer ignore-deprecated */ $this->backend->implementsActions(Backend::SET_DISPLAYNAME);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
340
	}
341
342
	/**
343
	 * check if the user is enabled
344
	 *
345
	 * @return bool
346
	 */
347
	public function isEnabled() {
348
		return $this->enabled;
349
	}
350
351
	/**
352
	 * set the enabled status for the user
353
	 *
354
	 * @param bool $enabled
355
	 */
356
	public function setEnabled(bool $enabled = true) {
357
		$oldStatus = $this->isEnabled();
358
		$this->enabled = $enabled;
359
		if ($oldStatus !== $this->enabled) {
360
			$this->triggerChange('enabled', $enabled);
361
			$this->config->setUserValue($this->uid, 'core', 'enabled', $enabled ? 'true' : 'false');
362
		}
363
	}
364
365
	/**
366
	 * get the users email address
367
	 *
368
	 * @return string|null
369
	 * @since 9.0.0
370
	 */
371
	public function getEMailAddress() {
372
		return $this->config->getUserValue($this->uid, 'settings', 'email', null);
373
	}
374
375
	/**
376
	 * get the users' quota
377
	 *
378
	 * @return string
379
	 * @since 9.0.0
380
	 */
381
	public function getQuota() {
382
		$quota = $this->config->getUserValue($this->uid, 'files', 'quota', 'default');
383
		if($quota === 'default') {
384
			$quota = $this->config->getAppValue('files', 'default_quota', 'none');
385
		}
386
		return $quota;
387
	}
388
389
	/**
390
	 * set the users' quota
391
	 *
392
	 * @param string $quota
393
	 * @return void
394
	 * @since 9.0.0
395
	 */
396
	public function setQuota($quota) {
397
		$oldQuota = $this->config->getUserValue($this->uid, 'files', 'quota', '');
398
		if($quota !== 'none' and $quota !== 'default') {
399
			$quota = OC_Helper::computerFileSize($quota);
400
			$quota = OC_Helper::humanFileSize($quota);
0 ignored issues
show
Bug introduced by
$quota of type double|false is incompatible with the type integer expected by parameter $bytes of OC_Helper::humanFileSize(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

400
			$quota = OC_Helper::humanFileSize(/** @scrutinizer ignore-type */ $quota);
Loading history...
401
		}
402
		$this->config->setUserValue($this->uid, 'files', 'quota', $quota);
403
		if($quota !== $oldQuota) {
404
			$this->triggerChange('quota', $quota);
405
		}
406
	}
407
408
	/**
409
	 * get the avatar image if it exists
410
	 *
411
	 * @param int $size
412
	 * @return IImage|null
413
	 * @since 9.0.0
414
	 */
415
	public function getAvatarImage($size) {
416
		// delay the initialization
417
		if (is_null($this->avatarManager)) {
418
			$this->avatarManager = \OC::$server->getAvatarManager();
419
		}
420
421
		$avatar = $this->avatarManager->getAvatar($this->uid);
422
		$image = $avatar->get(-1);
423
		if ($image) {
424
			return $image;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $image also could return the type true which is incompatible with the documented return type OCP\IImage|null.
Loading history...
425
		}
426
427
		return null;
428
	}
429
430
	/**
431
	 * get the federation cloud id
432
	 *
433
	 * @return string
434
	 * @since 9.0.0
435
	 */
436
	public function getCloudId() {
437
		$uid = $this->getUID();
438
		$server = $this->urlGenerator->getAbsoluteURL('/');
439
		$server =  rtrim( $this->removeProtocolFromUrl($server), '/');
440
		return \OC::$server->getCloudIdManager()->getCloudId($uid, $server)->getId();
441
	}
442
443
	/**
444
	 * @param string $url
445
	 * @return string
446
	 */
447
	private function removeProtocolFromUrl($url) {
448
		if (strpos($url, 'https://') === 0) {
449
			return substr($url, strlen('https://'));
450
		} else if (strpos($url, 'http://') === 0) {
451
			return substr($url, strlen('http://'));
452
		}
453
454
		return $url;
455
	}
456
457
	public function triggerChange($feature, $value = null, $oldValue = null) {
458
		if ($this->emitter) {
459
			$this->emitter->emit('\OC\User', 'changeUser', array($this, $feature, $value, $oldValue));
460
		}
461
	}
462
}
463