Completed
Push — master ( 811f7b...15314b )
by Morris
54:22 queued 31:53
created

UsersController::getUsersGroups()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 36
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

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