Completed
Push — master ( ee3189...470063 )
by Phil
17:54 queued 05:47
created

Users::getUserSubAdminGroups()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 11
nc 5
nop 1
dl 0
loc 19
rs 9.2
c 0
b 0
f 0
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) 2017, 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\NotFoundException;
36
use OCP\IGroup;
37
use OCP\IGroupManager;
38
use OCP\ILogger;
39
use OCP\IUser;
40
use OCP\IUserManager;
41
use OCP\IUserSession;
42
use OCP\Util;
43
44
class Users {
45
46
	/** @var IUserManager */
47
	private $userManager;
48
	/** @var IGroupManager|\OC\Group\Manager */ // FIXME Requires a method that is not on the interface
49
	private $groupManager;
50
	/** @var IUserSession */
51
	private $userSession;
52
	/** @var ILogger */
53
	private $logger;
54
	/** @var \OC\Authentication\TwoFactorAuth\Manager */
55
	private $twoFactorAuthManager;
56
57
	/**
58
	 * @param IUserManager $userManager
59
	 * @param IGroupManager $groupManager
60
	 * @param IUserSession $userSession
61
	 * @param ILogger $logger
62
	 */
63
	public function __construct(IUserManager $userManager,
64
								IGroupManager $groupManager,
65
								IUserSession $userSession,
66
								ILogger $logger,
67
								\OC\Authentication\TwoFactorAuth\Manager $twoFactorAuthManager ) {
68
		$this->userManager = $userManager;
69
		$this->groupManager = $groupManager;
70
		$this->userSession = $userSession;
71
		$this->logger = $logger;
72
		$this->twoFactorAuthManager = $twoFactorAuthManager;
73
	}
74
75
	/**
76
	 * returns a list of users
77
	 *
78
	 * @return Result
79
	 */
80
	public function getUsers() {
81
		$search = !empty($_GET['search']) ? $_GET['search'] : '';
82
		$limit = !empty($_GET['limit']) ? $_GET['limit'] : null;
83
		$offset = !empty($_GET['offset']) ? $_GET['offset'] : null;
84
85
		// Check if user is logged in
86
		$user = $this->userSession->getUser();
87
		if ($user === null) {
88
			return new Result(null, API::RESPOND_UNAUTHORISED);
89
		}
90
91
		// Admin? Or SubAdmin?
92
		$uid = $user->getUID();
93
		$subAdminManager = $this->groupManager->getSubAdmin();
94
		if($this->groupManager->isAdmin($uid)){
95
			$users = $this->userManager->search($search, $limit, $offset);
96
		} else if ($subAdminManager->isSubAdmin($user)) {
97
			$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
98
			foreach ($subAdminOfGroups as $key => $group) {
99
				$subAdminOfGroups[$key] = $group->getGID();
100
			}
101
102
			if($offset === null) {
103
				$offset = 0;
104
			}
105
106
			$users = [];
107
			foreach ($subAdminOfGroups as $group) {
108
				$users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search));
109
			}
110
111
			$users = array_slice($users, $offset, $limit);
112
		} else {
113
			return new Result(null, API::RESPOND_UNAUTHORISED);
114
		}
115
		$users = array_keys($users);
116
117
		return new Result([
118
			'users' => $users
119
		]);
120
	}
121
122
	/**
123
	 * @return Result
124
	 */
125
	public function addUser() {
126
		$userId = isset($_POST['userid']) ? $_POST['userid'] : null;
127
		$password = isset($_POST['password']) ? $_POST['password'] : null;
128
		$groups = isset($_POST['groups']) ? $_POST['groups'] : null;
129
		$user = $this->userSession->getUser();
130
		$isAdmin = $this->groupManager->isAdmin($user->getUID());
131
		$subAdminManager = $this->groupManager->getSubAdmin();
132
133
		if (!$isAdmin && !$subAdminManager->isSubAdmin($user)) {
0 ignored issues
show
Bug introduced by
It seems like $user defined by $this->userSession->getUser() on line 129 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...
134
			return new Result(null, API::RESPOND_UNAUTHORISED);
135
		}
136
137
		if($this->userManager->userExists($userId)) {
138
			$this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
139
			return new Result(null, 102, 'User already exists');
140
		}
141
142
		if(is_array($groups)) {
143
			foreach ($groups as $group) {
144
				if(!$this->groupManager->groupExists($group)){
145
					return new Result(null, 104, 'group '.$group.' does not exist');
146
				}
147
				if(!$isAdmin && !$subAdminManager->isSubAdminofGroup($user, $this->groupManager->get($group))) {
0 ignored issues
show
Bug introduced by
It seems like $user defined by $this->userSession->getUser() on line 129 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...
148
					return new Result(null, 105, 'insufficient privileges for group '. $group);
149
				}
150
			}
151
		} else {
152
			if(!$isAdmin) {
153
				return new Result(null, 106, 'no group specified (required for subadmins)');
154
			}
155
		}
156
157
		try {
158
			$newUser = $this->userManager->createUser($userId, $password);
159
			$this->logger->info('Successful addUser call with userid: '.$userId, ['app' => 'ocs_api']);
160
161
			if (is_array($groups)) {
162
				foreach ($groups as $group) {
163
					$this->groupManager->get($group)->addUser($newUser);
0 ignored issues
show
Bug introduced by
It seems like $newUser defined by $this->userManager->crea...ser($userId, $password) on line 158 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...
164
					$this->logger->info('Added userid '.$userId.' to group '.$group, ['app' => 'ocs_api']);
165
				}
166
			}
167
			return new Result(null, 100);
168
		} catch (\Exception $e) {
169
			$this->logger->error('Failed addUser attempt with exception: '.$e->getMessage(), ['app' => 'ocs_api']);
170
			$message = $e->getMessage();
171
			if (empty($message)) {
172
				$message = 'Bad request';
173
			}
174
			return new Result(null, 101, $e->getMessage());
175
		}
176
	}
177
178
	/**
179
	 * gets user info
180
	 *
181
	 * @param array $parameters
182
	 * @return Result
183
	 */
184
	public function getUser($parameters) {
185
		$userId = $parameters['userid'];
186
187
		// Check if user is logged in
188
		$currentLoggedInUser = $this->userSession->getUser();
189
		if ($currentLoggedInUser === null) {
190
			return new Result(null, API::RESPOND_UNAUTHORISED);
191
		}
192
193
		$data = [];
194
195
		// Check if the target user exists
196
		$targetUserObject = $this->userManager->get($userId);
197
		if($targetUserObject === null) {
198
			return new Result(null, API::RESPOND_NOT_FOUND, 'The requested user could not be found');
199
		}
200
201
		// Admin? Or SubAdmin?
202
		if($this->groupManager->isAdmin($currentLoggedInUser->getUID())
203
			|| $this->groupManager->getSubAdmin()->isUserAccessible($currentLoggedInUser, $targetUserObject)) {
204
			$data['enabled'] = $targetUserObject->isEnabled() ? 'true' : 'false';
205
		} else {
206
			// Check they are looking up themselves
207
			if($currentLoggedInUser->getUID() !== $userId) {
208
				return new Result(null, API::RESPOND_UNAUTHORISED);
209
			}
210
		}
211
212
		// Find the data
213
		$data['quota'] = $this->fillStorageInfo($userId);
214
		$data['email'] = $targetUserObject->getEMailAddress();
215
		$data['displayname'] = $targetUserObject->getDisplayName();
216
		$data['home'] = $targetUserObject->getHome();
217
		$data['two_factor_auth_enabled'] = $this->twoFactorAuthManager->isTwoFactorAuthenticated($targetUserObject) ? 'true' : 'false';
218
219
		return new Result($data);
220
	}
221
222
	/**
223
	 * edit users
224
	 *
225
	 * @param array $parameters
226
	 * @return Result
227
	 */
228
	public function editUser($parameters) {
229
		/** @var string $targetUserId */
230
		$targetUserId = $parameters['userid'];
231
232
		// Check if user is logged in
233
		$currentLoggedInUser = $this->userSession->getUser();
234
		if ($currentLoggedInUser === null) {
235
			return new Result(null, API::RESPOND_UNAUTHORISED);
236
		}
237
238
		$targetUser = $this->userManager->get($targetUserId);
239
		if($targetUser === null) {
240
			return new Result(null, 997);
241
		}
242
243
		if($targetUserId === $currentLoggedInUser->getUID()) {
244
			// Editing self (display, email)
245
			$permittedFields[] = 'display';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$permittedFields was never initialized. Although not strictly required by PHP, it is generally a good practice to add $permittedFields = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
246
			$permittedFields[] = 'email';
247
			$permittedFields[] = 'password';
248
			$permittedFields[] = 'two_factor_auth_enabled';
249
			// If admin they can edit their own quota
250
			if($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
251
				$permittedFields[] = 'quota';
252
			}
253
		} else {
254
			// Check if admin / subadmin
255
			$subAdminManager = $this->groupManager->getSubAdmin();
256
			if($subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
257
			|| $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
258
				// They have permissions over the user
259
				$permittedFields[] = 'display';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$permittedFields was never initialized. Although not strictly required by PHP, it is generally a good practice to add $permittedFields = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
260
				$permittedFields[] = 'quota';
261
				$permittedFields[] = 'password';
262
				$permittedFields[] = 'email';
263
				$permittedFields[] = 'two_factor_auth_enabled';
264
			} else {
265
				// No rights
266
				return new Result(null, 997);
267
			}
268
		}
269
		// Check if permitted to edit this field
270
		if(!in_array($parameters['_put']['key'], $permittedFields)) {
271
			return new Result(null, 997);
272
		}
273
		// Process the edit
274
		switch($parameters['_put']['key']) {
275
			case 'display':
276
				$targetUser->setDisplayName($parameters['_put']['value']);
277
				break;
278
			case 'quota':
279
				$quota = $parameters['_put']['value'];
280
				if($quota !== 'none' and $quota !== 'default') {
281
					if (is_numeric($quota)) {
282
						$quota = floatval($quota);
283
					} else {
284
						$quota = Util::computerFileSize($quota);
285
					}
286
					if ($quota === false) {
287
						return new Result(null, 103, "Invalid quota value {$parameters['_put']['value']}");
288
					}
289
					if($quota === 0) {
290
						$quota = 'default';
291
					}else if($quota === -1) {
292
						$quota = 'none';
293
					} else {
294
						$quota = Util::humanFileSize($quota);
295
					}
296
				}
297
				$targetUser->setQuota($quota);
298
				break;
299
			case 'password':
300
				try {
301
					$targetUser->setPassword($parameters['_put']['value']);
302
				} catch (\Exception $e) {
303
					return new Result(null, 403, $e->getMessage());
304
				}
305
				break;
306
			case 'two_factor_auth_enabled':
307
				if ($parameters['_put']['value'] === true) {
308
					$this->twoFactorAuthManager->enableTwoFactorAuthentication($targetUser);
309
				} else {
310
					$this->twoFactorAuthManager->disableTwoFactorAuthentication($targetUser);
311
				}
312
				break;
313
			case 'email':
314
				if(filter_var($parameters['_put']['value'], FILTER_VALIDATE_EMAIL)) {
315
					$targetUser->setEMailAddress($parameters['_put']['value']);
316
				} else {
317
					return new Result(null, 102);
318
				}
319
				break;
320
			default:
321
				return new Result(null, 103);
322
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
323
		}
324
		return new Result(null, 100);
325
	}
326
327
	/**
328
	 * @param array $parameters
329
	 * @return Result
330
	 */
331
	public function deleteUser($parameters) {
332
		// Check if user is logged in
333
		$currentLoggedInUser = $this->userSession->getUser();
334
		if ($currentLoggedInUser === null) {
335
			return new Result(null, API::RESPOND_UNAUTHORISED);
336
		}
337
338
		$targetUser = $this->userManager->get($parameters['userid']);
339
340 View Code Duplication
		if($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
341
			return new Result(null, 101);
342
		}
343
344
		// If not permitted
345
		$subAdminManager = $this->groupManager->getSubAdmin();
346 View Code Duplication
		if(!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
347
			return new Result(null, 997);
348
		}
349
350
		// Go ahead with the delete
351
		if($targetUser->delete()) {
352
			return new Result(null, 100);
353
		} else {
354
			return new Result(null, 101);
355
		}
356
	}
357
358
	/**
359
	 * @param array $parameters
360
	 * @return Result
361
	 */
362
	public function disableUser($parameters) {
363
		return $this->setEnabled($parameters, false);
364
	}
365
366
	/**
367
	 * @param array $parameters
368
	 * @return Result
369
	 */
370
	public function enableUser($parameters) {
371
		return $this->setEnabled($parameters, true);
372
	}
373
374
	/**
375
	 * @param array $parameters
376
	 * @param bool $value
377
	 * @return Result
378
	 */
379
	private function setEnabled($parameters, $value) {
380
		// Check if user is logged in
381
		$currentLoggedInUser = $this->userSession->getUser();
382
		if ($currentLoggedInUser === null) {
383
			return new Result(null, API::RESPOND_UNAUTHORISED);
384
		}
385
386
		$targetUser = $this->userManager->get($parameters['userid']);
387 View Code Duplication
		if($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
388
			return new Result(null, 101);
389
		}
390
391
		// If not permitted
392
		$subAdminManager = $this->groupManager->getSubAdmin();
393 View Code Duplication
		if(!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
394
			return new Result(null, 997);
395
		}
396
397
		// enable/disable the user now
398
		$targetUser->setEnabled($value);
399
		return new Result(null, 100);
400
	}
401
402
	/**
403
	 * @param array $parameters
404
	 * @return Result
405
	 */
406
	public function getUsersGroups($parameters) {
407
		// Check if user is logged in
408
		$loggedInUser = $this->userSession->getUser();
409
		if ($loggedInUser === null) {
410
			return new Result(null, API::RESPOND_UNAUTHORISED);
411
		}
412
413
		$targetUser = $this->userManager->get($parameters['userid']);
414
		if($targetUser === null) {
415
			return new Result(null, API::RESPOND_NOT_FOUND);
416
		}
417
418
		if($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
419
			// Self lookup or admin lookup
420
			return new Result([
421
				'groups' => $this->groupManager->getUserGroupIds($targetUser, 'management')
422
			]);
423
		} else {
424
			$subAdminManager = $this->groupManager->getSubAdmin();
425
426
			// Looking up someone else
427
			if($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
428
				// Return the group that the method caller is subadmin of for the user in question
429
				$getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
430
				foreach ($getSubAdminsGroups as $key => $group) {
431
					$getSubAdminsGroups[$key] = $group->getGID();
432
				}
433
				$groups = array_intersect(
434
					$getSubAdminsGroups,
435
					$this->groupManager->getUserGroupIds($targetUser)
436
				);
437
				return new Result(['groups' => $groups]);
438
			} else {
439
				// Not permitted
440
				return new Result(null, 997);
441
			}
442
		}
443
444
	}
445
446
	/**
447
	 * Returns whether the given user can manage the given group
448
	 *
449
	 * @param IUser $user user to check access
450
	 * @param IGroup|null $group group to check or null
451
	 *
452
	 * @return true if the user can manage the group
453
	 */
454
	private function canUserManageGroup($user, $group) {
455
		if ($this->groupManager->isAdmin($user->getUID())) {
456
			return true;
457
		}
458
459
		if ($group !== null) {
460
			$subAdminManager = $this->groupManager->getSubAdmin();
461
			return $subAdminManager->isSubAdminofGroup($user, $group);
462
		}
463
464
		return false;
465
	}
466
467
	/**
468
	 * @param array $parameters
469
	 * @return Result
470
	 */
471
	public function addToGroup($parameters) {
472
		// Check if user is logged in
473
		$user = $this->userSession->getUser();
474
		if ($user === null) {
475
			return new Result(null, API::RESPOND_UNAUTHORISED);
476
		}
477
478
		$groupId = isset($_POST['groupid']) ? $_POST['groupid'] : null;
479
		if (($groupId === '') || ($groupId === null) || ($groupId === false)) {
480
			return new Result(null, 101);
481
		}
482
483
		$group = $this->groupManager->get($groupId);
484
		if ($group === null) {
485
			return new Result(null, 102);
486
		}
487
488
		// Check they're an admin or subadmin of the group
489
		if(!$this->canUserManageGroup($user, $group)) {
490
			return new Result(null, 104);
491
		}
492
493
		$targetUser = $this->userManager->get($parameters['userid']);
494
		if($targetUser === null) {
495
			return new Result(null, 103);
496
		}
497
498
		// Add user to group
499
		$group->addUser($targetUser);
500
		return new Result(null, 100);
501
	}
502
503
	/**
504
	 * @param array $parameters
505
	 * @return Result
506
	 */
507
	public function removeFromGroup($parameters) {
508
		// Check if user is logged in
509
		$loggedInUser = $this->userSession->getUser();
510
		if ($loggedInUser === null) {
511
			return new Result(null, API::RESPOND_UNAUTHORISED);
512
		}
513
514
		$group = isset($parameters['_delete']['groupid']) ? $parameters['_delete']['groupid'] : null;
515
		if (($group === '') || ($group === null) || ($group === false)) {
516
			return new Result(null, 101);
517
		}
518
519
		$group = $this->groupManager->get($group);
520
		if($group === null) {
521
			return new Result(null, 102);
522
		}
523
524
		if(!$this->canUserManageGroup($loggedInUser, $group)) {
525
			return new Result(null, 104);
526
		}
527
528
		$targetUser = $this->userManager->get($parameters['userid']);
529
		if($targetUser === null) {
530
			return new Result(null, 103);
531
		}
532
		// Check they aren't removing themselves from 'admin' or their 'subadmin; group
533
		if($parameters['userid'] === $loggedInUser->getUID()) {
534
			if($this->groupManager->isAdmin($loggedInUser->getUID())) {
535
				if($group->getGID() === 'admin') {
536
					return new Result(null, 105, 'Cannot remove yourself from the admin group');
537
				}
538
			} else {
539
				// Not an admin, check they are not removing themself from their subadmin group
540
				$subAdminManager = $this->groupManager->getSubAdmin();
541
				$subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
542
				foreach ($subAdminGroups as $key => $group) {
543
					$subAdminGroups[$key] = $group->getGID();
544
				}
545
546
				if(in_array($group->getGID(), $subAdminGroups, true)) {
547
					return new Result(null, 105, 'Cannot remove yourself from this group as you are a SubAdmin');
548
				}
549
			}
550
		}
551
552
		// Remove user from group
553
		$group->removeUser($targetUser);
554
		return new Result(null, 100);
555
	}
556
557
	/**
558
	 * Creates a subadmin
559
	 *
560
	 * @param array $parameters
561
	 * @return Result
562
	 */
563
	public function addSubAdmin($parameters) {
564
		$group = $this->groupManager->get($_POST['groupid']);
565
		$user = $this->userManager->get($parameters['userid']);
566
567
		// Check if the user exists
568
		if($user === null) {
569
			return new Result(null, 101, 'User does not exist');
570
		}
571
		// Check if group exists
572
		if($group === null) {
573
			return new Result(null, 102, 'Group:'.$_POST['groupid'].' does not exist');
574
		}
575
		// Check if trying to make subadmin of admin group
576
		if(strtolower($_POST['groupid']) === 'admin') {
577
			return new Result(null, 103, 'Cannot create subadmins for admin group');
578
		}
579
580
		$subAdminManager = $this->groupManager->getSubAdmin();
581
582
		// We cannot be subadmin twice
583
		if ($subAdminManager->isSubAdminofGroup($user, $group)) {
584
			return new Result(null, 100);
585
		}
586
		// Go
587
		if($subAdminManager->createSubAdmin($user, $group)) {
588
			return new Result(null, 100);
589
		} else {
590
			return new Result(null, 103, 'Unknown error occurred');
591
		}
592
	}
593
594
	/**
595
	 * Removes a subadmin from a group
596
	 *
597
	 * @param array $parameters
598
	 * @return Result
599
	 */
600
	public function removeSubAdmin($parameters) {
601
		$group = $this->groupManager->get($parameters['_delete']['groupid']);
602
		$user = $this->userManager->get($parameters['userid']);
603
		$subAdminManager = $this->groupManager->getSubAdmin();
604
605
		// Check if the user exists
606
		if($user === null) {
607
			return new Result(null, 101, 'User does not exist');
608
		}
609
		// Check if the group exists
610
		if($group === null) {
611
			return new Result(null, 101, 'Group does not exist');
612
		}
613
		// Check if they are a subadmin of this said group
614
		if(!$subAdminManager->isSubAdminofGroup($user, $group)) {
615
			return new Result(null, 102, 'User is not a subadmin of this group');
616
		}
617
618
		// Go
619
		if($subAdminManager->deleteSubAdmin($user, $group)) {
620
			return new Result(null, 100);
621
		} else {
622
			return new Result(null, 103, 'Unknown error occurred');
623
		}
624
	}
625
626
	/**
627
	 * Get the groups a user is a subadmin of
628
	 *
629
	 * @param array $parameters
630
	 * @return Result
631
	 */
632
	public function getUserSubAdminGroups($parameters) {
633
		$user = $this->userManager->get($parameters['userid']);
634
		// Check if the user exists
635
		if($user === null) {
636
			return new Result(null, 101, 'User does not exist');
637
		}
638
639
		// Get the subadmin groups
640
		$groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($user);
641
		foreach ($groups as $key => $group) {
642
			$groups[$key] = $group->getGID();
643
		}
644
645
		if(!$groups) {
646
			return new Result(null, 102, 'Unknown error occurred');
647
		} else {
648
			return new Result($groups);
649
		}
650
	}
651
652
	/**
653
	 * @param string $userId
654
	 * @return array
655
	 * @throws \OCP\Files\NotFoundException
656
	 */
657
	protected function fillStorageInfo($userId) {
658
		try {
659
			\OC_Util::tearDownFS();
660
			\OC_Util::setupFS($userId);
661
			$storage = OC_Helper::getStorageInfo('/');
662
			$data = [
663
				'free' => $storage['free'],
664
				'used' => $storage['used'],
665
				'total' => $storage['total'],
666
				'relative' => $storage['relative'],
667
			];
668
		} catch (NotFoundException $ex) {
669
			$data = [];
670
		}
671
		return $data;
672
	}
673
}
674