Completed
Push — master ( 4c6036...8838ed )
by Morris
11:46
created

UsersController   F

Complexity

Total Complexity 87

Size/Duplication

Total Lines 752
Duplicated Lines 5.59 %

Coupling/Cohesion

Components 1
Dependencies 18

Importance

Changes 0
Metric Value
dl 42
loc 752
rs 1.263
c 0
b 0
f 0
wmc 87
lcom 1
cbo 18

11 Methods

Rating   Name   Duplication   Size   Complexity  
B stats() 0 29 6
B __construct() 0 38 2
B formatUserForIndex() 0 58 8
A getUsersForUID() 0 7 2
C index() 0 72 15
D create() 0 116 20
B destroy() 11 52 6
B setUserSettings() 0 70 4
D saveUserSettings() 18 30 9
C setDisplayName() 0 45 7
C setEMailAddress() 13 78 8

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like UsersController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use UsersController, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Clark Tomlinson <[email protected]>
7
 * @author Joas Schilling <[email protected]>
8
 * @author Lukas Reschke <[email protected]>
9
 * @author Morris Jobke <[email protected]>
10
 * @author Robin Appelman <[email protected]>
11
 * @author Roeland Jago Douma <[email protected]>
12
 * @author Thomas Müller <[email protected]>
13
 * @author Vincent Petry <[email protected]>
14
 *
15
 * @license AGPL-3.0
16
 *
17
 * This code is free software: you can redistribute it and/or modify
18
 * it under the terms of the GNU Affero General Public License, version 3,
19
 * as published by the Free Software Foundation.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
 * GNU Affero General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU Affero General Public License, version 3,
27
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
28
 *
29
 */
30
31
namespace OC\Settings\Controller;
32
33
use OC\Accounts\AccountManager;
34
use OC\AppFramework\Http;
35
use OC\ForbiddenException;
36
use OC\Settings\Mailer\NewUserMailHelper;
37
use OCP\App\IAppManager;
38
use OCP\AppFramework\Controller;
39
use OCP\AppFramework\Http\DataResponse;
40
use OCP\IConfig;
41
use OCP\IGroupManager;
42
use OCP\IL10N;
43
use OCP\ILogger;
44
use OCP\IRequest;
45
use OCP\IURLGenerator;
46
use OCP\IUser;
47
use OCP\IUserManager;
48
use OCP\IUserSession;
49
use OCP\Mail\IMailer;
50
use OCP\IAvatarManager;
51
use OCP\Security\ISecureRandom;
52
53
/**
54
 * @package OC\Settings\Controller
55
 */
56
class UsersController extends Controller {
57
	/** @var IL10N */
58
	private $l10n;
59
	/** @var IUserSession */
60
	private $userSession;
61
	/** @var bool */
62
	private $isAdmin;
63
	/** @var IUserManager */
64
	private $userManager;
65
	/** @var IGroupManager */
66
	private $groupManager;
67
	/** @var IConfig */
68
	private $config;
69
	/** @var ILogger */
70
	private $log;
71
	/** @var IMailer */
72
	private $mailer;
73
	/** @var bool contains the state of the encryption app */
74
	private $isEncryptionAppEnabled;
75
	/** @var bool contains the state of the admin recovery setting */
76
	private $isRestoreEnabled = false;
77
	/** @var IAvatarManager */
78
	private $avatarManager;
79
	/** @var AccountManager */
80
	private $accountManager;
81
	/** @var ISecureRandom */
82
	private $secureRandom;
83
	/** @var NewUserMailHelper */
84
	private $newUserMailHelper;
85
86
	/**
87
	 * @param string $appName
88
	 * @param IRequest $request
89
	 * @param IUserManager $userManager
90
	 * @param IGroupManager $groupManager
91
	 * @param IUserSession $userSession
92
	 * @param IConfig $config
93
	 * @param bool $isAdmin
94
	 * @param IL10N $l10n
95
	 * @param ILogger $log
96
	 * @param IMailer $mailer
97
	 * @param IURLGenerator $urlGenerator
98
	 * @param IAppManager $appManager
99
	 * @param IAvatarManager $avatarManager
100
	 * @param AccountManager $accountManager
101
	 * @param ISecureRandom $secureRandom
102
	 * @param NewUserMailHelper $newUserMailHelper
103
	 */
104
	public function __construct($appName,
105
								IRequest $request,
106
								IUserManager $userManager,
107
								IGroupManager $groupManager,
108
								IUserSession $userSession,
109
								IConfig $config,
110
								$isAdmin,
111
								IL10N $l10n,
112
								ILogger $log,
113
								IMailer $mailer,
114
								IURLGenerator $urlGenerator,
0 ignored issues
show
Unused Code introduced by
The parameter $urlGenerator is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
115
								IAppManager $appManager,
116
								IAvatarManager $avatarManager,
117
								AccountManager $accountManager,
118
								ISecureRandom $secureRandom,
119
								NewUserMailHelper $newUserMailHelper) {
120
		parent::__construct($appName, $request);
121
		$this->userManager = $userManager;
122
		$this->groupManager = $groupManager;
123
		$this->userSession = $userSession;
124
		$this->config = $config;
125
		$this->isAdmin = $isAdmin;
126
		$this->l10n = $l10n;
127
		$this->log = $log;
128
		$this->mailer = $mailer;
129
		$this->avatarManager = $avatarManager;
130
		$this->accountManager = $accountManager;
131
		$this->secureRandom = $secureRandom;
132
		$this->newUserMailHelper = $newUserMailHelper;
133
134
		// check for encryption state - TODO see formatUserForIndex
135
		$this->isEncryptionAppEnabled = $appManager->isEnabledForUser('encryption');
136
		if($this->isEncryptionAppEnabled) {
137
			// putting this directly in empty is possible in PHP 5.5+
138
			$result = $config->getAppValue('encryption', 'recoveryAdminEnabled', 0);
139
			$this->isRestoreEnabled = !empty($result);
140
		}
141
	}
142
143
	/**
144
	 * @param IUser $user
145
	 * @param array $userGroups
146
	 * @return array
147
	 */
148
	private function formatUserForIndex(IUser $user, array $userGroups = null) {
149
150
		// TODO: eliminate this encryption specific code below and somehow
151
		// hook in additional user info from other apps
152
153
		// recovery isn't possible if admin or user has it disabled and encryption
154
		// is enabled - so we eliminate the else paths in the conditional tree
155
		// below
156
		$restorePossible = false;
157
158
		if ($this->isEncryptionAppEnabled) {
159
			if ($this->isRestoreEnabled) {
160
				// check for the users recovery setting
161
				$recoveryMode = $this->config->getUserValue($user->getUID(), 'encryption', 'recoveryEnabled', '0');
162
				// method call inside empty is possible with PHP 5.5+
163
				$recoveryModeEnabled = !empty($recoveryMode);
164
				if ($recoveryModeEnabled) {
165
					// user also has recovery mode enabled
166
					$restorePossible = true;
167
				}
168
			}
169
		} else {
170
			// recovery is possible if encryption is disabled (plain files are
171
			// available)
172
			$restorePossible = true;
173
		}
174
175
		$subAdminGroups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($user);
176
		foreach($subAdminGroups as $key => $subAdminGroup) {
177
			$subAdminGroups[$key] = $subAdminGroup->getGID();
178
		}
179
180
		$displayName = $user->getEMailAddress();
181
		if (is_null($displayName)) {
182
			$displayName = '';
183
		}
184
185
		$avatarAvailable = false;
186
		try {
187
			$avatarAvailable = $this->avatarManager->getAvatar($user->getUID())->exists();
188
		} catch (\Exception $e) {
189
			//No avatar yet
190
		}
191
192
		return [
193
			'name' => $user->getUID(),
194
			'displayname' => $user->getDisplayName(),
195
			'groups' => (empty($userGroups)) ? $this->groupManager->getUserGroupIds($user) : $userGroups,
196
			'subadmin' => $subAdminGroups,
197
			'quota' => $user->getQuota(),
198
			'storageLocation' => $user->getHome(),
199
			'lastLogin' => $user->getLastLogin() * 1000,
200
			'backend' => $user->getBackendClassName(),
201
			'email' => $displayName,
202
			'isRestoreDisabled' => !$restorePossible,
203
			'isAvatarAvailable' => $avatarAvailable,
204
		];
205
	}
206
207
	/**
208
	 * @param array $userIDs Array with schema [$uid => $displayName]
209
	 * @return IUser[]
210
	 */
211
	private function getUsersForUID(array $userIDs) {
212
		$users = [];
213
		foreach ($userIDs as $uid => $displayName) {
214
			$users[$uid] = $this->userManager->get($uid);
215
		}
216
		return $users;
217
	}
218
219
	/**
220
	 * @NoAdminRequired
221
	 *
222
	 * @param int $offset
223
	 * @param int $limit
224
	 * @param string $gid GID to filter for
225
	 * @param string $pattern Pattern to search for in the username
226
	 * @param string $backend Backend to filter for (class-name)
227
	 * @return DataResponse
228
	 *
229
	 * TODO: Tidy up and write unit tests - code is mainly static method calls
230
	 */
231
	public function index($offset = 0, $limit = 10, $gid = '', $pattern = '', $backend = '') {
232
		// FIXME: The JS sends the group '_everyone' instead of no GID for the "all users" group.
233
		if($gid === '_everyone') {
234
			$gid = '';
235
		}
236
237
		// Remove backends
238
		if(!empty($backend)) {
239
			$activeBackends = $this->userManager->getBackends();
240
			$this->userManager->clearBackends();
241
			foreach($activeBackends as $singleActiveBackend) {
242
				if($backend === get_class($singleActiveBackend)) {
243
					$this->userManager->registerBackend($singleActiveBackend);
244
					break;
245
				}
246
			}
247
		}
248
249
		$users = [];
250
		if ($this->isAdmin) {
251
252
			if($gid !== '') {
253
				$batch = $this->getUsersForUID($this->groupManager->displayNamesInGroup($gid, $pattern, $limit, $offset));
254
			} else {
255
				$batch = $this->userManager->search($pattern, $limit, $offset);
256
			}
257
258
			foreach ($batch as $user) {
259
				$users[] = $this->formatUserForIndex($user);
260
			}
261
262
		} else {
263
			$subAdminOfGroups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($this->userSession->getUser());
264
			// New class returns IGroup[] so convert back
265
			$gids = [];
266
			foreach ($subAdminOfGroups as $group) {
267
				$gids[] = $group->getGID();
268
			}
269
			$subAdminOfGroups = $gids;
270
271
			// Set the $gid parameter to an empty value if the subadmin has no rights to access a specific group
272
			if($gid !== '' && !in_array($gid, $subAdminOfGroups)) {
273
				$gid = '';
274
			}
275
276
			// Batch all groups the user is subadmin of when a group is specified
277
			$batch = [];
278
			if($gid === '') {
279
				foreach($subAdminOfGroups as $group) {
280
					$groupUsers = $this->groupManager->displayNamesInGroup($group, $pattern, $limit, $offset);
281
282
					foreach($groupUsers as $uid => $displayName) {
283
						$batch[$uid] = $displayName;
284
					}
285
				}
286
			} else {
287
				$batch = $this->groupManager->displayNamesInGroup($gid, $pattern, $limit, $offset);
288
			}
289
			$batch = $this->getUsersForUID($batch);
290
291
			foreach ($batch as $user) {
292
				// Only add the groups, this user is a subadmin of
293
				$userGroups = array_values(array_intersect(
294
					$this->groupManager->getUserGroupIds($user),
295
					$subAdminOfGroups
296
				));
297
				$users[] = $this->formatUserForIndex($user, $userGroups);
298
			}
299
		}
300
301
		return new DataResponse($users);
302
	}
303
304
	/**
305
	 * @NoAdminRequired
306
	 * @PasswordConfirmationRequired
307
	 *
308
	 * @param string $username
309
	 * @param string $password
310
	 * @param array $groups
311
	 * @param string $email
312
	 * @return DataResponse
313
	 */
314
	public function create($username, $password, array $groups=array(), $email='') {
315
		if($email !== '' && !$this->mailer->validateMailAddress($email)) {
316
			return new DataResponse(
317
				array(
318
					'message' => (string)$this->l10n->t('Invalid mail address')
319
				),
320
				Http::STATUS_UNPROCESSABLE_ENTITY
321
			);
322
		}
323
324
		$currentUser = $this->userSession->getUser();
325
326
		if (!$this->isAdmin) {
327
			if (!empty($groups)) {
328
				foreach ($groups as $key => $group) {
329
					$groupObject = $this->groupManager->get($group);
330
					if($groupObject === null) {
331
						unset($groups[$key]);
332
						continue;
333
					}
334
335
					if (!$this->groupManager->getSubAdmin()->isSubAdminofGroup($currentUser, $groupObject)) {
336
						unset($groups[$key]);
337
					}
338
				}
339
			}
340
341
			if (empty($groups)) {
342
				return new DataResponse(
343
					array(
344
						'message' => $this->l10n->t('No valid group selected'),
345
					),
346
					Http::STATUS_FORBIDDEN
347
				);
348
			}
349
		}
350
351
		if ($this->userManager->userExists($username)) {
352
			return new DataResponse(
353
				array(
354
					'message' => (string)$this->l10n->t('A user with that name already exists.')
355
				),
356
				Http::STATUS_CONFLICT
357
			);
358
		}
359
360
		$generatePasswordResetToken = false;
361
		if ($password === '') {
362
			if ($email === '') {
363
				return new DataResponse(
364
					array(
365
						'message' => (string)$this->l10n->t('To send a password link to the user an email address is required.')
366
					),
367
					Http::STATUS_UNPROCESSABLE_ENTITY
368
				);
369
			}
370
371
			$password = $this->secureRandom->generate(32);
372
			$generatePasswordResetToken = true;
373
		}
374
375
		try {
376
			$user = $this->userManager->createUser($username, $password);
377
		} catch (\Exception $exception) {
378
			$message = $exception->getMessage();
379
			if (!$message) {
380
				$message = $this->l10n->t('Unable to create user.');
381
			}
382
			return new DataResponse(
383
				array(
384
					'message' => (string) $message,
385
				),
386
				Http::STATUS_FORBIDDEN
387
			);
388
		}
389
390
		if($user instanceof IUser) {
391
			if($groups !== null) {
392
				foreach($groups as $groupName) {
393
					$group = $this->groupManager->get($groupName);
394
395
					if(empty($group)) {
396
						$group = $this->groupManager->createGroup($groupName);
397
					}
398
					$group->addUser($user);
399
				}
400
			}
401
			/**
402
			 * Send new user mail only if a mail is set
403
			 */
404
			if($email !== '') {
405
				$user->setEMailAddress($email);
406
				try {
407
					$emailTemplate = $this->newUserMailHelper->generateTemplate($user, $generatePasswordResetToken);
408
					$this->newUserMailHelper->sendMail($user, $emailTemplate);
409
				} catch(\Exception $e) {
410
					$this->log->error("Can't send new user mail to $email: " . $e->getMessage(), array('app' => 'settings'));
411
				}
412
			}
413
			// fetch users groups
414
			$userGroups = $this->groupManager->getUserGroupIds($user);
415
416
			return new DataResponse(
417
				$this->formatUserForIndex($user, $userGroups),
418
				Http::STATUS_CREATED
419
			);
420
		}
421
422
		return new DataResponse(
423
			array(
424
				'message' => (string)$this->l10n->t('Unable to create user.')
425
			),
426
			Http::STATUS_FORBIDDEN
427
		);
428
429
	}
430
431
	/**
432
	 * @NoAdminRequired
433
	 * @PasswordConfirmationRequired
434
	 *
435
	 * @param string $id
436
	 * @return DataResponse
437
	 */
438
	public function destroy($id) {
439
		$userId = $this->userSession->getUser()->getUID();
440
		$user = $this->userManager->get($id);
441
442
		if($userId === $id) {
443
			return new DataResponse(
444
				array(
445
					'status' => 'error',
446
					'data' => array(
447
						'message' => (string)$this->l10n->t('Unable to delete user.')
448
					)
449
				),
450
				Http::STATUS_FORBIDDEN
451
			);
452
		}
453
454 View Code Duplication
		if(!$this->isAdmin && !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)) {
455
			return new DataResponse(
456
				array(
457
					'status' => 'error',
458
					'data' => array(
459
						'message' => (string)$this->l10n->t('Authentication error')
460
					)
461
				),
462
				Http::STATUS_FORBIDDEN
463
			);
464
		}
465
466
		if($user) {
467
			if($user->delete()) {
468
				return new DataResponse(
469
					array(
470
						'status' => 'success',
471
						'data' => array(
472
							'username' => $id
473
						)
474
					),
475
					Http::STATUS_NO_CONTENT
476
				);
477
			}
478
		}
479
480
		return new DataResponse(
481
			array(
482
				'status' => 'error',
483
				'data' => array(
484
					'message' => (string)$this->l10n->t('Unable to delete user.')
485
				)
486
			),
487
			Http::STATUS_FORBIDDEN
488
		);
489
	}
490
491
	/**
492
	 * @NoAdminRequired
493
	 * @NoSubadminRequired
494
	 * @PasswordConfirmationRequired
495
	 *
496
	 * @param string $avatarScope
497
	 * @param string $displayname
498
	 * @param string $displaynameScope
499
	 * @param string $phone
500
	 * @param string $phoneScope
501
	 * @param string $email
502
	 * @param string $emailScope
503
	 * @param string $website
504
	 * @param string $websiteScope
505
	 * @param string $address
506
	 * @param string $addressScope
507
	 * @param string $twitter
508
	 * @param string $twitterScope
509
	 * @return DataResponse
510
	 */
511
	public function setUserSettings($avatarScope,
512
									$displayname,
513
									$displaynameScope,
514
									$phone,
515
									$phoneScope,
516
									$email,
517
									$emailScope,
518
									$website,
519
									$websiteScope,
520
									$address,
521
									$addressScope,
522
									$twitter,
523
									$twitterScope
524
	) {
525
526
		if(!empty($email) && !$this->mailer->validateMailAddress($email)) {
527
			return new DataResponse(
528
				array(
529
					'status' => 'error',
530
					'data' => array(
531
						'message' => (string)$this->l10n->t('Invalid mail address')
532
					)
533
				),
534
				Http::STATUS_UNPROCESSABLE_ENTITY
535
			);
536
		}
537
538
		$data = [
539
			AccountManager::PROPERTY_AVATAR =>  ['scope' => $avatarScope],
540
			AccountManager::PROPERTY_DISPLAYNAME => ['value' => $displayname, 'scope' => $displaynameScope],
541
			AccountManager::PROPERTY_EMAIL=> ['value' => $email, 'scope' => $emailScope],
542
			AccountManager::PROPERTY_WEBSITE => ['value' => $website, 'scope' => $websiteScope],
543
			AccountManager::PROPERTY_ADDRESS => ['value' => $address, 'scope' => $addressScope],
544
			AccountManager::PROPERTY_PHONE => ['value' => $phone, 'scope' => $phoneScope],
545
			AccountManager::PROPERTY_TWITTER => ['value' => $twitter, 'scope' => $twitterScope]
546
		];
547
548
		$user = $this->userSession->getUser();
549
550
		try {
551
			$this->saveUserSettings($user, $data);
0 ignored issues
show
Bug introduced by
It seems like $user defined by $this->userSession->getUser() on line 548 can be null; however, OC\Settings\Controller\U...ler::saveUserSettings() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
552
			return new DataResponse(
553
				array(
554
					'status' => 'success',
555
					'data' => array(
556
						'userId' => $user->getUID(),
557
						'avatarScope' => $avatarScope,
558
						'displayname' => $displayname,
559
						'displaynameScope' => $displaynameScope,
560
						'email' => $email,
561
						'emailScope' => $emailScope,
562
						'website' => $website,
563
						'websiteScope' => $websiteScope,
564
						'address' => $address,
565
						'addressScope' => $addressScope,
566
						'message' => (string)$this->l10n->t('Settings saved')
567
					)
568
				),
569
				Http::STATUS_OK
570
			);
571
		} catch (ForbiddenException $e) {
572
			return new DataResponse([
573
				'status' => 'error',
574
				'data' => [
575
					'message' => $e->getMessage()
576
				],
577
			]);
578
		}
579
580
	}
581
582
583
	/**
584
	 * update account manager with new user data
585
	 *
586
	 * @param IUser $user
587
	 * @param array $data
588
	 * @throws ForbiddenException
589
	 */
590
	protected function saveUserSettings(IUser $user, $data) {
591
592
		// keep the user back-end up-to-date with the latest display name and email
593
		// address
594
		$oldDisplayName = $user->getDisplayName();
595
		$oldDisplayName = is_null($oldDisplayName) ? '' : $oldDisplayName;
596 View Code Duplication
		if (isset($data[AccountManager::PROPERTY_DISPLAYNAME]['value'])
597
			&& $oldDisplayName !== $data[AccountManager::PROPERTY_DISPLAYNAME]['value']
598
		) {
599
			$result = $user->setDisplayName($data[AccountManager::PROPERTY_DISPLAYNAME]['value']);
600
			if ($result === false) {
601
				throw new ForbiddenException($this->l10n->t('Unable to change full name'));
602
			}
603
		}
604
605
		$oldEmailAddress = $user->getEMailAddress();
606
		$oldEmailAddress = is_null($oldEmailAddress) ? '' : $oldEmailAddress;
607 View Code Duplication
		if (isset($data[AccountManager::PROPERTY_EMAIL]['value'])
608
			&& $oldEmailAddress !== $data[AccountManager::PROPERTY_EMAIL]['value']
609
		) {
610
			// this is the only permission a backend provides and is also used
611
			// for the permission of setting a email address
612
			if (!$user->canChangeDisplayName()) {
613
				throw new ForbiddenException($this->l10n->t('Unable to change email address'));
614
			}
615
			$user->setEMailAddress($data[AccountManager::PROPERTY_EMAIL]['value']);
616
		}
617
618
		$this->accountManager->updateUser($user, $data);
619
	}
620
621
	/**
622
	 * Count all unique users visible for the current admin/subadmin.
623
	 *
624
	 * @NoAdminRequired
625
	 *
626
	 * @return DataResponse
627
	 */
628
	public function stats() {
629
		$userCount = 0;
630
		if ($this->isAdmin) {
631
			$countByBackend = $this->userManager->countUsers();
632
633
			if (!empty($countByBackend)) {
634
				foreach ($countByBackend as $count) {
635
					$userCount += $count;
636
				}
637
			}
638
		} else {
639
			$groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($this->userSession->getUser());
640
641
			$uniqueUsers = [];
642
			foreach ($groups as $group) {
643
				foreach($group->getUsers() as $uid => $displayName) {
644
					$uniqueUsers[$uid] = true;
645
				}
646
			}
647
648
			$userCount = count($uniqueUsers);
649
		}
650
651
		return new DataResponse(
652
			[
653
				'totalUsers' => $userCount
654
			]
655
		);
656
	}
657
658
659
	/**
660
	 * Set the displayName of a user
661
	 *
662
	 * @NoAdminRequired
663
	 * @NoSubadminRequired
664
	 * @PasswordConfirmationRequired
665
	 * @todo merge into saveUserSettings
666
	 *
667
	 * @param string $username
668
	 * @param string $displayName
669
	 * @return DataResponse
670
	 */
671
	public function setDisplayName($username, $displayName) {
672
		$currentUser = $this->userSession->getUser();
673
		$user = $this->userManager->get($username);
674
675
		if ($user === null ||
676
			!$user->canChangeDisplayName() ||
677
			(
678
				!$this->groupManager->isAdmin($currentUser->getUID()) &&
679
				!$this->groupManager->getSubAdmin()->isUserAccessible($currentUser, $user) &&
680
				$currentUser->getUID() !== $username
681
682
			)
683
		) {
684
			return new DataResponse([
685
				'status' => 'error',
686
				'data' => [
687
					'message' => $this->l10n->t('Authentication error'),
688
				],
689
			]);
690
		}
691
692
		$userData = $this->accountManager->getUser($user);
693
		$userData[AccountManager::PROPERTY_DISPLAYNAME]['value'] = $displayName;
694
695
696
		try {
697
			$this->saveUserSettings($user, $userData);
698
			return new DataResponse([
699
				'status' => 'success',
700
				'data' => [
701
					'message' => $this->l10n->t('Your full name has been changed.'),
702
					'username' => $username,
703
					'displayName' => $displayName,
704
				],
705
			]);
706
		} catch (ForbiddenException $e) {
707
			return new DataResponse([
708
				'status' => 'error',
709
				'data' => [
710
					'message' => $e->getMessage(),
711
					'displayName' => $user->getDisplayName(),
712
				],
713
			]);
714
		}
715
	}
716
717
	/**
718
	 * Set the mail address of a user
719
	 *
720
	 * @NoAdminRequired
721
	 * @NoSubadminRequired
722
	 * @PasswordConfirmationRequired
723
	 *
724
	 * @param string $id
725
	 * @param string $mailAddress
726
	 * @return DataResponse
727
	 */
728
	public function setEMailAddress($id, $mailAddress) {
729
		$user = $this->userManager->get($id);
730 View Code Duplication
		if (!$this->isAdmin
731
			&& !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)
732
		) {
733
			return new DataResponse(
734
				array(
735
					'status' => 'error',
736
					'data' => array(
737
						'message' => (string)$this->l10n->t('Forbidden')
738
					)
739
				),
740
				Http::STATUS_FORBIDDEN
741
			);
742
		}
743
744
		if($mailAddress !== '' && !$this->mailer->validateMailAddress($mailAddress)) {
745
			return new DataResponse(
746
				array(
747
					'status' => 'error',
748
					'data' => array(
749
						'message' => (string)$this->l10n->t('Invalid mail address')
750
					)
751
				),
752
				Http::STATUS_UNPROCESSABLE_ENTITY
753
			);
754
		}
755
756
		if (!$user) {
757
			return new DataResponse(
758
				array(
759
					'status' => 'error',
760
					'data' => array(
761
						'message' => (string)$this->l10n->t('Invalid user')
762
					)
763
				),
764
				Http::STATUS_UNPROCESSABLE_ENTITY
765
			);
766
		}
767
		// this is the only permission a backend provides and is also used
768
		// for the permission of setting a email address
769
		if (!$user->canChangeDisplayName()) {
770
			return new DataResponse(
771
				array(
772
					'status' => 'error',
773
					'data' => array(
774
						'message' => (string)$this->l10n->t('Unable to change mail address')
775
					)
776
				),
777
				Http::STATUS_FORBIDDEN
778
			);
779
		}
780
781
		$userData = $this->accountManager->getUser($user);
782
		$userData[AccountManager::PROPERTY_EMAIL]['value'] = $mailAddress;
783
784
		try {
785
			$this->saveUserSettings($user, $userData);
786
			return new DataResponse(
787
				array(
788
					'status' => 'success',
789
					'data' => array(
790
						'username' => $id,
791
						'mailAddress' => $mailAddress,
792
						'message' => (string)$this->l10n->t('Email saved')
793
					)
794
				),
795
				Http::STATUS_OK
796
			);
797
		} catch (ForbiddenException $e) {
798
			return new DataResponse([
799
				'status' => 'error',
800
				'data' => [
801
					'message' => $e->getMessage()
802
				],
803
			]);
804
		}
805
	}
806
807
}
808