Passed
Push — master ( a58b4c...5325c3 )
by Roeland
13:16 queued 10s
created
apps/provisioning_api/lib/Middleware/ProvisioningApiMiddleware.php 1 patch
Indentation   +45 added lines, -45 removed lines patch added patch discarded remove patch
@@ -38,55 +38,55 @@
 block discarded – undo
38 38
 
39 39
 class ProvisioningApiMiddleware extends Middleware {
40 40
 
41
-	/** @var IControllerMethodReflector */
42
-	private $reflector;
41
+    /** @var IControllerMethodReflector */
42
+    private $reflector;
43 43
 
44
-	/** @var bool */
45
-	private $isAdmin;
44
+    /** @var bool */
45
+    private $isAdmin;
46 46
 
47
-	/** @var bool */
48
-	private $isSubAdmin;
47
+    /** @var bool */
48
+    private $isSubAdmin;
49 49
 
50
-	/**
51
-	 * ProvisioningApiMiddleware constructor.
52
-	 *
53
-	 * @param IControllerMethodReflector $reflector
54
-	 * @param bool $isAdmin
55
-	 * @param bool $isSubAdmin
56
-	 */
57
-	public function __construct(
58
-		IControllerMethodReflector $reflector,
59
-		bool $isAdmin,
60
-		bool $isSubAdmin) {
61
-		$this->reflector = $reflector;
62
-		$this->isAdmin = $isAdmin;
63
-		$this->isSubAdmin = $isSubAdmin;
64
-	}
50
+    /**
51
+     * ProvisioningApiMiddleware constructor.
52
+     *
53
+     * @param IControllerMethodReflector $reflector
54
+     * @param bool $isAdmin
55
+     * @param bool $isSubAdmin
56
+     */
57
+    public function __construct(
58
+        IControllerMethodReflector $reflector,
59
+        bool $isAdmin,
60
+        bool $isSubAdmin) {
61
+        $this->reflector = $reflector;
62
+        $this->isAdmin = $isAdmin;
63
+        $this->isSubAdmin = $isSubAdmin;
64
+    }
65 65
 
66
-	/**
67
-	 * @param Controller $controller
68
-	 * @param string $methodName
69
-	 *
70
-	 * @throws NotSubAdminException
71
-	 */
72
-	public function beforeController($controller, $methodName) {
73
-		if (!$this->isAdmin && !$this->reflector->hasAnnotation('NoSubAdminRequired') && !$this->isSubAdmin) {
74
-			throw new NotSubAdminException();
75
-		}
76
-	}
66
+    /**
67
+     * @param Controller $controller
68
+     * @param string $methodName
69
+     *
70
+     * @throws NotSubAdminException
71
+     */
72
+    public function beforeController($controller, $methodName) {
73
+        if (!$this->isAdmin && !$this->reflector->hasAnnotation('NoSubAdminRequired') && !$this->isSubAdmin) {
74
+            throw new NotSubAdminException();
75
+        }
76
+    }
77 77
 
78
-	/**
79
-	 * @param Controller $controller
80
-	 * @param string $methodName
81
-	 * @param \Exception $exception
82
-	 * @throws \Exception
83
-	 * @return Response
84
-	 */
85
-	public function afterException($controller, $methodName, \Exception $exception) {
86
-		if ($exception instanceof NotSubAdminException) {
87
-			throw new OCSException($exception->getMessage(), OCSController::RESPOND_UNAUTHORISED);
88
-		}
78
+    /**
79
+     * @param Controller $controller
80
+     * @param string $methodName
81
+     * @param \Exception $exception
82
+     * @throws \Exception
83
+     * @return Response
84
+     */
85
+    public function afterException($controller, $methodName, \Exception $exception) {
86
+        if ($exception instanceof NotSubAdminException) {
87
+            throw new OCSException($exception->getMessage(), OCSController::RESPOND_UNAUTHORISED);
88
+        }
89 89
 
90
-		throw $exception;
91
-	}
90
+        throw $exception;
91
+    }
92 92
 }
Please login to merge, or discard this patch.
apps/provisioning_api/lib/Controller/UsersController.php 1 patch
Indentation   +989 added lines, -989 removed lines patch added patch discarded remove patch
@@ -74,993 +74,993 @@
 block discarded – undo
74 74
 
75 75
 class UsersController extends AUserData {
76 76
 
77
-	/** @var IAppManager */
78
-	private $appManager;
79
-	/** @var IURLGenerator */
80
-	protected $urlGenerator;
81
-	/** @var LoggerInterface */
82
-	private $logger;
83
-	/** @var IFactory */
84
-	protected $l10nFactory;
85
-	/** @var NewUserMailHelper */
86
-	private $newUserMailHelper;
87
-	/** @var FederatedShareProviderFactory */
88
-	private $federatedShareProviderFactory;
89
-	/** @var ISecureRandom */
90
-	private $secureRandom;
91
-	/** @var RemoteWipe */
92
-	private $remoteWipe;
93
-	/** @var IEventDispatcher */
94
-	private $eventDispatcher;
95
-
96
-	public function __construct(string $appName,
97
-								IRequest $request,
98
-								IUserManager $userManager,
99
-								IConfig $config,
100
-								IAppManager $appManager,
101
-								IGroupManager $groupManager,
102
-								IUserSession $userSession,
103
-								AccountManager $accountManager,
104
-								IURLGenerator $urlGenerator,
105
-								LoggerInterface $logger,
106
-								IFactory $l10nFactory,
107
-								NewUserMailHelper $newUserMailHelper,
108
-								FederatedShareProviderFactory $federatedShareProviderFactory,
109
-								ISecureRandom $secureRandom,
110
-								RemoteWipe $remoteWipe,
111
-								IEventDispatcher $eventDispatcher) {
112
-		parent::__construct($appName,
113
-							$request,
114
-							$userManager,
115
-							$config,
116
-							$groupManager,
117
-							$userSession,
118
-							$accountManager,
119
-							$l10nFactory);
120
-
121
-		$this->appManager = $appManager;
122
-		$this->urlGenerator = $urlGenerator;
123
-		$this->logger = $logger;
124
-		$this->l10nFactory = $l10nFactory;
125
-		$this->newUserMailHelper = $newUserMailHelper;
126
-		$this->federatedShareProviderFactory = $federatedShareProviderFactory;
127
-		$this->secureRandom = $secureRandom;
128
-		$this->remoteWipe = $remoteWipe;
129
-		$this->eventDispatcher = $eventDispatcher;
130
-	}
131
-
132
-	/**
133
-	 * @NoAdminRequired
134
-	 *
135
-	 * returns a list of users
136
-	 *
137
-	 * @param string $search
138
-	 * @param int $limit
139
-	 * @param int $offset
140
-	 * @return DataResponse
141
-	 */
142
-	public function getUsers(string $search = '', int $limit = null, int $offset = 0): DataResponse {
143
-		$user = $this->userSession->getUser();
144
-		$users = [];
145
-
146
-		// Admin? Or SubAdmin?
147
-		$uid = $user->getUID();
148
-		$subAdminManager = $this->groupManager->getSubAdmin();
149
-		if ($this->groupManager->isAdmin($uid)) {
150
-			$users = $this->userManager->search($search, $limit, $offset);
151
-		} elseif ($subAdminManager->isSubAdmin($user)) {
152
-			$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
153
-			foreach ($subAdminOfGroups as $key => $group) {
154
-				$subAdminOfGroups[$key] = $group->getGID();
155
-			}
156
-
157
-			$users = [];
158
-			foreach ($subAdminOfGroups as $group) {
159
-				$users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
160
-			}
161
-		}
162
-
163
-		$users = array_keys($users);
164
-
165
-		return new DataResponse([
166
-			'users' => $users
167
-		]);
168
-	}
169
-
170
-	/**
171
-	 * @NoAdminRequired
172
-	 *
173
-	 * returns a list of users and their data
174
-	 */
175
-	public function getUsersDetails(string $search = '', int $limit = null, int $offset = 0): DataResponse {
176
-		$currentUser = $this->userSession->getUser();
177
-		$users = [];
178
-
179
-		// Admin? Or SubAdmin?
180
-		$uid = $currentUser->getUID();
181
-		$subAdminManager = $this->groupManager->getSubAdmin();
182
-		if ($this->groupManager->isAdmin($uid)) {
183
-			$users = $this->userManager->search($search, $limit, $offset);
184
-			$users = array_keys($users);
185
-		} elseif ($subAdminManager->isSubAdmin($currentUser)) {
186
-			$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($currentUser);
187
-			foreach ($subAdminOfGroups as $key => $group) {
188
-				$subAdminOfGroups[$key] = $group->getGID();
189
-			}
190
-
191
-			$users = [];
192
-			foreach ($subAdminOfGroups as $group) {
193
-				$users[] = array_keys($this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
194
-			}
195
-			$users = array_merge(...$users);
196
-		}
197
-
198
-		$usersDetails = [];
199
-		foreach ($users as $userId) {
200
-			$userId = (string) $userId;
201
-			$userData = $this->getUserData($userId);
202
-			// Do not insert empty entry
203
-			if (!empty($userData)) {
204
-				$usersDetails[$userId] = $userData;
205
-			} else {
206
-				// Logged user does not have permissions to see this user
207
-				// only showing its id
208
-				$usersDetails[$userId] = ['id' => $userId];
209
-			}
210
-		}
211
-
212
-		return new DataResponse([
213
-			'users' => $usersDetails
214
-		]);
215
-	}
216
-
217
-
218
-	/**
219
-	 * @NoAdminRequired
220
-	 * @NoSubAdminRequired
221
-	 *
222
-	 * @param string $location
223
-	 * @param array $search
224
-	 * @return DataResponse
225
-	 */
226
-	public function searchByPhoneNumbers(string $location, array $search): DataResponse {
227
-		$phoneUtil = PhoneNumberUtil::getInstance();
228
-
229
-		if ($phoneUtil->getCountryCodeForRegion($location) === 0) {
230
-			// Not a valid region code
231
-			return new DataResponse([], Http::STATUS_BAD_REQUEST);
232
-		}
233
-
234
-		$normalizedNumberToKey = [];
235
-		foreach ($search as $key => $phoneNumbers) {
236
-			foreach ($phoneNumbers as $phone) {
237
-				try {
238
-					$phoneNumber = $phoneUtil->parse($phone, $location);
239
-					if ($phoneNumber instanceof PhoneNumber && $phoneUtil->isValidNumber($phoneNumber)) {
240
-						$normalizedNumber = $phoneUtil->format($phoneNumber, PhoneNumberFormat::E164);
241
-						$normalizedNumberToKey[$normalizedNumber] = (string) $key;
242
-					}
243
-				} catch (NumberParseException $e) {
244
-				}
245
-			}
246
-		}
247
-
248
-		$phoneNumbers = array_keys($normalizedNumberToKey);
249
-
250
-		if (empty($phoneNumbers)) {
251
-			return new DataResponse();
252
-		}
253
-
254
-		$userMatches = $this->accountManager->searchUsers(IAccountManager::PROPERTY_PHONE, $phoneNumbers);
255
-
256
-		if (empty($userMatches)) {
257
-			return new DataResponse();
258
-		}
259
-
260
-		$cloudUrl = rtrim($this->urlGenerator->getAbsoluteURL('/'), '/');
261
-		if (strpos($cloudUrl, 'http://') === 0) {
262
-			$cloudUrl = substr($cloudUrl, strlen('http://'));
263
-		} elseif (strpos($cloudUrl, 'https://') === 0) {
264
-			$cloudUrl = substr($cloudUrl, strlen('https://'));
265
-		}
266
-
267
-		$matches = [];
268
-		foreach ($userMatches as $phone => $userId) {
269
-			// Not using the ICloudIdManager as that would run a search for each contact to find the display name in the address book
270
-			$matches[$normalizedNumberToKey[$phone]] = $userId . '@' . $cloudUrl;
271
-		}
272
-
273
-		return new DataResponse($matches);
274
-	}
275
-
276
-	/**
277
-	 * @throws OCSException
278
-	 */
279
-	private function createNewUserId(): string {
280
-		$attempts = 0;
281
-		do {
282
-			$uidCandidate = $this->secureRandom->generate(10, ISecureRandom::CHAR_HUMAN_READABLE);
283
-			if (!$this->userManager->userExists($uidCandidate)) {
284
-				return $uidCandidate;
285
-			}
286
-			$attempts++;
287
-		} while ($attempts < 10);
288
-		throw new OCSException('Could not create non-existing user id', 111);
289
-	}
290
-
291
-	/**
292
-	 * @PasswordConfirmationRequired
293
-	 * @NoAdminRequired
294
-	 *
295
-	 * @param string $userid
296
-	 * @param string $password
297
-	 * @param string $displayName
298
-	 * @param string $email
299
-	 * @param array $groups
300
-	 * @param array $subadmin
301
-	 * @param string $quota
302
-	 * @param string $language
303
-	 * @return DataResponse
304
-	 * @throws OCSException
305
-	 */
306
-	public function addUser(string $userid,
307
-							string $password = '',
308
-							string $displayName = '',
309
-							string $email = '',
310
-							array $groups = [],
311
-							array $subadmin = [],
312
-							string $quota = '',
313
-							string $language = ''): DataResponse {
314
-		$user = $this->userSession->getUser();
315
-		$isAdmin = $this->groupManager->isAdmin($user->getUID());
316
-		$subAdminManager = $this->groupManager->getSubAdmin();
317
-
318
-		if (empty($userid) && $this->config->getAppValue('core', 'newUser.generateUserID', 'no') === 'yes') {
319
-			$userid = $this->createNewUserId();
320
-		}
321
-
322
-		if ($this->userManager->userExists($userid)) {
323
-			$this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
324
-			throw new OCSException('User already exists', 102);
325
-		}
326
-
327
-		if ($groups !== []) {
328
-			foreach ($groups as $group) {
329
-				if (!$this->groupManager->groupExists($group)) {
330
-					throw new OCSException('group '.$group.' does not exist', 104);
331
-				}
332
-				if (!$isAdmin && !$subAdminManager->isSubAdminOfGroup($user, $this->groupManager->get($group))) {
333
-					throw new OCSException('insufficient privileges for group '. $group, 105);
334
-				}
335
-			}
336
-		} else {
337
-			if (!$isAdmin) {
338
-				throw new OCSException('no group specified (required for subadmins)', 106);
339
-			}
340
-		}
341
-
342
-		$subadminGroups = [];
343
-		if ($subadmin !== []) {
344
-			foreach ($subadmin as $groupid) {
345
-				$group = $this->groupManager->get($groupid);
346
-				// Check if group exists
347
-				if ($group === null) {
348
-					throw new OCSException('Subadmin group does not exist',  102);
349
-				}
350
-				// Check if trying to make subadmin of admin group
351
-				if ($group->getGID() === 'admin') {
352
-					throw new OCSException('Cannot create subadmins for admin group', 103);
353
-				}
354
-				// Check if has permission to promote subadmins
355
-				if (!$subAdminManager->isSubAdminOfGroup($user, $group) && !$isAdmin) {
356
-					throw new OCSForbiddenException('No permissions to promote subadmins');
357
-				}
358
-				$subadminGroups[] = $group;
359
-			}
360
-		}
361
-
362
-		$generatePasswordResetToken = false;
363
-		if ($password === '') {
364
-			if ($email === '') {
365
-				throw new OCSException('To send a password link to the user an email address is required.', 108);
366
-			}
367
-
368
-			$passwordEvent = new GenerateSecurePasswordEvent();
369
-			$this->eventDispatcher->dispatchTyped($passwordEvent);
370
-
371
-			$password = $passwordEvent->getPassword();
372
-			if ($password === null) {
373
-				// Fallback: ensure to pass password_policy in any case
374
-				$password = $this->secureRandom->generate(10)
375
-					. $this->secureRandom->generate(1, ISecureRandom::CHAR_UPPER)
376
-					. $this->secureRandom->generate(1, ISecureRandom::CHAR_LOWER)
377
-					. $this->secureRandom->generate(1, ISecureRandom::CHAR_DIGITS)
378
-					. $this->secureRandom->generate(1, ISecureRandom::CHAR_SYMBOLS);
379
-			}
380
-			$generatePasswordResetToken = true;
381
-		}
382
-
383
-		if ($email === '' && $this->config->getAppValue('core', 'newUser.requireEmail', 'no') === 'yes') {
384
-			throw new OCSException('Required email address was not provided', 110);
385
-		}
386
-
387
-		try {
388
-			$newUser = $this->userManager->createUser($userid, $password);
389
-			$this->logger->info('Successful addUser call with userid: ' . $userid, ['app' => 'ocs_api']);
390
-
391
-			foreach ($groups as $group) {
392
-				$this->groupManager->get($group)->addUser($newUser);
393
-				$this->logger->info('Added userid ' . $userid . ' to group ' . $group, ['app' => 'ocs_api']);
394
-			}
395
-			foreach ($subadminGroups as $group) {
396
-				$subAdminManager->createSubAdmin($newUser, $group);
397
-			}
398
-
399
-			if ($displayName !== '') {
400
-				$this->editUser($userid, 'display', $displayName);
401
-			}
402
-
403
-			if ($quota !== '') {
404
-				$this->editUser($userid, 'quota', $quota);
405
-			}
406
-
407
-			if ($language !== '') {
408
-				$this->editUser($userid, 'language', $language);
409
-			}
410
-
411
-			// Send new user mail only if a mail is set
412
-			if ($email !== '') {
413
-				$newUser->setEMailAddress($email);
414
-				if ($this->config->getAppValue('core', 'newUser.sendEmail', 'yes') === 'yes') {
415
-					try {
416
-						$emailTemplate = $this->newUserMailHelper->generateTemplate($newUser, $generatePasswordResetToken);
417
-						$this->newUserMailHelper->sendMail($newUser, $emailTemplate);
418
-					} catch (\Exception $e) {
419
-						// Mail could be failing hard or just be plain not configured
420
-						// Logging error as it is the hardest of the two
421
-						$this->logger->error("Unable to send the invitation mail to $email",
422
-							[
423
-								'app' => 'ocs_api',
424
-								'exception' => $e,
425
-							]
426
-						);
427
-					}
428
-				}
429
-			}
430
-
431
-			return new DataResponse(['id' => $userid]);
432
-		} catch (HintException $e) {
433
-			$this->logger->warning('Failed addUser attempt with hint exception.',
434
-				[
435
-					'app' => 'ocs_api',
436
-					'exception' => $e,
437
-				]
438
-			);
439
-			throw new OCSException($e->getHint(), 107);
440
-		} catch (OCSException $e) {
441
-			$this->logger->warning('Failed addUser attempt with ocs exeption.',
442
-				[
443
-					'app' => 'ocs_api',
444
-					'exception' => $e,
445
-				]
446
-			);
447
-			throw $e;
448
-		} catch (\Exception $e) {
449
-			$this->logger->error('Failed addUser attempt with exception.',
450
-				[
451
-					'app' => 'ocs_api',
452
-					'exception' => $e
453
-				]
454
-			);
455
-			throw new OCSException('Bad request', 101);
456
-		}
457
-	}
458
-
459
-	/**
460
-	 * @NoAdminRequired
461
-	 * @NoSubAdminRequired
462
-	 *
463
-	 * gets user info
464
-	 *
465
-	 * @param string $userId
466
-	 * @return DataResponse
467
-	 * @throws OCSException
468
-	 */
469
-	public function getUser(string $userId): DataResponse {
470
-		$data = $this->getUserData($userId);
471
-		// getUserData returns empty array if not enough permissions
472
-		if (empty($data)) {
473
-			throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
474
-		}
475
-		return new DataResponse($data);
476
-	}
477
-
478
-	/**
479
-	 * @NoAdminRequired
480
-	 * @NoSubAdminRequired
481
-	 *
482
-	 * gets user info from the currently logged in user
483
-	 *
484
-	 * @return DataResponse
485
-	 * @throws OCSException
486
-	 */
487
-	public function getCurrentUser(): DataResponse {
488
-		$user = $this->userSession->getUser();
489
-		if ($user) {
490
-			$data = $this->getUserData($user->getUID());
491
-			// rename "displayname" to "display-name" only for this call to keep
492
-			// the API stable.
493
-			$data['display-name'] = $data['displayname'];
494
-			unset($data['displayname']);
495
-			return new DataResponse($data);
496
-		}
497
-
498
-		throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
499
-	}
500
-
501
-	/**
502
-	 * @NoAdminRequired
503
-	 * @NoSubAdminRequired
504
-	 */
505
-	public function getEditableFields(): DataResponse {
506
-		$permittedFields = [];
507
-
508
-		// Editing self (display, email)
509
-		if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
510
-			$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
511
-			$permittedFields[] = IAccountManager::PROPERTY_EMAIL;
512
-		}
513
-
514
-		if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
515
-			$shareProvider = $this->federatedShareProviderFactory->get();
516
-			if ($shareProvider->isLookupServerUploadEnabled()) {
517
-				$permittedFields[] = IAccountManager::PROPERTY_PHONE;
518
-				$permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
519
-				$permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
520
-				$permittedFields[] = IAccountManager::PROPERTY_TWITTER;
521
-			}
522
-		}
523
-
524
-		return new DataResponse($permittedFields);
525
-	}
526
-
527
-	/**
528
-	 * @NoAdminRequired
529
-	 * @NoSubAdminRequired
530
-	 * @PasswordConfirmationRequired
531
-	 *
532
-	 * edit users
533
-	 *
534
-	 * @param string $userId
535
-	 * @param string $key
536
-	 * @param string $value
537
-	 * @return DataResponse
538
-	 * @throws OCSException
539
-	 */
540
-	public function editUser(string $userId, string $key, string $value): DataResponse {
541
-		$currentLoggedInUser = $this->userSession->getUser();
542
-
543
-		$targetUser = $this->userManager->get($userId);
544
-		if ($targetUser === null) {
545
-			throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
546
-		}
547
-
548
-		$permittedFields = [];
549
-		if ($targetUser->getUID() === $currentLoggedInUser->getUID()) {
550
-			// Editing self (display, email)
551
-			if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
552
-				$permittedFields[] = 'display';
553
-				$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
554
-				$permittedFields[] = IAccountManager::PROPERTY_EMAIL;
555
-			}
556
-
557
-			$permittedFields[] = 'password';
558
-			if ($this->config->getSystemValue('force_language', false) === false ||
559
-				$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
560
-				$permittedFields[] = 'language';
561
-			}
562
-
563
-			if ($this->config->getSystemValue('force_locale', false) === false ||
564
-				$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
565
-				$permittedFields[] = 'locale';
566
-			}
567
-
568
-			if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
569
-				$shareProvider = $this->federatedShareProviderFactory->get();
570
-				if ($shareProvider->isLookupServerUploadEnabled()) {
571
-					$permittedFields[] = IAccountManager::PROPERTY_PHONE;
572
-					$permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
573
-					$permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
574
-					$permittedFields[] = IAccountManager::PROPERTY_TWITTER;
575
-				}
576
-			}
577
-
578
-			// If admin they can edit their own quota
579
-			if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
580
-				$permittedFields[] = 'quota';
581
-			}
582
-		} else {
583
-			// Check if admin / subadmin
584
-			$subAdminManager = $this->groupManager->getSubAdmin();
585
-			if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())
586
-			|| $subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
587
-				// They have permissions over the user
588
-				$permittedFields[] = 'display';
589
-				$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
590
-				$permittedFields[] = IAccountManager::PROPERTY_EMAIL;
591
-				$permittedFields[] = 'password';
592
-				$permittedFields[] = 'language';
593
-				$permittedFields[] = 'locale';
594
-				$permittedFields[] = IAccountManager::PROPERTY_PHONE;
595
-				$permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
596
-				$permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
597
-				$permittedFields[] = IAccountManager::PROPERTY_TWITTER;
598
-				$permittedFields[] = 'quota';
599
-			} else {
600
-				// No rights
601
-				throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
602
-			}
603
-		}
604
-		// Check if permitted to edit this field
605
-		if (!in_array($key, $permittedFields)) {
606
-			throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
607
-		}
608
-		// Process the edit
609
-		switch ($key) {
610
-			case 'display':
611
-			case IAccountManager::PROPERTY_DISPLAYNAME:
612
-				$targetUser->setDisplayName($value);
613
-				break;
614
-			case 'quota':
615
-				$quota = $value;
616
-				if ($quota !== 'none' && $quota !== 'default') {
617
-					if (is_numeric($quota)) {
618
-						$quota = (float) $quota;
619
-					} else {
620
-						$quota = \OCP\Util::computerFileSize($quota);
621
-					}
622
-					if ($quota === false) {
623
-						throw new OCSException('Invalid quota value '.$value, 103);
624
-					}
625
-					if ($quota === -1) {
626
-						$quota = 'none';
627
-					} else {
628
-						$quota = \OCP\Util::humanFileSize($quota);
629
-					}
630
-				}
631
-				$targetUser->setQuota($quota);
632
-				break;
633
-			case 'password':
634
-				try {
635
-					if (!$targetUser->canChangePassword()) {
636
-						throw new OCSException('Setting the password is not supported by the users backend', 103);
637
-					}
638
-					$targetUser->setPassword($value);
639
-				} catch (HintException $e) { // password policy error
640
-					throw new OCSException($e->getMessage(), 103);
641
-				}
642
-				break;
643
-			case 'language':
644
-				$languagesCodes = $this->l10nFactory->findAvailableLanguages();
645
-				if (!in_array($value, $languagesCodes, true) && $value !== 'en') {
646
-					throw new OCSException('Invalid language', 102);
647
-				}
648
-				$this->config->setUserValue($targetUser->getUID(), 'core', 'lang', $value);
649
-				break;
650
-			case 'locale':
651
-				if (!$this->l10nFactory->localeExists($value)) {
652
-					throw new OCSException('Invalid locale', 102);
653
-				}
654
-				$this->config->setUserValue($targetUser->getUID(), 'core', 'locale', $value);
655
-				break;
656
-			case IAccountManager::PROPERTY_EMAIL:
657
-				if (filter_var($value, FILTER_VALIDATE_EMAIL) || $value === '') {
658
-					$targetUser->setEMailAddress($value);
659
-				} else {
660
-					throw new OCSException('', 102);
661
-				}
662
-				break;
663
-			case IAccountManager::PROPERTY_PHONE:
664
-			case IAccountManager::PROPERTY_ADDRESS:
665
-			case IAccountManager::PROPERTY_WEBSITE:
666
-			case IAccountManager::PROPERTY_TWITTER:
667
-				$userAccount = $this->accountManager->getUser($targetUser);
668
-				if ($userAccount[$key]['value'] !== $value) {
669
-					$userAccount[$key]['value'] = $value;
670
-					try {
671
-						$this->accountManager->updateUser($targetUser, $userAccount, true);
672
-					} catch (\InvalidArgumentException $e) {
673
-						throw new OCSException('Invalid ' . $e->getMessage(), 102);
674
-					}
675
-				}
676
-				break;
677
-			default:
678
-				throw new OCSException('', 103);
679
-		}
680
-		return new DataResponse();
681
-	}
682
-
683
-	/**
684
-	 * @PasswordConfirmationRequired
685
-	 * @NoAdminRequired
686
-	 *
687
-	 * @param string $userId
688
-	 *
689
-	 * @return DataResponse
690
-	 *
691
-	 * @throws OCSException
692
-	 */
693
-	public function wipeUserDevices(string $userId): DataResponse {
694
-		/** @var IUser $currentLoggedInUser */
695
-		$currentLoggedInUser = $this->userSession->getUser();
696
-
697
-		$targetUser = $this->userManager->get($userId);
698
-
699
-		if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
700
-			throw new OCSException('', 101);
701
-		}
702
-
703
-		// If not permitted
704
-		$subAdminManager = $this->groupManager->getSubAdmin();
705
-		if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
706
-			throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
707
-		}
708
-
709
-		$this->remoteWipe->markAllTokensForWipe($targetUser);
710
-
711
-		return new DataResponse();
712
-	}
713
-
714
-	/**
715
-	 * @PasswordConfirmationRequired
716
-	 * @NoAdminRequired
717
-	 *
718
-	 * @param string $userId
719
-	 * @return DataResponse
720
-	 * @throws OCSException
721
-	 */
722
-	public function deleteUser(string $userId): DataResponse {
723
-		$currentLoggedInUser = $this->userSession->getUser();
724
-
725
-		$targetUser = $this->userManager->get($userId);
726
-
727
-		if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
728
-			throw new OCSException('', 101);
729
-		}
730
-
731
-		// If not permitted
732
-		$subAdminManager = $this->groupManager->getSubAdmin();
733
-		if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
734
-			throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
735
-		}
736
-
737
-		// Go ahead with the delete
738
-		if ($targetUser->delete()) {
739
-			return new DataResponse();
740
-		} else {
741
-			throw new OCSException('', 101);
742
-		}
743
-	}
744
-
745
-	/**
746
-	 * @PasswordConfirmationRequired
747
-	 * @NoAdminRequired
748
-	 *
749
-	 * @param string $userId
750
-	 * @return DataResponse
751
-	 * @throws OCSException
752
-	 * @throws OCSForbiddenException
753
-	 */
754
-	public function disableUser(string $userId): DataResponse {
755
-		return $this->setEnabled($userId, false);
756
-	}
757
-
758
-	/**
759
-	 * @PasswordConfirmationRequired
760
-	 * @NoAdminRequired
761
-	 *
762
-	 * @param string $userId
763
-	 * @return DataResponse
764
-	 * @throws OCSException
765
-	 * @throws OCSForbiddenException
766
-	 */
767
-	public function enableUser(string $userId): DataResponse {
768
-		return $this->setEnabled($userId, true);
769
-	}
770
-
771
-	/**
772
-	 * @param string $userId
773
-	 * @param bool $value
774
-	 * @return DataResponse
775
-	 * @throws OCSException
776
-	 */
777
-	private function setEnabled(string $userId, bool $value): DataResponse {
778
-		$currentLoggedInUser = $this->userSession->getUser();
779
-
780
-		$targetUser = $this->userManager->get($userId);
781
-		if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
782
-			throw new OCSException('', 101);
783
-		}
784
-
785
-		// If not permitted
786
-		$subAdminManager = $this->groupManager->getSubAdmin();
787
-		if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
788
-			throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
789
-		}
790
-
791
-		// enable/disable the user now
792
-		$targetUser->setEnabled($value);
793
-		return new DataResponse();
794
-	}
795
-
796
-	/**
797
-	 * @NoAdminRequired
798
-	 * @NoSubAdminRequired
799
-	 *
800
-	 * @param string $userId
801
-	 * @return DataResponse
802
-	 * @throws OCSException
803
-	 */
804
-	public function getUsersGroups(string $userId): DataResponse {
805
-		$loggedInUser = $this->userSession->getUser();
806
-
807
-		$targetUser = $this->userManager->get($userId);
808
-		if ($targetUser === null) {
809
-			throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
810
-		}
811
-
812
-		if ($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
813
-			// Self lookup or admin lookup
814
-			return new DataResponse([
815
-				'groups' => $this->groupManager->getUserGroupIds($targetUser)
816
-			]);
817
-		} else {
818
-			$subAdminManager = $this->groupManager->getSubAdmin();
819
-
820
-			// Looking up someone else
821
-			if ($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
822
-				// Return the group that the method caller is subadmin of for the user in question
823
-				/** @var IGroup[] $getSubAdminsGroups */
824
-				$getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
825
-				foreach ($getSubAdminsGroups as $key => $group) {
826
-					$getSubAdminsGroups[$key] = $group->getGID();
827
-				}
828
-				$groups = array_intersect(
829
-					$getSubAdminsGroups,
830
-					$this->groupManager->getUserGroupIds($targetUser)
831
-				);
832
-				return new DataResponse(['groups' => $groups]);
833
-			} else {
834
-				// Not permitted
835
-				throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
836
-			}
837
-		}
838
-	}
839
-
840
-	/**
841
-	 * @PasswordConfirmationRequired
842
-	 * @NoAdminRequired
843
-	 *
844
-	 * @param string $userId
845
-	 * @param string $groupid
846
-	 * @return DataResponse
847
-	 * @throws OCSException
848
-	 */
849
-	public function addToGroup(string $userId, string $groupid = ''): DataResponse {
850
-		if ($groupid === '') {
851
-			throw new OCSException('', 101);
852
-		}
853
-
854
-		$group = $this->groupManager->get($groupid);
855
-		$targetUser = $this->userManager->get($userId);
856
-		if ($group === null) {
857
-			throw new OCSException('', 102);
858
-		}
859
-		if ($targetUser === null) {
860
-			throw new OCSException('', 103);
861
-		}
862
-
863
-		// If they're not an admin, check they are a subadmin of the group in question
864
-		$loggedInUser = $this->userSession->getUser();
865
-		$subAdminManager = $this->groupManager->getSubAdmin();
866
-		if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
867
-			throw new OCSException('', 104);
868
-		}
869
-
870
-		// Add user to group
871
-		$group->addUser($targetUser);
872
-		return new DataResponse();
873
-	}
874
-
875
-	/**
876
-	 * @PasswordConfirmationRequired
877
-	 * @NoAdminRequired
878
-	 *
879
-	 * @param string $userId
880
-	 * @param string $groupid
881
-	 * @return DataResponse
882
-	 * @throws OCSException
883
-	 */
884
-	public function removeFromGroup(string $userId, string $groupid): DataResponse {
885
-		$loggedInUser = $this->userSession->getUser();
886
-
887
-		if ($groupid === null || trim($groupid) === '') {
888
-			throw new OCSException('', 101);
889
-		}
890
-
891
-		$group = $this->groupManager->get($groupid);
892
-		if ($group === null) {
893
-			throw new OCSException('', 102);
894
-		}
895
-
896
-		$targetUser = $this->userManager->get($userId);
897
-		if ($targetUser === null) {
898
-			throw new OCSException('', 103);
899
-		}
900
-
901
-		// If they're not an admin, check they are a subadmin of the group in question
902
-		$subAdminManager = $this->groupManager->getSubAdmin();
903
-		if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
904
-			throw new OCSException('', 104);
905
-		}
906
-
907
-		// Check they aren't removing themselves from 'admin' or their 'subadmin; group
908
-		if ($targetUser->getUID() === $loggedInUser->getUID()) {
909
-			if ($this->groupManager->isAdmin($loggedInUser->getUID())) {
910
-				if ($group->getGID() === 'admin') {
911
-					throw new OCSException('Cannot remove yourself from the admin group', 105);
912
-				}
913
-			} else {
914
-				// Not an admin, so the user must be a subadmin of this group, but that is not allowed.
915
-				throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105);
916
-			}
917
-		} elseif (!$this->groupManager->isAdmin($loggedInUser->getUID())) {
918
-			/** @var IGroup[] $subAdminGroups */
919
-			$subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
920
-			$subAdminGroups = array_map(function (IGroup $subAdminGroup) {
921
-				return $subAdminGroup->getGID();
922
-			}, $subAdminGroups);
923
-			$userGroups = $this->groupManager->getUserGroupIds($targetUser);
924
-			$userSubAdminGroups = array_intersect($subAdminGroups, $userGroups);
925
-
926
-			if (count($userSubAdminGroups) <= 1) {
927
-				// Subadmin must not be able to remove a user from all their subadmin groups.
928
-				throw new OCSException('Not viable to remove user from the last group you are SubAdmin of', 105);
929
-			}
930
-		}
931
-
932
-		// Remove user from group
933
-		$group->removeUser($targetUser);
934
-		return new DataResponse();
935
-	}
936
-
937
-	/**
938
-	 * Creates a subadmin
939
-	 *
940
-	 * @PasswordConfirmationRequired
941
-	 *
942
-	 * @param string $userId
943
-	 * @param string $groupid
944
-	 * @return DataResponse
945
-	 * @throws OCSException
946
-	 */
947
-	public function addSubAdmin(string $userId, string $groupid): DataResponse {
948
-		$group = $this->groupManager->get($groupid);
949
-		$user = $this->userManager->get($userId);
950
-
951
-		// Check if the user exists
952
-		if ($user === null) {
953
-			throw new OCSException('User does not exist', 101);
954
-		}
955
-		// Check if group exists
956
-		if ($group === null) {
957
-			throw new OCSException('Group does not exist',  102);
958
-		}
959
-		// Check if trying to make subadmin of admin group
960
-		if ($group->getGID() === 'admin') {
961
-			throw new OCSException('Cannot create subadmins for admin group', 103);
962
-		}
963
-
964
-		$subAdminManager = $this->groupManager->getSubAdmin();
965
-
966
-		// We cannot be subadmin twice
967
-		if ($subAdminManager->isSubAdminOfGroup($user, $group)) {
968
-			return new DataResponse();
969
-		}
970
-		// Go
971
-		$subAdminManager->createSubAdmin($user, $group);
972
-		return new DataResponse();
973
-	}
974
-
975
-	/**
976
-	 * Removes a subadmin from a group
977
-	 *
978
-	 * @PasswordConfirmationRequired
979
-	 *
980
-	 * @param string $userId
981
-	 * @param string $groupid
982
-	 * @return DataResponse
983
-	 * @throws OCSException
984
-	 */
985
-	public function removeSubAdmin(string $userId, string $groupid): DataResponse {
986
-		$group = $this->groupManager->get($groupid);
987
-		$user = $this->userManager->get($userId);
988
-		$subAdminManager = $this->groupManager->getSubAdmin();
989
-
990
-		// Check if the user exists
991
-		if ($user === null) {
992
-			throw new OCSException('User does not exist', 101);
993
-		}
994
-		// Check if the group exists
995
-		if ($group === null) {
996
-			throw new OCSException('Group does not exist', 101);
997
-		}
998
-		// Check if they are a subadmin of this said group
999
-		if (!$subAdminManager->isSubAdminOfGroup($user, $group)) {
1000
-			throw new OCSException('User is not a subadmin of this group', 102);
1001
-		}
1002
-
1003
-		// Go
1004
-		$subAdminManager->deleteSubAdmin($user, $group);
1005
-		return new DataResponse();
1006
-	}
1007
-
1008
-	/**
1009
-	 * Get the groups a user is a subadmin of
1010
-	 *
1011
-	 * @param string $userId
1012
-	 * @return DataResponse
1013
-	 * @throws OCSException
1014
-	 */
1015
-	public function getUserSubAdminGroups(string $userId): DataResponse {
1016
-		$groups = $this->getUserSubAdminGroupsData($userId);
1017
-		return new DataResponse($groups);
1018
-	}
1019
-
1020
-	/**
1021
-	 * @NoAdminRequired
1022
-	 * @PasswordConfirmationRequired
1023
-	 *
1024
-	 * resend welcome message
1025
-	 *
1026
-	 * @param string $userId
1027
-	 * @return DataResponse
1028
-	 * @throws OCSException
1029
-	 */
1030
-	public function resendWelcomeMessage(string $userId): DataResponse {
1031
-		$currentLoggedInUser = $this->userSession->getUser();
1032
-
1033
-		$targetUser = $this->userManager->get($userId);
1034
-		if ($targetUser === null) {
1035
-			throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
1036
-		}
1037
-
1038
-		// Check if admin / subadmin
1039
-		$subAdminManager = $this->groupManager->getSubAdmin();
1040
-		if (!$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
1041
-			&& !$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
1042
-			// No rights
1043
-			throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
1044
-		}
1045
-
1046
-		$email = $targetUser->getEMailAddress();
1047
-		if ($email === '' || $email === null) {
1048
-			throw new OCSException('Email address not available', 101);
1049
-		}
1050
-
1051
-		try {
1052
-			$emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false);
1053
-			$this->newUserMailHelper->sendMail($targetUser, $emailTemplate);
1054
-		} catch (\Exception $e) {
1055
-			$this->logger->error("Can't send new user mail to $email",
1056
-				[
1057
-					'app' => 'settings',
1058
-					'exception' => $e,
1059
-				]
1060
-			);
1061
-			throw new OCSException('Sending email failed', 102);
1062
-		}
1063
-
1064
-		return new DataResponse();
1065
-	}
77
+    /** @var IAppManager */
78
+    private $appManager;
79
+    /** @var IURLGenerator */
80
+    protected $urlGenerator;
81
+    /** @var LoggerInterface */
82
+    private $logger;
83
+    /** @var IFactory */
84
+    protected $l10nFactory;
85
+    /** @var NewUserMailHelper */
86
+    private $newUserMailHelper;
87
+    /** @var FederatedShareProviderFactory */
88
+    private $federatedShareProviderFactory;
89
+    /** @var ISecureRandom */
90
+    private $secureRandom;
91
+    /** @var RemoteWipe */
92
+    private $remoteWipe;
93
+    /** @var IEventDispatcher */
94
+    private $eventDispatcher;
95
+
96
+    public function __construct(string $appName,
97
+                                IRequest $request,
98
+                                IUserManager $userManager,
99
+                                IConfig $config,
100
+                                IAppManager $appManager,
101
+                                IGroupManager $groupManager,
102
+                                IUserSession $userSession,
103
+                                AccountManager $accountManager,
104
+                                IURLGenerator $urlGenerator,
105
+                                LoggerInterface $logger,
106
+                                IFactory $l10nFactory,
107
+                                NewUserMailHelper $newUserMailHelper,
108
+                                FederatedShareProviderFactory $federatedShareProviderFactory,
109
+                                ISecureRandom $secureRandom,
110
+                                RemoteWipe $remoteWipe,
111
+                                IEventDispatcher $eventDispatcher) {
112
+        parent::__construct($appName,
113
+                            $request,
114
+                            $userManager,
115
+                            $config,
116
+                            $groupManager,
117
+                            $userSession,
118
+                            $accountManager,
119
+                            $l10nFactory);
120
+
121
+        $this->appManager = $appManager;
122
+        $this->urlGenerator = $urlGenerator;
123
+        $this->logger = $logger;
124
+        $this->l10nFactory = $l10nFactory;
125
+        $this->newUserMailHelper = $newUserMailHelper;
126
+        $this->federatedShareProviderFactory = $federatedShareProviderFactory;
127
+        $this->secureRandom = $secureRandom;
128
+        $this->remoteWipe = $remoteWipe;
129
+        $this->eventDispatcher = $eventDispatcher;
130
+    }
131
+
132
+    /**
133
+     * @NoAdminRequired
134
+     *
135
+     * returns a list of users
136
+     *
137
+     * @param string $search
138
+     * @param int $limit
139
+     * @param int $offset
140
+     * @return DataResponse
141
+     */
142
+    public function getUsers(string $search = '', int $limit = null, int $offset = 0): DataResponse {
143
+        $user = $this->userSession->getUser();
144
+        $users = [];
145
+
146
+        // Admin? Or SubAdmin?
147
+        $uid = $user->getUID();
148
+        $subAdminManager = $this->groupManager->getSubAdmin();
149
+        if ($this->groupManager->isAdmin($uid)) {
150
+            $users = $this->userManager->search($search, $limit, $offset);
151
+        } elseif ($subAdminManager->isSubAdmin($user)) {
152
+            $subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
153
+            foreach ($subAdminOfGroups as $key => $group) {
154
+                $subAdminOfGroups[$key] = $group->getGID();
155
+            }
156
+
157
+            $users = [];
158
+            foreach ($subAdminOfGroups as $group) {
159
+                $users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
160
+            }
161
+        }
162
+
163
+        $users = array_keys($users);
164
+
165
+        return new DataResponse([
166
+            'users' => $users
167
+        ]);
168
+    }
169
+
170
+    /**
171
+     * @NoAdminRequired
172
+     *
173
+     * returns a list of users and their data
174
+     */
175
+    public function getUsersDetails(string $search = '', int $limit = null, int $offset = 0): DataResponse {
176
+        $currentUser = $this->userSession->getUser();
177
+        $users = [];
178
+
179
+        // Admin? Or SubAdmin?
180
+        $uid = $currentUser->getUID();
181
+        $subAdminManager = $this->groupManager->getSubAdmin();
182
+        if ($this->groupManager->isAdmin($uid)) {
183
+            $users = $this->userManager->search($search, $limit, $offset);
184
+            $users = array_keys($users);
185
+        } elseif ($subAdminManager->isSubAdmin($currentUser)) {
186
+            $subAdminOfGroups = $subAdminManager->getSubAdminsGroups($currentUser);
187
+            foreach ($subAdminOfGroups as $key => $group) {
188
+                $subAdminOfGroups[$key] = $group->getGID();
189
+            }
190
+
191
+            $users = [];
192
+            foreach ($subAdminOfGroups as $group) {
193
+                $users[] = array_keys($this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
194
+            }
195
+            $users = array_merge(...$users);
196
+        }
197
+
198
+        $usersDetails = [];
199
+        foreach ($users as $userId) {
200
+            $userId = (string) $userId;
201
+            $userData = $this->getUserData($userId);
202
+            // Do not insert empty entry
203
+            if (!empty($userData)) {
204
+                $usersDetails[$userId] = $userData;
205
+            } else {
206
+                // Logged user does not have permissions to see this user
207
+                // only showing its id
208
+                $usersDetails[$userId] = ['id' => $userId];
209
+            }
210
+        }
211
+
212
+        return new DataResponse([
213
+            'users' => $usersDetails
214
+        ]);
215
+    }
216
+
217
+
218
+    /**
219
+     * @NoAdminRequired
220
+     * @NoSubAdminRequired
221
+     *
222
+     * @param string $location
223
+     * @param array $search
224
+     * @return DataResponse
225
+     */
226
+    public function searchByPhoneNumbers(string $location, array $search): DataResponse {
227
+        $phoneUtil = PhoneNumberUtil::getInstance();
228
+
229
+        if ($phoneUtil->getCountryCodeForRegion($location) === 0) {
230
+            // Not a valid region code
231
+            return new DataResponse([], Http::STATUS_BAD_REQUEST);
232
+        }
233
+
234
+        $normalizedNumberToKey = [];
235
+        foreach ($search as $key => $phoneNumbers) {
236
+            foreach ($phoneNumbers as $phone) {
237
+                try {
238
+                    $phoneNumber = $phoneUtil->parse($phone, $location);
239
+                    if ($phoneNumber instanceof PhoneNumber && $phoneUtil->isValidNumber($phoneNumber)) {
240
+                        $normalizedNumber = $phoneUtil->format($phoneNumber, PhoneNumberFormat::E164);
241
+                        $normalizedNumberToKey[$normalizedNumber] = (string) $key;
242
+                    }
243
+                } catch (NumberParseException $e) {
244
+                }
245
+            }
246
+        }
247
+
248
+        $phoneNumbers = array_keys($normalizedNumberToKey);
249
+
250
+        if (empty($phoneNumbers)) {
251
+            return new DataResponse();
252
+        }
253
+
254
+        $userMatches = $this->accountManager->searchUsers(IAccountManager::PROPERTY_PHONE, $phoneNumbers);
255
+
256
+        if (empty($userMatches)) {
257
+            return new DataResponse();
258
+        }
259
+
260
+        $cloudUrl = rtrim($this->urlGenerator->getAbsoluteURL('/'), '/');
261
+        if (strpos($cloudUrl, 'http://') === 0) {
262
+            $cloudUrl = substr($cloudUrl, strlen('http://'));
263
+        } elseif (strpos($cloudUrl, 'https://') === 0) {
264
+            $cloudUrl = substr($cloudUrl, strlen('https://'));
265
+        }
266
+
267
+        $matches = [];
268
+        foreach ($userMatches as $phone => $userId) {
269
+            // Not using the ICloudIdManager as that would run a search for each contact to find the display name in the address book
270
+            $matches[$normalizedNumberToKey[$phone]] = $userId . '@' . $cloudUrl;
271
+        }
272
+
273
+        return new DataResponse($matches);
274
+    }
275
+
276
+    /**
277
+     * @throws OCSException
278
+     */
279
+    private function createNewUserId(): string {
280
+        $attempts = 0;
281
+        do {
282
+            $uidCandidate = $this->secureRandom->generate(10, ISecureRandom::CHAR_HUMAN_READABLE);
283
+            if (!$this->userManager->userExists($uidCandidate)) {
284
+                return $uidCandidate;
285
+            }
286
+            $attempts++;
287
+        } while ($attempts < 10);
288
+        throw new OCSException('Could not create non-existing user id', 111);
289
+    }
290
+
291
+    /**
292
+     * @PasswordConfirmationRequired
293
+     * @NoAdminRequired
294
+     *
295
+     * @param string $userid
296
+     * @param string $password
297
+     * @param string $displayName
298
+     * @param string $email
299
+     * @param array $groups
300
+     * @param array $subadmin
301
+     * @param string $quota
302
+     * @param string $language
303
+     * @return DataResponse
304
+     * @throws OCSException
305
+     */
306
+    public function addUser(string $userid,
307
+                            string $password = '',
308
+                            string $displayName = '',
309
+                            string $email = '',
310
+                            array $groups = [],
311
+                            array $subadmin = [],
312
+                            string $quota = '',
313
+                            string $language = ''): DataResponse {
314
+        $user = $this->userSession->getUser();
315
+        $isAdmin = $this->groupManager->isAdmin($user->getUID());
316
+        $subAdminManager = $this->groupManager->getSubAdmin();
317
+
318
+        if (empty($userid) && $this->config->getAppValue('core', 'newUser.generateUserID', 'no') === 'yes') {
319
+            $userid = $this->createNewUserId();
320
+        }
321
+
322
+        if ($this->userManager->userExists($userid)) {
323
+            $this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
324
+            throw new OCSException('User already exists', 102);
325
+        }
326
+
327
+        if ($groups !== []) {
328
+            foreach ($groups as $group) {
329
+                if (!$this->groupManager->groupExists($group)) {
330
+                    throw new OCSException('group '.$group.' does not exist', 104);
331
+                }
332
+                if (!$isAdmin && !$subAdminManager->isSubAdminOfGroup($user, $this->groupManager->get($group))) {
333
+                    throw new OCSException('insufficient privileges for group '. $group, 105);
334
+                }
335
+            }
336
+        } else {
337
+            if (!$isAdmin) {
338
+                throw new OCSException('no group specified (required for subadmins)', 106);
339
+            }
340
+        }
341
+
342
+        $subadminGroups = [];
343
+        if ($subadmin !== []) {
344
+            foreach ($subadmin as $groupid) {
345
+                $group = $this->groupManager->get($groupid);
346
+                // Check if group exists
347
+                if ($group === null) {
348
+                    throw new OCSException('Subadmin group does not exist',  102);
349
+                }
350
+                // Check if trying to make subadmin of admin group
351
+                if ($group->getGID() === 'admin') {
352
+                    throw new OCSException('Cannot create subadmins for admin group', 103);
353
+                }
354
+                // Check if has permission to promote subadmins
355
+                if (!$subAdminManager->isSubAdminOfGroup($user, $group) && !$isAdmin) {
356
+                    throw new OCSForbiddenException('No permissions to promote subadmins');
357
+                }
358
+                $subadminGroups[] = $group;
359
+            }
360
+        }
361
+
362
+        $generatePasswordResetToken = false;
363
+        if ($password === '') {
364
+            if ($email === '') {
365
+                throw new OCSException('To send a password link to the user an email address is required.', 108);
366
+            }
367
+
368
+            $passwordEvent = new GenerateSecurePasswordEvent();
369
+            $this->eventDispatcher->dispatchTyped($passwordEvent);
370
+
371
+            $password = $passwordEvent->getPassword();
372
+            if ($password === null) {
373
+                // Fallback: ensure to pass password_policy in any case
374
+                $password = $this->secureRandom->generate(10)
375
+                    . $this->secureRandom->generate(1, ISecureRandom::CHAR_UPPER)
376
+                    . $this->secureRandom->generate(1, ISecureRandom::CHAR_LOWER)
377
+                    . $this->secureRandom->generate(1, ISecureRandom::CHAR_DIGITS)
378
+                    . $this->secureRandom->generate(1, ISecureRandom::CHAR_SYMBOLS);
379
+            }
380
+            $generatePasswordResetToken = true;
381
+        }
382
+
383
+        if ($email === '' && $this->config->getAppValue('core', 'newUser.requireEmail', 'no') === 'yes') {
384
+            throw new OCSException('Required email address was not provided', 110);
385
+        }
386
+
387
+        try {
388
+            $newUser = $this->userManager->createUser($userid, $password);
389
+            $this->logger->info('Successful addUser call with userid: ' . $userid, ['app' => 'ocs_api']);
390
+
391
+            foreach ($groups as $group) {
392
+                $this->groupManager->get($group)->addUser($newUser);
393
+                $this->logger->info('Added userid ' . $userid . ' to group ' . $group, ['app' => 'ocs_api']);
394
+            }
395
+            foreach ($subadminGroups as $group) {
396
+                $subAdminManager->createSubAdmin($newUser, $group);
397
+            }
398
+
399
+            if ($displayName !== '') {
400
+                $this->editUser($userid, 'display', $displayName);
401
+            }
402
+
403
+            if ($quota !== '') {
404
+                $this->editUser($userid, 'quota', $quota);
405
+            }
406
+
407
+            if ($language !== '') {
408
+                $this->editUser($userid, 'language', $language);
409
+            }
410
+
411
+            // Send new user mail only if a mail is set
412
+            if ($email !== '') {
413
+                $newUser->setEMailAddress($email);
414
+                if ($this->config->getAppValue('core', 'newUser.sendEmail', 'yes') === 'yes') {
415
+                    try {
416
+                        $emailTemplate = $this->newUserMailHelper->generateTemplate($newUser, $generatePasswordResetToken);
417
+                        $this->newUserMailHelper->sendMail($newUser, $emailTemplate);
418
+                    } catch (\Exception $e) {
419
+                        // Mail could be failing hard or just be plain not configured
420
+                        // Logging error as it is the hardest of the two
421
+                        $this->logger->error("Unable to send the invitation mail to $email",
422
+                            [
423
+                                'app' => 'ocs_api',
424
+                                'exception' => $e,
425
+                            ]
426
+                        );
427
+                    }
428
+                }
429
+            }
430
+
431
+            return new DataResponse(['id' => $userid]);
432
+        } catch (HintException $e) {
433
+            $this->logger->warning('Failed addUser attempt with hint exception.',
434
+                [
435
+                    'app' => 'ocs_api',
436
+                    'exception' => $e,
437
+                ]
438
+            );
439
+            throw new OCSException($e->getHint(), 107);
440
+        } catch (OCSException $e) {
441
+            $this->logger->warning('Failed addUser attempt with ocs exeption.',
442
+                [
443
+                    'app' => 'ocs_api',
444
+                    'exception' => $e,
445
+                ]
446
+            );
447
+            throw $e;
448
+        } catch (\Exception $e) {
449
+            $this->logger->error('Failed addUser attempt with exception.',
450
+                [
451
+                    'app' => 'ocs_api',
452
+                    'exception' => $e
453
+                ]
454
+            );
455
+            throw new OCSException('Bad request', 101);
456
+        }
457
+    }
458
+
459
+    /**
460
+     * @NoAdminRequired
461
+     * @NoSubAdminRequired
462
+     *
463
+     * gets user info
464
+     *
465
+     * @param string $userId
466
+     * @return DataResponse
467
+     * @throws OCSException
468
+     */
469
+    public function getUser(string $userId): DataResponse {
470
+        $data = $this->getUserData($userId);
471
+        // getUserData returns empty array if not enough permissions
472
+        if (empty($data)) {
473
+            throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
474
+        }
475
+        return new DataResponse($data);
476
+    }
477
+
478
+    /**
479
+     * @NoAdminRequired
480
+     * @NoSubAdminRequired
481
+     *
482
+     * gets user info from the currently logged in user
483
+     *
484
+     * @return DataResponse
485
+     * @throws OCSException
486
+     */
487
+    public function getCurrentUser(): DataResponse {
488
+        $user = $this->userSession->getUser();
489
+        if ($user) {
490
+            $data = $this->getUserData($user->getUID());
491
+            // rename "displayname" to "display-name" only for this call to keep
492
+            // the API stable.
493
+            $data['display-name'] = $data['displayname'];
494
+            unset($data['displayname']);
495
+            return new DataResponse($data);
496
+        }
497
+
498
+        throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
499
+    }
500
+
501
+    /**
502
+     * @NoAdminRequired
503
+     * @NoSubAdminRequired
504
+     */
505
+    public function getEditableFields(): DataResponse {
506
+        $permittedFields = [];
507
+
508
+        // Editing self (display, email)
509
+        if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
510
+            $permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
511
+            $permittedFields[] = IAccountManager::PROPERTY_EMAIL;
512
+        }
513
+
514
+        if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
515
+            $shareProvider = $this->federatedShareProviderFactory->get();
516
+            if ($shareProvider->isLookupServerUploadEnabled()) {
517
+                $permittedFields[] = IAccountManager::PROPERTY_PHONE;
518
+                $permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
519
+                $permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
520
+                $permittedFields[] = IAccountManager::PROPERTY_TWITTER;
521
+            }
522
+        }
523
+
524
+        return new DataResponse($permittedFields);
525
+    }
526
+
527
+    /**
528
+     * @NoAdminRequired
529
+     * @NoSubAdminRequired
530
+     * @PasswordConfirmationRequired
531
+     *
532
+     * edit users
533
+     *
534
+     * @param string $userId
535
+     * @param string $key
536
+     * @param string $value
537
+     * @return DataResponse
538
+     * @throws OCSException
539
+     */
540
+    public function editUser(string $userId, string $key, string $value): DataResponse {
541
+        $currentLoggedInUser = $this->userSession->getUser();
542
+
543
+        $targetUser = $this->userManager->get($userId);
544
+        if ($targetUser === null) {
545
+            throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
546
+        }
547
+
548
+        $permittedFields = [];
549
+        if ($targetUser->getUID() === $currentLoggedInUser->getUID()) {
550
+            // Editing self (display, email)
551
+            if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
552
+                $permittedFields[] = 'display';
553
+                $permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
554
+                $permittedFields[] = IAccountManager::PROPERTY_EMAIL;
555
+            }
556
+
557
+            $permittedFields[] = 'password';
558
+            if ($this->config->getSystemValue('force_language', false) === false ||
559
+                $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
560
+                $permittedFields[] = 'language';
561
+            }
562
+
563
+            if ($this->config->getSystemValue('force_locale', false) === false ||
564
+                $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
565
+                $permittedFields[] = 'locale';
566
+            }
567
+
568
+            if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
569
+                $shareProvider = $this->federatedShareProviderFactory->get();
570
+                if ($shareProvider->isLookupServerUploadEnabled()) {
571
+                    $permittedFields[] = IAccountManager::PROPERTY_PHONE;
572
+                    $permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
573
+                    $permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
574
+                    $permittedFields[] = IAccountManager::PROPERTY_TWITTER;
575
+                }
576
+            }
577
+
578
+            // If admin they can edit their own quota
579
+            if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
580
+                $permittedFields[] = 'quota';
581
+            }
582
+        } else {
583
+            // Check if admin / subadmin
584
+            $subAdminManager = $this->groupManager->getSubAdmin();
585
+            if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())
586
+            || $subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
587
+                // They have permissions over the user
588
+                $permittedFields[] = 'display';
589
+                $permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
590
+                $permittedFields[] = IAccountManager::PROPERTY_EMAIL;
591
+                $permittedFields[] = 'password';
592
+                $permittedFields[] = 'language';
593
+                $permittedFields[] = 'locale';
594
+                $permittedFields[] = IAccountManager::PROPERTY_PHONE;
595
+                $permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
596
+                $permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
597
+                $permittedFields[] = IAccountManager::PROPERTY_TWITTER;
598
+                $permittedFields[] = 'quota';
599
+            } else {
600
+                // No rights
601
+                throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
602
+            }
603
+        }
604
+        // Check if permitted to edit this field
605
+        if (!in_array($key, $permittedFields)) {
606
+            throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
607
+        }
608
+        // Process the edit
609
+        switch ($key) {
610
+            case 'display':
611
+            case IAccountManager::PROPERTY_DISPLAYNAME:
612
+                $targetUser->setDisplayName($value);
613
+                break;
614
+            case 'quota':
615
+                $quota = $value;
616
+                if ($quota !== 'none' && $quota !== 'default') {
617
+                    if (is_numeric($quota)) {
618
+                        $quota = (float) $quota;
619
+                    } else {
620
+                        $quota = \OCP\Util::computerFileSize($quota);
621
+                    }
622
+                    if ($quota === false) {
623
+                        throw new OCSException('Invalid quota value '.$value, 103);
624
+                    }
625
+                    if ($quota === -1) {
626
+                        $quota = 'none';
627
+                    } else {
628
+                        $quota = \OCP\Util::humanFileSize($quota);
629
+                    }
630
+                }
631
+                $targetUser->setQuota($quota);
632
+                break;
633
+            case 'password':
634
+                try {
635
+                    if (!$targetUser->canChangePassword()) {
636
+                        throw new OCSException('Setting the password is not supported by the users backend', 103);
637
+                    }
638
+                    $targetUser->setPassword($value);
639
+                } catch (HintException $e) { // password policy error
640
+                    throw new OCSException($e->getMessage(), 103);
641
+                }
642
+                break;
643
+            case 'language':
644
+                $languagesCodes = $this->l10nFactory->findAvailableLanguages();
645
+                if (!in_array($value, $languagesCodes, true) && $value !== 'en') {
646
+                    throw new OCSException('Invalid language', 102);
647
+                }
648
+                $this->config->setUserValue($targetUser->getUID(), 'core', 'lang', $value);
649
+                break;
650
+            case 'locale':
651
+                if (!$this->l10nFactory->localeExists($value)) {
652
+                    throw new OCSException('Invalid locale', 102);
653
+                }
654
+                $this->config->setUserValue($targetUser->getUID(), 'core', 'locale', $value);
655
+                break;
656
+            case IAccountManager::PROPERTY_EMAIL:
657
+                if (filter_var($value, FILTER_VALIDATE_EMAIL) || $value === '') {
658
+                    $targetUser->setEMailAddress($value);
659
+                } else {
660
+                    throw new OCSException('', 102);
661
+                }
662
+                break;
663
+            case IAccountManager::PROPERTY_PHONE:
664
+            case IAccountManager::PROPERTY_ADDRESS:
665
+            case IAccountManager::PROPERTY_WEBSITE:
666
+            case IAccountManager::PROPERTY_TWITTER:
667
+                $userAccount = $this->accountManager->getUser($targetUser);
668
+                if ($userAccount[$key]['value'] !== $value) {
669
+                    $userAccount[$key]['value'] = $value;
670
+                    try {
671
+                        $this->accountManager->updateUser($targetUser, $userAccount, true);
672
+                    } catch (\InvalidArgumentException $e) {
673
+                        throw new OCSException('Invalid ' . $e->getMessage(), 102);
674
+                    }
675
+                }
676
+                break;
677
+            default:
678
+                throw new OCSException('', 103);
679
+        }
680
+        return new DataResponse();
681
+    }
682
+
683
+    /**
684
+     * @PasswordConfirmationRequired
685
+     * @NoAdminRequired
686
+     *
687
+     * @param string $userId
688
+     *
689
+     * @return DataResponse
690
+     *
691
+     * @throws OCSException
692
+     */
693
+    public function wipeUserDevices(string $userId): DataResponse {
694
+        /** @var IUser $currentLoggedInUser */
695
+        $currentLoggedInUser = $this->userSession->getUser();
696
+
697
+        $targetUser = $this->userManager->get($userId);
698
+
699
+        if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
700
+            throw new OCSException('', 101);
701
+        }
702
+
703
+        // If not permitted
704
+        $subAdminManager = $this->groupManager->getSubAdmin();
705
+        if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
706
+            throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
707
+        }
708
+
709
+        $this->remoteWipe->markAllTokensForWipe($targetUser);
710
+
711
+        return new DataResponse();
712
+    }
713
+
714
+    /**
715
+     * @PasswordConfirmationRequired
716
+     * @NoAdminRequired
717
+     *
718
+     * @param string $userId
719
+     * @return DataResponse
720
+     * @throws OCSException
721
+     */
722
+    public function deleteUser(string $userId): DataResponse {
723
+        $currentLoggedInUser = $this->userSession->getUser();
724
+
725
+        $targetUser = $this->userManager->get($userId);
726
+
727
+        if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
728
+            throw new OCSException('', 101);
729
+        }
730
+
731
+        // If not permitted
732
+        $subAdminManager = $this->groupManager->getSubAdmin();
733
+        if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
734
+            throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
735
+        }
736
+
737
+        // Go ahead with the delete
738
+        if ($targetUser->delete()) {
739
+            return new DataResponse();
740
+        } else {
741
+            throw new OCSException('', 101);
742
+        }
743
+    }
744
+
745
+    /**
746
+     * @PasswordConfirmationRequired
747
+     * @NoAdminRequired
748
+     *
749
+     * @param string $userId
750
+     * @return DataResponse
751
+     * @throws OCSException
752
+     * @throws OCSForbiddenException
753
+     */
754
+    public function disableUser(string $userId): DataResponse {
755
+        return $this->setEnabled($userId, false);
756
+    }
757
+
758
+    /**
759
+     * @PasswordConfirmationRequired
760
+     * @NoAdminRequired
761
+     *
762
+     * @param string $userId
763
+     * @return DataResponse
764
+     * @throws OCSException
765
+     * @throws OCSForbiddenException
766
+     */
767
+    public function enableUser(string $userId): DataResponse {
768
+        return $this->setEnabled($userId, true);
769
+    }
770
+
771
+    /**
772
+     * @param string $userId
773
+     * @param bool $value
774
+     * @return DataResponse
775
+     * @throws OCSException
776
+     */
777
+    private function setEnabled(string $userId, bool $value): DataResponse {
778
+        $currentLoggedInUser = $this->userSession->getUser();
779
+
780
+        $targetUser = $this->userManager->get($userId);
781
+        if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
782
+            throw new OCSException('', 101);
783
+        }
784
+
785
+        // If not permitted
786
+        $subAdminManager = $this->groupManager->getSubAdmin();
787
+        if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
788
+            throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
789
+        }
790
+
791
+        // enable/disable the user now
792
+        $targetUser->setEnabled($value);
793
+        return new DataResponse();
794
+    }
795
+
796
+    /**
797
+     * @NoAdminRequired
798
+     * @NoSubAdminRequired
799
+     *
800
+     * @param string $userId
801
+     * @return DataResponse
802
+     * @throws OCSException
803
+     */
804
+    public function getUsersGroups(string $userId): DataResponse {
805
+        $loggedInUser = $this->userSession->getUser();
806
+
807
+        $targetUser = $this->userManager->get($userId);
808
+        if ($targetUser === null) {
809
+            throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
810
+        }
811
+
812
+        if ($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
813
+            // Self lookup or admin lookup
814
+            return new DataResponse([
815
+                'groups' => $this->groupManager->getUserGroupIds($targetUser)
816
+            ]);
817
+        } else {
818
+            $subAdminManager = $this->groupManager->getSubAdmin();
819
+
820
+            // Looking up someone else
821
+            if ($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
822
+                // Return the group that the method caller is subadmin of for the user in question
823
+                /** @var IGroup[] $getSubAdminsGroups */
824
+                $getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
825
+                foreach ($getSubAdminsGroups as $key => $group) {
826
+                    $getSubAdminsGroups[$key] = $group->getGID();
827
+                }
828
+                $groups = array_intersect(
829
+                    $getSubAdminsGroups,
830
+                    $this->groupManager->getUserGroupIds($targetUser)
831
+                );
832
+                return new DataResponse(['groups' => $groups]);
833
+            } else {
834
+                // Not permitted
835
+                throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
836
+            }
837
+        }
838
+    }
839
+
840
+    /**
841
+     * @PasswordConfirmationRequired
842
+     * @NoAdminRequired
843
+     *
844
+     * @param string $userId
845
+     * @param string $groupid
846
+     * @return DataResponse
847
+     * @throws OCSException
848
+     */
849
+    public function addToGroup(string $userId, string $groupid = ''): DataResponse {
850
+        if ($groupid === '') {
851
+            throw new OCSException('', 101);
852
+        }
853
+
854
+        $group = $this->groupManager->get($groupid);
855
+        $targetUser = $this->userManager->get($userId);
856
+        if ($group === null) {
857
+            throw new OCSException('', 102);
858
+        }
859
+        if ($targetUser === null) {
860
+            throw new OCSException('', 103);
861
+        }
862
+
863
+        // If they're not an admin, check they are a subadmin of the group in question
864
+        $loggedInUser = $this->userSession->getUser();
865
+        $subAdminManager = $this->groupManager->getSubAdmin();
866
+        if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
867
+            throw new OCSException('', 104);
868
+        }
869
+
870
+        // Add user to group
871
+        $group->addUser($targetUser);
872
+        return new DataResponse();
873
+    }
874
+
875
+    /**
876
+     * @PasswordConfirmationRequired
877
+     * @NoAdminRequired
878
+     *
879
+     * @param string $userId
880
+     * @param string $groupid
881
+     * @return DataResponse
882
+     * @throws OCSException
883
+     */
884
+    public function removeFromGroup(string $userId, string $groupid): DataResponse {
885
+        $loggedInUser = $this->userSession->getUser();
886
+
887
+        if ($groupid === null || trim($groupid) === '') {
888
+            throw new OCSException('', 101);
889
+        }
890
+
891
+        $group = $this->groupManager->get($groupid);
892
+        if ($group === null) {
893
+            throw new OCSException('', 102);
894
+        }
895
+
896
+        $targetUser = $this->userManager->get($userId);
897
+        if ($targetUser === null) {
898
+            throw new OCSException('', 103);
899
+        }
900
+
901
+        // If they're not an admin, check they are a subadmin of the group in question
902
+        $subAdminManager = $this->groupManager->getSubAdmin();
903
+        if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
904
+            throw new OCSException('', 104);
905
+        }
906
+
907
+        // Check they aren't removing themselves from 'admin' or their 'subadmin; group
908
+        if ($targetUser->getUID() === $loggedInUser->getUID()) {
909
+            if ($this->groupManager->isAdmin($loggedInUser->getUID())) {
910
+                if ($group->getGID() === 'admin') {
911
+                    throw new OCSException('Cannot remove yourself from the admin group', 105);
912
+                }
913
+            } else {
914
+                // Not an admin, so the user must be a subadmin of this group, but that is not allowed.
915
+                throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105);
916
+            }
917
+        } elseif (!$this->groupManager->isAdmin($loggedInUser->getUID())) {
918
+            /** @var IGroup[] $subAdminGroups */
919
+            $subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
920
+            $subAdminGroups = array_map(function (IGroup $subAdminGroup) {
921
+                return $subAdminGroup->getGID();
922
+            }, $subAdminGroups);
923
+            $userGroups = $this->groupManager->getUserGroupIds($targetUser);
924
+            $userSubAdminGroups = array_intersect($subAdminGroups, $userGroups);
925
+
926
+            if (count($userSubAdminGroups) <= 1) {
927
+                // Subadmin must not be able to remove a user from all their subadmin groups.
928
+                throw new OCSException('Not viable to remove user from the last group you are SubAdmin of', 105);
929
+            }
930
+        }
931
+
932
+        // Remove user from group
933
+        $group->removeUser($targetUser);
934
+        return new DataResponse();
935
+    }
936
+
937
+    /**
938
+     * Creates a subadmin
939
+     *
940
+     * @PasswordConfirmationRequired
941
+     *
942
+     * @param string $userId
943
+     * @param string $groupid
944
+     * @return DataResponse
945
+     * @throws OCSException
946
+     */
947
+    public function addSubAdmin(string $userId, string $groupid): DataResponse {
948
+        $group = $this->groupManager->get($groupid);
949
+        $user = $this->userManager->get($userId);
950
+
951
+        // Check if the user exists
952
+        if ($user === null) {
953
+            throw new OCSException('User does not exist', 101);
954
+        }
955
+        // Check if group exists
956
+        if ($group === null) {
957
+            throw new OCSException('Group does not exist',  102);
958
+        }
959
+        // Check if trying to make subadmin of admin group
960
+        if ($group->getGID() === 'admin') {
961
+            throw new OCSException('Cannot create subadmins for admin group', 103);
962
+        }
963
+
964
+        $subAdminManager = $this->groupManager->getSubAdmin();
965
+
966
+        // We cannot be subadmin twice
967
+        if ($subAdminManager->isSubAdminOfGroup($user, $group)) {
968
+            return new DataResponse();
969
+        }
970
+        // Go
971
+        $subAdminManager->createSubAdmin($user, $group);
972
+        return new DataResponse();
973
+    }
974
+
975
+    /**
976
+     * Removes a subadmin from a group
977
+     *
978
+     * @PasswordConfirmationRequired
979
+     *
980
+     * @param string $userId
981
+     * @param string $groupid
982
+     * @return DataResponse
983
+     * @throws OCSException
984
+     */
985
+    public function removeSubAdmin(string $userId, string $groupid): DataResponse {
986
+        $group = $this->groupManager->get($groupid);
987
+        $user = $this->userManager->get($userId);
988
+        $subAdminManager = $this->groupManager->getSubAdmin();
989
+
990
+        // Check if the user exists
991
+        if ($user === null) {
992
+            throw new OCSException('User does not exist', 101);
993
+        }
994
+        // Check if the group exists
995
+        if ($group === null) {
996
+            throw new OCSException('Group does not exist', 101);
997
+        }
998
+        // Check if they are a subadmin of this said group
999
+        if (!$subAdminManager->isSubAdminOfGroup($user, $group)) {
1000
+            throw new OCSException('User is not a subadmin of this group', 102);
1001
+        }
1002
+
1003
+        // Go
1004
+        $subAdminManager->deleteSubAdmin($user, $group);
1005
+        return new DataResponse();
1006
+    }
1007
+
1008
+    /**
1009
+     * Get the groups a user is a subadmin of
1010
+     *
1011
+     * @param string $userId
1012
+     * @return DataResponse
1013
+     * @throws OCSException
1014
+     */
1015
+    public function getUserSubAdminGroups(string $userId): DataResponse {
1016
+        $groups = $this->getUserSubAdminGroupsData($userId);
1017
+        return new DataResponse($groups);
1018
+    }
1019
+
1020
+    /**
1021
+     * @NoAdminRequired
1022
+     * @PasswordConfirmationRequired
1023
+     *
1024
+     * resend welcome message
1025
+     *
1026
+     * @param string $userId
1027
+     * @return DataResponse
1028
+     * @throws OCSException
1029
+     */
1030
+    public function resendWelcomeMessage(string $userId): DataResponse {
1031
+        $currentLoggedInUser = $this->userSession->getUser();
1032
+
1033
+        $targetUser = $this->userManager->get($userId);
1034
+        if ($targetUser === null) {
1035
+            throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
1036
+        }
1037
+
1038
+        // Check if admin / subadmin
1039
+        $subAdminManager = $this->groupManager->getSubAdmin();
1040
+        if (!$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
1041
+            && !$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
1042
+            // No rights
1043
+            throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
1044
+        }
1045
+
1046
+        $email = $targetUser->getEMailAddress();
1047
+        if ($email === '' || $email === null) {
1048
+            throw new OCSException('Email address not available', 101);
1049
+        }
1050
+
1051
+        try {
1052
+            $emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false);
1053
+            $this->newUserMailHelper->sendMail($targetUser, $emailTemplate);
1054
+        } catch (\Exception $e) {
1055
+            $this->logger->error("Can't send new user mail to $email",
1056
+                [
1057
+                    'app' => 'settings',
1058
+                    'exception' => $e,
1059
+                ]
1060
+            );
1061
+            throw new OCSException('Sending email failed', 102);
1062
+        }
1063
+
1064
+        return new DataResponse();
1065
+    }
1066 1066
 }
Please login to merge, or discard this patch.
apps/provisioning_api/lib/Controller/GroupsController.php 1 patch
Indentation   +266 added lines, -266 removed lines patch added patch discarded remove patch
@@ -52,270 +52,270 @@
 block discarded – undo
52 52
 
53 53
 class GroupsController extends AUserData {
54 54
 
55
-	/** @var LoggerInterface */
56
-	private $logger;
57
-
58
-	public function __construct(string $appName,
59
-								IRequest $request,
60
-								IUserManager $userManager,
61
-								IConfig $config,
62
-								IGroupManager $groupManager,
63
-								IUserSession $userSession,
64
-								AccountManager $accountManager,
65
-								IFactory $l10nFactory,
66
-								LoggerInterface $logger) {
67
-		parent::__construct($appName,
68
-			$request,
69
-			$userManager,
70
-			$config,
71
-			$groupManager,
72
-			$userSession,
73
-			$accountManager,
74
-			$l10nFactory
75
-		);
76
-
77
-		$this->logger = $logger;
78
-	}
79
-
80
-	/**
81
-	 * returns a list of groups
82
-	 *
83
-	 * @NoAdminRequired
84
-	 *
85
-	 * @param string $search
86
-	 * @param int $limit
87
-	 * @param int $offset
88
-	 * @return DataResponse
89
-	 */
90
-	public function getGroups(string $search = '', int $limit = null, int $offset = 0): DataResponse {
91
-		$groups = $this->groupManager->search($search, $limit, $offset);
92
-		$groups = array_map(function ($group) {
93
-			/** @var IGroup $group */
94
-			return $group->getGID();
95
-		}, $groups);
96
-
97
-		return new DataResponse(['groups' => $groups]);
98
-	}
99
-
100
-	/**
101
-	 * returns a list of groups details with ids and displaynames
102
-	 *
103
-	 * @NoAdminRequired
104
-	 *
105
-	 * @param string $search
106
-	 * @param int $limit
107
-	 * @param int $offset
108
-	 * @return DataResponse
109
-	 */
110
-	public function getGroupsDetails(string $search = '', int $limit = null, int $offset = 0): DataResponse {
111
-		$groups = $this->groupManager->search($search, $limit, $offset);
112
-		$groups = array_map(function ($group) {
113
-			/** @var IGroup $group */
114
-			return [
115
-				'id' => $group->getGID(),
116
-				'displayname' => $group->getDisplayName(),
117
-				'usercount' => $group->count(),
118
-				'disabled' => $group->countDisabled(),
119
-				'canAdd' => $group->canAddUser(),
120
-				'canRemove' => $group->canRemoveUser(),
121
-			];
122
-		}, $groups);
123
-
124
-		return new DataResponse(['groups' => $groups]);
125
-	}
126
-
127
-	/**
128
-	 * @NoAdminRequired
129
-	 *
130
-	 * @param string $groupId
131
-	 * @return DataResponse
132
-	 * @throws OCSException
133
-	 *
134
-	 * @deprecated 14 Use getGroupUsers
135
-	 */
136
-	public function getGroup(string $groupId): DataResponse {
137
-		return $this->getGroupUsers($groupId);
138
-	}
139
-
140
-	/**
141
-	 * returns an array of users in the specified group
142
-	 *
143
-	 * @NoAdminRequired
144
-	 *
145
-	 * @param string $groupId
146
-	 * @return DataResponse
147
-	 * @throws OCSException
148
-	 */
149
-	public function getGroupUsers(string $groupId): DataResponse {
150
-		$groupId = urldecode($groupId);
151
-
152
-		$user = $this->userSession->getUser();
153
-		$isSubadminOfGroup = false;
154
-
155
-		// Check the group exists
156
-		$group = $this->groupManager->get($groupId);
157
-		if ($group !== null) {
158
-			$isSubadminOfGroup = $this->groupManager->getSubAdmin()->isSubAdminOfGroup($user, $group);
159
-		} else {
160
-			throw new OCSNotFoundException('The requested group could not be found');
161
-		}
162
-
163
-		// Check subadmin has access to this group
164
-		if ($this->groupManager->isAdmin($user->getUID())
165
-		   || $isSubadminOfGroup) {
166
-			$users = $this->groupManager->get($groupId)->getUsers();
167
-			$users = array_map(function ($user) {
168
-				/** @var IUser $user */
169
-				return $user->getUID();
170
-			}, $users);
171
-			$users = array_values($users);
172
-			return new DataResponse(['users' => $users]);
173
-		}
174
-
175
-		throw new OCSForbiddenException();
176
-	}
177
-
178
-	/**
179
-	 * returns an array of users details in the specified group
180
-	 *
181
-	 * @NoAdminRequired
182
-	 *
183
-	 * @param string $groupId
184
-	 * @param string $search
185
-	 * @param int $limit
186
-	 * @param int $offset
187
-	 * @return DataResponse
188
-	 * @throws OCSException
189
-	 */
190
-	public function getGroupUsersDetails(string $groupId, string $search = '', int $limit = null, int $offset = 0): DataResponse {
191
-		$groupId = urldecode($groupId);
192
-		$currentUser = $this->userSession->getUser();
193
-
194
-		// Check the group exists
195
-		$group = $this->groupManager->get($groupId);
196
-		if ($group !== null) {
197
-			$isSubadminOfGroup = $this->groupManager->getSubAdmin()->isSubAdminOfGroup($currentUser, $group);
198
-		} else {
199
-			throw new OCSException('The requested group could not be found', OCSController::RESPOND_NOT_FOUND);
200
-		}
201
-
202
-		// Check subadmin has access to this group
203
-		if ($this->groupManager->isAdmin($currentUser->getUID()) || $isSubadminOfGroup) {
204
-			$users = $group->searchUsers($search, $limit, $offset);
205
-
206
-			// Extract required number
207
-			$usersDetails = [];
208
-			foreach ($users as $user) {
209
-				try {
210
-					/** @var IUser $user */
211
-					$userId = (string)$user->getUID();
212
-					$userData = $this->getUserData($userId);
213
-					// Do not insert empty entry
214
-					if (!empty($userData)) {
215
-						$usersDetails[$userId] = $userData;
216
-					} else {
217
-						// Logged user does not have permissions to see this user
218
-						// only showing its id
219
-						$usersDetails[$userId] = ['id' => $userId];
220
-					}
221
-				} catch (OCSNotFoundException $e) {
222
-					// continue if a users ceased to exist.
223
-				}
224
-			}
225
-			return new DataResponse(['users' => $usersDetails]);
226
-		}
227
-
228
-		throw new OCSException('User does not have access to specified group', OCSController::RESPOND_UNAUTHORISED);
229
-	}
230
-
231
-	/**
232
-	 * creates a new group
233
-	 *
234
-	 * @PasswordConfirmationRequired
235
-	 *
236
-	 * @param string $groupid
237
-	 * @return DataResponse
238
-	 * @throws OCSException
239
-	 */
240
-	public function addGroup(string $groupid): DataResponse {
241
-		// Validate name
242
-		if (empty($groupid)) {
243
-			$this->logger->error('Group name not supplied', ['app' => 'provisioning_api']);
244
-			throw new OCSException('Invalid group name', 101);
245
-		}
246
-		// Check if it exists
247
-		if ($this->groupManager->groupExists($groupid)) {
248
-			throw new OCSException('group exists', 102);
249
-		}
250
-		$this->groupManager->createGroup($groupid);
251
-		return new DataResponse();
252
-	}
253
-
254
-	/**
255
-	 * @PasswordConfirmationRequired
256
-	 *
257
-	 * @param string $groupId
258
-	 * @param string $key
259
-	 * @param string $value
260
-	 * @return DataResponse
261
-	 * @throws OCSException
262
-	 */
263
-	public function updateGroup(string $groupId, string $key, string $value): DataResponse {
264
-		$groupId = urldecode($groupId);
265
-
266
-		if ($key === 'displayname') {
267
-			$group = $this->groupManager->get($groupId);
268
-			if ($group->setDisplayName($value)) {
269
-				return new DataResponse();
270
-			}
271
-
272
-			throw new OCSException('Not supported by backend', 101);
273
-		} else {
274
-			throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
275
-		}
276
-	}
277
-
278
-	/**
279
-	 * @PasswordConfirmationRequired
280
-	 *
281
-	 * @param string $groupId
282
-	 * @return DataResponse
283
-	 * @throws OCSException
284
-	 */
285
-	public function deleteGroup(string $groupId): DataResponse {
286
-		$groupId = urldecode($groupId);
287
-
288
-		// Check it exists
289
-		if (!$this->groupManager->groupExists($groupId)) {
290
-			throw new OCSException('', 101);
291
-		} elseif ($groupId === 'admin' || !$this->groupManager->get($groupId)->delete()) {
292
-			// Cannot delete admin group
293
-			throw new OCSException('', 102);
294
-		}
295
-
296
-		return new DataResponse();
297
-	}
298
-
299
-	/**
300
-	 * @param string $groupId
301
-	 * @return DataResponse
302
-	 * @throws OCSException
303
-	 */
304
-	public function getSubAdminsOfGroup(string $groupId): DataResponse {
305
-		// Check group exists
306
-		$targetGroup = $this->groupManager->get($groupId);
307
-		if ($targetGroup === null) {
308
-			throw new OCSException('Group does not exist', 101);
309
-		}
310
-
311
-		/** @var IUser[] $subadmins */
312
-		$subadmins = $this->groupManager->getSubAdmin()->getGroupsSubAdmins($targetGroup);
313
-		// New class returns IUser[] so convert back
314
-		$uids = [];
315
-		foreach ($subadmins as $user) {
316
-			$uids[] = $user->getUID();
317
-		}
318
-
319
-		return new DataResponse($uids);
320
-	}
55
+    /** @var LoggerInterface */
56
+    private $logger;
57
+
58
+    public function __construct(string $appName,
59
+                                IRequest $request,
60
+                                IUserManager $userManager,
61
+                                IConfig $config,
62
+                                IGroupManager $groupManager,
63
+                                IUserSession $userSession,
64
+                                AccountManager $accountManager,
65
+                                IFactory $l10nFactory,
66
+                                LoggerInterface $logger) {
67
+        parent::__construct($appName,
68
+            $request,
69
+            $userManager,
70
+            $config,
71
+            $groupManager,
72
+            $userSession,
73
+            $accountManager,
74
+            $l10nFactory
75
+        );
76
+
77
+        $this->logger = $logger;
78
+    }
79
+
80
+    /**
81
+     * returns a list of groups
82
+     *
83
+     * @NoAdminRequired
84
+     *
85
+     * @param string $search
86
+     * @param int $limit
87
+     * @param int $offset
88
+     * @return DataResponse
89
+     */
90
+    public function getGroups(string $search = '', int $limit = null, int $offset = 0): DataResponse {
91
+        $groups = $this->groupManager->search($search, $limit, $offset);
92
+        $groups = array_map(function ($group) {
93
+            /** @var IGroup $group */
94
+            return $group->getGID();
95
+        }, $groups);
96
+
97
+        return new DataResponse(['groups' => $groups]);
98
+    }
99
+
100
+    /**
101
+     * returns a list of groups details with ids and displaynames
102
+     *
103
+     * @NoAdminRequired
104
+     *
105
+     * @param string $search
106
+     * @param int $limit
107
+     * @param int $offset
108
+     * @return DataResponse
109
+     */
110
+    public function getGroupsDetails(string $search = '', int $limit = null, int $offset = 0): DataResponse {
111
+        $groups = $this->groupManager->search($search, $limit, $offset);
112
+        $groups = array_map(function ($group) {
113
+            /** @var IGroup $group */
114
+            return [
115
+                'id' => $group->getGID(),
116
+                'displayname' => $group->getDisplayName(),
117
+                'usercount' => $group->count(),
118
+                'disabled' => $group->countDisabled(),
119
+                'canAdd' => $group->canAddUser(),
120
+                'canRemove' => $group->canRemoveUser(),
121
+            ];
122
+        }, $groups);
123
+
124
+        return new DataResponse(['groups' => $groups]);
125
+    }
126
+
127
+    /**
128
+     * @NoAdminRequired
129
+     *
130
+     * @param string $groupId
131
+     * @return DataResponse
132
+     * @throws OCSException
133
+     *
134
+     * @deprecated 14 Use getGroupUsers
135
+     */
136
+    public function getGroup(string $groupId): DataResponse {
137
+        return $this->getGroupUsers($groupId);
138
+    }
139
+
140
+    /**
141
+     * returns an array of users in the specified group
142
+     *
143
+     * @NoAdminRequired
144
+     *
145
+     * @param string $groupId
146
+     * @return DataResponse
147
+     * @throws OCSException
148
+     */
149
+    public function getGroupUsers(string $groupId): DataResponse {
150
+        $groupId = urldecode($groupId);
151
+
152
+        $user = $this->userSession->getUser();
153
+        $isSubadminOfGroup = false;
154
+
155
+        // Check the group exists
156
+        $group = $this->groupManager->get($groupId);
157
+        if ($group !== null) {
158
+            $isSubadminOfGroup = $this->groupManager->getSubAdmin()->isSubAdminOfGroup($user, $group);
159
+        } else {
160
+            throw new OCSNotFoundException('The requested group could not be found');
161
+        }
162
+
163
+        // Check subadmin has access to this group
164
+        if ($this->groupManager->isAdmin($user->getUID())
165
+           || $isSubadminOfGroup) {
166
+            $users = $this->groupManager->get($groupId)->getUsers();
167
+            $users = array_map(function ($user) {
168
+                /** @var IUser $user */
169
+                return $user->getUID();
170
+            }, $users);
171
+            $users = array_values($users);
172
+            return new DataResponse(['users' => $users]);
173
+        }
174
+
175
+        throw new OCSForbiddenException();
176
+    }
177
+
178
+    /**
179
+     * returns an array of users details in the specified group
180
+     *
181
+     * @NoAdminRequired
182
+     *
183
+     * @param string $groupId
184
+     * @param string $search
185
+     * @param int $limit
186
+     * @param int $offset
187
+     * @return DataResponse
188
+     * @throws OCSException
189
+     */
190
+    public function getGroupUsersDetails(string $groupId, string $search = '', int $limit = null, int $offset = 0): DataResponse {
191
+        $groupId = urldecode($groupId);
192
+        $currentUser = $this->userSession->getUser();
193
+
194
+        // Check the group exists
195
+        $group = $this->groupManager->get($groupId);
196
+        if ($group !== null) {
197
+            $isSubadminOfGroup = $this->groupManager->getSubAdmin()->isSubAdminOfGroup($currentUser, $group);
198
+        } else {
199
+            throw new OCSException('The requested group could not be found', OCSController::RESPOND_NOT_FOUND);
200
+        }
201
+
202
+        // Check subadmin has access to this group
203
+        if ($this->groupManager->isAdmin($currentUser->getUID()) || $isSubadminOfGroup) {
204
+            $users = $group->searchUsers($search, $limit, $offset);
205
+
206
+            // Extract required number
207
+            $usersDetails = [];
208
+            foreach ($users as $user) {
209
+                try {
210
+                    /** @var IUser $user */
211
+                    $userId = (string)$user->getUID();
212
+                    $userData = $this->getUserData($userId);
213
+                    // Do not insert empty entry
214
+                    if (!empty($userData)) {
215
+                        $usersDetails[$userId] = $userData;
216
+                    } else {
217
+                        // Logged user does not have permissions to see this user
218
+                        // only showing its id
219
+                        $usersDetails[$userId] = ['id' => $userId];
220
+                    }
221
+                } catch (OCSNotFoundException $e) {
222
+                    // continue if a users ceased to exist.
223
+                }
224
+            }
225
+            return new DataResponse(['users' => $usersDetails]);
226
+        }
227
+
228
+        throw new OCSException('User does not have access to specified group', OCSController::RESPOND_UNAUTHORISED);
229
+    }
230
+
231
+    /**
232
+     * creates a new group
233
+     *
234
+     * @PasswordConfirmationRequired
235
+     *
236
+     * @param string $groupid
237
+     * @return DataResponse
238
+     * @throws OCSException
239
+     */
240
+    public function addGroup(string $groupid): DataResponse {
241
+        // Validate name
242
+        if (empty($groupid)) {
243
+            $this->logger->error('Group name not supplied', ['app' => 'provisioning_api']);
244
+            throw new OCSException('Invalid group name', 101);
245
+        }
246
+        // Check if it exists
247
+        if ($this->groupManager->groupExists($groupid)) {
248
+            throw new OCSException('group exists', 102);
249
+        }
250
+        $this->groupManager->createGroup($groupid);
251
+        return new DataResponse();
252
+    }
253
+
254
+    /**
255
+     * @PasswordConfirmationRequired
256
+     *
257
+     * @param string $groupId
258
+     * @param string $key
259
+     * @param string $value
260
+     * @return DataResponse
261
+     * @throws OCSException
262
+     */
263
+    public function updateGroup(string $groupId, string $key, string $value): DataResponse {
264
+        $groupId = urldecode($groupId);
265
+
266
+        if ($key === 'displayname') {
267
+            $group = $this->groupManager->get($groupId);
268
+            if ($group->setDisplayName($value)) {
269
+                return new DataResponse();
270
+            }
271
+
272
+            throw new OCSException('Not supported by backend', 101);
273
+        } else {
274
+            throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
275
+        }
276
+    }
277
+
278
+    /**
279
+     * @PasswordConfirmationRequired
280
+     *
281
+     * @param string $groupId
282
+     * @return DataResponse
283
+     * @throws OCSException
284
+     */
285
+    public function deleteGroup(string $groupId): DataResponse {
286
+        $groupId = urldecode($groupId);
287
+
288
+        // Check it exists
289
+        if (!$this->groupManager->groupExists($groupId)) {
290
+            throw new OCSException('', 101);
291
+        } elseif ($groupId === 'admin' || !$this->groupManager->get($groupId)->delete()) {
292
+            // Cannot delete admin group
293
+            throw new OCSException('', 102);
294
+        }
295
+
296
+        return new DataResponse();
297
+    }
298
+
299
+    /**
300
+     * @param string $groupId
301
+     * @return DataResponse
302
+     * @throws OCSException
303
+     */
304
+    public function getSubAdminsOfGroup(string $groupId): DataResponse {
305
+        // Check group exists
306
+        $targetGroup = $this->groupManager->get($groupId);
307
+        if ($targetGroup === null) {
308
+            throw new OCSException('Group does not exist', 101);
309
+        }
310
+
311
+        /** @var IUser[] $subadmins */
312
+        $subadmins = $this->groupManager->getSubAdmin()->getGroupsSubAdmins($targetGroup);
313
+        // New class returns IUser[] so convert back
314
+        $uids = [];
315
+        foreach ($subadmins as $user) {
316
+            $uids[] = $user->getUID();
317
+        }
318
+
319
+        return new DataResponse($uids);
320
+    }
321 321
 }
Please login to merge, or discard this patch.
apps/provisioning_api/lib/Controller/AppsController.php 1 patch
Indentation   +73 added lines, -73 removed lines patch added patch discarded remove patch
@@ -39,84 +39,84 @@
 block discarded – undo
39 39
 use OCP\IRequest;
40 40
 
41 41
 class AppsController extends OCSController {
42
-	/** @var IAppManager */
43
-	private $appManager;
42
+    /** @var IAppManager */
43
+    private $appManager;
44 44
 
45
-	public function __construct(
46
-		string $appName,
47
-		IRequest $request,
48
-		IAppManager $appManager
49
-	) {
50
-		parent::__construct($appName, $request);
45
+    public function __construct(
46
+        string $appName,
47
+        IRequest $request,
48
+        IAppManager $appManager
49
+    ) {
50
+        parent::__construct($appName, $request);
51 51
 
52
-		$this->appManager = $appManager;
53
-	}
52
+        $this->appManager = $appManager;
53
+    }
54 54
 
55
-	/**
56
-	 * @param string|null $filter
57
-	 * @return DataResponse
58
-	 * @throws OCSException
59
-	 */
60
-	public function getApps(string $filter = null): DataResponse {
61
-		$apps = (new OC_App())->listAllApps();
62
-		$list = [];
63
-		foreach ($apps as $app) {
64
-			$list[] = $app['id'];
65
-		}
66
-		if ($filter) {
67
-			switch ($filter) {
68
-				case 'enabled':
69
-					return new DataResponse(['apps' => \OC_App::getEnabledApps()]);
70
-					break;
71
-				case 'disabled':
72
-					$enabled = OC_App::getEnabledApps();
73
-					return new DataResponse(['apps' => array_diff($list, $enabled)]);
74
-					break;
75
-				default:
76
-					// Invalid filter variable
77
-					throw new OCSException('', 101);
78
-			}
79
-		} else {
80
-			return new DataResponse(['apps' => $list]);
81
-		}
82
-	}
55
+    /**
56
+     * @param string|null $filter
57
+     * @return DataResponse
58
+     * @throws OCSException
59
+     */
60
+    public function getApps(string $filter = null): DataResponse {
61
+        $apps = (new OC_App())->listAllApps();
62
+        $list = [];
63
+        foreach ($apps as $app) {
64
+            $list[] = $app['id'];
65
+        }
66
+        if ($filter) {
67
+            switch ($filter) {
68
+                case 'enabled':
69
+                    return new DataResponse(['apps' => \OC_App::getEnabledApps()]);
70
+                    break;
71
+                case 'disabled':
72
+                    $enabled = OC_App::getEnabledApps();
73
+                    return new DataResponse(['apps' => array_diff($list, $enabled)]);
74
+                    break;
75
+                default:
76
+                    // Invalid filter variable
77
+                    throw new OCSException('', 101);
78
+            }
79
+        } else {
80
+            return new DataResponse(['apps' => $list]);
81
+        }
82
+    }
83 83
 
84
-	/**
85
-	 * @param string $app
86
-	 * @return DataResponse
87
-	 * @throws OCSException
88
-	 */
89
-	public function getAppInfo(string $app): DataResponse {
90
-		$info = $this->appManager->getAppInfo($app);
91
-		if (!is_null($info)) {
92
-			return new DataResponse($info);
93
-		}
84
+    /**
85
+     * @param string $app
86
+     * @return DataResponse
87
+     * @throws OCSException
88
+     */
89
+    public function getAppInfo(string $app): DataResponse {
90
+        $info = $this->appManager->getAppInfo($app);
91
+        if (!is_null($info)) {
92
+            return new DataResponse($info);
93
+        }
94 94
 
95
-		throw new OCSException('The request app was not found', OCSController::RESPOND_NOT_FOUND);
96
-	}
95
+        throw new OCSException('The request app was not found', OCSController::RESPOND_NOT_FOUND);
96
+    }
97 97
 
98
-	/**
99
-	 * @PasswordConfirmationRequired
100
-	 * @param string $app
101
-	 * @return DataResponse
102
-	 * @throws OCSException
103
-	 */
104
-	public function enable(string $app): DataResponse {
105
-		try {
106
-			$this->appManager->enableApp($app);
107
-		} catch (AppPathNotFoundException $e) {
108
-			throw new OCSException('The request app was not found', OCSController::RESPOND_NOT_FOUND);
109
-		}
110
-		return new DataResponse();
111
-	}
98
+    /**
99
+     * @PasswordConfirmationRequired
100
+     * @param string $app
101
+     * @return DataResponse
102
+     * @throws OCSException
103
+     */
104
+    public function enable(string $app): DataResponse {
105
+        try {
106
+            $this->appManager->enableApp($app);
107
+        } catch (AppPathNotFoundException $e) {
108
+            throw new OCSException('The request app was not found', OCSController::RESPOND_NOT_FOUND);
109
+        }
110
+        return new DataResponse();
111
+    }
112 112
 
113
-	/**
114
-	 * @PasswordConfirmationRequired
115
-	 * @param string $app
116
-	 * @return DataResponse
117
-	 */
118
-	public function disable(string $app): DataResponse {
119
-		$this->appManager->disableApp($app);
120
-		return new DataResponse();
121
-	}
113
+    /**
114
+     * @PasswordConfirmationRequired
115
+     * @param string $app
116
+     * @return DataResponse
117
+     */
118
+    public function disable(string $app): DataResponse {
119
+        $this->appManager->disableApp($app);
120
+        return new DataResponse();
121
+    }
122 122
 }
Please login to merge, or discard this patch.
ocs/v1.php 1 patch
Indentation   +32 added lines, -32 removed lines patch added patch discarded remove patch
@@ -32,13 +32,13 @@  discard block
 block discarded – undo
32 32
 require_once __DIR__ . '/../lib/base.php';
33 33
 
34 34
 if (\OCP\Util::needUpgrade()
35
-	|| \OC::$server->getConfig()->getSystemValueBool('maintenance')) {
36
-	// since the behavior of apps or remotes are unpredictable during
37
-	// an upgrade, return a 503 directly
38
-	http_response_code(503);
39
-	$response = new \OC\OCS\Result(null, 503, 'Service unavailable');
40
-	OC_API::respond($response, OC_API::requestedFormat());
41
-	exit;
35
+    || \OC::$server->getConfig()->getSystemValueBool('maintenance')) {
36
+    // since the behavior of apps or remotes are unpredictable during
37
+    // an upgrade, return a 503 directly
38
+    http_response_code(503);
39
+    $response = new \OC\OCS\Result(null, 503, 'Service unavailable');
40
+    OC_API::respond($response, OC_API::requestedFormat());
41
+    exit;
42 42
 }
43 43
 
44 44
 use Symfony\Component\Routing\Exception\ResourceNotFoundException;
@@ -48,39 +48,39 @@  discard block
 block discarded – undo
48 48
  * Try the appframework routes
49 49
  */
50 50
 try {
51
-	OC_App::loadApps(['session']);
52
-	OC_App::loadApps(['authentication']);
51
+    OC_App::loadApps(['session']);
52
+    OC_App::loadApps(['authentication']);
53 53
 
54
-	// load all apps to get all api routes properly setup
55
-	// FIXME: this should ideally appear after handleLogin but will cause
56
-	// side effects in existing apps
57
-	OC_App::loadApps();
54
+    // load all apps to get all api routes properly setup
55
+    // FIXME: this should ideally appear after handleLogin but will cause
56
+    // side effects in existing apps
57
+    OC_App::loadApps();
58 58
 
59
-	if (!\OC::$server->getUserSession()->isLoggedIn()) {
60
-		OC::handleLogin(\OC::$server->getRequest());
61
-	}
59
+    if (!\OC::$server->getUserSession()->isLoggedIn()) {
60
+        OC::handleLogin(\OC::$server->getRequest());
61
+    }
62 62
 
63
-	OC::$server->get(\OC\Route\Router::class)->match('/ocsapp'.\OC::$server->getRequest()->getRawPathInfo());
63
+    OC::$server->get(\OC\Route\Router::class)->match('/ocsapp'.\OC::$server->getRequest()->getRawPathInfo());
64 64
 } catch (ResourceNotFoundException $e) {
65
-	OC_API::setContentType();
65
+    OC_API::setContentType();
66 66
 
67
-	$format = \OC::$server->getRequest()->getParam('format', 'xml');
68
-	$txt = 'Invalid query, please check the syntax. API specifications are here:'
69
-		.' http://www.freedesktop.org/wiki/Specifications/open-collaboration-services.'."\n";
70
-	OC_API::respond(new \OC\OCS\Result(null, \OCP\AppFramework\OCSController::RESPOND_NOT_FOUND, $txt), $format);
67
+    $format = \OC::$server->getRequest()->getParam('format', 'xml');
68
+    $txt = 'Invalid query, please check the syntax. API specifications are here:'
69
+        .' http://www.freedesktop.org/wiki/Specifications/open-collaboration-services.'."\n";
70
+    OC_API::respond(new \OC\OCS\Result(null, \OCP\AppFramework\OCSController::RESPOND_NOT_FOUND, $txt), $format);
71 71
 } catch (MethodNotAllowedException $e) {
72
-	OC_API::setContentType();
73
-	http_response_code(405);
72
+    OC_API::setContentType();
73
+    http_response_code(405);
74 74
 } catch (\OC\OCS\Exception $ex) {
75
-	OC_API::respond($ex->getResult(), OC_API::requestedFormat());
75
+    OC_API::respond($ex->getResult(), OC_API::requestedFormat());
76 76
 } catch (\OC\User\LoginException $e) {
77
-	OC_API::respond(new \OC\OCS\Result(null, \OCP\AppFramework\OCSController::RESPOND_UNAUTHORISED, 'Unauthorised'));
77
+    OC_API::respond(new \OC\OCS\Result(null, \OCP\AppFramework\OCSController::RESPOND_UNAUTHORISED, 'Unauthorised'));
78 78
 } catch (\Exception $e) {
79
-	\OC::$server->getLogger()->logException($e);
80
-	OC_API::setContentType();
79
+    \OC::$server->getLogger()->logException($e);
80
+    OC_API::setContentType();
81 81
 
82
-	$format = \OC::$server->getRequest()->getParam('format', 'xml');
83
-	$txt = 'Invalid query, please check the syntax. API specifications are here:'
84
-		.' http://www.freedesktop.org/wiki/Specifications/open-collaboration-services.'."\n";
85
-	OC_API::respond(new \OC\OCS\Result(null, \OCP\AppFramework\OCSController::RESPOND_NOT_FOUND, $txt), $format);
82
+    $format = \OC::$server->getRequest()->getParam('format', 'xml');
83
+    $txt = 'Invalid query, please check the syntax. API specifications are here:'
84
+        .' http://www.freedesktop.org/wiki/Specifications/open-collaboration-services.'."\n";
85
+    OC_API::respond(new \OC\OCS\Result(null, \OCP\AppFramework\OCSController::RESPOND_NOT_FOUND, $txt), $format);
86 86
 }
Please login to merge, or discard this patch.
lib/public/AppFramework/OCSController.php 1 patch
Indentation   +68 added lines, -68 removed lines patch added patch discarded remove patch
@@ -42,77 +42,77 @@
 block discarded – undo
42 42
  * @since 8.1.0
43 43
  */
44 44
 abstract class OCSController extends ApiController {
45
-	public const RESPOND_UNAUTHORISED = 997;
46
-	public const RESPOND_SERVER_ERROR = 996;
47
-	public const RESPOND_NOT_FOUND = 998;
48
-	public const RESPOND_UNKNOWN_ERROR = 999;
45
+    public const RESPOND_UNAUTHORISED = 997;
46
+    public const RESPOND_SERVER_ERROR = 996;
47
+    public const RESPOND_NOT_FOUND = 998;
48
+    public const RESPOND_UNKNOWN_ERROR = 999;
49 49
 
50
-	/** @var int */
51
-	private $ocsVersion;
50
+    /** @var int */
51
+    private $ocsVersion;
52 52
 
53
-	/**
54
-	 * constructor of the controller
55
-	 * @param string $appName the name of the app
56
-	 * @param IRequest $request an instance of the request
57
-	 * @param string $corsMethods comma separated string of HTTP verbs which
58
-	 * should be allowed for websites or webapps when calling your API, defaults to
59
-	 * 'PUT, POST, GET, DELETE, PATCH'
60
-	 * @param string $corsAllowedHeaders comma separated string of HTTP headers
61
-	 * which should be allowed for websites or webapps when calling your API,
62
-	 * defaults to 'Authorization, Content-Type, Accept'
63
-	 * @param int $corsMaxAge number in seconds how long a preflighted OPTIONS
64
-	 * request should be cached, defaults to 1728000 seconds
65
-	 * @since 8.1.0
66
-	 */
67
-	public function __construct($appName,
68
-								IRequest $request,
69
-								$corsMethods = 'PUT, POST, GET, DELETE, PATCH',
70
-								$corsAllowedHeaders = 'Authorization, Content-Type, Accept',
71
-								$corsMaxAge = 1728000) {
72
-		parent::__construct($appName, $request, $corsMethods,
73
-							$corsAllowedHeaders, $corsMaxAge);
74
-		$this->registerResponder('json', function ($data) {
75
-			return $this->buildOCSResponse('json', $data);
76
-		});
77
-		$this->registerResponder('xml', function ($data) {
78
-			return $this->buildOCSResponse('xml', $data);
79
-		});
80
-	}
53
+    /**
54
+     * constructor of the controller
55
+     * @param string $appName the name of the app
56
+     * @param IRequest $request an instance of the request
57
+     * @param string $corsMethods comma separated string of HTTP verbs which
58
+     * should be allowed for websites or webapps when calling your API, defaults to
59
+     * 'PUT, POST, GET, DELETE, PATCH'
60
+     * @param string $corsAllowedHeaders comma separated string of HTTP headers
61
+     * which should be allowed for websites or webapps when calling your API,
62
+     * defaults to 'Authorization, Content-Type, Accept'
63
+     * @param int $corsMaxAge number in seconds how long a preflighted OPTIONS
64
+     * request should be cached, defaults to 1728000 seconds
65
+     * @since 8.1.0
66
+     */
67
+    public function __construct($appName,
68
+                                IRequest $request,
69
+                                $corsMethods = 'PUT, POST, GET, DELETE, PATCH',
70
+                                $corsAllowedHeaders = 'Authorization, Content-Type, Accept',
71
+                                $corsMaxAge = 1728000) {
72
+        parent::__construct($appName, $request, $corsMethods,
73
+                            $corsAllowedHeaders, $corsMaxAge);
74
+        $this->registerResponder('json', function ($data) {
75
+            return $this->buildOCSResponse('json', $data);
76
+        });
77
+        $this->registerResponder('xml', function ($data) {
78
+            return $this->buildOCSResponse('xml', $data);
79
+        });
80
+    }
81 81
 
82
-	/**
83
-	 * @param int $version
84
-	 * @since 11.0.0
85
-	 * @internal
86
-	 */
87
-	public function setOCSVersion($version) {
88
-		$this->ocsVersion = $version;
89
-	}
82
+    /**
83
+     * @param int $version
84
+     * @since 11.0.0
85
+     * @internal
86
+     */
87
+    public function setOCSVersion($version) {
88
+        $this->ocsVersion = $version;
89
+    }
90 90
 
91
-	/**
92
-	 * Since the OCS endpoints default to XML we need to find out the format
93
-	 * again
94
-	 * @param mixed $response the value that was returned from a controller and
95
-	 * is not a Response instance
96
-	 * @param string $format the format for which a formatter has been registered
97
-	 * @throws \DomainException if format does not match a registered formatter
98
-	 * @return Response
99
-	 * @since 9.1.0
100
-	 */
101
-	public function buildResponse($response, $format = 'xml') {
102
-		return parent::buildResponse($response, $format);
103
-	}
91
+    /**
92
+     * Since the OCS endpoints default to XML we need to find out the format
93
+     * again
94
+     * @param mixed $response the value that was returned from a controller and
95
+     * is not a Response instance
96
+     * @param string $format the format for which a formatter has been registered
97
+     * @throws \DomainException if format does not match a registered formatter
98
+     * @return Response
99
+     * @since 9.1.0
100
+     */
101
+    public function buildResponse($response, $format = 'xml') {
102
+        return parent::buildResponse($response, $format);
103
+    }
104 104
 
105
-	/**
106
-	 * Unwrap data and build ocs response
107
-	 * @param string $format json or xml
108
-	 * @param DataResponse $data the data which should be transformed
109
-	 * @since 8.1.0
110
-	 * @return \OC\AppFramework\OCS\BaseResponse
111
-	 */
112
-	private function buildOCSResponse($format, DataResponse $data) {
113
-		if ($this->ocsVersion === 1) {
114
-			return new \OC\AppFramework\OCS\V1Response($data, $format);
115
-		}
116
-		return new \OC\AppFramework\OCS\V2Response($data, $format);
117
-	}
105
+    /**
106
+     * Unwrap data and build ocs response
107
+     * @param string $format json or xml
108
+     * @param DataResponse $data the data which should be transformed
109
+     * @since 8.1.0
110
+     * @return \OC\AppFramework\OCS\BaseResponse
111
+     */
112
+    private function buildOCSResponse($format, DataResponse $data) {
113
+        if ($this->ocsVersion === 1) {
114
+            return new \OC\AppFramework\OCS\V1Response($data, $format);
115
+        }
116
+        return new \OC\AppFramework\OCS\V2Response($data, $format);
117
+    }
118 118
 }
Please login to merge, or discard this patch.
lib/private/Remote/Api/OCS.php 1 patch
Indentation   +62 added lines, -62 removed lines patch added patch discarded remove patch
@@ -32,70 +32,70 @@
 block discarded – undo
32 32
 use OCP\Remote\Api\IUserApi;
33 33
 
34 34
 class OCS extends ApiBase implements ICapabilitiesApi, IUserApi {
35
-	/**
36
-	 * @param string $method
37
-	 * @param string $url
38
-	 * @param array $body
39
-	 * @param array $query
40
-	 * @param array $headers
41
-	 * @return array
42
-	 * @throws ForbiddenException
43
-	 * @throws NotFoundException
44
-	 * @throws \Exception
45
-	 */
46
-	protected function request($method, $url, array $body = [], array $query = [], array $headers = []) {
47
-		try {
48
-			$response = json_decode(parent::request($method, 'ocs/v2.php/' . $url, $body, $query, $headers), true);
49
-		} catch (ClientException $e) {
50
-			if ($e->getResponse()->getStatusCode() === 404) {
51
-				throw new NotFoundException();
52
-			} elseif ($e->getResponse()->getStatusCode() === 403 || $e->getResponse()->getStatusCode() === 401) {
53
-				throw new ForbiddenException();
54
-			} else {
55
-				throw $e;
56
-			}
57
-		}
58
-		if (!isset($response['ocs']) || !isset($response['ocs']['meta'])) {
59
-			throw new \Exception('Invalid ocs response');
60
-		}
61
-		if ($response['ocs']['meta']['statuscode'] === OCSController::RESPOND_UNAUTHORISED) {
62
-			throw new ForbiddenException();
63
-		}
64
-		if ($response['ocs']['meta']['statuscode'] === OCSController::RESPOND_NOT_FOUND) {
65
-			throw new NotFoundException();
66
-		}
67
-		if ($response['ocs']['meta']['status'] !== 'ok') {
68
-			throw new \Exception('Unknown ocs error ' . $response['ocs']['meta']['message']);
69
-		}
35
+    /**
36
+     * @param string $method
37
+     * @param string $url
38
+     * @param array $body
39
+     * @param array $query
40
+     * @param array $headers
41
+     * @return array
42
+     * @throws ForbiddenException
43
+     * @throws NotFoundException
44
+     * @throws \Exception
45
+     */
46
+    protected function request($method, $url, array $body = [], array $query = [], array $headers = []) {
47
+        try {
48
+            $response = json_decode(parent::request($method, 'ocs/v2.php/' . $url, $body, $query, $headers), true);
49
+        } catch (ClientException $e) {
50
+            if ($e->getResponse()->getStatusCode() === 404) {
51
+                throw new NotFoundException();
52
+            } elseif ($e->getResponse()->getStatusCode() === 403 || $e->getResponse()->getStatusCode() === 401) {
53
+                throw new ForbiddenException();
54
+            } else {
55
+                throw $e;
56
+            }
57
+        }
58
+        if (!isset($response['ocs']) || !isset($response['ocs']['meta'])) {
59
+            throw new \Exception('Invalid ocs response');
60
+        }
61
+        if ($response['ocs']['meta']['statuscode'] === OCSController::RESPOND_UNAUTHORISED) {
62
+            throw new ForbiddenException();
63
+        }
64
+        if ($response['ocs']['meta']['statuscode'] === OCSController::RESPOND_NOT_FOUND) {
65
+            throw new NotFoundException();
66
+        }
67
+        if ($response['ocs']['meta']['status'] !== 'ok') {
68
+            throw new \Exception('Unknown ocs error ' . $response['ocs']['meta']['message']);
69
+        }
70 70
 
71
-		return $response['ocs']['data'];
72
-	}
71
+        return $response['ocs']['data'];
72
+    }
73 73
 
74
-	/**
75
-	 * @param array $data
76
-	 * @param string $type
77
-	 * @param string[] $keys
78
-	 * @throws \Exception
79
-	 */
80
-	private function checkResponseArray(array $data, $type, array $keys) {
81
-		foreach ($keys as $key) {
82
-			if (!array_key_exists($key, $data)) {
83
-				throw new \Exception('Invalid ' . $type . ' response, expected field ' . $key . ' not found');
84
-			}
85
-		}
86
-	}
74
+    /**
75
+     * @param array $data
76
+     * @param string $type
77
+     * @param string[] $keys
78
+     * @throws \Exception
79
+     */
80
+    private function checkResponseArray(array $data, $type, array $keys) {
81
+        foreach ($keys as $key) {
82
+            if (!array_key_exists($key, $data)) {
83
+                throw new \Exception('Invalid ' . $type . ' response, expected field ' . $key . ' not found');
84
+            }
85
+        }
86
+    }
87 87
 
88
-	public function getUser($userId) {
89
-		$result = $this->request('get', 'cloud/users/' . $userId);
90
-		$this->checkResponseArray($result, 'user', User::EXPECTED_KEYS);
91
-		return new User($result);
92
-	}
88
+    public function getUser($userId) {
89
+        $result = $this->request('get', 'cloud/users/' . $userId);
90
+        $this->checkResponseArray($result, 'user', User::EXPECTED_KEYS);
91
+        return new User($result);
92
+    }
93 93
 
94
-	/**
95
-	 * @return array The capabilities in the form of [$appId => [$capability => $value]]
96
-	 */
97
-	public function getCapabilities() {
98
-		$result = $this->request('get', 'cloud/capabilities');
99
-		return $result['capabilities'];
100
-	}
94
+    /**
95
+     * @return array The capabilities in the form of [$appId => [$capability => $value]]
96
+     */
97
+    public function getCapabilities() {
98
+        $result = $this->request('get', 'cloud/capabilities');
99
+        return $result['capabilities'];
100
+    }
101 101
 }
Please login to merge, or discard this patch.
lib/private/AppFramework/OCS/V1Response.php 1 patch
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -29,52 +29,52 @@
 block discarded – undo
29 29
 
30 30
 class V1Response extends BaseResponse {
31 31
 
32
-	/**
33
-	 * The V1 endpoint has very limited http status codes basically everything
34
-	 * is status 200 except 401
35
-	 *
36
-	 * @return int
37
-	 */
38
-	public function getStatus() {
39
-		$status = parent::getStatus();
40
-		if ($status === Http::STATUS_FORBIDDEN || $status === OCSController::RESPOND_UNAUTHORISED) {
41
-			return Http::STATUS_UNAUTHORIZED;
42
-		}
32
+    /**
33
+     * The V1 endpoint has very limited http status codes basically everything
34
+     * is status 200 except 401
35
+     *
36
+     * @return int
37
+     */
38
+    public function getStatus() {
39
+        $status = parent::getStatus();
40
+        if ($status === Http::STATUS_FORBIDDEN || $status === OCSController::RESPOND_UNAUTHORISED) {
41
+            return Http::STATUS_UNAUTHORIZED;
42
+        }
43 43
 
44
-		return Http::STATUS_OK;
45
-	}
44
+        return Http::STATUS_OK;
45
+    }
46 46
 
47
-	/**
48
-	 * In v1 all OK is 100
49
-	 *
50
-	 * @return int
51
-	 */
52
-	public function getOCSStatus() {
53
-		$status = parent::getOCSStatus();
47
+    /**
48
+     * In v1 all OK is 100
49
+     *
50
+     * @return int
51
+     */
52
+    public function getOCSStatus() {
53
+        $status = parent::getOCSStatus();
54 54
 
55
-		if ($status === Http::STATUS_OK) {
56
-			return 100;
57
-		}
55
+        if ($status === Http::STATUS_OK) {
56
+            return 100;
57
+        }
58 58
 
59
-		return $status;
60
-	}
59
+        return $status;
60
+    }
61 61
 
62
-	/**
63
-	 * Construct the meta part of the response
64
-	 * And then late the base class render
65
-	 *
66
-	 * @return string
67
-	 */
68
-	public function render() {
69
-		$meta = [
70
-			'status' => $this->getOCSStatus() === 100 ? 'ok' : 'failure',
71
-			'statuscode' => $this->getOCSStatus(),
72
-			'message' => $this->getOCSStatus() === 100 ? 'OK' : $this->statusMessage,
73
-		];
62
+    /**
63
+     * Construct the meta part of the response
64
+     * And then late the base class render
65
+     *
66
+     * @return string
67
+     */
68
+    public function render() {
69
+        $meta = [
70
+            'status' => $this->getOCSStatus() === 100 ? 'ok' : 'failure',
71
+            'statuscode' => $this->getOCSStatus(),
72
+            'message' => $this->getOCSStatus() === 100 ? 'OK' : $this->statusMessage,
73
+        ];
74 74
 
75
-		$meta['totalitems'] = $this->itemsCount !== null ? (string)$this->itemsCount : '';
76
-		$meta['itemsperpage'] = $this->itemsPerPage !== null ? (string)$this->itemsPerPage: '';
75
+        $meta['totalitems'] = $this->itemsCount !== null ? (string)$this->itemsCount : '';
76
+        $meta['itemsperpage'] = $this->itemsPerPage !== null ? (string)$this->itemsPerPage: '';
77 77
 
78
-		return $this->renderResult($meta);
79
-	}
78
+        return $this->renderResult($meta);
79
+    }
80 80
 }
Please login to merge, or discard this patch.
lib/private/AppFramework/OCS/V2Response.php 1 patch
Indentation   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -29,49 +29,49 @@
 block discarded – undo
29 29
 
30 30
 class V2Response extends BaseResponse {
31 31
 
32
-	/**
33
-	 * The V2 endpoint just passes on status codes.
34
-	 * Of course we have to map the OCS specific codes to proper HTTP status codes
35
-	 *
36
-	 * @return int
37
-	 */
38
-	public function getStatus() {
39
-		$status = parent::getStatus();
40
-		if ($status === OCSController::RESPOND_UNAUTHORISED) {
41
-			return Http::STATUS_UNAUTHORIZED;
42
-		} elseif ($status === OCSController::RESPOND_NOT_FOUND) {
43
-			return Http::STATUS_NOT_FOUND;
44
-		} elseif ($status === OCSController::RESPOND_SERVER_ERROR || $status === OCSController::RESPOND_UNKNOWN_ERROR) {
45
-			return Http::STATUS_INTERNAL_SERVER_ERROR;
46
-		} elseif ($status < 200 || $status > 600) {
47
-			return Http::STATUS_BAD_REQUEST;
48
-		}
32
+    /**
33
+     * The V2 endpoint just passes on status codes.
34
+     * Of course we have to map the OCS specific codes to proper HTTP status codes
35
+     *
36
+     * @return int
37
+     */
38
+    public function getStatus() {
39
+        $status = parent::getStatus();
40
+        if ($status === OCSController::RESPOND_UNAUTHORISED) {
41
+            return Http::STATUS_UNAUTHORIZED;
42
+        } elseif ($status === OCSController::RESPOND_NOT_FOUND) {
43
+            return Http::STATUS_NOT_FOUND;
44
+        } elseif ($status === OCSController::RESPOND_SERVER_ERROR || $status === OCSController::RESPOND_UNKNOWN_ERROR) {
45
+            return Http::STATUS_INTERNAL_SERVER_ERROR;
46
+        } elseif ($status < 200 || $status > 600) {
47
+            return Http::STATUS_BAD_REQUEST;
48
+        }
49 49
 
50
-		return $status;
51
-	}
50
+        return $status;
51
+    }
52 52
 
53
-	/**
54
-	 * Construct the meta part of the response
55
-	 * And then late the base class render
56
-	 *
57
-	 * @return string
58
-	 */
59
-	public function render() {
60
-		$status = parent::getStatus();
53
+    /**
54
+     * Construct the meta part of the response
55
+     * And then late the base class render
56
+     *
57
+     * @return string
58
+     */
59
+    public function render() {
60
+        $status = parent::getStatus();
61 61
 
62
-		$meta = [
63
-			'status' => $status >= 200 && $status < 300 ? 'ok' : 'failure',
64
-			'statuscode' => $this->getOCSStatus(),
65
-			'message' => $status >= 200 && $status < 300 ? 'OK' : $this->statusMessage,
66
-		];
62
+        $meta = [
63
+            'status' => $status >= 200 && $status < 300 ? 'ok' : 'failure',
64
+            'statuscode' => $this->getOCSStatus(),
65
+            'message' => $status >= 200 && $status < 300 ? 'OK' : $this->statusMessage,
66
+        ];
67 67
 
68
-		if ($this->itemsCount !== null) {
69
-			$meta['totalitems'] = $this->itemsCount;
70
-		}
71
-		if ($this->itemsPerPage !== null) {
72
-			$meta['itemsperpage'] = $this->itemsPerPage;
73
-		}
68
+        if ($this->itemsCount !== null) {
69
+            $meta['totalitems'] = $this->itemsCount;
70
+        }
71
+        if ($this->itemsPerPage !== null) {
72
+            $meta['itemsperpage'] = $this->itemsPerPage;
73
+        }
74 74
 
75
-		return $this->renderResult($meta);
76
-	}
75
+        return $this->renderResult($meta);
76
+    }
77 77
 }
Please login to merge, or discard this patch.