Passed
Push — master ( 633a19...58658f )
by Roeland
10:40 queued 11s
created
apps/provisioning_api/lib/Controller/UsersController.php 1 patch
Indentation   +856 added lines, -856 removed lines patch added patch discarded remove patch
@@ -54,860 +54,860 @@
 block discarded – undo
54 54
 
55 55
 class UsersController extends AUserData {
56 56
 
57
-	/** @var IAppManager */
58
-	private $appManager;
59
-	/** @var ILogger */
60
-	private $logger;
61
-	/** @var IFactory */
62
-	private $l10nFactory;
63
-	/** @var NewUserMailHelper */
64
-	private $newUserMailHelper;
65
-	/** @var FederatedFileSharingFactory */
66
-	private $federatedFileSharingFactory;
67
-	/** @var ISecureRandom */
68
-	private $secureRandom;
69
-
70
-	/**
71
-	 * @param string $appName
72
-	 * @param IRequest $request
73
-	 * @param IUserManager $userManager
74
-	 * @param IConfig $config
75
-	 * @param IAppManager $appManager
76
-	 * @param IGroupManager $groupManager
77
-	 * @param IUserSession $userSession
78
-	 * @param AccountManager $accountManager
79
-	 * @param ILogger $logger
80
-	 * @param IFactory $l10nFactory
81
-	 * @param NewUserMailHelper $newUserMailHelper
82
-	 * @param FederatedFileSharingFactory $federatedFileSharingFactory
83
-	 * @param ISecureRandom $secureRandom
84
-	 */
85
-	public function __construct(string $appName,
86
-								IRequest $request,
87
-								IUserManager $userManager,
88
-								IConfig $config,
89
-								IAppManager $appManager,
90
-								IGroupManager $groupManager,
91
-								IUserSession $userSession,
92
-								AccountManager $accountManager,
93
-								ILogger $logger,
94
-								IFactory $l10nFactory,
95
-								NewUserMailHelper $newUserMailHelper,
96
-								FederatedFileSharingFactory $federatedFileSharingFactory,
97
-								ISecureRandom $secureRandom) {
98
-		parent::__construct($appName,
99
-							$request,
100
-							$userManager,
101
-							$config,
102
-							$groupManager,
103
-							$userSession,
104
-							$accountManager);
105
-
106
-		$this->appManager = $appManager;
107
-		$this->logger = $logger;
108
-		$this->l10nFactory = $l10nFactory;
109
-		$this->newUserMailHelper = $newUserMailHelper;
110
-		$this->federatedFileSharingFactory = $federatedFileSharingFactory;
111
-		$this->secureRandom = $secureRandom;
112
-	}
113
-
114
-	/**
115
-	 * @NoAdminRequired
116
-	 *
117
-	 * returns a list of users
118
-	 *
119
-	 * @param string $search
120
-	 * @param int $limit
121
-	 * @param int $offset
122
-	 * @return DataResponse
123
-	 */
124
-	public function getUsers(string $search = '', $limit = null, $offset = 0): DataResponse {
125
-		$user = $this->userSession->getUser();
126
-		$users = [];
127
-
128
-		// Admin? Or SubAdmin?
129
-		$uid = $user->getUID();
130
-		$subAdminManager = $this->groupManager->getSubAdmin();
131
-		if ($this->groupManager->isAdmin($uid)){
132
-			$users = $this->userManager->search($search, $limit, $offset);
133
-		} else if ($subAdminManager->isSubAdmin($user)) {
134
-			$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
135
-			foreach ($subAdminOfGroups as $key => $group) {
136
-				$subAdminOfGroups[$key] = $group->getGID();
137
-			}
138
-
139
-			$users = [];
140
-			foreach ($subAdminOfGroups as $group) {
141
-				$users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
142
-			}
143
-		}
144
-
145
-		$users = array_keys($users);
146
-
147
-		return new DataResponse([
148
-			'users' => $users
149
-		]);
150
-	}
151
-
152
-	/**
153
-	 * @NoAdminRequired
154
-	 *
155
-	 * returns a list of users and their data
156
-	 */
157
-	public function getUsersDetails(string $search = '', $limit = null, $offset = 0): DataResponse {
158
-		$currentUser = $this->userSession->getUser();
159
-		$users = [];
160
-
161
-		// Admin? Or SubAdmin?
162
-		$uid = $currentUser->getUID();
163
-		$subAdminManager = $this->groupManager->getSubAdmin();
164
-		if ($this->groupManager->isAdmin($uid)){
165
-			$users = $this->userManager->search($search, $limit, $offset);
166
-			$users = array_keys($users);
167
-		} else if ($subAdminManager->isSubAdmin($currentUser)) {
168
-			$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($currentUser);
169
-			foreach ($subAdminOfGroups as $key => $group) {
170
-				$subAdminOfGroups[$key] = $group->getGID();
171
-			}
172
-
173
-			$users = [];
174
-			foreach ($subAdminOfGroups as $group) {
175
-				$users[] = array_keys($this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
176
-			}
177
-			$users = array_merge(...$users);
178
-		}
179
-
180
-		$usersDetails = [];
181
-		foreach ($users as $userId) {
182
-			$userId = (string) $userId;
183
-			$userData = $this->getUserData($userId);
184
-			// Do not insert empty entry
185
-			if (!empty($userData)) {
186
-				$usersDetails[$userId] = $userData;
187
-			} else {
188
-				// Logged user does not have permissions to see this user
189
-				// only showing its id
190
-				$usersDetails[$userId] = ['id' => $userId];
191
-			}
192
-		}
193
-
194
-		return new DataResponse([
195
-			'users' => $usersDetails
196
-		]);
197
-	}
198
-
199
-	/**
200
-	 * @PasswordConfirmationRequired
201
-	 * @NoAdminRequired
202
-	 *
203
-	 * @param string $userid
204
-	 * @param string $password
205
-	 * @param string $displayName
206
-	 * @param string $email
207
-	 * @param array $groups
208
-	 * @param array $subadmin
209
-	 * @param string $quota
210
-	 * @param string $language
211
-	 * @return DataResponse
212
-	 * @throws OCSException
213
-	 */
214
-	public function addUser(string $userid,
215
-							string $password = '',
216
-							string $displayName = '',
217
-							string $email = '',
218
-							array $groups = [],
219
-							array $subadmin = [],
220
-							string $quota = '',
221
-							string $language = ''): DataResponse {
222
-		$user = $this->userSession->getUser();
223
-		$isAdmin = $this->groupManager->isAdmin($user->getUID());
224
-		$subAdminManager = $this->groupManager->getSubAdmin();
225
-
226
-		if ($this->userManager->userExists($userid)) {
227
-			$this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
228
-			throw new OCSException('User already exists', 102);
229
-		}
230
-
231
-		if ($groups !== []) {
232
-			foreach ($groups as $group) {
233
-				if (!$this->groupManager->groupExists($group)) {
234
-					throw new OCSException('group '.$group.' does not exist', 104);
235
-				}
236
-				if (!$isAdmin && !$subAdminManager->isSubAdminOfGroup($user, $this->groupManager->get($group))) {
237
-					throw new OCSException('insufficient privileges for group '. $group, 105);
238
-				}
239
-			}
240
-		} else {
241
-			if (!$isAdmin) {
242
-				throw new OCSException('no group specified (required for subadmins)', 106);
243
-			}
244
-		}
245
-
246
-		$subadminGroups = [];
247
-		if ($subadmin !== []) {
248
-			foreach ($subadmin as $groupid) {
249
-				$group = $this->groupManager->get($groupid);
250
-				// Check if group exists
251
-				if ($group === null) {
252
-					throw new OCSException('Subadmin group does not exist',  102);
253
-				}
254
-				// Check if trying to make subadmin of admin group
255
-				if ($group->getGID() === 'admin') {
256
-					throw new OCSException('Cannot create subadmins for admin group', 103);
257
-				}
258
-				// Check if has permission to promote subadmins
259
-				if (!$subAdminManager->isSubAdminOfGroup($user, $group) && !$isAdmin) {
260
-					throw new OCSForbiddenException('No permissions to promote subadmins');
261
-				}
262
-				$subadminGroups[] = $group;
263
-			}
264
-		}
265
-
266
-		$generatePasswordResetToken = false;
267
-		if ($password === '') {
268
-			if ($email === '') {
269
-				throw new OCSException('To send a password link to the user an email address is required.', 108);
270
-			}
271
-
272
-			$password = $this->secureRandom->generate(10);
273
-			// Make sure we pass the password_policy
274
-			$password .= $this->secureRandom->generate(2, '$!.,;:-~+*[]{}()');
275
-			$generatePasswordResetToken = true;
276
-		}
277
-
278
-		try {
279
-			$newUser = $this->userManager->createUser($userid, $password);
280
-			$this->logger->info('Successful addUser call with userid: ' . $userid, ['app' => 'ocs_api']);
281
-
282
-			foreach ($groups as $group) {
283
-				$this->groupManager->get($group)->addUser($newUser);
284
-				$this->logger->info('Added userid ' . $userid . ' to group ' . $group, ['app' => 'ocs_api']);
285
-			}
286
-			foreach ($subadminGroups as $group) {
287
-				$subAdminManager->createSubAdmin($newUser, $group);
288
-			}
289
-
290
-			if ($displayName !== '') {
291
-				$this->editUser($userid, 'display', $displayName);
292
-			}
293
-
294
-			if ($quota !== '') {
295
-				$this->editUser($userid, 'quota', $quota);
296
-			}
297
-
298
-			if ($language !== '') {
299
-				$this->editUser($userid, 'language', $language);
300
-			}
301
-
302
-			// Send new user mail only if a mail is set
303
-			if ($email !== '') {
304
-				$newUser->setEMailAddress($email);
305
-				try {
306
-					$emailTemplate = $this->newUserMailHelper->generateTemplate($newUser, $generatePasswordResetToken);
307
-					$this->newUserMailHelper->sendMail($newUser, $emailTemplate);
308
-				} catch (\Exception $e) {
309
-					$this->logger->logException($e, [
310
-						'message' => "Can't send new user mail to $email",
311
-						'level' => ILogger::ERROR,
312
-						'app' => 'ocs_api',
313
-					]);
314
-					throw new OCSException('Unable to send the invitation mail', 109);
315
-				}
316
-			}
317
-
318
-			return new DataResponse();
319
-
320
-		} catch (HintException $e ) {
321
-			$this->logger->logException($e, [
322
-				'message' => 'Failed addUser attempt with hint exception.',
323
-				'level' => ILogger::WARN,
324
-				'app' => 'ocs_api',
325
-			]);
326
-			throw new OCSException($e->getHint(), 107);
327
-		} catch (\Exception $e) {
328
-			$this->logger->logException($e, [
329
-				'message' => 'Failed addUser attempt with exception.',
330
-				'level' => ILogger::ERROR,
331
-				'app' => 'ocs_api',
332
-			]);
333
-			throw new OCSException('Bad request', 101);
334
-		}
335
-	}
336
-
337
-	/**
338
-	 * @NoAdminRequired
339
-	 * @NoSubAdminRequired
340
-	 *
341
-	 * gets user info
342
-	 *
343
-	 * @param string $userId
344
-	 * @return DataResponse
345
-	 * @throws OCSException
346
-	 */
347
-	public function getUser(string $userId): DataResponse {
348
-		$data = $this->getUserData($userId);
349
-		// getUserData returns empty array if not enough permissions
350
-		if (empty($data)) {
351
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
352
-		}
353
-		return new DataResponse($data);
354
-	}
355
-
356
-	/**
357
-	 * @NoAdminRequired
358
-	 * @NoSubAdminRequired
359
-	 *
360
-	 * gets user info from the currently logged in user
361
-	 *
362
-	 * @return DataResponse
363
-	 * @throws OCSException
364
-	 */
365
-	public function getCurrentUser(): DataResponse {
366
-		$user = $this->userSession->getUser();
367
-		if ($user) {
368
-			$data =  $this->getUserData($user->getUID());
369
-			// rename "displayname" to "display-name" only for this call to keep
370
-			// the API stable.
371
-			$data['display-name'] = $data['displayname'];
372
-			unset($data['displayname']);
373
-			return new DataResponse($data);
374
-
375
-		}
376
-
377
-		throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
378
-	}
379
-
380
-	/**
381
-	 * @NoAdminRequired
382
-	 * @NoSubAdminRequired
383
-	 */
384
-	public function getEditableFields(): DataResponse {
385
-		$permittedFields = [];
386
-
387
-		// Editing self (display, email)
388
-		if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
389
-			$permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
390
-			$permittedFields[] = AccountManager::PROPERTY_EMAIL;
391
-		}
392
-
393
-		if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
394
-			$federatedFileSharing = $this->federatedFileSharingFactory->get();
395
-			$shareProvider = $federatedFileSharing->getFederatedShareProvider();
396
-			if ($shareProvider->isLookupServerUploadEnabled()) {
397
-				$permittedFields[] = AccountManager::PROPERTY_PHONE;
398
-				$permittedFields[] = AccountManager::PROPERTY_ADDRESS;
399
-				$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
400
-				$permittedFields[] = AccountManager::PROPERTY_TWITTER;
401
-			}
402
-		}
403
-
404
-		return new DataResponse($permittedFields);
405
-	}
406
-
407
-	/**
408
-	 * @NoAdminRequired
409
-	 * @NoSubAdminRequired
410
-	 * @PasswordConfirmationRequired
411
-	 *
412
-	 * edit users
413
-	 *
414
-	 * @param string $userId
415
-	 * @param string $key
416
-	 * @param string $value
417
-	 * @return DataResponse
418
-	 * @throws OCSException
419
-	 */
420
-	public function editUser(string $userId, string $key, string $value): DataResponse {
421
-		$currentLoggedInUser = $this->userSession->getUser();
422
-
423
-		$targetUser = $this->userManager->get($userId);
424
-		if ($targetUser === null) {
425
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
426
-		}
427
-
428
-		$permittedFields = [];
429
-		if ($targetUser->getUID() === $currentLoggedInUser->getUID()) {
430
-			// Editing self (display, email)
431
-			if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
432
-				$permittedFields[] = 'display';
433
-				$permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
434
-				$permittedFields[] = AccountManager::PROPERTY_EMAIL;
435
-			}
436
-
437
-			$permittedFields[] = 'password';
438
-			if ($this->config->getSystemValue('force_language', false) === false ||
439
-				$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
440
-				$permittedFields[] = 'language';
441
-			}
442
-
443
-			if ($this->config->getSystemValue('force_locale', false) === false ||
444
-				$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
445
-				$permittedFields[] = 'locale';
446
-			}
447
-
448
-			if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
449
-				$federatedFileSharing = new \OCA\FederatedFileSharing\AppInfo\Application();
450
-				$shareProvider = $federatedFileSharing->getFederatedShareProvider();
451
-				if ($shareProvider->isLookupServerUploadEnabled()) {
452
-					$permittedFields[] = AccountManager::PROPERTY_PHONE;
453
-					$permittedFields[] = AccountManager::PROPERTY_ADDRESS;
454
-					$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
455
-					$permittedFields[] = AccountManager::PROPERTY_TWITTER;
456
-				}
457
-			}
458
-
459
-			// If admin they can edit their own quota
460
-			if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
461
-				$permittedFields[] = 'quota';
462
-			}
463
-		} else {
464
-			// Check if admin / subadmin
465
-			$subAdminManager = $this->groupManager->getSubAdmin();
466
-			if ($subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
467
-			|| $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
468
-				// They have permissions over the user
469
-				$permittedFields[] = 'display';
470
-				$permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
471
-				$permittedFields[] = AccountManager::PROPERTY_EMAIL;
472
-				$permittedFields[] = 'password';
473
-				$permittedFields[] = 'language';
474
-				$permittedFields[] = 'locale';
475
-				$permittedFields[] = AccountManager::PROPERTY_PHONE;
476
-				$permittedFields[] = AccountManager::PROPERTY_ADDRESS;
477
-				$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
478
-				$permittedFields[] = AccountManager::PROPERTY_TWITTER;
479
-				$permittedFields[] = 'quota';
480
-			} else {
481
-				// No rights
482
-				throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
483
-			}
484
-		}
485
-		// Check if permitted to edit this field
486
-		if (!in_array($key, $permittedFields)) {
487
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
488
-		}
489
-		// Process the edit
490
-		switch($key) {
491
-			case 'display':
492
-			case AccountManager::PROPERTY_DISPLAYNAME:
493
-				$targetUser->setDisplayName($value);
494
-				break;
495
-			case 'quota':
496
-				$quota = $value;
497
-				if ($quota !== 'none' && $quota !== 'default') {
498
-					if (is_numeric($quota)) {
499
-						$quota = (float) $quota;
500
-					} else {
501
-						$quota = \OCP\Util::computerFileSize($quota);
502
-					}
503
-					if ($quota === false) {
504
-						throw new OCSException('Invalid quota value '.$value, 103);
505
-					}
506
-					if ($quota === -1) {
507
-						$quota = 'none';
508
-					} else {
509
-						$quota = \OCP\Util::humanFileSize($quota);
510
-					}
511
-				}
512
-				$targetUser->setQuota($quota);
513
-				break;
514
-			case 'password':
515
-				try {
516
-					if (!$targetUser->canChangePassword()) {
517
-						throw new OCSException('Setting the password is not supported by the users backend', 103);
518
-					}
519
-					$targetUser->setPassword($value);
520
-				} catch (HintException $e) { // password policy error
521
-					throw new OCSException($e->getMessage(), 103);
522
-				}
523
-				break;
524
-			case 'language':
525
-				$languagesCodes = $this->l10nFactory->findAvailableLanguages();
526
-				if (!in_array($value, $languagesCodes, true) && $value !== 'en') {
527
-					throw new OCSException('Invalid language', 102);
528
-				}
529
-				$this->config->setUserValue($targetUser->getUID(), 'core', 'lang', $value);
530
-				break;
531
-			case 'locale':
532
-				if (!$this->l10nFactory->localeExists($value)) {
533
-					throw new OCSException('Invalid locale', 102);
534
-				}
535
-				$this->config->setUserValue($targetUser->getUID(), 'core', 'locale', $value);
536
-				break;
537
-			case AccountManager::PROPERTY_EMAIL:
538
-				if (filter_var($value, FILTER_VALIDATE_EMAIL) || $value === '') {
539
-					$targetUser->setEMailAddress($value);
540
-				} else {
541
-					throw new OCSException('', 102);
542
-				}
543
-				break;
544
-			case AccountManager::PROPERTY_PHONE:
545
-			case AccountManager::PROPERTY_ADDRESS:
546
-			case AccountManager::PROPERTY_WEBSITE:
547
-			case AccountManager::PROPERTY_TWITTER:
548
-				$userAccount = $this->accountManager->getUser($targetUser);
549
-				if ($userAccount[$key]['value'] !== $value) {
550
-					$userAccount[$key]['value'] = $value;
551
-					$this->accountManager->updateUser($targetUser, $userAccount);
552
-				}
553
-				break;
554
-			default:
555
-				throw new OCSException('', 103);
556
-		}
557
-		return new DataResponse();
558
-	}
559
-
560
-	/**
561
-	 * @PasswordConfirmationRequired
562
-	 * @NoAdminRequired
563
-	 *
564
-	 * @param string $userId
565
-	 * @return DataResponse
566
-	 * @throws OCSException
567
-	 */
568
-	public function deleteUser(string $userId): DataResponse {
569
-		$currentLoggedInUser = $this->userSession->getUser();
570
-
571
-		$targetUser = $this->userManager->get($userId);
572
-
573
-		if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
574
-			throw new OCSException('', 101);
575
-		}
576
-
577
-		// If not permitted
578
-		$subAdminManager = $this->groupManager->getSubAdmin();
579
-		if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
580
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
581
-		}
582
-
583
-		// Go ahead with the delete
584
-		if ($targetUser->delete()) {
585
-			return new DataResponse();
586
-		} else {
587
-			throw new OCSException('', 101);
588
-		}
589
-	}
590
-
591
-	/**
592
-	 * @PasswordConfirmationRequired
593
-	 * @NoAdminRequired
594
-	 *
595
-	 * @param string $userId
596
-	 * @return DataResponse
597
-	 * @throws OCSException
598
-	 * @throws OCSForbiddenException
599
-	 */
600
-	public function disableUser(string $userId): DataResponse {
601
-		return $this->setEnabled($userId, false);
602
-	}
603
-
604
-	/**
605
-	 * @PasswordConfirmationRequired
606
-	 * @NoAdminRequired
607
-	 *
608
-	 * @param string $userId
609
-	 * @return DataResponse
610
-	 * @throws OCSException
611
-	 * @throws OCSForbiddenException
612
-	 */
613
-	public function enableUser(string $userId): DataResponse {
614
-		return $this->setEnabled($userId, true);
615
-	}
616
-
617
-	/**
618
-	 * @param string $userId
619
-	 * @param bool $value
620
-	 * @return DataResponse
621
-	 * @throws OCSException
622
-	 */
623
-	private function setEnabled(string $userId, bool $value): DataResponse {
624
-		$currentLoggedInUser = $this->userSession->getUser();
625
-
626
-		$targetUser = $this->userManager->get($userId);
627
-		if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
628
-			throw new OCSException('', 101);
629
-		}
630
-
631
-		// If not permitted
632
-		$subAdminManager = $this->groupManager->getSubAdmin();
633
-		if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
634
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
635
-		}
636
-
637
-		// enable/disable the user now
638
-		$targetUser->setEnabled($value);
639
-		return new DataResponse();
640
-	}
641
-
642
-	/**
643
-	 * @NoAdminRequired
644
-	 * @NoSubAdminRequired
645
-	 *
646
-	 * @param string $userId
647
-	 * @return DataResponse
648
-	 * @throws OCSException
649
-	 */
650
-	public function getUsersGroups(string $userId): DataResponse {
651
-		$loggedInUser = $this->userSession->getUser();
652
-
653
-		$targetUser = $this->userManager->get($userId);
654
-		if ($targetUser === null) {
655
-			throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
656
-		}
657
-
658
-		if ($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
659
-			// Self lookup or admin lookup
660
-			return new DataResponse([
661
-				'groups' => $this->groupManager->getUserGroupIds($targetUser)
662
-			]);
663
-		} else {
664
-			$subAdminManager = $this->groupManager->getSubAdmin();
665
-
666
-			// Looking up someone else
667
-			if ($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
668
-				// Return the group that the method caller is subadmin of for the user in question
669
-				/** @var IGroup[] $getSubAdminsGroups */
670
-				$getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
671
-				foreach ($getSubAdminsGroups as $key => $group) {
672
-					$getSubAdminsGroups[$key] = $group->getGID();
673
-				}
674
-				$groups = array_intersect(
675
-					$getSubAdminsGroups,
676
-					$this->groupManager->getUserGroupIds($targetUser)
677
-				);
678
-				return new DataResponse(['groups' => $groups]);
679
-			} else {
680
-				// Not permitted
681
-				throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
682
-			}
683
-		}
684
-
685
-	}
686
-
687
-	/**
688
-	 * @PasswordConfirmationRequired
689
-	 * @NoAdminRequired
690
-	 *
691
-	 * @param string $userId
692
-	 * @param string $groupid
693
-	 * @return DataResponse
694
-	 * @throws OCSException
695
-	 */
696
-	public function addToGroup(string $userId, string $groupid = ''): DataResponse {
697
-		if ($groupid === '') {
698
-			throw new OCSException('', 101);
699
-		}
700
-
701
-		$group = $this->groupManager->get($groupid);
702
-		$targetUser = $this->userManager->get($userId);
703
-		if ($group === null) {
704
-			throw new OCSException('', 102);
705
-		}
706
-		if ($targetUser === null) {
707
-			throw new OCSException('', 103);
708
-		}
709
-
710
-		// If they're not an admin, check they are a subadmin of the group in question
711
-		$loggedInUser = $this->userSession->getUser();
712
-		$subAdminManager = $this->groupManager->getSubAdmin();
713
-		if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
714
-			throw new OCSException('', 104);
715
-		}
716
-
717
-		// Add user to group
718
-		$group->addUser($targetUser);
719
-		return new DataResponse();
720
-	}
721
-
722
-	/**
723
-	 * @PasswordConfirmationRequired
724
-	 * @NoAdminRequired
725
-	 *
726
-	 * @param string $userId
727
-	 * @param string $groupid
728
-	 * @return DataResponse
729
-	 * @throws OCSException
730
-	 */
731
-	public function removeFromGroup(string $userId, string $groupid): DataResponse {
732
-		$loggedInUser = $this->userSession->getUser();
733
-
734
-		if ($groupid === null || trim($groupid) === '') {
735
-			throw new OCSException('', 101);
736
-		}
737
-
738
-		$group = $this->groupManager->get($groupid);
739
-		if ($group === null) {
740
-			throw new OCSException('', 102);
741
-		}
742
-
743
-		$targetUser = $this->userManager->get($userId);
744
-		if ($targetUser === null) {
745
-			throw new OCSException('', 103);
746
-		}
747
-
748
-		// If they're not an admin, check they are a subadmin of the group in question
749
-		$subAdminManager = $this->groupManager->getSubAdmin();
750
-		if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
751
-			throw new OCSException('', 104);
752
-		}
753
-
754
-		// Check they aren't removing themselves from 'admin' or their 'subadmin; group
755
-		if ($targetUser->getUID() === $loggedInUser->getUID()) {
756
-			if ($this->groupManager->isAdmin($loggedInUser->getUID())) {
757
-				if ($group->getGID() === 'admin') {
758
-					throw new OCSException('Cannot remove yourself from the admin group', 105);
759
-				}
760
-			} else {
761
-				// Not an admin, so the user must be a subadmin of this group, but that is not allowed.
762
-				throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105);
763
-			}
764
-
765
-		} else if (!$this->groupManager->isAdmin($loggedInUser->getUID())) {
766
-			/** @var IGroup[] $subAdminGroups */
767
-			$subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
768
-			$subAdminGroups = array_map(function (IGroup $subAdminGroup) {
769
-				return $subAdminGroup->getGID();
770
-			}, $subAdminGroups);
771
-			$userGroups = $this->groupManager->getUserGroupIds($targetUser);
772
-			$userSubAdminGroups = array_intersect($subAdminGroups, $userGroups);
773
-
774
-			if (count($userSubAdminGroups) <= 1) {
775
-				// Subadmin must not be able to remove a user from all their subadmin groups.
776
-				throw new OCSException('Not viable to remove user from the last group you are SubAdmin of', 105);
777
-			}
778
-		}
779
-
780
-		// Remove user from group
781
-		$group->removeUser($targetUser);
782
-		return new DataResponse();
783
-	}
784
-
785
-	/**
786
-	 * Creates a subadmin
787
-	 *
788
-	 * @PasswordConfirmationRequired
789
-	 *
790
-	 * @param string $userId
791
-	 * @param string $groupid
792
-	 * @return DataResponse
793
-	 * @throws OCSException
794
-	 */
795
-	public function addSubAdmin(string $userId, string $groupid): DataResponse {
796
-		$group = $this->groupManager->get($groupid);
797
-		$user = $this->userManager->get($userId);
798
-
799
-		// Check if the user exists
800
-		if ($user === null) {
801
-			throw new OCSException('User does not exist', 101);
802
-		}
803
-		// Check if group exists
804
-		if ($group === null) {
805
-			throw new OCSException('Group does not exist',  102);
806
-		}
807
-		// Check if trying to make subadmin of admin group
808
-		if ($group->getGID() === 'admin') {
809
-			throw new OCSException('Cannot create subadmins for admin group', 103);
810
-		}
811
-
812
-		$subAdminManager = $this->groupManager->getSubAdmin();
813
-
814
-		// We cannot be subadmin twice
815
-		if ($subAdminManager->isSubAdminOfGroup($user, $group)) {
816
-			return new DataResponse();
817
-		}
818
-		// Go
819
-		$subAdminManager->createSubAdmin($user, $group);
820
-		return new DataResponse();
821
-	}
822
-
823
-	/**
824
-	 * Removes a subadmin from a group
825
-	 *
826
-	 * @PasswordConfirmationRequired
827
-	 *
828
-	 * @param string $userId
829
-	 * @param string $groupid
830
-	 * @return DataResponse
831
-	 * @throws OCSException
832
-	 */
833
-	public function removeSubAdmin(string $userId, string $groupid): DataResponse {
834
-		$group = $this->groupManager->get($groupid);
835
-		$user = $this->userManager->get($userId);
836
-		$subAdminManager = $this->groupManager->getSubAdmin();
837
-
838
-		// Check if the user exists
839
-		if ($user === null) {
840
-			throw new OCSException('User does not exist', 101);
841
-		}
842
-		// Check if the group exists
843
-		if ($group === null) {
844
-			throw new OCSException('Group does not exist', 101);
845
-		}
846
-		// Check if they are a subadmin of this said group
847
-		if (!$subAdminManager->isSubAdminOfGroup($user, $group)) {
848
-			throw new OCSException('User is not a subadmin of this group', 102);
849
-		}
850
-
851
-		// Go
852
-		$subAdminManager->deleteSubAdmin($user, $group);
853
-		return new DataResponse();
854
-	}
855
-
856
-	/**
857
-	 * Get the groups a user is a subadmin of
858
-	 *
859
-	 * @param string $userId
860
-	 * @return DataResponse
861
-	 * @throws OCSException
862
-	 */
863
-	public function getUserSubAdminGroups(string $userId): DataResponse {
864
-		$groups = $this->getUserSubAdminGroupsData($userId);
865
-		return new DataResponse($groups);
866
-	}
867
-
868
-	/**
869
-	 * @NoAdminRequired
870
-	 * @PasswordConfirmationRequired
871
-	 *
872
-	 * resend welcome message
873
-	 *
874
-	 * @param string $userId
875
-	 * @return DataResponse
876
-	 * @throws OCSException
877
-	 */
878
-	public function resendWelcomeMessage(string $userId): DataResponse {
879
-		$currentLoggedInUser = $this->userSession->getUser();
880
-
881
-		$targetUser = $this->userManager->get($userId);
882
-		if ($targetUser === null) {
883
-			throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
884
-		}
885
-
886
-		// Check if admin / subadmin
887
-		$subAdminManager = $this->groupManager->getSubAdmin();
888
-		if (!$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
889
-			&& !$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
890
-			// No rights
891
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
892
-		}
893
-
894
-		$email = $targetUser->getEMailAddress();
895
-		if ($email === '' || $email === null) {
896
-			throw new OCSException('Email address not available', 101);
897
-		}
898
-
899
-		try {
900
-			$emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false);
901
-			$this->newUserMailHelper->sendMail($targetUser, $emailTemplate);
902
-		} catch(\Exception $e) {
903
-			$this->logger->logException($e, [
904
-				'message' => "Can't send new user mail to $email",
905
-				'level' => ILogger::ERROR,
906
-				'app' => 'settings',
907
-			]);
908
-			throw new OCSException('Sending email failed', 102);
909
-		}
910
-
911
-		return new DataResponse();
912
-	}
57
+    /** @var IAppManager */
58
+    private $appManager;
59
+    /** @var ILogger */
60
+    private $logger;
61
+    /** @var IFactory */
62
+    private $l10nFactory;
63
+    /** @var NewUserMailHelper */
64
+    private $newUserMailHelper;
65
+    /** @var FederatedFileSharingFactory */
66
+    private $federatedFileSharingFactory;
67
+    /** @var ISecureRandom */
68
+    private $secureRandom;
69
+
70
+    /**
71
+     * @param string $appName
72
+     * @param IRequest $request
73
+     * @param IUserManager $userManager
74
+     * @param IConfig $config
75
+     * @param IAppManager $appManager
76
+     * @param IGroupManager $groupManager
77
+     * @param IUserSession $userSession
78
+     * @param AccountManager $accountManager
79
+     * @param ILogger $logger
80
+     * @param IFactory $l10nFactory
81
+     * @param NewUserMailHelper $newUserMailHelper
82
+     * @param FederatedFileSharingFactory $federatedFileSharingFactory
83
+     * @param ISecureRandom $secureRandom
84
+     */
85
+    public function __construct(string $appName,
86
+                                IRequest $request,
87
+                                IUserManager $userManager,
88
+                                IConfig $config,
89
+                                IAppManager $appManager,
90
+                                IGroupManager $groupManager,
91
+                                IUserSession $userSession,
92
+                                AccountManager $accountManager,
93
+                                ILogger $logger,
94
+                                IFactory $l10nFactory,
95
+                                NewUserMailHelper $newUserMailHelper,
96
+                                FederatedFileSharingFactory $federatedFileSharingFactory,
97
+                                ISecureRandom $secureRandom) {
98
+        parent::__construct($appName,
99
+                            $request,
100
+                            $userManager,
101
+                            $config,
102
+                            $groupManager,
103
+                            $userSession,
104
+                            $accountManager);
105
+
106
+        $this->appManager = $appManager;
107
+        $this->logger = $logger;
108
+        $this->l10nFactory = $l10nFactory;
109
+        $this->newUserMailHelper = $newUserMailHelper;
110
+        $this->federatedFileSharingFactory = $federatedFileSharingFactory;
111
+        $this->secureRandom = $secureRandom;
112
+    }
113
+
114
+    /**
115
+     * @NoAdminRequired
116
+     *
117
+     * returns a list of users
118
+     *
119
+     * @param string $search
120
+     * @param int $limit
121
+     * @param int $offset
122
+     * @return DataResponse
123
+     */
124
+    public function getUsers(string $search = '', $limit = null, $offset = 0): DataResponse {
125
+        $user = $this->userSession->getUser();
126
+        $users = [];
127
+
128
+        // Admin? Or SubAdmin?
129
+        $uid = $user->getUID();
130
+        $subAdminManager = $this->groupManager->getSubAdmin();
131
+        if ($this->groupManager->isAdmin($uid)){
132
+            $users = $this->userManager->search($search, $limit, $offset);
133
+        } else if ($subAdminManager->isSubAdmin($user)) {
134
+            $subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
135
+            foreach ($subAdminOfGroups as $key => $group) {
136
+                $subAdminOfGroups[$key] = $group->getGID();
137
+            }
138
+
139
+            $users = [];
140
+            foreach ($subAdminOfGroups as $group) {
141
+                $users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
142
+            }
143
+        }
144
+
145
+        $users = array_keys($users);
146
+
147
+        return new DataResponse([
148
+            'users' => $users
149
+        ]);
150
+    }
151
+
152
+    /**
153
+     * @NoAdminRequired
154
+     *
155
+     * returns a list of users and their data
156
+     */
157
+    public function getUsersDetails(string $search = '', $limit = null, $offset = 0): DataResponse {
158
+        $currentUser = $this->userSession->getUser();
159
+        $users = [];
160
+
161
+        // Admin? Or SubAdmin?
162
+        $uid = $currentUser->getUID();
163
+        $subAdminManager = $this->groupManager->getSubAdmin();
164
+        if ($this->groupManager->isAdmin($uid)){
165
+            $users = $this->userManager->search($search, $limit, $offset);
166
+            $users = array_keys($users);
167
+        } else if ($subAdminManager->isSubAdmin($currentUser)) {
168
+            $subAdminOfGroups = $subAdminManager->getSubAdminsGroups($currentUser);
169
+            foreach ($subAdminOfGroups as $key => $group) {
170
+                $subAdminOfGroups[$key] = $group->getGID();
171
+            }
172
+
173
+            $users = [];
174
+            foreach ($subAdminOfGroups as $group) {
175
+                $users[] = array_keys($this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
176
+            }
177
+            $users = array_merge(...$users);
178
+        }
179
+
180
+        $usersDetails = [];
181
+        foreach ($users as $userId) {
182
+            $userId = (string) $userId;
183
+            $userData = $this->getUserData($userId);
184
+            // Do not insert empty entry
185
+            if (!empty($userData)) {
186
+                $usersDetails[$userId] = $userData;
187
+            } else {
188
+                // Logged user does not have permissions to see this user
189
+                // only showing its id
190
+                $usersDetails[$userId] = ['id' => $userId];
191
+            }
192
+        }
193
+
194
+        return new DataResponse([
195
+            'users' => $usersDetails
196
+        ]);
197
+    }
198
+
199
+    /**
200
+     * @PasswordConfirmationRequired
201
+     * @NoAdminRequired
202
+     *
203
+     * @param string $userid
204
+     * @param string $password
205
+     * @param string $displayName
206
+     * @param string $email
207
+     * @param array $groups
208
+     * @param array $subadmin
209
+     * @param string $quota
210
+     * @param string $language
211
+     * @return DataResponse
212
+     * @throws OCSException
213
+     */
214
+    public function addUser(string $userid,
215
+                            string $password = '',
216
+                            string $displayName = '',
217
+                            string $email = '',
218
+                            array $groups = [],
219
+                            array $subadmin = [],
220
+                            string $quota = '',
221
+                            string $language = ''): DataResponse {
222
+        $user = $this->userSession->getUser();
223
+        $isAdmin = $this->groupManager->isAdmin($user->getUID());
224
+        $subAdminManager = $this->groupManager->getSubAdmin();
225
+
226
+        if ($this->userManager->userExists($userid)) {
227
+            $this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
228
+            throw new OCSException('User already exists', 102);
229
+        }
230
+
231
+        if ($groups !== []) {
232
+            foreach ($groups as $group) {
233
+                if (!$this->groupManager->groupExists($group)) {
234
+                    throw new OCSException('group '.$group.' does not exist', 104);
235
+                }
236
+                if (!$isAdmin && !$subAdminManager->isSubAdminOfGroup($user, $this->groupManager->get($group))) {
237
+                    throw new OCSException('insufficient privileges for group '. $group, 105);
238
+                }
239
+            }
240
+        } else {
241
+            if (!$isAdmin) {
242
+                throw new OCSException('no group specified (required for subadmins)', 106);
243
+            }
244
+        }
245
+
246
+        $subadminGroups = [];
247
+        if ($subadmin !== []) {
248
+            foreach ($subadmin as $groupid) {
249
+                $group = $this->groupManager->get($groupid);
250
+                // Check if group exists
251
+                if ($group === null) {
252
+                    throw new OCSException('Subadmin group does not exist',  102);
253
+                }
254
+                // Check if trying to make subadmin of admin group
255
+                if ($group->getGID() === 'admin') {
256
+                    throw new OCSException('Cannot create subadmins for admin group', 103);
257
+                }
258
+                // Check if has permission to promote subadmins
259
+                if (!$subAdminManager->isSubAdminOfGroup($user, $group) && !$isAdmin) {
260
+                    throw new OCSForbiddenException('No permissions to promote subadmins');
261
+                }
262
+                $subadminGroups[] = $group;
263
+            }
264
+        }
265
+
266
+        $generatePasswordResetToken = false;
267
+        if ($password === '') {
268
+            if ($email === '') {
269
+                throw new OCSException('To send a password link to the user an email address is required.', 108);
270
+            }
271
+
272
+            $password = $this->secureRandom->generate(10);
273
+            // Make sure we pass the password_policy
274
+            $password .= $this->secureRandom->generate(2, '$!.,;:-~+*[]{}()');
275
+            $generatePasswordResetToken = true;
276
+        }
277
+
278
+        try {
279
+            $newUser = $this->userManager->createUser($userid, $password);
280
+            $this->logger->info('Successful addUser call with userid: ' . $userid, ['app' => 'ocs_api']);
281
+
282
+            foreach ($groups as $group) {
283
+                $this->groupManager->get($group)->addUser($newUser);
284
+                $this->logger->info('Added userid ' . $userid . ' to group ' . $group, ['app' => 'ocs_api']);
285
+            }
286
+            foreach ($subadminGroups as $group) {
287
+                $subAdminManager->createSubAdmin($newUser, $group);
288
+            }
289
+
290
+            if ($displayName !== '') {
291
+                $this->editUser($userid, 'display', $displayName);
292
+            }
293
+
294
+            if ($quota !== '') {
295
+                $this->editUser($userid, 'quota', $quota);
296
+            }
297
+
298
+            if ($language !== '') {
299
+                $this->editUser($userid, 'language', $language);
300
+            }
301
+
302
+            // Send new user mail only if a mail is set
303
+            if ($email !== '') {
304
+                $newUser->setEMailAddress($email);
305
+                try {
306
+                    $emailTemplate = $this->newUserMailHelper->generateTemplate($newUser, $generatePasswordResetToken);
307
+                    $this->newUserMailHelper->sendMail($newUser, $emailTemplate);
308
+                } catch (\Exception $e) {
309
+                    $this->logger->logException($e, [
310
+                        'message' => "Can't send new user mail to $email",
311
+                        'level' => ILogger::ERROR,
312
+                        'app' => 'ocs_api',
313
+                    ]);
314
+                    throw new OCSException('Unable to send the invitation mail', 109);
315
+                }
316
+            }
317
+
318
+            return new DataResponse();
319
+
320
+        } catch (HintException $e ) {
321
+            $this->logger->logException($e, [
322
+                'message' => 'Failed addUser attempt with hint exception.',
323
+                'level' => ILogger::WARN,
324
+                'app' => 'ocs_api',
325
+            ]);
326
+            throw new OCSException($e->getHint(), 107);
327
+        } catch (\Exception $e) {
328
+            $this->logger->logException($e, [
329
+                'message' => 'Failed addUser attempt with exception.',
330
+                'level' => ILogger::ERROR,
331
+                'app' => 'ocs_api',
332
+            ]);
333
+            throw new OCSException('Bad request', 101);
334
+        }
335
+    }
336
+
337
+    /**
338
+     * @NoAdminRequired
339
+     * @NoSubAdminRequired
340
+     *
341
+     * gets user info
342
+     *
343
+     * @param string $userId
344
+     * @return DataResponse
345
+     * @throws OCSException
346
+     */
347
+    public function getUser(string $userId): DataResponse {
348
+        $data = $this->getUserData($userId);
349
+        // getUserData returns empty array if not enough permissions
350
+        if (empty($data)) {
351
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
352
+        }
353
+        return new DataResponse($data);
354
+    }
355
+
356
+    /**
357
+     * @NoAdminRequired
358
+     * @NoSubAdminRequired
359
+     *
360
+     * gets user info from the currently logged in user
361
+     *
362
+     * @return DataResponse
363
+     * @throws OCSException
364
+     */
365
+    public function getCurrentUser(): DataResponse {
366
+        $user = $this->userSession->getUser();
367
+        if ($user) {
368
+            $data =  $this->getUserData($user->getUID());
369
+            // rename "displayname" to "display-name" only for this call to keep
370
+            // the API stable.
371
+            $data['display-name'] = $data['displayname'];
372
+            unset($data['displayname']);
373
+            return new DataResponse($data);
374
+
375
+        }
376
+
377
+        throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
378
+    }
379
+
380
+    /**
381
+     * @NoAdminRequired
382
+     * @NoSubAdminRequired
383
+     */
384
+    public function getEditableFields(): DataResponse {
385
+        $permittedFields = [];
386
+
387
+        // Editing self (display, email)
388
+        if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
389
+            $permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
390
+            $permittedFields[] = AccountManager::PROPERTY_EMAIL;
391
+        }
392
+
393
+        if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
394
+            $federatedFileSharing = $this->federatedFileSharingFactory->get();
395
+            $shareProvider = $federatedFileSharing->getFederatedShareProvider();
396
+            if ($shareProvider->isLookupServerUploadEnabled()) {
397
+                $permittedFields[] = AccountManager::PROPERTY_PHONE;
398
+                $permittedFields[] = AccountManager::PROPERTY_ADDRESS;
399
+                $permittedFields[] = AccountManager::PROPERTY_WEBSITE;
400
+                $permittedFields[] = AccountManager::PROPERTY_TWITTER;
401
+            }
402
+        }
403
+
404
+        return new DataResponse($permittedFields);
405
+    }
406
+
407
+    /**
408
+     * @NoAdminRequired
409
+     * @NoSubAdminRequired
410
+     * @PasswordConfirmationRequired
411
+     *
412
+     * edit users
413
+     *
414
+     * @param string $userId
415
+     * @param string $key
416
+     * @param string $value
417
+     * @return DataResponse
418
+     * @throws OCSException
419
+     */
420
+    public function editUser(string $userId, string $key, string $value): DataResponse {
421
+        $currentLoggedInUser = $this->userSession->getUser();
422
+
423
+        $targetUser = $this->userManager->get($userId);
424
+        if ($targetUser === null) {
425
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
426
+        }
427
+
428
+        $permittedFields = [];
429
+        if ($targetUser->getUID() === $currentLoggedInUser->getUID()) {
430
+            // Editing self (display, email)
431
+            if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
432
+                $permittedFields[] = 'display';
433
+                $permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
434
+                $permittedFields[] = AccountManager::PROPERTY_EMAIL;
435
+            }
436
+
437
+            $permittedFields[] = 'password';
438
+            if ($this->config->getSystemValue('force_language', false) === false ||
439
+                $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
440
+                $permittedFields[] = 'language';
441
+            }
442
+
443
+            if ($this->config->getSystemValue('force_locale', false) === false ||
444
+                $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
445
+                $permittedFields[] = 'locale';
446
+            }
447
+
448
+            if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
449
+                $federatedFileSharing = new \OCA\FederatedFileSharing\AppInfo\Application();
450
+                $shareProvider = $federatedFileSharing->getFederatedShareProvider();
451
+                if ($shareProvider->isLookupServerUploadEnabled()) {
452
+                    $permittedFields[] = AccountManager::PROPERTY_PHONE;
453
+                    $permittedFields[] = AccountManager::PROPERTY_ADDRESS;
454
+                    $permittedFields[] = AccountManager::PROPERTY_WEBSITE;
455
+                    $permittedFields[] = AccountManager::PROPERTY_TWITTER;
456
+                }
457
+            }
458
+
459
+            // If admin they can edit their own quota
460
+            if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
461
+                $permittedFields[] = 'quota';
462
+            }
463
+        } else {
464
+            // Check if admin / subadmin
465
+            $subAdminManager = $this->groupManager->getSubAdmin();
466
+            if ($subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
467
+            || $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
468
+                // They have permissions over the user
469
+                $permittedFields[] = 'display';
470
+                $permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
471
+                $permittedFields[] = AccountManager::PROPERTY_EMAIL;
472
+                $permittedFields[] = 'password';
473
+                $permittedFields[] = 'language';
474
+                $permittedFields[] = 'locale';
475
+                $permittedFields[] = AccountManager::PROPERTY_PHONE;
476
+                $permittedFields[] = AccountManager::PROPERTY_ADDRESS;
477
+                $permittedFields[] = AccountManager::PROPERTY_WEBSITE;
478
+                $permittedFields[] = AccountManager::PROPERTY_TWITTER;
479
+                $permittedFields[] = 'quota';
480
+            } else {
481
+                // No rights
482
+                throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
483
+            }
484
+        }
485
+        // Check if permitted to edit this field
486
+        if (!in_array($key, $permittedFields)) {
487
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
488
+        }
489
+        // Process the edit
490
+        switch($key) {
491
+            case 'display':
492
+            case AccountManager::PROPERTY_DISPLAYNAME:
493
+                $targetUser->setDisplayName($value);
494
+                break;
495
+            case 'quota':
496
+                $quota = $value;
497
+                if ($quota !== 'none' && $quota !== 'default') {
498
+                    if (is_numeric($quota)) {
499
+                        $quota = (float) $quota;
500
+                    } else {
501
+                        $quota = \OCP\Util::computerFileSize($quota);
502
+                    }
503
+                    if ($quota === false) {
504
+                        throw new OCSException('Invalid quota value '.$value, 103);
505
+                    }
506
+                    if ($quota === -1) {
507
+                        $quota = 'none';
508
+                    } else {
509
+                        $quota = \OCP\Util::humanFileSize($quota);
510
+                    }
511
+                }
512
+                $targetUser->setQuota($quota);
513
+                break;
514
+            case 'password':
515
+                try {
516
+                    if (!$targetUser->canChangePassword()) {
517
+                        throw new OCSException('Setting the password is not supported by the users backend', 103);
518
+                    }
519
+                    $targetUser->setPassword($value);
520
+                } catch (HintException $e) { // password policy error
521
+                    throw new OCSException($e->getMessage(), 103);
522
+                }
523
+                break;
524
+            case 'language':
525
+                $languagesCodes = $this->l10nFactory->findAvailableLanguages();
526
+                if (!in_array($value, $languagesCodes, true) && $value !== 'en') {
527
+                    throw new OCSException('Invalid language', 102);
528
+                }
529
+                $this->config->setUserValue($targetUser->getUID(), 'core', 'lang', $value);
530
+                break;
531
+            case 'locale':
532
+                if (!$this->l10nFactory->localeExists($value)) {
533
+                    throw new OCSException('Invalid locale', 102);
534
+                }
535
+                $this->config->setUserValue($targetUser->getUID(), 'core', 'locale', $value);
536
+                break;
537
+            case AccountManager::PROPERTY_EMAIL:
538
+                if (filter_var($value, FILTER_VALIDATE_EMAIL) || $value === '') {
539
+                    $targetUser->setEMailAddress($value);
540
+                } else {
541
+                    throw new OCSException('', 102);
542
+                }
543
+                break;
544
+            case AccountManager::PROPERTY_PHONE:
545
+            case AccountManager::PROPERTY_ADDRESS:
546
+            case AccountManager::PROPERTY_WEBSITE:
547
+            case AccountManager::PROPERTY_TWITTER:
548
+                $userAccount = $this->accountManager->getUser($targetUser);
549
+                if ($userAccount[$key]['value'] !== $value) {
550
+                    $userAccount[$key]['value'] = $value;
551
+                    $this->accountManager->updateUser($targetUser, $userAccount);
552
+                }
553
+                break;
554
+            default:
555
+                throw new OCSException('', 103);
556
+        }
557
+        return new DataResponse();
558
+    }
559
+
560
+    /**
561
+     * @PasswordConfirmationRequired
562
+     * @NoAdminRequired
563
+     *
564
+     * @param string $userId
565
+     * @return DataResponse
566
+     * @throws OCSException
567
+     */
568
+    public function deleteUser(string $userId): DataResponse {
569
+        $currentLoggedInUser = $this->userSession->getUser();
570
+
571
+        $targetUser = $this->userManager->get($userId);
572
+
573
+        if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
574
+            throw new OCSException('', 101);
575
+        }
576
+
577
+        // If not permitted
578
+        $subAdminManager = $this->groupManager->getSubAdmin();
579
+        if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
580
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
581
+        }
582
+
583
+        // Go ahead with the delete
584
+        if ($targetUser->delete()) {
585
+            return new DataResponse();
586
+        } else {
587
+            throw new OCSException('', 101);
588
+        }
589
+    }
590
+
591
+    /**
592
+     * @PasswordConfirmationRequired
593
+     * @NoAdminRequired
594
+     *
595
+     * @param string $userId
596
+     * @return DataResponse
597
+     * @throws OCSException
598
+     * @throws OCSForbiddenException
599
+     */
600
+    public function disableUser(string $userId): DataResponse {
601
+        return $this->setEnabled($userId, false);
602
+    }
603
+
604
+    /**
605
+     * @PasswordConfirmationRequired
606
+     * @NoAdminRequired
607
+     *
608
+     * @param string $userId
609
+     * @return DataResponse
610
+     * @throws OCSException
611
+     * @throws OCSForbiddenException
612
+     */
613
+    public function enableUser(string $userId): DataResponse {
614
+        return $this->setEnabled($userId, true);
615
+    }
616
+
617
+    /**
618
+     * @param string $userId
619
+     * @param bool $value
620
+     * @return DataResponse
621
+     * @throws OCSException
622
+     */
623
+    private function setEnabled(string $userId, bool $value): DataResponse {
624
+        $currentLoggedInUser = $this->userSession->getUser();
625
+
626
+        $targetUser = $this->userManager->get($userId);
627
+        if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
628
+            throw new OCSException('', 101);
629
+        }
630
+
631
+        // If not permitted
632
+        $subAdminManager = $this->groupManager->getSubAdmin();
633
+        if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
634
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
635
+        }
636
+
637
+        // enable/disable the user now
638
+        $targetUser->setEnabled($value);
639
+        return new DataResponse();
640
+    }
641
+
642
+    /**
643
+     * @NoAdminRequired
644
+     * @NoSubAdminRequired
645
+     *
646
+     * @param string $userId
647
+     * @return DataResponse
648
+     * @throws OCSException
649
+     */
650
+    public function getUsersGroups(string $userId): DataResponse {
651
+        $loggedInUser = $this->userSession->getUser();
652
+
653
+        $targetUser = $this->userManager->get($userId);
654
+        if ($targetUser === null) {
655
+            throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
656
+        }
657
+
658
+        if ($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
659
+            // Self lookup or admin lookup
660
+            return new DataResponse([
661
+                'groups' => $this->groupManager->getUserGroupIds($targetUser)
662
+            ]);
663
+        } else {
664
+            $subAdminManager = $this->groupManager->getSubAdmin();
665
+
666
+            // Looking up someone else
667
+            if ($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
668
+                // Return the group that the method caller is subadmin of for the user in question
669
+                /** @var IGroup[] $getSubAdminsGroups */
670
+                $getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
671
+                foreach ($getSubAdminsGroups as $key => $group) {
672
+                    $getSubAdminsGroups[$key] = $group->getGID();
673
+                }
674
+                $groups = array_intersect(
675
+                    $getSubAdminsGroups,
676
+                    $this->groupManager->getUserGroupIds($targetUser)
677
+                );
678
+                return new DataResponse(['groups' => $groups]);
679
+            } else {
680
+                // Not permitted
681
+                throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
682
+            }
683
+        }
684
+
685
+    }
686
+
687
+    /**
688
+     * @PasswordConfirmationRequired
689
+     * @NoAdminRequired
690
+     *
691
+     * @param string $userId
692
+     * @param string $groupid
693
+     * @return DataResponse
694
+     * @throws OCSException
695
+     */
696
+    public function addToGroup(string $userId, string $groupid = ''): DataResponse {
697
+        if ($groupid === '') {
698
+            throw new OCSException('', 101);
699
+        }
700
+
701
+        $group = $this->groupManager->get($groupid);
702
+        $targetUser = $this->userManager->get($userId);
703
+        if ($group === null) {
704
+            throw new OCSException('', 102);
705
+        }
706
+        if ($targetUser === null) {
707
+            throw new OCSException('', 103);
708
+        }
709
+
710
+        // If they're not an admin, check they are a subadmin of the group in question
711
+        $loggedInUser = $this->userSession->getUser();
712
+        $subAdminManager = $this->groupManager->getSubAdmin();
713
+        if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
714
+            throw new OCSException('', 104);
715
+        }
716
+
717
+        // Add user to group
718
+        $group->addUser($targetUser);
719
+        return new DataResponse();
720
+    }
721
+
722
+    /**
723
+     * @PasswordConfirmationRequired
724
+     * @NoAdminRequired
725
+     *
726
+     * @param string $userId
727
+     * @param string $groupid
728
+     * @return DataResponse
729
+     * @throws OCSException
730
+     */
731
+    public function removeFromGroup(string $userId, string $groupid): DataResponse {
732
+        $loggedInUser = $this->userSession->getUser();
733
+
734
+        if ($groupid === null || trim($groupid) === '') {
735
+            throw new OCSException('', 101);
736
+        }
737
+
738
+        $group = $this->groupManager->get($groupid);
739
+        if ($group === null) {
740
+            throw new OCSException('', 102);
741
+        }
742
+
743
+        $targetUser = $this->userManager->get($userId);
744
+        if ($targetUser === null) {
745
+            throw new OCSException('', 103);
746
+        }
747
+
748
+        // If they're not an admin, check they are a subadmin of the group in question
749
+        $subAdminManager = $this->groupManager->getSubAdmin();
750
+        if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
751
+            throw new OCSException('', 104);
752
+        }
753
+
754
+        // Check they aren't removing themselves from 'admin' or their 'subadmin; group
755
+        if ($targetUser->getUID() === $loggedInUser->getUID()) {
756
+            if ($this->groupManager->isAdmin($loggedInUser->getUID())) {
757
+                if ($group->getGID() === 'admin') {
758
+                    throw new OCSException('Cannot remove yourself from the admin group', 105);
759
+                }
760
+            } else {
761
+                // Not an admin, so the user must be a subadmin of this group, but that is not allowed.
762
+                throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105);
763
+            }
764
+
765
+        } else if (!$this->groupManager->isAdmin($loggedInUser->getUID())) {
766
+            /** @var IGroup[] $subAdminGroups */
767
+            $subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
768
+            $subAdminGroups = array_map(function (IGroup $subAdminGroup) {
769
+                return $subAdminGroup->getGID();
770
+            }, $subAdminGroups);
771
+            $userGroups = $this->groupManager->getUserGroupIds($targetUser);
772
+            $userSubAdminGroups = array_intersect($subAdminGroups, $userGroups);
773
+
774
+            if (count($userSubAdminGroups) <= 1) {
775
+                // Subadmin must not be able to remove a user from all their subadmin groups.
776
+                throw new OCSException('Not viable to remove user from the last group you are SubAdmin of', 105);
777
+            }
778
+        }
779
+
780
+        // Remove user from group
781
+        $group->removeUser($targetUser);
782
+        return new DataResponse();
783
+    }
784
+
785
+    /**
786
+     * Creates a subadmin
787
+     *
788
+     * @PasswordConfirmationRequired
789
+     *
790
+     * @param string $userId
791
+     * @param string $groupid
792
+     * @return DataResponse
793
+     * @throws OCSException
794
+     */
795
+    public function addSubAdmin(string $userId, string $groupid): DataResponse {
796
+        $group = $this->groupManager->get($groupid);
797
+        $user = $this->userManager->get($userId);
798
+
799
+        // Check if the user exists
800
+        if ($user === null) {
801
+            throw new OCSException('User does not exist', 101);
802
+        }
803
+        // Check if group exists
804
+        if ($group === null) {
805
+            throw new OCSException('Group does not exist',  102);
806
+        }
807
+        // Check if trying to make subadmin of admin group
808
+        if ($group->getGID() === 'admin') {
809
+            throw new OCSException('Cannot create subadmins for admin group', 103);
810
+        }
811
+
812
+        $subAdminManager = $this->groupManager->getSubAdmin();
813
+
814
+        // We cannot be subadmin twice
815
+        if ($subAdminManager->isSubAdminOfGroup($user, $group)) {
816
+            return new DataResponse();
817
+        }
818
+        // Go
819
+        $subAdminManager->createSubAdmin($user, $group);
820
+        return new DataResponse();
821
+    }
822
+
823
+    /**
824
+     * Removes a subadmin from a group
825
+     *
826
+     * @PasswordConfirmationRequired
827
+     *
828
+     * @param string $userId
829
+     * @param string $groupid
830
+     * @return DataResponse
831
+     * @throws OCSException
832
+     */
833
+    public function removeSubAdmin(string $userId, string $groupid): DataResponse {
834
+        $group = $this->groupManager->get($groupid);
835
+        $user = $this->userManager->get($userId);
836
+        $subAdminManager = $this->groupManager->getSubAdmin();
837
+
838
+        // Check if the user exists
839
+        if ($user === null) {
840
+            throw new OCSException('User does not exist', 101);
841
+        }
842
+        // Check if the group exists
843
+        if ($group === null) {
844
+            throw new OCSException('Group does not exist', 101);
845
+        }
846
+        // Check if they are a subadmin of this said group
847
+        if (!$subAdminManager->isSubAdminOfGroup($user, $group)) {
848
+            throw new OCSException('User is not a subadmin of this group', 102);
849
+        }
850
+
851
+        // Go
852
+        $subAdminManager->deleteSubAdmin($user, $group);
853
+        return new DataResponse();
854
+    }
855
+
856
+    /**
857
+     * Get the groups a user is a subadmin of
858
+     *
859
+     * @param string $userId
860
+     * @return DataResponse
861
+     * @throws OCSException
862
+     */
863
+    public function getUserSubAdminGroups(string $userId): DataResponse {
864
+        $groups = $this->getUserSubAdminGroupsData($userId);
865
+        return new DataResponse($groups);
866
+    }
867
+
868
+    /**
869
+     * @NoAdminRequired
870
+     * @PasswordConfirmationRequired
871
+     *
872
+     * resend welcome message
873
+     *
874
+     * @param string $userId
875
+     * @return DataResponse
876
+     * @throws OCSException
877
+     */
878
+    public function resendWelcomeMessage(string $userId): DataResponse {
879
+        $currentLoggedInUser = $this->userSession->getUser();
880
+
881
+        $targetUser = $this->userManager->get($userId);
882
+        if ($targetUser === null) {
883
+            throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
884
+        }
885
+
886
+        // Check if admin / subadmin
887
+        $subAdminManager = $this->groupManager->getSubAdmin();
888
+        if (!$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
889
+            && !$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
890
+            // No rights
891
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
892
+        }
893
+
894
+        $email = $targetUser->getEMailAddress();
895
+        if ($email === '' || $email === null) {
896
+            throw new OCSException('Email address not available', 101);
897
+        }
898
+
899
+        try {
900
+            $emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false);
901
+            $this->newUserMailHelper->sendMail($targetUser, $emailTemplate);
902
+        } catch(\Exception $e) {
903
+            $this->logger->logException($e, [
904
+                'message' => "Can't send new user mail to $email",
905
+                'level' => ILogger::ERROR,
906
+                'app' => 'settings',
907
+            ]);
908
+            throw new OCSException('Sending email failed', 102);
909
+        }
910
+
911
+        return new DataResponse();
912
+    }
913 913
 }
Please login to merge, or discard this patch.