Completed
Push — master ( 325f92...4c6036 )
by Morris
12:20
created

UsersController::editUser()   D

Complexity

Conditions 24
Paths 74

Size

Total Lines 99
Code Lines 77

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 24
eloc 77
nc 74
nop 3
dl 0
loc 99
rs 4.5989
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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_Helper;
34
use OCP\AppFramework\Http\DataResponse;
35
use OCP\AppFramework\Http\TemplateResponse;
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\IURLGenerator;
46
use OCP\IUserManager;
47
use OCP\IUserSession;
48
use OCP\L10N\IFactory;
49
use OCP\Mail\IMailer;
50
51
class UsersController extends OCSController {
52
53
	/** @var IUserManager */
54
	private $userManager;
55
	/** @var IConfig */
56
	private $config;
57
	/** @var IGroupManager|\OC\Group\Manager */ // FIXME Requires a method that is not on the interface
58
	private $groupManager;
59
	/** @var IUserSession */
60
	private $userSession;
61
	/** @var AccountManager */
62
	private $accountManager;
63
	/** @var ILogger */
64
	private $logger;
65
	/** @var string */
66
	private $fromMailAddress;
67
	/** @var IURLGenerator */
68
	private $urlGenerator;
69
	/** @var IMailer */
70
	private $mailer;
71
	/** @var \OC_Defaults */
72
	private $defaults;
73
	/** @var IFactory */
74
	private $l10nFactory;
75
76
	/**
77
	 * @param string $appName
78
	 * @param IRequest $request
79
	 * @param IUserManager $userManager
80
	 * @param IConfig $config
81
	 * @param IGroupManager $groupManager
82
	 * @param IUserSession $userSession
83
	 * @param AccountManager $accountManager
84
	 * @param ILogger $logger
85
	 * @param string $fromMailAddress
86
	 * @param IURLGenerator $urlGenerator
87
	 * @param IMailer $mailer
88
	 * @param \OC_Defaults $defaults
89
	 * @param IFactory $l10nFactory
90
	 */
91
	public function __construct($appName,
92
								IRequest $request,
93
								IUserManager $userManager,
94
								IConfig $config,
95
								IGroupManager $groupManager,
96
								IUserSession $userSession,
97
								AccountManager $accountManager,
98
								ILogger $logger,
99
								$fromMailAddress,
100
								IURLGenerator $urlGenerator,
101
								IMailer $mailer,
102
								\OC_Defaults $defaults,
103
								IFactory $l10nFactory) {
104
		parent::__construct($appName, $request);
105
106
		$this->userManager = $userManager;
107
		$this->config = $config;
108
		$this->groupManager = $groupManager;
109
		$this->userSession = $userSession;
110
		$this->accountManager = $accountManager;
111
		$this->logger = $logger;
112
		$this->fromMailAddress = $fromMailAddress;
113
		$this->urlGenerator = $urlGenerator;
114
		$this->mailer = $mailer;
115
		$this->defaults = $defaults;
116
		$this->l10nFactory = $l10nFactory;
117
	}
118
119
	/**
120
	 * @NoAdminRequired
121
	 *
122
	 * returns a list of users
123
	 *
124
	 * @param string $search
125
	 * @param int $limit
126
	 * @param int $offset
127
	 * @return DataResponse
128
	 */
129
	public function getUsers($search = '', $limit = null, $offset = null) {
130
		$user = $this->userSession->getUser();
131
		$users = [];
132
133
		// 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...
134
		$uid = $user->getUID();
135
		$subAdminManager = $this->groupManager->getSubAdmin();
136
		if($this->groupManager->isAdmin($uid)){
137
			$users = $this->userManager->search($search, $limit, $offset);
138
		} else if ($subAdminManager->isSubAdmin($user)) {
139
			$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
140
			foreach ($subAdminOfGroups as $key => $group) {
141
				$subAdminOfGroups[$key] = $group->getGID();
142
			}
143
144
			if($offset === null) {
145
				$offset = 0;
146
			}
147
148
			$users = [];
149
			foreach ($subAdminOfGroups as $group) {
150
				$users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search));
151
			}
152
153
			$users = array_slice($users, $offset, $limit);
154
		}
155
156
		$users = array_keys($users);
157
158
		return new DataResponse([
159
			'users' => $users
160
		]);
161
	}
162
163
	/**
164
	 * @PasswordConfirmationRequired
165
	 * @NoAdminRequired
166
	 *
167
	 * @param string $userid
168
	 * @param string $password
169
	 * @param array $groups
170
	 * @return DataResponse
171
	 * @throws OCSException
172
	 */
173
	public function addUser($userid, $password, $groups = null) {
174
		$user = $this->userSession->getUser();
175
		$isAdmin = $this->groupManager->isAdmin($user->getUID());
176
		$subAdminManager = $this->groupManager->getSubAdmin();
177
178
		if($this->userManager->userExists($userid)) {
179
			$this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
180
			throw new OCSException('User already exists', 102);
181
		}
182
183
		if(is_array($groups)) {
184
			foreach ($groups as $group) {
185
				if(!$this->groupManager->groupExists($group)) {
186
					throw new OCSException('group '.$group.' does not exist', 104);
187
				}
188
				if(!$isAdmin && !$subAdminManager->isSubAdminofGroup($user, $this->groupManager->get($group))) {
189
					throw new OCSException('insufficient privileges for group '. $group, 105);
190
				}
191
			}
192
		} else {
193
			if(!$isAdmin) {
194
				throw new OCSException('no group specified (required for subadmins)', 106);
195
			}
196
		}
197
198
		try {
199
			$newUser = $this->userManager->createUser($userid, $password);
200
			$this->logger->info('Successful addUser call with userid: '.$userid, ['app' => 'ocs_api']);
201
202
			if (is_array($groups)) {
203
				foreach ($groups as $group) {
204
					$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 199 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...
205
					$this->logger->info('Added userid '.$userid.' to group '.$group, ['app' => 'ocs_api']);
206
				}
207
			}
208
			return new DataResponse();
209
		} catch (\Exception $e) {
210
			$this->logger->error('Failed addUser attempt with exception: '.$e->getMessage(), ['app' => 'ocs_api']);
211
			throw new OCSException('Bad request', 101);
212
		}
213
	}
214
215
	/**
216
	 * @NoAdminRequired
217
	 * @NoSubAdminRequired
218
	 *
219
	 * gets user info
220
	 *
221
	 * @param string $userId
222
	 * @return DataResponse
223
	 * @throws OCSException
224
	 */
225
	public function getUser($userId) {
226
		$data = $this->getUserData($userId);
227
		return new DataResponse($data);
228
	}
229
230
	/**
231
	 * @NoAdminRequired
232
	 * @NoSubAdminRequired
233
	 *
234
	 * gets user info from the currently logged in user
235
	 *
236
	 * @return DataResponse
237
	 * @throws OCSException
238
	 */
239
	public function getCurrentUser() {
240
		$user = $this->userSession->getUser();
241
		if ($user) {
242
			$data =  $this->getUserData($user->getUID());
243
			// rename "displayname" to "display-name" only for this call to keep
244
			// the API stable.
245
			$data['display-name'] = $data['displayname'];
246
			unset($data['displayname']);
247
			return new DataResponse($data);
248
249
		}
250
251
		throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
252
	}
253
254
	/**
255
	 * creates a array with all user data
256
	 *
257
	 * @param $userId
258
	 * @return array
259
	 * @throws OCSException
260
	 */
261
	protected function getUserData($userId) {
262
		$currentLoggedInUser = $this->userSession->getUser();
263
264
		$data = [];
265
266
		// Check if the target user exists
267
		$targetUserObject = $this->userManager->get($userId);
268
		if($targetUserObject === null) {
269
			throw new OCSException('The requested user could not be found', \OCP\API::RESPOND_NOT_FOUND);
270
		}
271
272
		// 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...
273
		if($this->groupManager->isAdmin($currentLoggedInUser->getUID())
274
			|| $this->groupManager->getSubAdmin()->isUserAccessible($currentLoggedInUser, $targetUserObject)) {
275
			$data['enabled'] = $this->config->getUserValue($userId, 'core', 'enabled', 'true');
276
		} else {
277
			// Check they are looking up themselves
278
			if($currentLoggedInUser->getUID() !== $userId) {
279
				throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
280
			}
281
		}
282
283
		$userAccount = $this->accountManager->getUser($targetUserObject);
284
		$groups = $this->groupManager->getUserGroups($targetUserObject);
285
		$gids = [];
286
		foreach ($groups as $group) {
287
			$gids[] = $group->getDisplayName();
288
		}
289
290
		// Find the data
291
		$data['id'] = $targetUserObject->getUID();
292
		$data['quota'] = $this->fillStorageInfo($userId);
293
		$data[AccountManager::PROPERTY_EMAIL] = $targetUserObject->getEMailAddress();
294
		$data[AccountManager::PROPERTY_DISPLAYNAME] = $targetUserObject->getDisplayName();
295
		$data[AccountManager::PROPERTY_PHONE] = $userAccount[AccountManager::PROPERTY_PHONE]['value'];
296
		$data[AccountManager::PROPERTY_ADDRESS] = $userAccount[AccountManager::PROPERTY_ADDRESS]['value'];
297
		$data[AccountManager::PROPERTY_WEBSITE] = $userAccount[AccountManager::PROPERTY_WEBSITE]['value'];
298
		$data[AccountManager::PROPERTY_TWITTER] = $userAccount[AccountManager::PROPERTY_TWITTER]['value'];
299
		$data['groups'] = $gids;
300
301
		return $data;
302
	}
303
304
	/**
305
	 * @NoAdminRequired
306
	 * @NoSubAdminRequired
307
	 * @PasswordConfirmationRequired
308
	 *
309
	 * edit users
310
	 *
311
	 * @param string $userId
312
	 * @param string $key
313
	 * @param string $value
314
	 * @return DataResponse
315
	 * @throws OCSException
316
	 * @throws OCSForbiddenException
317
	 */
318
	public function editUser($userId, $key, $value) {
319
		$currentLoggedInUser = $this->userSession->getUser();
320
321
		$targetUser = $this->userManager->get($userId);
322
		if($targetUser === null) {
323
			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
324
		}
325
326
		$permittedFields = [];
327
		if($userId === $currentLoggedInUser->getUID()) {
328
			// 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...
329
			$permittedFields[] = 'display';
330
			$permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
331
			$permittedFields[] = AccountManager::PROPERTY_EMAIL;
332
			$permittedFields[] = 'password';
333
			$permittedFields[] = AccountManager::PROPERTY_PHONE;
334
			$permittedFields[] = AccountManager::PROPERTY_ADDRESS;
335
			$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
336
			$permittedFields[] = AccountManager::PROPERTY_TWITTER;
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 ($userId === $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
	public function addSubAdmin($userId, $groupid) {
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:'.$groupid.' does not exist',  102);
666
		}
667
		// Check if trying to make subadmin of admin group
668
		if(strtolower($groupid) === '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
	public function removeSubAdmin($userId, $groupid) {
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_UNAUTHORISED);
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
		// data for the mail template
811
		$mailData = [
812
			'username' => $username,
813
			'url' => $this->urlGenerator->getAbsoluteURL('/')
814
		];
815
816
		// FIXME: set users language in email
817
		$mail = new TemplateResponse('settings', 'email.new_user', $mailData, 'blank');
818
		$mailContent = $mail->render();
819
820
		// FIXME: set users language in email
821
		$mail = new TemplateResponse('settings', 'email.new_user_plain_text', $mailData, 'blank');
822
		$plainTextMailContent = $mail->render();
823
824
		$subject = $l10n->t('Your %s account was created', [$this->defaults->getName()]);
825
826
		try {
827
			$message = $this->mailer->createMessage();
828
			$message->setTo([$email => $username]);
829
			$message->setSubject($subject);
830
			$message->setHtmlBody($mailContent);
0 ignored issues
show
Bug introduced by
It seems like $mailContent defined by $mail->render() on line 818 can also be of type boolean; however, OC\Mail\Message::setHtmlBody() does only seem to accept string, 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...
831
			$message->setPlainBody($plainTextMailContent);
0 ignored issues
show
Bug introduced by
It seems like $plainTextMailContent defined by $mail->render() on line 822 can also be of type boolean; however, OC\Mail\Message::setPlainBody() does only seem to accept string, 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...
832
			$message->setFrom([$this->fromMailAddress => $this->defaults->getName()]);
833
			$this->mailer->send($message);
834
		} catch(\Exception $e) {
835
			$this->logger->error("Can't send new user mail to $email: " . $e->getMessage(), array('app' => 'settings'));
836
			throw new OCSException('Sending email failed', 102);
837
		}
838
839
		return new DataResponse();
840
	}
841
}
842