Issues (1798)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

apps/provisioning_api/lib/Users.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * @author Arthur Schiwon <[email protected]>
4
 * @author Joas Schilling <[email protected]>
5
 * @author Lukas Reschke <[email protected]>
6
 * @author michag86 <[email protected]>
7
 * @author Morris Jobke <[email protected]>
8
 * @author Roeland Jago Douma <[email protected]>
9
 * @author Thomas Müller <[email protected]>
10
 * @author Tom Needham <[email protected]>
11
 * @author Vincent Petry <[email protected]>
12
 *
13
 * @copyright Copyright (c) 2018, ownCloud GmbH
14
 * @license AGPL-3.0
15
 *
16
 * This code is free software: you can redistribute it and/or modify
17
 * it under the terms of the GNU Affero General Public License, version 3,
18
 * as published by the Free Software Foundation.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
 * GNU Affero General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU Affero General Public License, version 3,
26
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
27
 *
28
 */
29
30
namespace OCA\Provisioning_API;
31
32
use OC\OCS\Result;
33
use OC_Helper;
34
use OCP\API;
35
use OCP\Files\FileInfo;
36
use OCP\Files\NotFoundException;
37
use OCP\IGroup;
38
use OCP\IGroupManager;
39
use OCP\ILogger;
40
use OCP\IUser;
41
use OCP\IUserManager;
42
use OCP\IUserSession;
43
use OCP\Util;
44
45
class Users {
46
47
	/** @var IUserManager */
48
	private $userManager;
49
	/** @var IGroupManager|\OC\Group\Manager */ // FIXME Requires a method that is not on the interface
50
	private $groupManager;
51
	/** @var IUserSession */
52
	private $userSession;
53
	/** @var ILogger */
54
	private $logger;
55
	/** @var \OC\Authentication\TwoFactorAuth\Manager */
56
	private $twoFactorAuthManager;
57
58
	/**
59
	 * @param IUserManager $userManager
60
	 * @param IGroupManager $groupManager
61
	 * @param IUserSession $userSession
62
	 * @param ILogger $logger
63
	 */
64
	public function __construct(IUserManager $userManager,
65
								IGroupManager $groupManager,
66
								IUserSession $userSession,
67
								ILogger $logger,
68
								\OC\Authentication\TwoFactorAuth\Manager $twoFactorAuthManager) {
69
		$this->userManager = $userManager;
70
		$this->groupManager = $groupManager;
71
		$this->userSession = $userSession;
72
		$this->logger = $logger;
73
		$this->twoFactorAuthManager = $twoFactorAuthManager;
74
	}
75
76
	/**
77
	 * returns a list of users
78
	 *
79
	 * @return Result
80
	 */
81
	public function getUsers() {
82
		$search = !empty($_GET['search']) ? $_GET['search'] : '';
83
		$limit = !empty($_GET['limit']) ? $_GET['limit'] : null;
84
		$offset = !empty($_GET['offset']) ? $_GET['offset'] : null;
85
86
		// Check if user is logged in
87
		$user = $this->userSession->getUser();
88
		if ($user === null) {
89
			return new Result(null, API::RESPOND_UNAUTHORISED);
90
		}
91
92
		// Admin? Or SubAdmin?
93
		$uid = $user->getUID();
94
		$subAdminManager = $this->groupManager->getSubAdmin();
95
		if ($this->groupManager->isAdmin($uid)) {
96
			$users = $this->userManager->search($search, $limit, $offset);
97
		} elseif ($subAdminManager->isSubAdmin($user)) {
98
			$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
99
			foreach ($subAdminOfGroups as $key => $group) {
100
				$subAdminOfGroups[$key] = $group->getGID();
101
			}
102
103
			if ($offset === null) {
104
				$offset = 0;
105
			}
106
107
			$users = [];
108
			foreach ($subAdminOfGroups as $group) {
109
				$users = \array_merge($users, $this->groupManager->displayNamesInGroup($group, $search));
110
			}
111
112
			$users = \array_slice($users, $offset, $limit);
113
		} else {
114
			return new Result(null, API::RESPOND_UNAUTHORISED);
115
		}
116
		$users = \array_keys($users);
117
118
		return new Result([
119
			'users' => $users
120
		]);
121
	}
122
123
	/**
124
	 * @return Result
125
	 */
126
	public function addUser() {
127
		$userId = isset($_POST['userid']) ? $_POST['userid'] : null;
128
		$password = isset($_POST['password']) ? $_POST['password'] : null;
129
		$groups = isset($_POST['groups']) ? $_POST['groups'] : null;
130
		$user = $this->userSession->getUser();
131
		$isAdmin = $this->groupManager->isAdmin($user->getUID());
132
		$subAdminManager = $this->groupManager->getSubAdmin();
133
134
		if (!$isAdmin && !$subAdminManager->isSubAdmin($user)) {
0 ignored issues
show
It seems like $user defined by $this->userSession->getUser() on line 130 can be null; however, OCP\ISubAdminManager::isSubAdmin() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
135
			return new Result(null, API::RESPOND_UNAUTHORISED);
136
		}
137
138
		if ($this->userManager->userExists($userId)) {
139
			$this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
140
			return new Result(null, 102, 'User already exists');
141
		}
142
143
		if (\is_array($groups)) {
144
			foreach ($groups as $group) {
145
				if (!$this->groupManager->groupExists($group)) {
146
					return new Result(null, 104, 'group '.$group.' does not exist');
147
				}
148
				if (!$isAdmin && !$subAdminManager->isSubAdminofGroup($user, $this->groupManager->get($group))) {
0 ignored issues
show
It seems like $user defined by $this->userSession->getUser() on line 130 can be null; however, OCP\ISubAdminManager::isSubAdminofGroup() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
149
					return new Result(null, 105, 'insufficient privileges for group '. $group);
150
				}
151
			}
152
		} else {
153
			if (!$isAdmin) {
154
				return new Result(null, 106, 'no group specified (required for subadmins)');
155
			}
156
		}
157
158
		try {
159
			$newUser = $this->userManager->createUser($userId, $password);
160
			$this->logger->info('Successful addUser call with userid: '.$userId, ['app' => 'ocs_api']);
161
162
			if (\is_array($groups)) {
163
				foreach ($groups as $group) {
164
					$this->groupManager->get($group)->addUser($newUser);
0 ignored issues
show
It seems like $newUser defined by $this->userManager->crea...ser($userId, $password) on line 159 can also be of type boolean; however, OCP\IGroup::addUser() does only seem to accept object<OCP\IUser>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
165
					$this->logger->info('Added userid '.$userId.' to group '.$group, ['app' => 'ocs_api']);
166
				}
167
			}
168
			return new Result(null, 100);
169
		} catch (\Exception $e) {
170
			$this->logger->error('Failed addUser attempt with exception: '.$e->getMessage(), ['app' => 'ocs_api']);
171
			$message = $e->getMessage();
172
			if (empty($message)) {
173
				$message = 'Bad request';
174
			}
175
			return new Result(null, 101, $e->getMessage());
176
		}
177
	}
178
179
	/**
180
	 * gets user info
181
	 *
182
	 * @param array $parameters
183
	 * @return Result
184
	 */
185
	public function getUser($parameters) {
186
		$userId = $parameters['userid'];
187
188
		// Check if user is logged in
189
		$currentLoggedInUser = $this->userSession->getUser();
190
		if ($currentLoggedInUser === null) {
191
			return new Result(null, API::RESPOND_UNAUTHORISED);
192
		}
193
194
		$data = [];
195
196
		// Check if the target user exists
197
		$targetUserObject = $this->userManager->get($userId);
198
		if ($targetUserObject === null) {
199
			return new Result(null, API::RESPOND_NOT_FOUND, 'The requested user could not be found');
200
		}
201
202
		// Admin? Or SubAdmin?
203
		if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())
204
			|| $this->groupManager->getSubAdmin()->isUserAccessible($currentLoggedInUser, $targetUserObject)) {
205
			$data['enabled'] = $targetUserObject->isEnabled() ? 'true' : 'false';
206
		} else {
207
			// Check they are looking up themselves
208
			if ($currentLoggedInUser->getUID() !== $userId) {
209
				return new Result(null, API::RESPOND_UNAUTHORISED);
210
			}
211
		}
212
213
		// Find the data
214
		$data['quota'] = $this->fillStorageInfo($userId);
215
		$data['quota']['definition'] = $targetUserObject->getQuota();
216
		$data['email'] = $targetUserObject->getEMailAddress();
217
		$data['displayname'] = $targetUserObject->getDisplayName();
218
		$data['home'] = $targetUserObject->getHome();
219
		$data['two_factor_auth_enabled'] = $this->twoFactorAuthManager->isTwoFactorAuthenticated($targetUserObject) ? 'true' : 'false';
220
221
		return new Result($data);
222
	}
223
224
	/**
225
	 * edit users
226
	 *
227
	 * @param array $parameters
228
	 * @return Result
229
	 */
230
	public function editUser($parameters) {
231
		/** @var string $targetUserId */
232
		$targetUserId = $parameters['userid'];
233
234
		// Check if user is logged in
235
		$currentLoggedInUser = $this->userSession->getUser();
236
		if ($currentLoggedInUser === null) {
237
			return new Result(null, API::RESPOND_UNAUTHORISED);
238
		}
239
240
		$targetUser = $this->userManager->get($targetUserId);
241
		if ($targetUser === null) {
242
			return new Result(null, 997);
243
		}
244
245
		if ($targetUserId === $currentLoggedInUser->getUID()) {
246
			// Editing self (display, email)
247
			$permittedFields[] = 'display';
248
			$permittedFields[] = 'displayname';
249
			$permittedFields[] = 'email';
250
			$permittedFields[] = 'password';
251
			$permittedFields[] = 'two_factor_auth_enabled';
252
			// If admin they can edit their own quota
253
			if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
254
				$permittedFields[] = 'quota';
255
			}
256
		} else {
257
			// Check if admin / subadmin
258
			$subAdminManager = $this->groupManager->getSubAdmin();
259
			if ($subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
260
			|| $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
261
				// They have permissions over the user
262
				$permittedFields[] = 'display';
263
				$permittedFields[] = 'displayname';
264
				$permittedFields[] = 'quota';
265
				$permittedFields[] = 'password';
266
				$permittedFields[] = 'email';
267
				$permittedFields[] = 'two_factor_auth_enabled';
268
			} else {
269
				// No rights
270
				return new Result(null, 997);
271
			}
272
		}
273
		// Check if permitted to edit this field
274
		if (!\in_array($parameters['_put']['key'], $permittedFields)) {
275
			return new Result(null, 997);
276
		}
277
		// Process the edit
278
		switch ($parameters['_put']['key']) {
279
			case 'display':
280
			case 'displayname':
281
				$targetUser->setDisplayName($parameters['_put']['value']);
282
				break;
283
			case 'quota':
284
				$quota = $parameters['_put']['value'];
285
				if ($quota !== 'none' && $quota !== 'default') {
286
					if (\is_numeric($quota)) {
287
						$quota = \floatval($quota);
288
					} else {
289
						$quota = Util::computerFileSize($quota);
290
					}
291
					if ($quota === false) {
292
						return new Result(null, 103, "Invalid quota value {$parameters['_put']['value']}");
293
					}
294
					$quota = Util::humanFileSize($quota);
295
				}
296
				$targetUser->setQuota($quota);
297
				break;
298
			case 'password':
299
				try {
300
					$targetUser->setPassword($parameters['_put']['value']);
301
				} catch (\Exception $e) {
302
					return new Result(null, 403, $e->getMessage());
303
				}
304
				break;
305
			case 'two_factor_auth_enabled':
306
				if ($parameters['_put']['value'] === true) {
307
					$this->twoFactorAuthManager->enableTwoFactorAuthentication($targetUser);
308
				} else {
309
					$this->twoFactorAuthManager->disableTwoFactorAuthentication($targetUser);
310
				}
311
				break;
312
			case 'email':
313
				if (\filter_var($parameters['_put']['value'], FILTER_VALIDATE_EMAIL)) {
314
					$targetUser->setEMailAddress($parameters['_put']['value']);
315
				} else {
316
					return new Result(null, 102);
317
				}
318
				break;
319
			default:
320
				return new Result(null, 103);
321
				break;
322
		}
323
		return new Result(null, 100);
324
	}
325
326
	/**
327
	 * @param array $parameters
328
	 * @return Result
329
	 */
330
	public function deleteUser($parameters) {
331
		// Check if user is logged in
332
		$currentLoggedInUser = $this->userSession->getUser();
333
		if ($currentLoggedInUser === null) {
334
			return new Result(null, API::RESPOND_UNAUTHORISED);
335
		}
336
337
		$targetUser = $this->userManager->get($parameters['userid']);
338
339 View Code Duplication
		if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
340
			return new Result(null, 101);
341
		}
342
343
		// If not permitted
344
		$subAdminManager = $this->groupManager->getSubAdmin();
345 View Code Duplication
		if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
346
			return new Result(null, 997);
347
		}
348
349
		// Go ahead with the delete
350
		if ($targetUser->delete()) {
351
			return new Result(null, 100);
352
		} else {
353
			return new Result(null, 101);
354
		}
355
	}
356
357
	/**
358
	 * @param array $parameters
359
	 * @return Result
360
	 */
361
	public function disableUser($parameters) {
362
		return $this->setEnabled($parameters, false);
363
	}
364
365
	/**
366
	 * @param array $parameters
367
	 * @return Result
368
	 */
369
	public function enableUser($parameters) {
370
		return $this->setEnabled($parameters, true);
371
	}
372
373
	/**
374
	 * @param array $parameters
375
	 * @param bool $value
376
	 * @return Result
377
	 */
378
	private function setEnabled($parameters, $value) {
379
		// Check if user is logged in
380
		$currentLoggedInUser = $this->userSession->getUser();
381
		if ($currentLoggedInUser === null) {
382
			return new Result(null, API::RESPOND_UNAUTHORISED);
383
		}
384
385
		$targetUser = $this->userManager->get($parameters['userid']);
386 View Code Duplication
		if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
387
			return new Result(null, 101);
388
		}
389
390
		// If not permitted
391
		$subAdminManager = $this->groupManager->getSubAdmin();
392 View Code Duplication
		if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
393
			return new Result(null, 997);
394
		}
395
396
		// enable/disable the user now
397
		$targetUser->setEnabled($value);
398
		return new Result(null, 100);
399
	}
400
401
	/**
402
	 * @param array $parameters
403
	 * @return Result
404
	 */
405
	public function getUsersGroups($parameters) {
406
		// Check if user is logged in
407
		$loggedInUser = $this->userSession->getUser();
408
		if ($loggedInUser === null) {
409
			return new Result(null, API::RESPOND_UNAUTHORISED);
410
		}
411
412
		$targetUser = $this->userManager->get($parameters['userid']);
413
		if ($targetUser === null) {
414
			return new Result(null, API::RESPOND_NOT_FOUND);
415
		}
416
417
		if ($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
418
			// Self lookup or admin lookup
419
			return new Result([
420
				'groups' => $this->groupManager->getUserGroupIds($targetUser, 'management')
421
			]);
422
		} else {
423
			$subAdminManager = $this->groupManager->getSubAdmin();
424
425
			// Looking up someone else
426
			if ($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
427
				// Return the group that the method caller is subadmin of for the user in question
428
				$getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
429
				foreach ($getSubAdminsGroups as $key => $group) {
430
					$getSubAdminsGroups[$key] = $group->getGID();
431
				}
432
				$groups = \array_intersect(
433
					$getSubAdminsGroups,
434
					$this->groupManager->getUserGroupIds($targetUser)
435
				);
436
				return new Result(['groups' => $groups]);
437
			} else {
438
				// Not permitted
439
				return new Result(null, 997);
440
			}
441
		}
442
	}
443
444
	/**
445
	 * Returns whether the given user can manage the given group
446
	 *
447
	 * @param IUser $user user to check access
448
	 * @param IGroup|null $group group to check or null
449
	 *
450
	 * @return true if the user can manage the group
451
	 */
452
	private function canUserManageGroup($user, $group) {
453
		if ($this->groupManager->isAdmin($user->getUID())) {
454
			return true;
455
		}
456
457
		if ($group !== null) {
458
			$subAdminManager = $this->groupManager->getSubAdmin();
459
			return $subAdminManager->isSubAdminofGroup($user, $group);
460
		}
461
462
		return false;
463
	}
464
465
	/**
466
	 * @param array $parameters
467
	 * @return Result
468
	 */
469
	public function addToGroup($parameters) {
470
		// Check if user is logged in
471
		$user = $this->userSession->getUser();
472
		if ($user === null) {
473
			return new Result(null, API::RESPOND_UNAUTHORISED);
474
		}
475
476
		$groupId = isset($_POST['groupid']) ? $_POST['groupid'] : null;
477
		if (($groupId === '') || ($groupId === null) || ($groupId === false)) {
478
			return new Result(null, 101);
479
		}
480
481
		$group = $this->groupManager->get($groupId);
482
		if ($group === null) {
483
			return new Result(null, 102);
484
		}
485
486
		if (!$this->groupManager->isAdmin($user->getUID())) {
487
			return new Result(null, 104);
488
		}
489
490
		$targetUser = $this->userManager->get($parameters['userid']);
491
		if ($targetUser === null) {
492
			return new Result(null, 103);
493
		}
494
495
		// Add user to group
496
		$group->addUser($targetUser);
497
		return new Result(null, 100);
498
	}
499
500
	/**
501
	 * @param array $parameters
502
	 * @return Result
503
	 */
504
	public function removeFromGroup($parameters) {
505
		// Check if user is logged in
506
		$loggedInUser = $this->userSession->getUser();
507
		if ($loggedInUser === null) {
508
			return new Result(null, API::RESPOND_UNAUTHORISED);
509
		}
510
511
		$group = isset($parameters['_delete']['groupid']) ? $parameters['_delete']['groupid'] : null;
512
		if (($group === '') || ($group === null) || ($group === false)) {
513
			return new Result(null, 101);
514
		}
515
516
		$group = $this->groupManager->get($group);
517
		if ($group === null) {
518
			return new Result(null, 102);
519
		}
520
521
		if (!$this->canUserManageGroup($loggedInUser, $group)) {
522
			return new Result(null, 104);
523
		}
524
525
		$targetUser = $this->userManager->get($parameters['userid']);
526
		if ($targetUser === null) {
527
			return new Result(null, 103);
528
		}
529
		// Check they aren't removing themselves from 'admin' or their 'subadmin; group
530
		if ($parameters['userid'] === $loggedInUser->getUID()) {
531
			if ($this->groupManager->isAdmin($loggedInUser->getUID())) {
532
				if ($group->getGID() === 'admin') {
533
					return new Result(null, 105, 'Cannot remove yourself from the admin group');
534
				}
535
			} else {
536
				// Not an admin, check they are not removing themself from their subadmin group
537
				$subAdminManager = $this->groupManager->getSubAdmin();
538
				$subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
539
				foreach ($subAdminGroups as $key => $group) {
540
					$subAdminGroups[$key] = $group->getGID();
541
				}
542
543
				if (\in_array($group->getGID(), $subAdminGroups, true)) {
544
					return new Result(null, 105, 'Cannot remove yourself from this group as you are a SubAdmin');
545
				}
546
			}
547
		}
548
549
		// Remove user from group
550
		$group->removeUser($targetUser);
551
		return new Result(null, 100);
552
	}
553
554
	/**
555
	 * Creates a subadmin
556
	 *
557
	 * @param array $parameters
558
	 * @return Result
559
	 */
560
	public function addSubAdmin($parameters) {
561
		$group = $this->groupManager->get($_POST['groupid']);
562
		$user = $this->userManager->get($parameters['userid']);
563
564
		// Check if the user exists
565
		if ($user === null) {
566
			return new Result(null, 101, 'User does not exist');
567
		}
568
		// Check if group exists
569
		if ($group === null) {
570
			return new Result(null, 102, 'Group:'.$_POST['groupid'].' does not exist');
571
		}
572
		// Check if trying to make subadmin of admin group
573
		if (\strtolower($_POST['groupid']) === 'admin') {
574
			return new Result(null, 103, 'Cannot create subadmins for admin group');
575
		}
576
577
		$subAdminManager = $this->groupManager->getSubAdmin();
578
579
		// We cannot be subadmin twice
580
		if ($subAdminManager->isSubAdminofGroup($user, $group)) {
581
			return new Result(null, 100);
582
		}
583
		// Go
584
		if ($subAdminManager->createSubAdmin($user, $group)) {
585
			return new Result(null, 100);
586
		} else {
587
			return new Result(null, 103, 'Unknown error occurred');
588
		}
589
	}
590
591
	/**
592
	 * Removes a subadmin from a group
593
	 *
594
	 * @param array $parameters
595
	 * @return Result
596
	 */
597
	public function removeSubAdmin($parameters) {
598
		$group = $this->groupManager->get($parameters['_delete']['groupid']);
599
		$user = $this->userManager->get($parameters['userid']);
600
		$subAdminManager = $this->groupManager->getSubAdmin();
601
602
		// Check if the user exists
603
		if ($user === null) {
604
			return new Result(null, 101, 'User does not exist');
605
		}
606
		// Check if the group exists
607
		if ($group === null) {
608
			return new Result(null, 101, 'Group does not exist');
609
		}
610
		// Check if they are a subadmin of this said group
611
		if (!$subAdminManager->isSubAdminofGroup($user, $group)) {
612
			return new Result(null, 102, 'User is not a subadmin of this group');
613
		}
614
615
		// Go
616
		if ($subAdminManager->deleteSubAdmin($user, $group)) {
617
			return new Result(null, 100);
618
		} else {
619
			return new Result(null, 103, 'Unknown error occurred');
620
		}
621
	}
622
623
	/**
624
	 * Get the groups a user is a subadmin of
625
	 *
626
	 * @param array $parameters
627
	 * @return Result
628
	 */
629
	public function getUserSubAdminGroups($parameters) {
630
		$user = $this->userManager->get($parameters['userid']);
631
		// Check if the user exists
632
		if ($user === null) {
633
			return new Result(null, 101, 'User does not exist');
634
		}
635
636
		// Get the subadmin groups
637
		$groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($user);
638
		foreach ($groups as $key => $group) {
639
			$groups[$key] = $group->getGID();
640
		}
641
642
		if (!$groups) {
643
			return new Result(null, 102, 'Unknown error occurred');
644
		} else {
645
			return new Result($groups);
646
		}
647
	}
648
649
	/**
650
	 * @param string $userId
651
	 * @return array
652
	 * @throws \OCP\Files\NotFoundException
653
	 */
654
	protected function fillStorageInfo($userId) {
655
		try {
656
			\OC_Util::tearDownFS();
657
			\OC_Util::setupFS($userId);
658
			$storage = OC_Helper::getStorageInfo('/');
659
			$data = [
660
				'free' => $storage['free'],
661
				'used' => $storage['used'],
662
				'total' => $storage['total'],
663
				'relative' => $storage['relative'],
664
			];
665
		} catch (NotFoundException $ex) {
666
			$data = [];
667
		}
668
669
		return $data;
670
	}
671
}
672