Passed
Push — master ( ca88a1...d94625 )
by Blizzz
16:18 queued 14s
created
lib/private/User/User.php 1 patch
Indentation   +527 added lines, -527 removed lines patch added patch discarded remove patch
@@ -61,531 +61,531 @@
 block discarded – undo
61 61
 use Symfony\Component\EventDispatcher\GenericEvent;
62 62
 
63 63
 class User implements IUser {
64
-	/** @var IAccountManager */
65
-	protected $accountManager;
66
-	/** @var string */
67
-	private $uid;
68
-
69
-	/** @var string|null */
70
-	private $displayName;
71
-
72
-	/** @var UserInterface|null */
73
-	private $backend;
74
-	/** @var EventDispatcherInterface */
75
-	private $legacyDispatcher;
76
-
77
-	/** @var IEventDispatcher */
78
-	private $dispatcher;
79
-
80
-	/** @var bool|null */
81
-	private $enabled;
82
-
83
-	/** @var Emitter|Manager */
84
-	private $emitter;
85
-
86
-	/** @var string */
87
-	private $home;
88
-
89
-	/** @var int|null */
90
-	private $lastLogin;
91
-
92
-	/** @var \OCP\IConfig */
93
-	private $config;
94
-
95
-	/** @var IAvatarManager */
96
-	private $avatarManager;
97
-
98
-	/** @var IURLGenerator */
99
-	private $urlGenerator;
100
-
101
-	public function __construct(string $uid, ?UserInterface $backend, EventDispatcherInterface $dispatcher, $emitter = null, IConfig $config = null, $urlGenerator = null) {
102
-		$this->uid = $uid;
103
-		$this->backend = $backend;
104
-		$this->legacyDispatcher = $dispatcher;
105
-		$this->emitter = $emitter;
106
-		if (is_null($config)) {
107
-			$config = \OC::$server->getConfig();
108
-		}
109
-		$this->config = $config;
110
-		$this->urlGenerator = $urlGenerator;
111
-		if (is_null($this->urlGenerator)) {
112
-			$this->urlGenerator = \OC::$server->getURLGenerator();
113
-		}
114
-		// TODO: inject
115
-		$this->dispatcher = \OC::$server->query(IEventDispatcher::class);
116
-	}
117
-
118
-	/**
119
-	 * get the user id
120
-	 *
121
-	 * @return string
122
-	 */
123
-	public function getUID() {
124
-		return $this->uid;
125
-	}
126
-
127
-	/**
128
-	 * get the display name for the user, if no specific display name is set it will fallback to the user id
129
-	 *
130
-	 * @return string
131
-	 */
132
-	public function getDisplayName() {
133
-		if ($this->displayName === null) {
134
-			$displayName = '';
135
-			if ($this->backend && $this->backend->implementsActions(Backend::GET_DISPLAYNAME)) {
136
-				// get display name and strip whitespace from the beginning and end of it
137
-				$backendDisplayName = $this->backend->getDisplayName($this->uid);
138
-				if (is_string($backendDisplayName)) {
139
-					$displayName = trim($backendDisplayName);
140
-				}
141
-			}
142
-
143
-			if (!empty($displayName)) {
144
-				$this->displayName = $displayName;
145
-			} else {
146
-				$this->displayName = $this->uid;
147
-			}
148
-		}
149
-		return $this->displayName;
150
-	}
151
-
152
-	/**
153
-	 * set the displayname for the user
154
-	 *
155
-	 * @param string $displayName
156
-	 * @return bool
157
-	 *
158
-	 * @since 25.0.0 Throw InvalidArgumentException
159
-	 * @throws \InvalidArgumentException
160
-	 */
161
-	public function setDisplayName($displayName) {
162
-		$displayName = trim($displayName);
163
-		$oldDisplayName = $this->getDisplayName();
164
-		if ($this->backend->implementsActions(Backend::SET_DISPLAYNAME) && !empty($displayName) && $displayName !== $oldDisplayName) {
165
-			/** @var ISetDisplayNameBackend $backend */
166
-			$backend = $this->backend;
167
-			$result = $backend->setDisplayName($this->uid, $displayName);
168
-			if ($result) {
169
-				$this->displayName = $displayName;
170
-				$this->triggerChange('displayName', $displayName, $oldDisplayName);
171
-			}
172
-			return $result !== false;
173
-		}
174
-		return false;
175
-	}
176
-
177
-	/**
178
-	 * @inheritDoc
179
-	 */
180
-	public function setEMailAddress($mailAddress) {
181
-		$this->setSystemEMailAddress($mailAddress);
182
-	}
183
-
184
-	/**
185
-	 * @inheritDoc
186
-	 */
187
-	public function setSystemEMailAddress(string $mailAddress): void {
188
-		$oldMailAddress = $this->getSystemEMailAddress();
189
-
190
-		if ($mailAddress === '') {
191
-			$this->config->deleteUserValue($this->uid, 'settings', 'email');
192
-		} else {
193
-			$this->config->setUserValue($this->uid, 'settings', 'email', $mailAddress);
194
-		}
195
-
196
-		$primaryAddress = $this->getPrimaryEMailAddress();
197
-		if ($primaryAddress === $mailAddress) {
198
-			// on match no dedicated primary settings is necessary
199
-			$this->setPrimaryEMailAddress('');
200
-		}
201
-
202
-		if ($oldMailAddress !== strtolower($mailAddress)) {
203
-			$this->triggerChange('eMailAddress', $mailAddress, $oldMailAddress);
204
-		}
205
-	}
206
-
207
-	/**
208
-	 * @inheritDoc
209
-	 */
210
-	public function setPrimaryEMailAddress(string $mailAddress): void {
211
-		if ($mailAddress === '') {
212
-			$this->config->deleteUserValue($this->uid, 'settings', 'primary_email');
213
-			return;
214
-		}
215
-
216
-		$this->ensureAccountManager();
217
-		$account = $this->accountManager->getAccount($this);
218
-		$property = $account->getPropertyCollection(IAccountManager::COLLECTION_EMAIL)
219
-			->getPropertyByValue($mailAddress);
220
-
221
-		if ($property === null || $property->getLocallyVerified() !== IAccountManager::VERIFIED) {
222
-			throw new InvalidArgumentException('Only verified emails can be set as primary');
223
-		}
224
-		$this->config->setUserValue($this->uid, 'settings', 'primary_email', $mailAddress);
225
-	}
226
-
227
-	private function ensureAccountManager() {
228
-		if (!$this->accountManager instanceof IAccountManager) {
229
-			$this->accountManager = \OC::$server->get(IAccountManager::class);
230
-		}
231
-	}
232
-
233
-	/**
234
-	 * returns the timestamp of the user's last login or 0 if the user did never
235
-	 * login
236
-	 *
237
-	 * @return int
238
-	 */
239
-	public function getLastLogin() {
240
-		if ($this->lastLogin === null) {
241
-			$this->lastLogin = (int) $this->config->getUserValue($this->uid, 'login', 'lastLogin', 0);
242
-		}
243
-		return (int) $this->lastLogin;
244
-	}
245
-
246
-	/**
247
-	 * updates the timestamp of the most recent login of this user
248
-	 */
249
-	public function updateLastLoginTimestamp() {
250
-		$previousLogin = $this->getLastLogin();
251
-		$now = time();
252
-		$firstTimeLogin = $previousLogin === 0;
253
-
254
-		if ($now - $previousLogin > 60) {
255
-			$this->lastLogin = time();
256
-			$this->config->setUserValue(
257
-				$this->uid, 'login', 'lastLogin', (string)$this->lastLogin);
258
-		}
259
-
260
-		return $firstTimeLogin;
261
-	}
262
-
263
-	/**
264
-	 * Delete the user
265
-	 *
266
-	 * @return bool
267
-	 */
268
-	public function delete() {
269
-		/** @deprecated 21.0.0 use BeforeUserDeletedEvent event with the IEventDispatcher instead */
270
-		$this->legacyDispatcher->dispatch(IUser::class . '::preDelete', new GenericEvent($this));
271
-		if ($this->emitter) {
272
-			/** @deprecated 21.0.0 use BeforeUserDeletedEvent event with the IEventDispatcher instead */
273
-			$this->emitter->emit('\OC\User', 'preDelete', [$this]);
274
-		}
275
-		$this->dispatcher->dispatchTyped(new BeforeUserDeletedEvent($this));
276
-		$result = $this->backend->deleteUser($this->uid);
277
-		if ($result) {
278
-			// FIXME: Feels like an hack - suggestions?
279
-
280
-			$groupManager = \OC::$server->getGroupManager();
281
-			// We have to delete the user from all groups
282
-			foreach ($groupManager->getUserGroupIds($this) as $groupId) {
283
-				$group = $groupManager->get($groupId);
284
-				if ($group) {
285
-					$this->dispatcher->dispatchTyped(new BeforeUserRemovedEvent($group, $this));
286
-					$group->removeUser($this);
287
-					$this->dispatcher->dispatchTyped(new UserRemovedEvent($group, $this));
288
-				}
289
-			}
290
-			// Delete the user's keys in preferences
291
-			\OC::$server->getConfig()->deleteAllUserValues($this->uid);
292
-
293
-			\OC::$server->getCommentsManager()->deleteReferencesOfActor('users', $this->uid);
294
-			\OC::$server->getCommentsManager()->deleteReadMarksFromUser($this);
295
-
296
-			/** @var AvatarManager $avatarManager */
297
-			$avatarManager = \OC::$server->query(AvatarManager::class);
298
-			$avatarManager->deleteUserAvatar($this->uid);
299
-
300
-			$notification = \OC::$server->getNotificationManager()->createNotification();
301
-			$notification->setUser($this->uid);
302
-			\OC::$server->getNotificationManager()->markProcessed($notification);
303
-
304
-			/** @var AccountManager $accountManager */
305
-			$accountManager = \OC::$server->query(AccountManager::class);
306
-			$accountManager->deleteUser($this);
307
-
308
-			/** @deprecated 21.0.0 use UserDeletedEvent event with the IEventDispatcher instead */
309
-			$this->legacyDispatcher->dispatch(IUser::class . '::postDelete', new GenericEvent($this));
310
-			if ($this->emitter) {
311
-				/** @deprecated 21.0.0 use UserDeletedEvent event with the IEventDispatcher instead */
312
-				$this->emitter->emit('\OC\User', 'postDelete', [$this]);
313
-			}
314
-			$this->dispatcher->dispatchTyped(new UserDeletedEvent($this));
315
-		}
316
-		return !($result === false);
317
-	}
318
-
319
-	/**
320
-	 * Set the password of the user
321
-	 *
322
-	 * @param string $password
323
-	 * @param string $recoveryPassword for the encryption app to reset encryption keys
324
-	 * @return bool
325
-	 */
326
-	public function setPassword($password, $recoveryPassword = null) {
327
-		$this->legacyDispatcher->dispatch(IUser::class . '::preSetPassword', new GenericEvent($this, [
328
-			'password' => $password,
329
-			'recoveryPassword' => $recoveryPassword,
330
-		]));
331
-		if ($this->emitter) {
332
-			$this->emitter->emit('\OC\User', 'preSetPassword', [$this, $password, $recoveryPassword]);
333
-		}
334
-		if ($this->backend->implementsActions(Backend::SET_PASSWORD)) {
335
-			/** @var ISetPasswordBackend $backend */
336
-			$backend = $this->backend;
337
-			$result = $backend->setPassword($this->uid, $password);
338
-
339
-			if ($result !== false) {
340
-				$this->legacyDispatcher->dispatch(IUser::class . '::postSetPassword', new GenericEvent($this, [
341
-					'password' => $password,
342
-					'recoveryPassword' => $recoveryPassword,
343
-				]));
344
-				if ($this->emitter) {
345
-					$this->emitter->emit('\OC\User', 'postSetPassword', [$this, $password, $recoveryPassword]);
346
-				}
347
-			}
348
-
349
-			return !($result === false);
350
-		} else {
351
-			return false;
352
-		}
353
-	}
354
-
355
-	/**
356
-	 * get the users home folder to mount
357
-	 *
358
-	 * @return string
359
-	 */
360
-	public function getHome() {
361
-		if (!$this->home) {
362
-			/** @psalm-suppress UndefinedInterfaceMethod Once we get rid of the legacy implementsActions, psalm won't complain anymore */
363
-			if (($this->backend instanceof IGetHomeBackend || $this->backend->implementsActions(Backend::GET_HOME)) && $home = $this->backend->getHome($this->uid)) {
364
-				$this->home = $home;
365
-			} elseif ($this->config) {
366
-				$this->home = $this->config->getSystemValueString('datadirectory', \OC::$SERVERROOT . '/data') . '/' . $this->uid;
367
-			} else {
368
-				$this->home = \OC::$SERVERROOT . '/data/' . $this->uid;
369
-			}
370
-		}
371
-		return $this->home;
372
-	}
373
-
374
-	/**
375
-	 * Get the name of the backend class the user is connected with
376
-	 *
377
-	 * @return string
378
-	 */
379
-	public function getBackendClassName() {
380
-		if ($this->backend instanceof IUserBackend) {
381
-			return $this->backend->getBackendName();
382
-		}
383
-		return get_class($this->backend);
384
-	}
385
-
386
-	public function getBackend(): ?UserInterface {
387
-		return $this->backend;
388
-	}
389
-
390
-	/**
391
-	 * Check if the backend allows the user to change his avatar on Personal page
392
-	 *
393
-	 * @return bool
394
-	 */
395
-	public function canChangeAvatar() {
396
-		if ($this->backend instanceof IProvideAvatarBackend || $this->backend->implementsActions(Backend::PROVIDE_AVATAR)) {
397
-			/** @var IProvideAvatarBackend $backend */
398
-			$backend = $this->backend;
399
-			return $backend->canChangeAvatar($this->uid);
400
-		}
401
-		return true;
402
-	}
403
-
404
-	/**
405
-	 * check if the backend supports changing passwords
406
-	 *
407
-	 * @return bool
408
-	 */
409
-	public function canChangePassword() {
410
-		return $this->backend->implementsActions(Backend::SET_PASSWORD);
411
-	}
412
-
413
-	/**
414
-	 * check if the backend supports changing display names
415
-	 *
416
-	 * @return bool
417
-	 */
418
-	public function canChangeDisplayName() {
419
-		if (!$this->config->getSystemValueBool('allow_user_to_change_display_name', true)) {
420
-			return false;
421
-		}
422
-		return $this->backend->implementsActions(Backend::SET_DISPLAYNAME);
423
-	}
424
-
425
-	/**
426
-	 * check if the user is enabled
427
-	 *
428
-	 * @return bool
429
-	 */
430
-	public function isEnabled() {
431
-		if ($this->enabled === null) {
432
-			$enabled = $this->config->getUserValue($this->uid, 'core', 'enabled', 'true');
433
-			$this->enabled = $enabled === 'true';
434
-		}
435
-		return (bool) $this->enabled;
436
-	}
437
-
438
-	/**
439
-	 * set the enabled status for the user
440
-	 *
441
-	 * @param bool $enabled
442
-	 */
443
-	public function setEnabled(bool $enabled = true) {
444
-		$oldStatus = $this->isEnabled();
445
-		$this->enabled = $enabled;
446
-		if ($oldStatus !== $this->enabled) {
447
-			// TODO: First change the value, then trigger the event as done for all other properties.
448
-			$this->triggerChange('enabled', $enabled, $oldStatus);
449
-			$this->config->setUserValue($this->uid, 'core', 'enabled', $enabled ? 'true' : 'false');
450
-		}
451
-	}
452
-
453
-	/**
454
-	 * get the users email address
455
-	 *
456
-	 * @return string|null
457
-	 * @since 9.0.0
458
-	 */
459
-	public function getEMailAddress() {
460
-		return $this->getPrimaryEMailAddress() ?? $this->getSystemEMailAddress();
461
-	}
462
-
463
-	/**
464
-	 * @inheritDoc
465
-	 */
466
-	public function getSystemEMailAddress(): ?string {
467
-		return $this->config->getUserValue($this->uid, 'settings', 'email', null);
468
-	}
469
-
470
-	/**
471
-	 * @inheritDoc
472
-	 */
473
-	public function getPrimaryEMailAddress(): ?string {
474
-		return $this->config->getUserValue($this->uid, 'settings', 'primary_email', null);
475
-	}
476
-
477
-	/**
478
-	 * get the users' quota
479
-	 *
480
-	 * @return string
481
-	 * @since 9.0.0
482
-	 */
483
-	public function getQuota() {
484
-		// allow apps to modify the user quota by hooking into the event
485
-		$event = new GetQuotaEvent($this);
486
-		$this->dispatcher->dispatchTyped($event);
487
-		$overwriteQuota = $event->getQuota();
488
-		if ($overwriteQuota) {
489
-			$quota = $overwriteQuota;
490
-		} else {
491
-			$quota = $this->config->getUserValue($this->uid, 'files', 'quota', 'default');
492
-		}
493
-		if ($quota === 'default') {
494
-			$quota = $this->config->getAppValue('files', 'default_quota', 'none');
495
-
496
-			// if unlimited quota is not allowed => avoid getting 'unlimited' as default_quota fallback value
497
-			// use the first preset instead
498
-			$allowUnlimitedQuota = $this->config->getAppValue('files', 'allow_unlimited_quota', '1') === '1';
499
-			if (!$allowUnlimitedQuota) {
500
-				$presets = $this->config->getAppValue('files', 'quota_preset', '1 GB, 5 GB, 10 GB');
501
-				$presets = array_filter(array_map('trim', explode(',', $presets)));
502
-				$quotaPreset = array_values(array_diff($presets, ['default', 'none']));
503
-				if (count($quotaPreset) > 0) {
504
-					$quota = $this->config->getAppValue('files', 'default_quota', $quotaPreset[0]);
505
-				}
506
-			}
507
-		}
508
-		return $quota;
509
-	}
510
-
511
-	/**
512
-	 * set the users' quota
513
-	 *
514
-	 * @param string $quota
515
-	 * @return void
516
-	 * @throws InvalidArgumentException
517
-	 * @since 9.0.0
518
-	 */
519
-	public function setQuota($quota) {
520
-		$oldQuota = $this->config->getUserValue($this->uid, 'files', 'quota', '');
521
-		if ($quota !== 'none' and $quota !== 'default') {
522
-			$bytesQuota = OC_Helper::computerFileSize($quota);
523
-			if ($bytesQuota === false) {
524
-				throw new InvalidArgumentException('Failed to set quota to invalid value '.$quota);
525
-			}
526
-			$quota = OC_Helper::humanFileSize($bytesQuota);
527
-		}
528
-		if ($quota !== $oldQuota) {
529
-			$this->config->setUserValue($this->uid, 'files', 'quota', $quota);
530
-			$this->triggerChange('quota', $quota, $oldQuota);
531
-		}
532
-		\OC_Helper::clearStorageInfo('/' . $this->uid . '/files');
533
-	}
534
-
535
-	/**
536
-	 * get the avatar image if it exists
537
-	 *
538
-	 * @param int $size
539
-	 * @return IImage|null
540
-	 * @since 9.0.0
541
-	 */
542
-	public function getAvatarImage($size) {
543
-		// delay the initialization
544
-		if (is_null($this->avatarManager)) {
545
-			$this->avatarManager = \OC::$server->getAvatarManager();
546
-		}
547
-
548
-		$avatar = $this->avatarManager->getAvatar($this->uid);
549
-		$image = $avatar->get(-1);
550
-		if ($image) {
551
-			return $image;
552
-		}
553
-
554
-		return null;
555
-	}
556
-
557
-	/**
558
-	 * get the federation cloud id
559
-	 *
560
-	 * @return string
561
-	 * @since 9.0.0
562
-	 */
563
-	public function getCloudId() {
564
-		$uid = $this->getUID();
565
-		$server = rtrim($this->urlGenerator->getAbsoluteURL('/'), '/');
566
-		if (substr($server, -10) === '/index.php') {
567
-			$server = substr($server, 0, -10);
568
-		}
569
-		$server = $this->removeProtocolFromUrl($server);
570
-		return $uid . '@' . $server;
571
-	}
572
-
573
-	private function removeProtocolFromUrl(string $url): string {
574
-		if (strpos($url, 'https://') === 0) {
575
-			return substr($url, strlen('https://'));
576
-		}
577
-
578
-		return $url;
579
-	}
580
-
581
-	public function triggerChange($feature, $value = null, $oldValue = null) {
582
-		$this->legacyDispatcher->dispatch(IUser::class . '::changeUser', new GenericEvent($this, [
583
-			'feature' => $feature,
584
-			'value' => $value,
585
-			'oldValue' => $oldValue,
586
-		]));
587
-		if ($this->emitter) {
588
-			$this->emitter->emit('\OC\User', 'changeUser', [$this, $feature, $value, $oldValue]);
589
-		}
590
-	}
64
+    /** @var IAccountManager */
65
+    protected $accountManager;
66
+    /** @var string */
67
+    private $uid;
68
+
69
+    /** @var string|null */
70
+    private $displayName;
71
+
72
+    /** @var UserInterface|null */
73
+    private $backend;
74
+    /** @var EventDispatcherInterface */
75
+    private $legacyDispatcher;
76
+
77
+    /** @var IEventDispatcher */
78
+    private $dispatcher;
79
+
80
+    /** @var bool|null */
81
+    private $enabled;
82
+
83
+    /** @var Emitter|Manager */
84
+    private $emitter;
85
+
86
+    /** @var string */
87
+    private $home;
88
+
89
+    /** @var int|null */
90
+    private $lastLogin;
91
+
92
+    /** @var \OCP\IConfig */
93
+    private $config;
94
+
95
+    /** @var IAvatarManager */
96
+    private $avatarManager;
97
+
98
+    /** @var IURLGenerator */
99
+    private $urlGenerator;
100
+
101
+    public function __construct(string $uid, ?UserInterface $backend, EventDispatcherInterface $dispatcher, $emitter = null, IConfig $config = null, $urlGenerator = null) {
102
+        $this->uid = $uid;
103
+        $this->backend = $backend;
104
+        $this->legacyDispatcher = $dispatcher;
105
+        $this->emitter = $emitter;
106
+        if (is_null($config)) {
107
+            $config = \OC::$server->getConfig();
108
+        }
109
+        $this->config = $config;
110
+        $this->urlGenerator = $urlGenerator;
111
+        if (is_null($this->urlGenerator)) {
112
+            $this->urlGenerator = \OC::$server->getURLGenerator();
113
+        }
114
+        // TODO: inject
115
+        $this->dispatcher = \OC::$server->query(IEventDispatcher::class);
116
+    }
117
+
118
+    /**
119
+     * get the user id
120
+     *
121
+     * @return string
122
+     */
123
+    public function getUID() {
124
+        return $this->uid;
125
+    }
126
+
127
+    /**
128
+     * get the display name for the user, if no specific display name is set it will fallback to the user id
129
+     *
130
+     * @return string
131
+     */
132
+    public function getDisplayName() {
133
+        if ($this->displayName === null) {
134
+            $displayName = '';
135
+            if ($this->backend && $this->backend->implementsActions(Backend::GET_DISPLAYNAME)) {
136
+                // get display name and strip whitespace from the beginning and end of it
137
+                $backendDisplayName = $this->backend->getDisplayName($this->uid);
138
+                if (is_string($backendDisplayName)) {
139
+                    $displayName = trim($backendDisplayName);
140
+                }
141
+            }
142
+
143
+            if (!empty($displayName)) {
144
+                $this->displayName = $displayName;
145
+            } else {
146
+                $this->displayName = $this->uid;
147
+            }
148
+        }
149
+        return $this->displayName;
150
+    }
151
+
152
+    /**
153
+     * set the displayname for the user
154
+     *
155
+     * @param string $displayName
156
+     * @return bool
157
+     *
158
+     * @since 25.0.0 Throw InvalidArgumentException
159
+     * @throws \InvalidArgumentException
160
+     */
161
+    public function setDisplayName($displayName) {
162
+        $displayName = trim($displayName);
163
+        $oldDisplayName = $this->getDisplayName();
164
+        if ($this->backend->implementsActions(Backend::SET_DISPLAYNAME) && !empty($displayName) && $displayName !== $oldDisplayName) {
165
+            /** @var ISetDisplayNameBackend $backend */
166
+            $backend = $this->backend;
167
+            $result = $backend->setDisplayName($this->uid, $displayName);
168
+            if ($result) {
169
+                $this->displayName = $displayName;
170
+                $this->triggerChange('displayName', $displayName, $oldDisplayName);
171
+            }
172
+            return $result !== false;
173
+        }
174
+        return false;
175
+    }
176
+
177
+    /**
178
+     * @inheritDoc
179
+     */
180
+    public function setEMailAddress($mailAddress) {
181
+        $this->setSystemEMailAddress($mailAddress);
182
+    }
183
+
184
+    /**
185
+     * @inheritDoc
186
+     */
187
+    public function setSystemEMailAddress(string $mailAddress): void {
188
+        $oldMailAddress = $this->getSystemEMailAddress();
189
+
190
+        if ($mailAddress === '') {
191
+            $this->config->deleteUserValue($this->uid, 'settings', 'email');
192
+        } else {
193
+            $this->config->setUserValue($this->uid, 'settings', 'email', $mailAddress);
194
+        }
195
+
196
+        $primaryAddress = $this->getPrimaryEMailAddress();
197
+        if ($primaryAddress === $mailAddress) {
198
+            // on match no dedicated primary settings is necessary
199
+            $this->setPrimaryEMailAddress('');
200
+        }
201
+
202
+        if ($oldMailAddress !== strtolower($mailAddress)) {
203
+            $this->triggerChange('eMailAddress', $mailAddress, $oldMailAddress);
204
+        }
205
+    }
206
+
207
+    /**
208
+     * @inheritDoc
209
+     */
210
+    public function setPrimaryEMailAddress(string $mailAddress): void {
211
+        if ($mailAddress === '') {
212
+            $this->config->deleteUserValue($this->uid, 'settings', 'primary_email');
213
+            return;
214
+        }
215
+
216
+        $this->ensureAccountManager();
217
+        $account = $this->accountManager->getAccount($this);
218
+        $property = $account->getPropertyCollection(IAccountManager::COLLECTION_EMAIL)
219
+            ->getPropertyByValue($mailAddress);
220
+
221
+        if ($property === null || $property->getLocallyVerified() !== IAccountManager::VERIFIED) {
222
+            throw new InvalidArgumentException('Only verified emails can be set as primary');
223
+        }
224
+        $this->config->setUserValue($this->uid, 'settings', 'primary_email', $mailAddress);
225
+    }
226
+
227
+    private function ensureAccountManager() {
228
+        if (!$this->accountManager instanceof IAccountManager) {
229
+            $this->accountManager = \OC::$server->get(IAccountManager::class);
230
+        }
231
+    }
232
+
233
+    /**
234
+     * returns the timestamp of the user's last login or 0 if the user did never
235
+     * login
236
+     *
237
+     * @return int
238
+     */
239
+    public function getLastLogin() {
240
+        if ($this->lastLogin === null) {
241
+            $this->lastLogin = (int) $this->config->getUserValue($this->uid, 'login', 'lastLogin', 0);
242
+        }
243
+        return (int) $this->lastLogin;
244
+    }
245
+
246
+    /**
247
+     * updates the timestamp of the most recent login of this user
248
+     */
249
+    public function updateLastLoginTimestamp() {
250
+        $previousLogin = $this->getLastLogin();
251
+        $now = time();
252
+        $firstTimeLogin = $previousLogin === 0;
253
+
254
+        if ($now - $previousLogin > 60) {
255
+            $this->lastLogin = time();
256
+            $this->config->setUserValue(
257
+                $this->uid, 'login', 'lastLogin', (string)$this->lastLogin);
258
+        }
259
+
260
+        return $firstTimeLogin;
261
+    }
262
+
263
+    /**
264
+     * Delete the user
265
+     *
266
+     * @return bool
267
+     */
268
+    public function delete() {
269
+        /** @deprecated 21.0.0 use BeforeUserDeletedEvent event with the IEventDispatcher instead */
270
+        $this->legacyDispatcher->dispatch(IUser::class . '::preDelete', new GenericEvent($this));
271
+        if ($this->emitter) {
272
+            /** @deprecated 21.0.0 use BeforeUserDeletedEvent event with the IEventDispatcher instead */
273
+            $this->emitter->emit('\OC\User', 'preDelete', [$this]);
274
+        }
275
+        $this->dispatcher->dispatchTyped(new BeforeUserDeletedEvent($this));
276
+        $result = $this->backend->deleteUser($this->uid);
277
+        if ($result) {
278
+            // FIXME: Feels like an hack - suggestions?
279
+
280
+            $groupManager = \OC::$server->getGroupManager();
281
+            // We have to delete the user from all groups
282
+            foreach ($groupManager->getUserGroupIds($this) as $groupId) {
283
+                $group = $groupManager->get($groupId);
284
+                if ($group) {
285
+                    $this->dispatcher->dispatchTyped(new BeforeUserRemovedEvent($group, $this));
286
+                    $group->removeUser($this);
287
+                    $this->dispatcher->dispatchTyped(new UserRemovedEvent($group, $this));
288
+                }
289
+            }
290
+            // Delete the user's keys in preferences
291
+            \OC::$server->getConfig()->deleteAllUserValues($this->uid);
292
+
293
+            \OC::$server->getCommentsManager()->deleteReferencesOfActor('users', $this->uid);
294
+            \OC::$server->getCommentsManager()->deleteReadMarksFromUser($this);
295
+
296
+            /** @var AvatarManager $avatarManager */
297
+            $avatarManager = \OC::$server->query(AvatarManager::class);
298
+            $avatarManager->deleteUserAvatar($this->uid);
299
+
300
+            $notification = \OC::$server->getNotificationManager()->createNotification();
301
+            $notification->setUser($this->uid);
302
+            \OC::$server->getNotificationManager()->markProcessed($notification);
303
+
304
+            /** @var AccountManager $accountManager */
305
+            $accountManager = \OC::$server->query(AccountManager::class);
306
+            $accountManager->deleteUser($this);
307
+
308
+            /** @deprecated 21.0.0 use UserDeletedEvent event with the IEventDispatcher instead */
309
+            $this->legacyDispatcher->dispatch(IUser::class . '::postDelete', new GenericEvent($this));
310
+            if ($this->emitter) {
311
+                /** @deprecated 21.0.0 use UserDeletedEvent event with the IEventDispatcher instead */
312
+                $this->emitter->emit('\OC\User', 'postDelete', [$this]);
313
+            }
314
+            $this->dispatcher->dispatchTyped(new UserDeletedEvent($this));
315
+        }
316
+        return !($result === false);
317
+    }
318
+
319
+    /**
320
+     * Set the password of the user
321
+     *
322
+     * @param string $password
323
+     * @param string $recoveryPassword for the encryption app to reset encryption keys
324
+     * @return bool
325
+     */
326
+    public function setPassword($password, $recoveryPassword = null) {
327
+        $this->legacyDispatcher->dispatch(IUser::class . '::preSetPassword', new GenericEvent($this, [
328
+            'password' => $password,
329
+            'recoveryPassword' => $recoveryPassword,
330
+        ]));
331
+        if ($this->emitter) {
332
+            $this->emitter->emit('\OC\User', 'preSetPassword', [$this, $password, $recoveryPassword]);
333
+        }
334
+        if ($this->backend->implementsActions(Backend::SET_PASSWORD)) {
335
+            /** @var ISetPasswordBackend $backend */
336
+            $backend = $this->backend;
337
+            $result = $backend->setPassword($this->uid, $password);
338
+
339
+            if ($result !== false) {
340
+                $this->legacyDispatcher->dispatch(IUser::class . '::postSetPassword', new GenericEvent($this, [
341
+                    'password' => $password,
342
+                    'recoveryPassword' => $recoveryPassword,
343
+                ]));
344
+                if ($this->emitter) {
345
+                    $this->emitter->emit('\OC\User', 'postSetPassword', [$this, $password, $recoveryPassword]);
346
+                }
347
+            }
348
+
349
+            return !($result === false);
350
+        } else {
351
+            return false;
352
+        }
353
+    }
354
+
355
+    /**
356
+     * get the users home folder to mount
357
+     *
358
+     * @return string
359
+     */
360
+    public function getHome() {
361
+        if (!$this->home) {
362
+            /** @psalm-suppress UndefinedInterfaceMethod Once we get rid of the legacy implementsActions, psalm won't complain anymore */
363
+            if (($this->backend instanceof IGetHomeBackend || $this->backend->implementsActions(Backend::GET_HOME)) && $home = $this->backend->getHome($this->uid)) {
364
+                $this->home = $home;
365
+            } elseif ($this->config) {
366
+                $this->home = $this->config->getSystemValueString('datadirectory', \OC::$SERVERROOT . '/data') . '/' . $this->uid;
367
+            } else {
368
+                $this->home = \OC::$SERVERROOT . '/data/' . $this->uid;
369
+            }
370
+        }
371
+        return $this->home;
372
+    }
373
+
374
+    /**
375
+     * Get the name of the backend class the user is connected with
376
+     *
377
+     * @return string
378
+     */
379
+    public function getBackendClassName() {
380
+        if ($this->backend instanceof IUserBackend) {
381
+            return $this->backend->getBackendName();
382
+        }
383
+        return get_class($this->backend);
384
+    }
385
+
386
+    public function getBackend(): ?UserInterface {
387
+        return $this->backend;
388
+    }
389
+
390
+    /**
391
+     * Check if the backend allows the user to change his avatar on Personal page
392
+     *
393
+     * @return bool
394
+     */
395
+    public function canChangeAvatar() {
396
+        if ($this->backend instanceof IProvideAvatarBackend || $this->backend->implementsActions(Backend::PROVIDE_AVATAR)) {
397
+            /** @var IProvideAvatarBackend $backend */
398
+            $backend = $this->backend;
399
+            return $backend->canChangeAvatar($this->uid);
400
+        }
401
+        return true;
402
+    }
403
+
404
+    /**
405
+     * check if the backend supports changing passwords
406
+     *
407
+     * @return bool
408
+     */
409
+    public function canChangePassword() {
410
+        return $this->backend->implementsActions(Backend::SET_PASSWORD);
411
+    }
412
+
413
+    /**
414
+     * check if the backend supports changing display names
415
+     *
416
+     * @return bool
417
+     */
418
+    public function canChangeDisplayName() {
419
+        if (!$this->config->getSystemValueBool('allow_user_to_change_display_name', true)) {
420
+            return false;
421
+        }
422
+        return $this->backend->implementsActions(Backend::SET_DISPLAYNAME);
423
+    }
424
+
425
+    /**
426
+     * check if the user is enabled
427
+     *
428
+     * @return bool
429
+     */
430
+    public function isEnabled() {
431
+        if ($this->enabled === null) {
432
+            $enabled = $this->config->getUserValue($this->uid, 'core', 'enabled', 'true');
433
+            $this->enabled = $enabled === 'true';
434
+        }
435
+        return (bool) $this->enabled;
436
+    }
437
+
438
+    /**
439
+     * set the enabled status for the user
440
+     *
441
+     * @param bool $enabled
442
+     */
443
+    public function setEnabled(bool $enabled = true) {
444
+        $oldStatus = $this->isEnabled();
445
+        $this->enabled = $enabled;
446
+        if ($oldStatus !== $this->enabled) {
447
+            // TODO: First change the value, then trigger the event as done for all other properties.
448
+            $this->triggerChange('enabled', $enabled, $oldStatus);
449
+            $this->config->setUserValue($this->uid, 'core', 'enabled', $enabled ? 'true' : 'false');
450
+        }
451
+    }
452
+
453
+    /**
454
+     * get the users email address
455
+     *
456
+     * @return string|null
457
+     * @since 9.0.0
458
+     */
459
+    public function getEMailAddress() {
460
+        return $this->getPrimaryEMailAddress() ?? $this->getSystemEMailAddress();
461
+    }
462
+
463
+    /**
464
+     * @inheritDoc
465
+     */
466
+    public function getSystemEMailAddress(): ?string {
467
+        return $this->config->getUserValue($this->uid, 'settings', 'email', null);
468
+    }
469
+
470
+    /**
471
+     * @inheritDoc
472
+     */
473
+    public function getPrimaryEMailAddress(): ?string {
474
+        return $this->config->getUserValue($this->uid, 'settings', 'primary_email', null);
475
+    }
476
+
477
+    /**
478
+     * get the users' quota
479
+     *
480
+     * @return string
481
+     * @since 9.0.0
482
+     */
483
+    public function getQuota() {
484
+        // allow apps to modify the user quota by hooking into the event
485
+        $event = new GetQuotaEvent($this);
486
+        $this->dispatcher->dispatchTyped($event);
487
+        $overwriteQuota = $event->getQuota();
488
+        if ($overwriteQuota) {
489
+            $quota = $overwriteQuota;
490
+        } else {
491
+            $quota = $this->config->getUserValue($this->uid, 'files', 'quota', 'default');
492
+        }
493
+        if ($quota === 'default') {
494
+            $quota = $this->config->getAppValue('files', 'default_quota', 'none');
495
+
496
+            // if unlimited quota is not allowed => avoid getting 'unlimited' as default_quota fallback value
497
+            // use the first preset instead
498
+            $allowUnlimitedQuota = $this->config->getAppValue('files', 'allow_unlimited_quota', '1') === '1';
499
+            if (!$allowUnlimitedQuota) {
500
+                $presets = $this->config->getAppValue('files', 'quota_preset', '1 GB, 5 GB, 10 GB');
501
+                $presets = array_filter(array_map('trim', explode(',', $presets)));
502
+                $quotaPreset = array_values(array_diff($presets, ['default', 'none']));
503
+                if (count($quotaPreset) > 0) {
504
+                    $quota = $this->config->getAppValue('files', 'default_quota', $quotaPreset[0]);
505
+                }
506
+            }
507
+        }
508
+        return $quota;
509
+    }
510
+
511
+    /**
512
+     * set the users' quota
513
+     *
514
+     * @param string $quota
515
+     * @return void
516
+     * @throws InvalidArgumentException
517
+     * @since 9.0.0
518
+     */
519
+    public function setQuota($quota) {
520
+        $oldQuota = $this->config->getUserValue($this->uid, 'files', 'quota', '');
521
+        if ($quota !== 'none' and $quota !== 'default') {
522
+            $bytesQuota = OC_Helper::computerFileSize($quota);
523
+            if ($bytesQuota === false) {
524
+                throw new InvalidArgumentException('Failed to set quota to invalid value '.$quota);
525
+            }
526
+            $quota = OC_Helper::humanFileSize($bytesQuota);
527
+        }
528
+        if ($quota !== $oldQuota) {
529
+            $this->config->setUserValue($this->uid, 'files', 'quota', $quota);
530
+            $this->triggerChange('quota', $quota, $oldQuota);
531
+        }
532
+        \OC_Helper::clearStorageInfo('/' . $this->uid . '/files');
533
+    }
534
+
535
+    /**
536
+     * get the avatar image if it exists
537
+     *
538
+     * @param int $size
539
+     * @return IImage|null
540
+     * @since 9.0.0
541
+     */
542
+    public function getAvatarImage($size) {
543
+        // delay the initialization
544
+        if (is_null($this->avatarManager)) {
545
+            $this->avatarManager = \OC::$server->getAvatarManager();
546
+        }
547
+
548
+        $avatar = $this->avatarManager->getAvatar($this->uid);
549
+        $image = $avatar->get(-1);
550
+        if ($image) {
551
+            return $image;
552
+        }
553
+
554
+        return null;
555
+    }
556
+
557
+    /**
558
+     * get the federation cloud id
559
+     *
560
+     * @return string
561
+     * @since 9.0.0
562
+     */
563
+    public function getCloudId() {
564
+        $uid = $this->getUID();
565
+        $server = rtrim($this->urlGenerator->getAbsoluteURL('/'), '/');
566
+        if (substr($server, -10) === '/index.php') {
567
+            $server = substr($server, 0, -10);
568
+        }
569
+        $server = $this->removeProtocolFromUrl($server);
570
+        return $uid . '@' . $server;
571
+    }
572
+
573
+    private function removeProtocolFromUrl(string $url): string {
574
+        if (strpos($url, 'https://') === 0) {
575
+            return substr($url, strlen('https://'));
576
+        }
577
+
578
+        return $url;
579
+    }
580
+
581
+    public function triggerChange($feature, $value = null, $oldValue = null) {
582
+        $this->legacyDispatcher->dispatch(IUser::class . '::changeUser', new GenericEvent($this, [
583
+            'feature' => $feature,
584
+            'value' => $value,
585
+            'oldValue' => $oldValue,
586
+        ]));
587
+        if ($this->emitter) {
588
+            $this->emitter->emit('\OC\User', 'changeUser', [$this, $feature, $value, $oldValue]);
589
+        }
590
+    }
591 591
 }
Please login to merge, or discard this patch.