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