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