Completed
Push — master ( 363c28...b15611 )
by Morris
19:07
created

UsersController::getUserData()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 42
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 27
nc 6
nop 1
dl 0
loc 42
rs 8.439
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Joas Schilling <[email protected]>
7
 * @author Lukas Reschke <[email protected]>
8
 * @author michag86 <[email protected]>
9
 * @author Morris Jobke <[email protected]>
10
 * @author Roeland Jago Douma <[email protected]>
11
 * @author Thomas Müller <[email protected]>
12
 * @author Tom Needham <[email protected]>
13
 *
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\Controller;
31
32
use OC\Accounts\AccountManager;
33
use OC\Settings\Mailer\NewUserMailHelper;
34
use OC_Helper;
35
use OCP\AppFramework\Http\DataResponse;
36
use OCP\AppFramework\OCS\OCSException;
37
use OCP\AppFramework\OCS\OCSForbiddenException;
38
use OCP\AppFramework\OCSController;
39
use OCP\Files\NotFoundException;
40
use OCP\IConfig;
41
use OCP\IGroup;
42
use OCP\IGroupManager;
43
use OCP\ILogger;
44
use OCP\IRequest;
45
use OCP\IUserManager;
46
use OCP\IUserSession;
47
use OCP\L10N\IFactory;
48
49
class UsersController extends OCSController {
50
51
	/** @var IUserManager */
52
	private $userManager;
53
	/** @var IConfig */
54
	private $config;
55
	/** @var IGroupManager|\OC\Group\Manager */ // FIXME Requires a method that is not on the interface
56
	private $groupManager;
57
	/** @var IUserSession */
58
	private $userSession;
59
	/** @var AccountManager */
60
	private $accountManager;
61
	/** @var ILogger */
62
	private $logger;
63
	/** @var IFactory */
64
	private $l10nFactory;
65
	/** @var NewUserMailHelper */
66
	private $newUserMailHelper;
67
68
	/**
69
	 * @param string $appName
70
	 * @param IRequest $request
71
	 * @param IUserManager $userManager
72
	 * @param IConfig $config
73
	 * @param IGroupManager $groupManager
74
	 * @param IUserSession $userSession
75
	 * @param AccountManager $accountManager
76
	 * @param ILogger $logger
77
	 * @param IFactory $l10nFactory
78
	 * @param NewUserMailHelper $newUserMailHelper
79
	 */
80 View Code Duplication
	public function __construct($appName,
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
81
								IRequest $request,
82
								IUserManager $userManager,
83
								IConfig $config,
84
								IGroupManager $groupManager,
85
								IUserSession $userSession,
86
								AccountManager $accountManager,
87
								ILogger $logger,
88
								IFactory $l10nFactory,
89
								NewUserMailHelper $newUserMailHelper) {
90
		parent::__construct($appName, $request);
91
92
		$this->userManager = $userManager;
93
		$this->config = $config;
94
		$this->groupManager = $groupManager;
95
		$this->userSession = $userSession;
96
		$this->accountManager = $accountManager;
97
		$this->logger = $logger;
98
		$this->l10nFactory = $l10nFactory;
99
		$this->newUserMailHelper = $newUserMailHelper;
100
	}
101
102
	/**
103
	 * @NoAdminRequired
104
	 *
105
	 * returns a list of users
106
	 *
107
	 * @param string $search
108
	 * @param int $limit
109
	 * @param int $offset
110
	 * @return DataResponse
111
	 */
112
	public function getUsers($search = '', $limit = null, $offset = null) {
113
		$user = $this->userSession->getUser();
114
		$users = [];
115
116
		// Admin? Or SubAdmin?
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
117
		$uid = $user->getUID();
118
		$subAdminManager = $this->groupManager->getSubAdmin();
119
		if($this->groupManager->isAdmin($uid)){
120
			$users = $this->userManager->search($search, $limit, $offset);
121
		} else if ($subAdminManager->isSubAdmin($user)) {
122
			$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
123
			foreach ($subAdminOfGroups as $key => $group) {
124
				$subAdminOfGroups[$key] = $group->getGID();
125
			}
126
127
			if($offset === null) {
128
				$offset = 0;
129
			}
130
131
			$users = [];
132
			foreach ($subAdminOfGroups as $group) {
133
				$users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search));
134
			}
135
136
			$users = array_slice($users, $offset, $limit);
137
		}
138
139
		$users = array_keys($users);
140
141
		return new DataResponse([
142
			'users' => $users
143
		]);
144
	}
145
146
	/**
147
	 * @PasswordConfirmationRequired
148
	 * @NoAdminRequired
149
	 *
150
	 * @param string $userid
151
	 * @param string $password
152
	 * @param array $groups
153
	 * @return DataResponse
154
	 * @throws OCSException
155
	 */
156
	public function addUser($userid, $password, $groups = null) {
157
		$user = $this->userSession->getUser();
158
		$isAdmin = $this->groupManager->isAdmin($user->getUID());
159
		$subAdminManager = $this->groupManager->getSubAdmin();
160
161
		if($this->userManager->userExists($userid)) {
162
			$this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
163
			throw new OCSException('User already exists', 102);
164
		}
165
166
		if(is_array($groups)) {
167
			foreach ($groups as $group) {
168
				if(!$this->groupManager->groupExists($group)) {
169
					throw new OCSException('group '.$group.' does not exist', 104);
170
				}
171
				if(!$isAdmin && !$subAdminManager->isSubAdminofGroup($user, $this->groupManager->get($group))) {
172
					throw new OCSException('insufficient privileges for group '. $group, 105);
173
				}
174
			}
175
		} else {
176
			if(!$isAdmin) {
177
				throw new OCSException('no group specified (required for subadmins)', 106);
178
			}
179
		}
180
181
		try {
182
			$newUser = $this->userManager->createUser($userid, $password);
183
			$this->logger->info('Successful addUser call with userid: '.$userid, ['app' => 'ocs_api']);
184
185
			if (is_array($groups)) {
186
				foreach ($groups as $group) {
187
					$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 182 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...
188
					$this->logger->info('Added userid '.$userid.' to group '.$group, ['app' => 'ocs_api']);
189
				}
190
			}
191
			return new DataResponse();
192
		} catch (\Exception $e) {
193
			$this->logger->error('Failed addUser attempt with exception: '.$e->getMessage(), ['app' => 'ocs_api']);
194
			throw new OCSException('Bad request', 101);
195
		}
196
	}
197
198
	/**
199
	 * @NoAdminRequired
200
	 * @NoSubAdminRequired
201
	 *
202
	 * gets user info
203
	 *
204
	 * @param string $userId
205
	 * @return DataResponse
206
	 * @throws OCSException
207
	 */
208
	public function getUser($userId) {
209
		$data = $this->getUserData($userId);
210
		return new DataResponse($data);
211
	}
212
213
	/**
214
	 * @NoAdminRequired
215
	 * @NoSubAdminRequired
216
	 *
217
	 * gets user info from the currently logged in user
218
	 *
219
	 * @return DataResponse
220
	 * @throws OCSException
221
	 */
222
	public function getCurrentUser() {
223
		$user = $this->userSession->getUser();
224
		if ($user) {
225
			$data =  $this->getUserData($user->getUID());
226
			// rename "displayname" to "display-name" only for this call to keep
227
			// the API stable.
228
			$data['display-name'] = $data['displayname'];
229
			unset($data['displayname']);
230
			return new DataResponse($data);
231
232
		}
233
234
		throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
235
	}
236
237
	/**
238
	 * creates a array with all user data
239
	 *
240
	 * @param $userId
241
	 * @return array
242
	 * @throws OCSException
243
	 */
244
	protected function getUserData($userId) {
245
		$currentLoggedInUser = $this->userSession->getUser();
246
247
		$data = [];
248
249
		// Check if the target user exists
250
		$targetUserObject = $this->userManager->get($userId);
251
		if($targetUserObject === null) {
252
			throw new OCSException('The requested user could not be found', \OCP\API::RESPOND_NOT_FOUND);
253
		}
254
255
		// Admin? Or SubAdmin?
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
256
		if($this->groupManager->isAdmin($currentLoggedInUser->getUID())
257
			|| $this->groupManager->getSubAdmin()->isUserAccessible($currentLoggedInUser, $targetUserObject)) {
258
			$data['enabled'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'enabled', 'true');
259
		} else {
260
			// Check they are looking up themselves
261
			if($currentLoggedInUser->getUID() !== $targetUserObject->getUID()) {
262
				throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
263
			}
264
		}
265
266
		$userAccount = $this->accountManager->getUser($targetUserObject);
267
		$groups = $this->groupManager->getUserGroups($targetUserObject);
268
		$gids = [];
269
		foreach ($groups as $group) {
270
			$gids[] = $group->getDisplayName();
271
		}
272
273
		// Find the data
274
		$data['id'] = $targetUserObject->getUID();
275
		$data['quota'] = $this->fillStorageInfo($targetUserObject->getUID());
276
		$data[AccountManager::PROPERTY_EMAIL] = $targetUserObject->getEMailAddress();
277
		$data[AccountManager::PROPERTY_DISPLAYNAME] = $targetUserObject->getDisplayName();
278
		$data[AccountManager::PROPERTY_PHONE] = $userAccount[AccountManager::PROPERTY_PHONE]['value'];
279
		$data[AccountManager::PROPERTY_ADDRESS] = $userAccount[AccountManager::PROPERTY_ADDRESS]['value'];
280
		$data[AccountManager::PROPERTY_WEBSITE] = $userAccount[AccountManager::PROPERTY_WEBSITE]['value'];
281
		$data[AccountManager::PROPERTY_TWITTER] = $userAccount[AccountManager::PROPERTY_TWITTER]['value'];
282
		$data['groups'] = $gids;
283
284
		return $data;
285
	}
286
287
	/**
288
	 * @NoAdminRequired
289
	 * @NoSubAdminRequired
290
	 * @PasswordConfirmationRequired
291
	 *
292
	 * edit users
293
	 *
294
	 * @param string $userId
295
	 * @param string $key
296
	 * @param string $value
297
	 * @return DataResponse
298
	 * @throws OCSException
299
	 * @throws OCSForbiddenException
300
	 */
301
	public function editUser($userId, $key, $value) {
302
		$currentLoggedInUser = $this->userSession->getUser();
303
304
		$targetUser = $this->userManager->get($userId);
305
		if($targetUser === null) {
306
			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
307
		}
308
309
		$permittedFields = [];
310
		if($targetUser->getUID() === $currentLoggedInUser->getUID()) {
311
			// Editing self (display, email)
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
312
			$permittedFields[] = 'display';
313
			$permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
314
			$permittedFields[] = AccountManager::PROPERTY_EMAIL;
315
			$permittedFields[] = 'password';
316
			$permittedFields[] = AccountManager::PROPERTY_PHONE;
317
			$permittedFields[] = AccountManager::PROPERTY_ADDRESS;
318
			$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
319
			$permittedFields[] = AccountManager::PROPERTY_TWITTER;
320
			// If admin they can edit their own quota
321
			if($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
322
				$permittedFields[] = 'quota';
323
			}
324
		} else {
325
			// Check if admin / subadmin
326
			$subAdminManager = $this->groupManager->getSubAdmin();
327
			if($subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
328
			|| $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
329
				// They have permissions over the user
330
				$permittedFields[] = 'display';
331
				$permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
332
				$permittedFields[] = AccountManager::PROPERTY_EMAIL;
333
				$permittedFields[] = 'password';
334
				$permittedFields[] = AccountManager::PROPERTY_PHONE;
335
				$permittedFields[] = AccountManager::PROPERTY_ADDRESS;
336
				$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
337
				$permittedFields[] = AccountManager::PROPERTY_TWITTER;
338
				$permittedFields[] = 'quota';
339
			} else {
340
				// No rights
341
				throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
342
			}
343
		}
344
		// Check if permitted to edit this field
345
		if(!in_array($key, $permittedFields)) {
346
			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
347
		}
348
		// Process the edit
349
		switch($key) {
350
			case 'display':
351
			case AccountManager::PROPERTY_DISPLAYNAME:
352
				$targetUser->setDisplayName($value);
353
				break;
354
			case 'quota':
355
				$quota = $value;
356
				if($quota !== 'none' && $quota !== 'default') {
357
					if (is_numeric($quota)) {
358
						$quota = (float) $quota;
359
					} else {
360
						$quota = \OCP\Util::computerFileSize($quota);
361
					}
362
					if ($quota === false) {
363
						throw new OCSException('Invalid quota value '.$value, 103);
364
					}
365
					if($quota === 0) {
366
						$quota = 'default';
367
					}else if($quota === -1) {
368
						$quota = 'none';
369
					} else {
370
						$quota = \OCP\Util::humanFileSize($quota);
371
					}
372
				}
373
				$targetUser->setQuota($quota);
374
				break;
375
			case 'password':
376
				$targetUser->setPassword($value);
377
				break;
378
			case AccountManager::PROPERTY_EMAIL:
379
				if(filter_var($value, FILTER_VALIDATE_EMAIL)) {
380
					$targetUser->setEMailAddress($value);
381
				} else {
382
					throw new OCSException('', 102);
383
				}
384
				break;
385
			case AccountManager::PROPERTY_PHONE:
386
			case AccountManager::PROPERTY_ADDRESS:
387
			case AccountManager::PROPERTY_WEBSITE:
388
			case AccountManager::PROPERTY_TWITTER:
389
				$userAccount = $this->accountManager->getUser($targetUser);
390
				if ($userAccount[$key]['value'] !== $value) {
391
					$userAccount[$key]['value'] = $value;
392
					$this->accountManager->updateUser($targetUser, $userAccount);
393
				}
394
				break;
395
			default:
396
				throw new OCSException('', 103);
397
		}
398
		return new DataResponse();
399
	}
400
401
	/**
402
	 * @PasswordConfirmationRequired
403
	 * @NoAdminRequired
404
	 *
405
	 * @param string $userId
406
	 * @return DataResponse
407
	 * @throws OCSException
408
	 * @throws OCSForbiddenException
409
	 */
410
	public function deleteUser($userId) {
411
		$currentLoggedInUser = $this->userSession->getUser();
412
413
		$targetUser = $this->userManager->get($userId);
414
415 View Code Duplication
		if($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
416
			throw new OCSException('', 101);
417
		}
418
419
		// If not permitted
420
		$subAdminManager = $this->groupManager->getSubAdmin();
421 View Code Duplication
		if(!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
422
			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
423
		}
424
425
		// Go ahead with the delete
426
		if($targetUser->delete()) {
427
			return new DataResponse();
428
		} else {
429
			throw new OCSException('', 101);
430
		}
431
	}
432
433
	/**
434
	 * @PasswordConfirmationRequired
435
	 * @NoAdminRequired
436
	 *
437
	 * @param string $userId
438
	 * @return DataResponse
439
	 * @throws OCSException
440
	 * @throws OCSForbiddenException
441
	 */
442
	public function disableUser($userId) {
443
		return $this->setEnabled($userId, false);
444
	}
445
446
	/**
447
	 * @PasswordConfirmationRequired
448
	 * @NoAdminRequired
449
	 *
450
	 * @param string $userId
451
	 * @return DataResponse
452
	 * @throws OCSException
453
	 * @throws OCSForbiddenException
454
	 */
455
	public function enableUser($userId) {
456
		return $this->setEnabled($userId, true);
457
	}
458
459
	/**
460
	 * @param string $userId
461
	 * @param bool $value
462
	 * @return DataResponse
463
	 * @throws OCSException
464
	 * @throws OCSForbiddenException
465
	 */
466
	private function setEnabled($userId, $value) {
467
		$currentLoggedInUser = $this->userSession->getUser();
468
469
		$targetUser = $this->userManager->get($userId);
470 View Code Duplication
		if($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
471
			throw new OCSException('', 101);
472
		}
473
474
		// If not permitted
475
		$subAdminManager = $this->groupManager->getSubAdmin();
476 View Code Duplication
		if(!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
477
			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
478
		}
479
480
		// enable/disable the user now
481
		$targetUser->setEnabled($value);
482
		return new DataResponse();
483
	}
484
485
	/**
486
	 * @NoAdminRequired
487
	 * @NoSubAdminRequired
488
	 *
489
	 * @param string $userId
490
	 * @return DataResponse
491
	 * @throws OCSException
492
	 */
493
	public function getUsersGroups($userId) {
494
		$loggedInUser = $this->userSession->getUser();
495
496
		$targetUser = $this->userManager->get($userId);
497
		if($targetUser === null) {
498
			throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
499
		}
500
501
		if($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
502
			// Self lookup or admin lookup
503
			return new DataResponse([
504
				'groups' => $this->groupManager->getUserGroupIds($targetUser)
505
			]);
506
		} else {
507
			$subAdminManager = $this->groupManager->getSubAdmin();
508
509
			// Looking up someone else
510
			if($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
511
				// Return the group that the method caller is subadmin of for the user in question
512
				/** @var IGroup[] $getSubAdminsGroups */
513
				$getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
514
				foreach ($getSubAdminsGroups as $key => $group) {
515
					$getSubAdminsGroups[$key] = $group->getGID();
516
				}
517
				$groups = array_intersect(
518
					$getSubAdminsGroups,
519
					$this->groupManager->getUserGroupIds($targetUser)
520
				);
521
				return new DataResponse(['groups' => $groups]);
522
			} else {
523
				// Not permitted
524
				throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
525
			}
526
		}
527
528
	}
529
530
	/**
531
	 * @PasswordConfirmationRequired
532
	 * @NoAdminRequired
533
	 *
534
	 * @param string $userId
535
	 * @param string $groupid
536
	 * @return DataResponse
537
	 * @throws OCSException
538
	 */
539
	public function addToGroup($userId, $groupid = '') {
540
		if($groupid === '') {
541
			throw new OCSException('', 101);
542
		}
543
544
		$group = $this->groupManager->get($groupid);
545
		$targetUser = $this->userManager->get($userId);
546
		if($group === null) {
547
			throw new OCSException('', 102);
548
		}
549
		if($targetUser === null) {
550
			throw new OCSException('', 103);
551
		}
552
553
		// If they're not an admin, check they are a subadmin of the group in question
554
		$loggedInUser = $this->userSession->getUser();
555
		$subAdminManager = $this->groupManager->getSubAdmin();
556 View Code Duplication
		if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
557
			throw new OCSException('', 104);
558
		}
559
560
		// Add user to group
561
		$group->addUser($targetUser);
562
		return new DataResponse();
563
	}
564
565
	/**
566
	 * @PasswordConfirmationRequired
567
	 * @NoAdminRequired
568
	 *
569
	 * @param string $userId
570
	 * @param string $groupid
571
	 * @return DataResponse
572
	 * @throws OCSException
573
	 */
574
	public function removeFromGroup($userId, $groupid) {
575
		$loggedInUser = $this->userSession->getUser();
576
577
		if($groupid === null) {
578
			throw new OCSException('', 101);
579
		}
580
581
		$group = $this->groupManager->get($groupid);
582
		if($group === null) {
583
			throw new OCSException('', 102);
584
		}
585
586
		$targetUser = $this->userManager->get($userId);
587
		if($targetUser === null) {
588
			throw new OCSException('', 103);
589
		}
590
591
		// If they're not an admin, check they are a subadmin of the group in question
592
		$subAdminManager = $this->groupManager->getSubAdmin();
593 View Code Duplication
		if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
594
			throw new OCSException('', 104);
595
		}
596
597
		// Check they aren't removing themselves from 'admin' or their 'subadmin; group
598
		if ($targetUser->getUID() === $loggedInUser->getUID()) {
599
			if ($this->groupManager->isAdmin($loggedInUser->getUID())) {
600
				if ($group->getGID() === 'admin') {
601
					throw new OCSException('Cannot remove yourself from the admin group', 105);
602
				}
603
			} else {
604
				// Not an admin, so the user must be a subadmin of this group, but that is not allowed.
605
				throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105);
606
			}
607
608
		} else if (!$this->groupManager->isAdmin($loggedInUser->getUID())) {
609
			/** @var IGroup[] $subAdminGroups */
610
			$subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
611
			$subAdminGroups = array_map(function (IGroup $subAdminGroup) {
612
				return $subAdminGroup->getGID();
613
			}, $subAdminGroups);
614
			$userGroups = $this->groupManager->getUserGroupIds($targetUser);
615
			$userSubAdminGroups = array_intersect($subAdminGroups, $userGroups);
616
617
			if (count($userSubAdminGroups) <= 1) {
618
				// Subadmin must not be able to remove a user from all their subadmin groups.
619
				throw new OCSException('Cannot remove user from this group as this is the only remaining group you are a SubAdmin of', 105);
620
			}
621
		}
622
623
		// Remove user from group
624
		$group->removeUser($targetUser);
625
		return new DataResponse();
626
	}
627
628
	/**
629
	 * Creates a subadmin
630
	 *
631
	 * @PasswordConfirmationRequired
632
	 *
633
	 * @param string $userId
634
	 * @param string $groupid
635
	 * @return DataResponse
636
	 * @throws OCSException
637
	 */
638 View Code Duplication
	public function addSubAdmin($userId, $groupid) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
639
		$group = $this->groupManager->get($groupid);
640
		$user = $this->userManager->get($userId);
641
642
		// Check if the user exists
643
		if($user === null) {
644
			throw new OCSException('User does not exist', 101);
645
		}
646
		// Check if group exists
647
		if($group === null) {
648
			throw new OCSException('Group does not exist',  102);
649
		}
650
		// Check if trying to make subadmin of admin group
651
		if($group->getGID() === 'admin') {
652
			throw new OCSException('Cannot create subadmins for admin group', 103);
653
		}
654
655
		$subAdminManager = $this->groupManager->getSubAdmin();
656
657
		// We cannot be subadmin twice
658
		if ($subAdminManager->isSubAdminofGroup($user, $group)) {
659
			return new DataResponse();
660
		}
661
		// Go
662
		if($subAdminManager->createSubAdmin($user, $group)) {
663
			return new DataResponse();
664
		} else {
665
			throw new OCSException('Unknown error occurred', 103);
666
		}
667
	}
668
669
	/**
670
	 * Removes a subadmin from a group
671
	 *
672
	 * @PasswordConfirmationRequired
673
	 *
674
	 * @param string $userId
675
	 * @param string $groupid
676
	 * @return DataResponse
677
	 * @throws OCSException
678
	 */
679 View Code Duplication
	public function removeSubAdmin($userId, $groupid) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
680
		$group = $this->groupManager->get($groupid);
681
		$user = $this->userManager->get($userId);
682
		$subAdminManager = $this->groupManager->getSubAdmin();
683
684
		// Check if the user exists
685
		if($user === null) {
686
			throw new OCSException('User does not exist', 101);
687
		}
688
		// Check if the group exists
689
		if($group === null) {
690
			throw new OCSException('Group does not exist', 101);
691
		}
692
		// Check if they are a subadmin of this said group
693
		if(!$subAdminManager->isSubAdminOfGroup($user, $group)) {
694
			throw new OCSException('User is not a subadmin of this group', 102);
695
		}
696
697
		// Go
698
		if($subAdminManager->deleteSubAdmin($user, $group)) {
699
			return new DataResponse();
700
		} else {
701
			throw new OCSException('Unknown error occurred', 103);
702
		}
703
	}
704
705
	/**
706
	 * Get the groups a user is a subadmin of
707
	 *
708
	 * @param string $userId
709
	 * @return DataResponse
710
	 * @throws OCSException
711
	 */
712
	public function getUserSubAdminGroups($userId) {
713
		$user = $this->userManager->get($userId);
714
		// Check if the user exists
715
		if($user === null) {
716
			throw new OCSException('User does not exist', 101);
717
		}
718
719
		// Get the subadmin groups
720
		$groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($user);
721
		foreach ($groups as $key => $group) {
722
			$groups[$key] = $group->getGID();
723
		}
724
725
		if(!$groups) {
726
			throw new OCSException('Unknown error occurred', 102);
727
		} else {
728
			return new DataResponse($groups);
729
		}
730
	}
731
732
	/**
733
	 * @param string $userId
734
	 * @return array
735
	 * @throws \OCP\Files\NotFoundException
736
	 */
737
	protected function fillStorageInfo($userId) {
738
		try {
739
			\OC_Util::tearDownFS();
740
			\OC_Util::setupFS($userId);
741
			$storage = OC_Helper::getStorageInfo('/');
742
			$data = [
743
				'free' => $storage['free'],
744
				'used' => $storage['used'],
745
				'total' => $storage['total'],
746
				'relative' => $storage['relative'],
747
				'quota' => $storage['quota'],
748
			];
749
		} catch (NotFoundException $ex) {
750
			$data = [];
751
		}
752
		return $data;
753
	}
754
755
	/**
756
	 * @NoAdminRequired
757
	 * @PasswordConfirmationRequired
758
	 *
759
	 * resend welcome message
760
	 *
761
	 * @param string $userId
762
	 * @return DataResponse
763
	 * @throws OCSException
764
	 */
765
	public function resendWelcomeMessage($userId) {
766
		$currentLoggedInUser = $this->userSession->getUser();
767
768
		$targetUser = $this->userManager->get($userId);
769
		if($targetUser === null) {
770
			throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
771
		}
772
773
		// Check if admin / subadmin
774
		$subAdminManager = $this->groupManager->getSubAdmin();
775 View Code Duplication
		if(!$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
776
			&& !$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
777
			// No rights
778
			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
779
		}
780
781
		$email = $targetUser->getEMailAddress();
782
		if ($email === '' || $email === null) {
783
			throw new OCSException('Email address not available', 101);
784
		}
785
		$username = $targetUser->getUID();
786
		$lang = $this->config->getUserValue($username, 'core', 'lang', 'en');
787
		if (!$this->l10nFactory->languageExists('settings', $lang)) {
788
			$lang = 'en';
789
		}
790
791
		$l10n = $this->l10nFactory->get('settings', $lang);
792
793
		try {
794
			$this->newUserMailHelper->setL10N($l10n);
795
			$emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false);
796
			$this->newUserMailHelper->sendMail($targetUser, $emailTemplate);
797
		} catch(\Exception $e) {
798
			$this->logger->error("Can't send new user mail to $email: " . $e->getMessage(), array('app' => 'settings'));
799
			throw new OCSException('Sending email failed', 102);
800
		}
801
802
		return new DataResponse();
803
	}
804
}
805