Completed
Pull Request — master (#8375)
by Morris
22:22 queued 02:13
created
settings/Controller/ChangePasswordController.php 1 patch
Indentation   +234 added lines, -234 removed lines patch added patch discarded remove patch
@@ -35,256 +35,256 @@
 block discarded – undo
35 35
 
36 36
 class ChangePasswordController extends Controller {
37 37
 
38
-	/** @var string */
39
-	private $userId;
38
+    /** @var string */
39
+    private $userId;
40 40
 
41
-	/** @var UserManager */
42
-	private $userManager;
41
+    /** @var UserManager */
42
+    private $userManager;
43 43
 
44
-	/** @var IL10N */
45
-	private $l;
44
+    /** @var IL10N */
45
+    private $l;
46 46
 
47
-	/** @var GroupManager */
48
-	private $groupManager;
47
+    /** @var GroupManager */
48
+    private $groupManager;
49 49
 
50
-	/** @var Session */
51
-	private $userSession;
50
+    /** @var Session */
51
+    private $userSession;
52 52
 
53
-	/** @var IAppManager */
54
-	private $appManager;
53
+    /** @var IAppManager */
54
+    private $appManager;
55 55
 
56
-	/**
57
-	 * ChangePasswordController constructor.
58
-	 *
59
-	 * @param string $appName
60
-	 * @param IRequest $request
61
-	 * @param $userId
62
-	 * @param UserManager $userManager
63
-	 * @param IUserSession $userSession
64
-	 * @param GroupManager $groupManager
65
-	 * @param IAppManager $appManager
66
-	 * @param IL10N $l
67
-	 */
68
-	public function __construct($appName,
69
-								IRequest $request,
70
-								$userId,
71
-								UserManager $userManager,
72
-								IUserSession $userSession,
73
-								GroupManager $groupManager,
74
-								IAppManager $appManager,
75
-								IL10N $l) {
76
-		parent::__construct($appName, $request);
56
+    /**
57
+     * ChangePasswordController constructor.
58
+     *
59
+     * @param string $appName
60
+     * @param IRequest $request
61
+     * @param $userId
62
+     * @param UserManager $userManager
63
+     * @param IUserSession $userSession
64
+     * @param GroupManager $groupManager
65
+     * @param IAppManager $appManager
66
+     * @param IL10N $l
67
+     */
68
+    public function __construct($appName,
69
+                                IRequest $request,
70
+                                $userId,
71
+                                UserManager $userManager,
72
+                                IUserSession $userSession,
73
+                                GroupManager $groupManager,
74
+                                IAppManager $appManager,
75
+                                IL10N $l) {
76
+        parent::__construct($appName, $request);
77 77
 
78
-		$this->userId = $userId;
79
-		$this->userManager = $userManager;
80
-		$this->userSession = $userSession;
81
-		$this->groupManager = $groupManager;
82
-		$this->appManager = $appManager;
83
-		$this->l = $l;
84
-	}
78
+        $this->userId = $userId;
79
+        $this->userManager = $userManager;
80
+        $this->userSession = $userSession;
81
+        $this->groupManager = $groupManager;
82
+        $this->appManager = $appManager;
83
+        $this->l = $l;
84
+    }
85 85
 
86
-	/**
87
-	 * @NoAdminRequired
88
-	 * @NoSubadminRequired
89
-	 * @BruteForceProtection(action=changePersonalPassword)
90
-	 *
91
-	 * @param string $oldpassword
92
-	 * @param string $newpassword
93
-	 *
94
-	 * @return JSONResponse
95
-	 */
96
-	public function changePersonalPassword($oldpassword = '', $newpassword = null) {
97
-		/** @var IUser $user */
98
-		$user = $this->userManager->checkPassword($this->userId, $oldpassword);
99
-		if ($user === false) {
100
-			$response = new JSONResponse([
101
-				'status' => 'error',
102
-				'data' => [
103
-					'message' => $this->l->t('Wrong password'),
104
-				],
105
-			]);
106
-			$response->throttle();
107
-			return $response;
108
-		}
86
+    /**
87
+     * @NoAdminRequired
88
+     * @NoSubadminRequired
89
+     * @BruteForceProtection(action=changePersonalPassword)
90
+     *
91
+     * @param string $oldpassword
92
+     * @param string $newpassword
93
+     *
94
+     * @return JSONResponse
95
+     */
96
+    public function changePersonalPassword($oldpassword = '', $newpassword = null) {
97
+        /** @var IUser $user */
98
+        $user = $this->userManager->checkPassword($this->userId, $oldpassword);
99
+        if ($user === false) {
100
+            $response = new JSONResponse([
101
+                'status' => 'error',
102
+                'data' => [
103
+                    'message' => $this->l->t('Wrong password'),
104
+                ],
105
+            ]);
106
+            $response->throttle();
107
+            return $response;
108
+        }
109 109
 
110
-		try {
111
-			if ($newpassword === null || $user->setPassword($newpassword) === false) {
112
-				return new JSONResponse([
113
-					'status' => 'error'
114
-				]);
115
-			}
116
-		// password policy app throws exception
117
-		} catch(HintException $e) {
118
-			return new JSONResponse([
119
-				'status' => 'error',
120
-				'data' => [
121
-					'message' => $e->getHint(),
122
-				],
123
-			]);
124
-		}
110
+        try {
111
+            if ($newpassword === null || $user->setPassword($newpassword) === false) {
112
+                return new JSONResponse([
113
+                    'status' => 'error'
114
+                ]);
115
+            }
116
+        // password policy app throws exception
117
+        } catch(HintException $e) {
118
+            return new JSONResponse([
119
+                'status' => 'error',
120
+                'data' => [
121
+                    'message' => $e->getHint(),
122
+                ],
123
+            ]);
124
+        }
125 125
 
126
-		$this->userSession->updateSessionTokenPassword($newpassword);
126
+        $this->userSession->updateSessionTokenPassword($newpassword);
127 127
 
128
-		return new JSONResponse([
129
-			'status' => 'success',
130
-			'data' => [
131
-				'message' => $this->l->t('Saved'),
132
-			],
133
-		]);
134
-	}
128
+        return new JSONResponse([
129
+            'status' => 'success',
130
+            'data' => [
131
+                'message' => $this->l->t('Saved'),
132
+            ],
133
+        ]);
134
+    }
135 135
 
136
-	/**
137
-	 * @NoAdminRequired
138
-	 * @PasswordConfirmationRequired
139
-	 *
140
-	 * @param string $username
141
-	 * @param string $password
142
-	 * @param string $recoveryPassword
143
-	 *
144
-	 * @return JSONResponse
145
-	 */
146
-	public function changeUserPassword($username = null, $password = null, $recoveryPassword = null) {
147
-		if ($username === null) {
148
-			return new JSONResponse([
149
-				'status' => 'error',
150
-				'data' => [
151
-					'message' => $this->l->t('No user supplied'),
152
-				],
153
-			]);
154
-		}
136
+    /**
137
+     * @NoAdminRequired
138
+     * @PasswordConfirmationRequired
139
+     *
140
+     * @param string $username
141
+     * @param string $password
142
+     * @param string $recoveryPassword
143
+     *
144
+     * @return JSONResponse
145
+     */
146
+    public function changeUserPassword($username = null, $password = null, $recoveryPassword = null) {
147
+        if ($username === null) {
148
+            return new JSONResponse([
149
+                'status' => 'error',
150
+                'data' => [
151
+                    'message' => $this->l->t('No user supplied'),
152
+                ],
153
+            ]);
154
+        }
155 155
 
156
-		if ($password === null) {
157
-			return new JSONResponse([
158
-				'status' => 'error',
159
-				'data' => [
160
-					'message' => $this->l->t('Unable to change password'),
161
-				],
162
-			]);
163
-		}
156
+        if ($password === null) {
157
+            return new JSONResponse([
158
+                'status' => 'error',
159
+                'data' => [
160
+                    'message' => $this->l->t('Unable to change password'),
161
+                ],
162
+            ]);
163
+        }
164 164
 
165
-		$currentUser = $this->userSession->getUser();
166
-		$targetUser = $this->userManager->get($username);
167
-		if ($currentUser === null || $targetUser === null ||
168
-			!($this->groupManager->isAdmin($this->userId) ||
169
-			 $this->groupManager->getSubAdmin()->isUserAccessible($currentUser, $targetUser))
170
-		) {
171
-			return new JSONResponse([
172
-				'status' => 'error',
173
-				'data' => [
174
-					'message' => $this->l->t('Authentication error'),
175
-				],
176
-			]);
177
-		}
165
+        $currentUser = $this->userSession->getUser();
166
+        $targetUser = $this->userManager->get($username);
167
+        if ($currentUser === null || $targetUser === null ||
168
+            !($this->groupManager->isAdmin($this->userId) ||
169
+             $this->groupManager->getSubAdmin()->isUserAccessible($currentUser, $targetUser))
170
+        ) {
171
+            return new JSONResponse([
172
+                'status' => 'error',
173
+                'data' => [
174
+                    'message' => $this->l->t('Authentication error'),
175
+                ],
176
+            ]);
177
+        }
178 178
 
179
-		if ($this->appManager->isEnabledForUser('encryption')) {
180
-			//handle the recovery case
181
-			$crypt = new \OCA\Encryption\Crypto\Crypt(
182
-				\OC::$server->getLogger(),
183
-				\OC::$server->getUserSession(),
184
-				\OC::$server->getConfig(),
185
-				\OC::$server->getL10N('encryption'));
186
-			$keyStorage = \OC::$server->getEncryptionKeyStorage();
187
-			$util = new \OCA\Encryption\Util(
188
-				new \OC\Files\View(),
189
-				$crypt,
190
-				\OC::$server->getLogger(),
191
-				\OC::$server->getUserSession(),
192
-				\OC::$server->getConfig(),
193
-				\OC::$server->getUserManager());
194
-			$keyManager = new \OCA\Encryption\KeyManager(
195
-				$keyStorage,
196
-				$crypt,
197
-				\OC::$server->getConfig(),
198
-				\OC::$server->getUserSession(),
199
-				new \OCA\Encryption\Session(\OC::$server->getSession()),
200
-				\OC::$server->getLogger(),
201
-				$util);
202
-			$recovery = new \OCA\Encryption\Recovery(
203
-				\OC::$server->getUserSession(),
204
-				$crypt,
205
-				\OC::$server->getSecureRandom(),
206
-				$keyManager,
207
-				\OC::$server->getConfig(),
208
-				$keyStorage,
209
-				\OC::$server->getEncryptionFilesHelper(),
210
-				new \OC\Files\View());
211
-			$recoveryAdminEnabled = $recovery->isRecoveryKeyEnabled();
179
+        if ($this->appManager->isEnabledForUser('encryption')) {
180
+            //handle the recovery case
181
+            $crypt = new \OCA\Encryption\Crypto\Crypt(
182
+                \OC::$server->getLogger(),
183
+                \OC::$server->getUserSession(),
184
+                \OC::$server->getConfig(),
185
+                \OC::$server->getL10N('encryption'));
186
+            $keyStorage = \OC::$server->getEncryptionKeyStorage();
187
+            $util = new \OCA\Encryption\Util(
188
+                new \OC\Files\View(),
189
+                $crypt,
190
+                \OC::$server->getLogger(),
191
+                \OC::$server->getUserSession(),
192
+                \OC::$server->getConfig(),
193
+                \OC::$server->getUserManager());
194
+            $keyManager = new \OCA\Encryption\KeyManager(
195
+                $keyStorage,
196
+                $crypt,
197
+                \OC::$server->getConfig(),
198
+                \OC::$server->getUserSession(),
199
+                new \OCA\Encryption\Session(\OC::$server->getSession()),
200
+                \OC::$server->getLogger(),
201
+                $util);
202
+            $recovery = new \OCA\Encryption\Recovery(
203
+                \OC::$server->getUserSession(),
204
+                $crypt,
205
+                \OC::$server->getSecureRandom(),
206
+                $keyManager,
207
+                \OC::$server->getConfig(),
208
+                $keyStorage,
209
+                \OC::$server->getEncryptionFilesHelper(),
210
+                new \OC\Files\View());
211
+            $recoveryAdminEnabled = $recovery->isRecoveryKeyEnabled();
212 212
 
213
-			$validRecoveryPassword = false;
214
-			$recoveryEnabledForUser = false;
215
-			if ($recoveryAdminEnabled) {
216
-				$validRecoveryPassword = $keyManager->checkRecoveryPassword($recoveryPassword);
217
-				$recoveryEnabledForUser = $recovery->isRecoveryEnabledForUser($username);
218
-			}
213
+            $validRecoveryPassword = false;
214
+            $recoveryEnabledForUser = false;
215
+            if ($recoveryAdminEnabled) {
216
+                $validRecoveryPassword = $keyManager->checkRecoveryPassword($recoveryPassword);
217
+                $recoveryEnabledForUser = $recovery->isRecoveryEnabledForUser($username);
218
+            }
219 219
 
220
-			if ($recoveryEnabledForUser && $recoveryPassword === '') {
221
-				return new JSONResponse([
222
-					'status' => 'error',
223
-					'data' => [
224
-						'message' => $this->l->t('Please provide an admin recovery password; otherwise, all user data will be lost.'),
225
-					]
226
-				]);
227
-			} elseif ($recoveryEnabledForUser && ! $validRecoveryPassword) {
228
-				return new JSONResponse([
229
-					'status' => 'error',
230
-					'data' => [
231
-						'message' => $this->l->t('Wrong admin recovery password. Please check the password and try again.'),
232
-					]
233
-				]);
234
-			} else { // now we know that everything is fine regarding the recovery password, let's try to change the password
235
-				try {
236
-					$result = $targetUser->setPassword($password, $recoveryPassword);
237
-				// password policy app throws exception
238
-				} catch(HintException $e) {
239
-					return new JSONResponse([
240
-						'status' => 'error',
241
-						'data' => [
242
-							'message' => $e->getHint(),
243
-						],
244
-					]);
245
-				}
246
-				if (!$result && $recoveryEnabledForUser) {
247
-					return new JSONResponse([
248
-						'status' => 'error',
249
-						'data' => [
250
-							'message' => $this->l->t('Backend doesn\'t support password change, but the user\'s encryption key was updated.'),
251
-						]
252
-					]);
253
-				} elseif (!$result && !$recoveryEnabledForUser) {
254
-					return new JSONResponse([
255
-						'status' => 'error',
256
-						'data' => [
257
-							'message' => $this->l->t('Unable to change password'),
258
-						]
259
-					]);
260
-				}
261
-			}
262
-		} else {
263
-			try {
264
-				if ($targetUser->setPassword($password) === false) {
265
-					return new JSONResponse([
266
-						'status' => 'error',
267
-						'data' => [
268
-							'message' => $this->l->t('Unable to change password'),
269
-						],
270
-					]);
271
-				}
272
-			// password policy app throws exception
273
-			} catch(HintException $e) {
274
-				return new JSONResponse([
275
-					'status' => 'error',
276
-					'data' => [
277
-						'message' => $e->getHint(),
278
-					],
279
-				]);
280
-			}
281
-		}
220
+            if ($recoveryEnabledForUser && $recoveryPassword === '') {
221
+                return new JSONResponse([
222
+                    'status' => 'error',
223
+                    'data' => [
224
+                        'message' => $this->l->t('Please provide an admin recovery password; otherwise, all user data will be lost.'),
225
+                    ]
226
+                ]);
227
+            } elseif ($recoveryEnabledForUser && ! $validRecoveryPassword) {
228
+                return new JSONResponse([
229
+                    'status' => 'error',
230
+                    'data' => [
231
+                        'message' => $this->l->t('Wrong admin recovery password. Please check the password and try again.'),
232
+                    ]
233
+                ]);
234
+            } else { // now we know that everything is fine regarding the recovery password, let's try to change the password
235
+                try {
236
+                    $result = $targetUser->setPassword($password, $recoveryPassword);
237
+                // password policy app throws exception
238
+                } catch(HintException $e) {
239
+                    return new JSONResponse([
240
+                        'status' => 'error',
241
+                        'data' => [
242
+                            'message' => $e->getHint(),
243
+                        ],
244
+                    ]);
245
+                }
246
+                if (!$result && $recoveryEnabledForUser) {
247
+                    return new JSONResponse([
248
+                        'status' => 'error',
249
+                        'data' => [
250
+                            'message' => $this->l->t('Backend doesn\'t support password change, but the user\'s encryption key was updated.'),
251
+                        ]
252
+                    ]);
253
+                } elseif (!$result && !$recoveryEnabledForUser) {
254
+                    return new JSONResponse([
255
+                        'status' => 'error',
256
+                        'data' => [
257
+                            'message' => $this->l->t('Unable to change password'),
258
+                        ]
259
+                    ]);
260
+                }
261
+            }
262
+        } else {
263
+            try {
264
+                if ($targetUser->setPassword($password) === false) {
265
+                    return new JSONResponse([
266
+                        'status' => 'error',
267
+                        'data' => [
268
+                            'message' => $this->l->t('Unable to change password'),
269
+                        ],
270
+                    ]);
271
+                }
272
+            // password policy app throws exception
273
+            } catch(HintException $e) {
274
+                return new JSONResponse([
275
+                    'status' => 'error',
276
+                    'data' => [
277
+                        'message' => $e->getHint(),
278
+                    ],
279
+                ]);
280
+            }
281
+        }
282 282
 
283
-		return new JSONResponse([
284
-			'status' => 'success',
285
-			'data' => [
286
-				'username' => $username,
287
-			],
288
-		]);
289
-	}
283
+        return new JSONResponse([
284
+            'status' => 'success',
285
+            'data' => [
286
+                'username' => $username,
287
+            ],
288
+        ]);
289
+    }
290 290
 }
Please login to merge, or discard this patch.
settings/Controller/UsersController.php 1 patch
Indentation   +971 added lines, -971 removed lines patch added patch discarded remove patch
@@ -67,976 +67,976 @@
 block discarded – undo
67 67
  * @package OC\Settings\Controller
68 68
  */
69 69
 class UsersController extends Controller {
70
-	/** @var IL10N */
71
-	private $l10n;
72
-	/** @var IUserSession */
73
-	private $userSession;
74
-	/** @var bool */
75
-	private $isAdmin;
76
-	/** @var IUserManager */
77
-	private $userManager;
78
-	/** @var \OC\Group\Manager */
79
-	private $groupManager;
80
-	/** @var IConfig */
81
-	private $config;
82
-	/** @var ILogger */
83
-	private $log;
84
-	/** @var IMailer */
85
-	private $mailer;
86
-	/** @var bool contains the state of the encryption app */
87
-	private $isEncryptionAppEnabled;
88
-	/** @var bool contains the state of the admin recovery setting */
89
-	private $isRestoreEnabled = false;
90
-	/** @var IAppManager */
91
-	private $appManager;
92
-	/** @var IAvatarManager */
93
-	private $avatarManager;
94
-	/** @var AccountManager */
95
-	private $accountManager;
96
-	/** @var ISecureRandom */
97
-	private $secureRandom;
98
-	/** @var NewUserMailHelper */
99
-	private $newUserMailHelper;
100
-	/** @var Manager */
101
-	private $keyManager;
102
-	/** @var IJobList */
103
-	private $jobList;
104
-
105
-	/** @var IUserMountCache */
106
-	private $userMountCache;
107
-
108
-	/** @var IManager */
109
-	private $encryptionManager;
110
-
111
-
112
-	/**
113
-	 * @param string $appName
114
-	 * @param IRequest $request
115
-	 * @param IUserManager $userManager
116
-	 * @param \OC\Group\Manager $groupManager
117
-	 * @param IUserSession $userSession
118
-	 * @param IConfig $config
119
-	 * @param bool $isAdmin
120
-	 * @param IL10N $l10n
121
-	 * @param ILogger $log
122
-	 * @param IMailer $mailer
123
-	 * @param IURLGenerator $urlGenerator
124
-	 * @param IAppManager $appManager
125
-	 * @param IAvatarManager $avatarManager
126
-	 * @param AccountManager $accountManager
127
-	 * @param ISecureRandom $secureRandom
128
-	 * @param NewUserMailHelper $newUserMailHelper
129
-	 * @param Manager $keyManager
130
-	 * @param IJobList $jobList
131
-	 * @param IUserMountCache $userMountCache
132
-	 * @param IManager $encryptionManager
133
-	 */
134
-	public function __construct($appName,
135
-								IRequest $request,
136
-								IUserManager $userManager,
137
-								\OC\Group\Manager $groupManager,
138
-								IUserSession $userSession,
139
-								IConfig $config,
140
-								$isAdmin,
141
-								IL10N $l10n,
142
-								ILogger $log,
143
-								IMailer $mailer,
144
-								IURLGenerator $urlGenerator,
145
-								IAppManager $appManager,
146
-								IAvatarManager $avatarManager,
147
-								AccountManager $accountManager,
148
-								ISecureRandom $secureRandom,
149
-								NewUserMailHelper $newUserMailHelper,
150
-								Manager $keyManager,
151
-								IJobList $jobList,
152
-								IUserMountCache $userMountCache,
153
-								IManager $encryptionManager) {
154
-		parent::__construct($appName, $request);
155
-		$this->userManager = $userManager;
156
-		$this->groupManager = $groupManager;
157
-		$this->userSession = $userSession;
158
-		$this->config = $config;
159
-		$this->isAdmin = $isAdmin;
160
-		$this->l10n = $l10n;
161
-		$this->log = $log;
162
-		$this->mailer = $mailer;
163
-		$this->appManager = $appManager;
164
-		$this->avatarManager = $avatarManager;
165
-		$this->accountManager = $accountManager;
166
-		$this->secureRandom = $secureRandom;
167
-		$this->newUserMailHelper = $newUserMailHelper;
168
-		$this->keyManager = $keyManager;
169
-		$this->jobList = $jobList;
170
-		$this->userMountCache = $userMountCache;
171
-		$this->encryptionManager = $encryptionManager;
172
-
173
-		// check for encryption state - TODO see formatUserForIndex
174
-		$this->isEncryptionAppEnabled = $appManager->isEnabledForUser('encryption');
175
-		if ($this->isEncryptionAppEnabled) {
176
-			// putting this directly in empty is possible in PHP 5.5+
177
-			$result = $config->getAppValue('encryption', 'recoveryAdminEnabled', '0');
178
-			$this->isRestoreEnabled = !empty($result);
179
-		}
180
-	}
181
-
182
-	/**
183
-	 * @param IUser $user
184
-	 * @param array|null $userGroups
185
-	 * @return array
186
-	 */
187
-	private function formatUserForIndex(IUser $user, array $userGroups = null) {
188
-
189
-		// TODO: eliminate this encryption specific code below and somehow
190
-		// hook in additional user info from other apps
191
-
192
-		// recovery isn't possible if admin or user has it disabled and encryption
193
-		// is enabled - so we eliminate the else paths in the conditional tree
194
-		// below
195
-		$restorePossible = false;
196
-
197
-		if ($this->isEncryptionAppEnabled) {
198
-			if ($this->isRestoreEnabled) {
199
-				// check for the users recovery setting
200
-				$recoveryMode = $this->config->getUserValue($user->getUID(), 'encryption', 'recoveryEnabled', '0');
201
-				// method call inside empty is possible with PHP 5.5+
202
-				$recoveryModeEnabled = !empty($recoveryMode);
203
-				if ($recoveryModeEnabled) {
204
-					// user also has recovery mode enabled
205
-					$restorePossible = true;
206
-				}
207
-			} else {
208
-				$modules = $this->encryptionManager->getEncryptionModules();
209
-				$restorePossible = true;
210
-				foreach ($modules as $id => $module) {
211
-					/* @var IEncryptionModule $instance */
212
-					$instance = call_user_func($module['callback']);
213
-					if ($instance->needDetailedAccessList()) {
214
-						$restorePossible = false;
215
-						break;
216
-					}
217
-				}
218
-			}
219
-		} else {
220
-			// recovery is possible if encryption is disabled (plain files are
221
-			// available)
222
-			$restorePossible = true;
223
-		}
224
-
225
-		$subAdminGroups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($user);
226
-		foreach ($subAdminGroups as $key => $subAdminGroup) {
227
-			$subAdminGroups[$key] = $subAdminGroup->getGID();
228
-		}
229
-
230
-		$displayName = $user->getEMailAddress();
231
-		if (is_null($displayName)) {
232
-			$displayName = '';
233
-		}
234
-
235
-		$avatarAvailable = false;
236
-		try {
237
-			$avatarAvailable = $this->avatarManager->getAvatar($user->getUID())->exists();
238
-		} catch (\Exception $e) {
239
-			//No avatar yet
240
-		}
241
-
242
-		return [
243
-			'name' => $user->getUID(),
244
-			'displayname' => $user->getDisplayName(),
245
-			'groups' => empty($userGroups) ? $this->groupManager->getUserGroupIds($user) : $userGroups,
246
-			'subadmin' => $subAdminGroups,
247
-			'quota' => $user->getQuota(),
248
-			'quota_bytes' => Util::computerFileSize($user->getQuota()),
249
-			'storageLocation' => $user->getHome(),
250
-			'lastLogin' => $user->getLastLogin() * 1000,
251
-			'backend' => $user->getBackendClassName(),
252
-			'email' => $displayName,
253
-			'isRestoreDisabled' => !$restorePossible,
254
-			'isAvatarAvailable' => $avatarAvailable,
255
-			'isEnabled' => $user->isEnabled(),
256
-		];
257
-	}
258
-
259
-	/**
260
-	 * @param array $userIDs Array with schema [$uid => $displayName]
261
-	 * @return IUser[]
262
-	 */
263
-	private function getUsersForUID(array $userIDs) {
264
-		$users = [];
265
-		foreach ($userIDs as $uid => $displayName) {
266
-			$users[$uid] = $this->userManager->get($uid);
267
-		}
268
-		return $users;
269
-	}
270
-
271
-	/**
272
-	 * @NoAdminRequired
273
-	 *
274
-	 * @param int $offset
275
-	 * @param int $limit
276
-	 * @param string $gid GID to filter for
277
-	 * @param string $pattern Pattern to search for in the username
278
-	 * @param string $backend Backend to filter for (class-name)
279
-	 * @return DataResponse
280
-	 *
281
-	 * TODO: Tidy up and write unit tests - code is mainly static method calls
282
-	 */
283
-	public function index($offset = 0, $limit = 10, $gid = '', $pattern = '', $backend = '') {
284
-		// Remove backends
285
-		if (!empty($backend)) {
286
-			$activeBackends = $this->userManager->getBackends();
287
-			$this->userManager->clearBackends();
288
-			foreach ($activeBackends as $singleActiveBackend) {
289
-				if ($backend === get_class($singleActiveBackend)) {
290
-					$this->userManager->registerBackend($singleActiveBackend);
291
-					break;
292
-				}
293
-			}
294
-		}
295
-
296
-		$userObjects = [];
297
-		$users = [];
298
-		if ($this->isAdmin) {
299
-			if ($gid !== '' && $gid !== '_disabledUsers' && $gid !== '_everyone') {
300
-				$batch = $this->getUsersForUID($this->groupManager->displayNamesInGroup($gid, $pattern, $limit, $offset));
301
-			} else {
302
-				$batch = $this->userManager->search($pattern, $limit, $offset);
303
-			}
304
-
305
-			foreach ($batch as $user) {
306
-				if (($gid !== '_disabledUsers' && $user->isEnabled()) ||
307
-					($gid === '_disabledUsers' && !$user->isEnabled())
308
-				) {
309
-					$userObjects[] = $user;
310
-					$users[] = $this->formatUserForIndex($user);
311
-				}
312
-			}
313
-
314
-		} else {
315
-			$subAdminOfGroups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($this->userSession->getUser());
316
-			// New class returns IGroup[] so convert back
317
-			$gids = [];
318
-			foreach ($subAdminOfGroups as $group) {
319
-				$gids[] = $group->getGID();
320
-			}
321
-			$subAdminOfGroups = $gids;
322
-
323
-			// Set the $gid parameter to an empty value if the subadmin has no rights to access a specific group
324
-			if ($gid !== '' && $gid !== '_disabledUsers' && !in_array($gid, $subAdminOfGroups)) {
325
-				$gid = '';
326
-			}
327
-
328
-			// Batch all groups the user is subadmin of when a group is specified
329
-			$batch = [];
330
-			if ($gid !== '' && $gid !== '_disabledUsers' && $gid !== '_everyone') {
331
-				$batch = $this->groupManager->displayNamesInGroup($gid, $pattern, $limit, $offset);
332
-			} else {
333
-				foreach ($subAdminOfGroups as $group) {
334
-					$groupUsers = $this->groupManager->displayNamesInGroup($group, $pattern, $limit, $offset);
335
-
336
-					foreach ($groupUsers as $uid => $displayName) {
337
-						$batch[$uid] = $displayName;
338
-					}
339
-				}
340
-			}
341
-			$batch = $this->getUsersForUID($batch);
342
-
343
-			foreach ($batch as $user) {
344
-				// Only add the groups, this user is a subadmin of
345
-				$userGroups = array_values(array_intersect(
346
-					$this->groupManager->getUserGroupIds($user),
347
-					$subAdminOfGroups
348
-				));
349
-				if (($gid !== '_disabledUsers' && $user->isEnabled()) ||
350
-					($gid === '_disabledUsers' && !$user->isEnabled())
351
-				) {
352
-					$userObjects[] = $user;
353
-					$users[] = $this->formatUserForIndex($user, $userGroups);
354
-				}
355
-			}
356
-		}
357
-
358
-		$usedSpace = $this->userMountCache->getUsedSpaceForUsers($userObjects);
359
-
360
-		foreach ($users as &$userData) {
361
-			$userData['size'] = isset($usedSpace[$userData['name']]) ? $usedSpace[$userData['name']] : 0;
362
-		}
363
-
364
-		return new DataResponse($users);
365
-	}
366
-
367
-	/**
368
-	 * @NoAdminRequired
369
-	 * @PasswordConfirmationRequired
370
-	 *
371
-	 * @param string $username
372
-	 * @param string $password
373
-	 * @param array $groups
374
-	 * @param string $email
375
-	 * @return DataResponse
376
-	 */
377
-	public function create($username, $password, array $groups = [], $email = '') {
378
-		if ($email !== '' && !$this->mailer->validateMailAddress($email)) {
379
-			return new DataResponse(
380
-				[
381
-					'message' => (string)$this->l10n->t('Invalid mail address')
382
-				],
383
-				Http::STATUS_UNPROCESSABLE_ENTITY
384
-			);
385
-		}
386
-
387
-		$currentUser = $this->userSession->getUser();
388
-
389
-		if (!$this->isAdmin) {
390
-			if (!empty($groups)) {
391
-				foreach ($groups as $key => $group) {
392
-					$groupObject = $this->groupManager->get($group);
393
-					if ($groupObject === null) {
394
-						unset($groups[$key]);
395
-						continue;
396
-					}
397
-
398
-					if (!$this->groupManager->getSubAdmin()->isSubAdminofGroup($currentUser, $groupObject)) {
399
-						unset($groups[$key]);
400
-					}
401
-				}
402
-			}
403
-
404
-			if (empty($groups)) {
405
-				return new DataResponse(
406
-					[
407
-						'message' => $this->l10n->t('No valid group selected'),
408
-					],
409
-					Http::STATUS_FORBIDDEN
410
-				);
411
-			}
412
-		}
413
-
414
-		if ($this->userManager->userExists($username)) {
415
-			return new DataResponse(
416
-				[
417
-					'message' => (string)$this->l10n->t('A user with that name already exists.')
418
-				],
419
-				Http::STATUS_CONFLICT
420
-			);
421
-		}
422
-
423
-		$generatePasswordResetToken = false;
424
-		if ($password === '') {
425
-			if ($email === '') {
426
-				return new DataResponse(
427
-					[
428
-						'message' => (string)$this->l10n->t('To send a password link to the user an email address is required.')
429
-					],
430
-					Http::STATUS_UNPROCESSABLE_ENTITY
431
-				);
432
-			}
433
-
434
-			$password = $this->secureRandom->generate(30);
435
-			// Make sure we pass the password_policy
436
-			$password .= $this->secureRandom->generate(2, '$!.,;:-~+*[]{}()');
437
-			$generatePasswordResetToken = true;
438
-		}
439
-
440
-		try {
441
-			$user = $this->userManager->createUser($username, $password);
442
-		} catch (\Exception $exception) {
443
-			$message = $exception->getMessage();
444
-			if ($exception instanceof HintException && $exception->getHint()) {
445
-				$message = $exception->getHint();
446
-			}
447
-			if (!$message) {
448
-				$message = $this->l10n->t('Unable to create user.');
449
-			}
450
-			return new DataResponse(
451
-				[
452
-					'message' => (string)$message,
453
-				],
454
-				Http::STATUS_FORBIDDEN
455
-			);
456
-		}
457
-
458
-		if ($user instanceof IUser) {
459
-			if ($groups !== null) {
460
-				foreach ($groups as $groupName) {
461
-					$group = $this->groupManager->get($groupName);
462
-
463
-					if (empty($group)) {
464
-						$group = $this->groupManager->createGroup($groupName);
465
-					}
466
-					$group->addUser($user);
467
-				}
468
-			}
469
-			/**
470
-			 * Send new user mail only if a mail is set
471
-			 */
472
-			if ($email !== '') {
473
-				$user->setEMailAddress($email);
474
-				try {
475
-					$emailTemplate = $this->newUserMailHelper->generateTemplate($user, $generatePasswordResetToken);
476
-					$this->newUserMailHelper->sendMail($user, $emailTemplate);
477
-				} catch (\Exception $e) {
478
-					$this->log->logException($e, [
479
-						'message' => "Can't send new user mail to $email",
480
-						'level' => \OCP\Util::ERROR,
481
-						'app' => 'settings',
482
-					]);
483
-				}
484
-			}
485
-			// fetch users groups
486
-			$userGroups = $this->groupManager->getUserGroupIds($user);
487
-
488
-			return new DataResponse(
489
-				$this->formatUserForIndex($user, $userGroups),
490
-				Http::STATUS_CREATED
491
-			);
492
-		}
493
-
494
-		return new DataResponse(
495
-			[
496
-				'message' => (string)$this->l10n->t('Unable to create user.')
497
-			],
498
-			Http::STATUS_FORBIDDEN
499
-		);
500
-
501
-	}
502
-
503
-	/**
504
-	 * @NoAdminRequired
505
-	 * @PasswordConfirmationRequired
506
-	 *
507
-	 * @param string $id
508
-	 * @return DataResponse
509
-	 */
510
-	public function destroy($id) {
511
-		$userId = $this->userSession->getUser()->getUID();
512
-		$user = $this->userManager->get($id);
513
-
514
-		if ($userId === $id) {
515
-			return new DataResponse(
516
-				[
517
-					'status' => 'error',
518
-					'data' => [
519
-						'message' => (string)$this->l10n->t('Unable to delete user.')
520
-					]
521
-				],
522
-				Http::STATUS_FORBIDDEN
523
-			);
524
-		}
525
-
526
-		if (!$this->isAdmin && !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)) {
527
-			return new DataResponse(
528
-				[
529
-					'status' => 'error',
530
-					'data' => [
531
-						'message' => (string)$this->l10n->t('Authentication error')
532
-					]
533
-				],
534
-				Http::STATUS_FORBIDDEN
535
-			);
536
-		}
537
-
538
-		if ($user) {
539
-			if ($user->delete()) {
540
-				return new DataResponse(
541
-					[
542
-						'status' => 'success',
543
-						'data' => [
544
-							'username' => $id
545
-						]
546
-					],
547
-					Http::STATUS_NO_CONTENT
548
-				);
549
-			}
550
-		}
551
-
552
-		return new DataResponse(
553
-			[
554
-				'status' => 'error',
555
-				'data' => [
556
-					'message' => (string)$this->l10n->t('Unable to delete user.')
557
-				]
558
-			],
559
-			Http::STATUS_FORBIDDEN
560
-		);
561
-	}
562
-
563
-	/**
564
-	 * @NoAdminRequired
565
-	 *
566
-	 * @param string $id
567
-	 * @param int $enabled
568
-	 * @return DataResponse
569
-	 */
570
-	public function setEnabled($id, $enabled) {
571
-		$enabled = (bool)$enabled;
572
-		if ($enabled) {
573
-			$errorMsgGeneral = (string)$this->l10n->t('Error while enabling user.');
574
-		} else {
575
-			$errorMsgGeneral = (string)$this->l10n->t('Error while disabling user.');
576
-		}
577
-
578
-		$userId = $this->userSession->getUser()->getUID();
579
-		$user = $this->userManager->get($id);
580
-
581
-		if ($userId === $id) {
582
-			return new DataResponse(
583
-				[
584
-					'status' => 'error',
585
-					'data' => [
586
-						'message' => $errorMsgGeneral
587
-					]
588
-				], Http::STATUS_FORBIDDEN
589
-			);
590
-		}
591
-
592
-		if ($user) {
593
-			if (!$this->isAdmin && !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)) {
594
-				return new DataResponse(
595
-					[
596
-						'status' => 'error',
597
-						'data' => [
598
-							'message' => (string)$this->l10n->t('Authentication error')
599
-						]
600
-					],
601
-					Http::STATUS_FORBIDDEN
602
-				);
603
-			}
604
-
605
-			$user->setEnabled($enabled);
606
-			return new DataResponse(
607
-				[
608
-					'status' => 'success',
609
-					'data' => [
610
-						'username' => $id,
611
-						'enabled' => $enabled
612
-					]
613
-				]
614
-			);
615
-		} else {
616
-			return new DataResponse(
617
-				[
618
-					'status' => 'error',
619
-					'data' => [
620
-						'message' => $errorMsgGeneral
621
-					]
622
-				],
623
-				Http::STATUS_FORBIDDEN
624
-			);
625
-		}
626
-
627
-	}
628
-
629
-	/**
630
-	 * Set the mail address of a user
631
-	 *
632
-	 * @NoAdminRequired
633
-	 * @NoSubadminRequired
634
-	 * @PasswordConfirmationRequired
635
-	 *
636
-	 * @param string $account
637
-	 * @param bool $onlyVerificationCode only return verification code without updating the data
638
-	 * @return DataResponse
639
-	 */
640
-	public function getVerificationCode($account, $onlyVerificationCode) {
641
-
642
-		$user = $this->userSession->getUser();
643
-
644
-		if ($user === null) {
645
-			return new DataResponse([], Http::STATUS_BAD_REQUEST);
646
-		}
647
-
648
-		$accountData = $this->accountManager->getUser($user);
649
-		$cloudId = $user->getCloudId();
650
-		$message = "Use my Federated Cloud ID to share with me: " . $cloudId;
651
-		$signature = $this->signMessage($user, $message);
652
-
653
-		$code = $message . ' ' . $signature;
654
-		$codeMd5 = $message . ' ' . md5($signature);
655
-
656
-		switch ($account) {
657
-			case 'verify-twitter':
658
-				$accountData[AccountManager::PROPERTY_TWITTER]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
659
-				$msg = $this->l10n->t('In order to verify your Twitter account, post the following tweet on Twitter (please make sure to post it without any line breaks):');
660
-				$code = $codeMd5;
661
-				$type = AccountManager::PROPERTY_TWITTER;
662
-				$data = $accountData[AccountManager::PROPERTY_TWITTER]['value'];
663
-				$accountData[AccountManager::PROPERTY_TWITTER]['signature'] = $signature;
664
-				break;
665
-			case 'verify-website':
666
-				$accountData[AccountManager::PROPERTY_WEBSITE]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
667
-				$msg = $this->l10n->t('In order to verify your Website, store the following content in your web-root at \'.well-known/CloudIdVerificationCode.txt\' (please make sure that the complete text is in one line):');
668
-				$type = AccountManager::PROPERTY_WEBSITE;
669
-				$data = $accountData[AccountManager::PROPERTY_WEBSITE]['value'];
670
-				$accountData[AccountManager::PROPERTY_WEBSITE]['signature'] = $signature;
671
-				break;
672
-			default:
673
-				return new DataResponse([], Http::STATUS_BAD_REQUEST);
674
-		}
675
-
676
-		if ($onlyVerificationCode === false) {
677
-			$this->accountManager->updateUser($user, $accountData);
678
-
679
-			$this->jobList->add(VerifyUserData::class,
680
-				[
681
-					'verificationCode' => $code,
682
-					'data' => $data,
683
-					'type' => $type,
684
-					'uid' => $user->getUID(),
685
-					'try' => 0,
686
-					'lastRun' => $this->getCurrentTime()
687
-				]
688
-			);
689
-		}
690
-
691
-		return new DataResponse(['msg' => $msg, 'code' => $code]);
692
-	}
693
-
694
-	/**
695
-	 * get current timestamp
696
-	 *
697
-	 * @return int
698
-	 */
699
-	protected function getCurrentTime() {
700
-		return time();
701
-	}
702
-
703
-	/**
704
-	 * sign message with users private key
705
-	 *
706
-	 * @param IUser $user
707
-	 * @param string $message
708
-	 *
709
-	 * @return string base64 encoded signature
710
-	 */
711
-	protected function signMessage(IUser $user, $message) {
712
-		$privateKey = $this->keyManager->getKey($user)->getPrivate();
713
-		openssl_sign(json_encode($message), $signature, $privateKey, OPENSSL_ALGO_SHA512);
714
-		return base64_encode($signature);
715
-	}
716
-
717
-	/**
718
-	 * @NoAdminRequired
719
-	 * @NoSubadminRequired
720
-	 * @PasswordConfirmationRequired
721
-	 *
722
-	 * @param string $avatarScope
723
-	 * @param string $displayname
724
-	 * @param string $displaynameScope
725
-	 * @param string $phone
726
-	 * @param string $phoneScope
727
-	 * @param string $email
728
-	 * @param string $emailScope
729
-	 * @param string $website
730
-	 * @param string $websiteScope
731
-	 * @param string $address
732
-	 * @param string $addressScope
733
-	 * @param string $twitter
734
-	 * @param string $twitterScope
735
-	 * @return DataResponse
736
-	 */
737
-	public function setUserSettings($avatarScope,
738
-									$displayname,
739
-									$displaynameScope,
740
-									$phone,
741
-									$phoneScope,
742
-									$email,
743
-									$emailScope,
744
-									$website,
745
-									$websiteScope,
746
-									$address,
747
-									$addressScope,
748
-									$twitter,
749
-									$twitterScope
750
-	) {
751
-
752
-		if (!empty($email) && !$this->mailer->validateMailAddress($email)) {
753
-			return new DataResponse(
754
-				[
755
-					'status' => 'error',
756
-					'data' => [
757
-						'message' => (string)$this->l10n->t('Invalid mail address')
758
-					]
759
-				],
760
-				Http::STATUS_UNPROCESSABLE_ENTITY
761
-			);
762
-		}
763
-
764
-		$user = $this->userSession->getUser();
765
-
766
-		$data = $this->accountManager->getUser($user);
767
-
768
-		$data[AccountManager::PROPERTY_AVATAR] = ['scope' => $avatarScope];
769
-		if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
770
-			$data[AccountManager::PROPERTY_DISPLAYNAME] = ['value' => $displayname, 'scope' => $displaynameScope];
771
-			$data[AccountManager::PROPERTY_EMAIL] = ['value' => $email, 'scope' => $emailScope];
772
-		}
773
-
774
-		if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
775
-			$federatedFileSharing = new \OCA\FederatedFileSharing\AppInfo\Application();
776
-			$shareProvider = $federatedFileSharing->getFederatedShareProvider();
777
-			if ($shareProvider->isLookupServerUploadEnabled()) {
778
-				$data[AccountManager::PROPERTY_WEBSITE] = ['value' => $website, 'scope' => $websiteScope];
779
-				$data[AccountManager::PROPERTY_ADDRESS] = ['value' => $address, 'scope' => $addressScope];
780
-				$data[AccountManager::PROPERTY_PHONE] = ['value' => $phone, 'scope' => $phoneScope];
781
-				$data[AccountManager::PROPERTY_TWITTER] = ['value' => $twitter, 'scope' => $twitterScope];
782
-			}
783
-		}
784
-
785
-		try {
786
-			$this->saveUserSettings($user, $data);
787
-			return new DataResponse(
788
-				[
789
-					'status' => 'success',
790
-					'data' => [
791
-						'userId' => $user->getUID(),
792
-						'avatarScope' => $data[AccountManager::PROPERTY_AVATAR]['scope'],
793
-						'displayname' => $data[AccountManager::PROPERTY_DISPLAYNAME]['value'],
794
-						'displaynameScope' => $data[AccountManager::PROPERTY_DISPLAYNAME]['scope'],
795
-						'email' => $data[AccountManager::PROPERTY_EMAIL]['value'],
796
-						'emailScope' => $data[AccountManager::PROPERTY_EMAIL]['scope'],
797
-						'website' => $data[AccountManager::PROPERTY_WEBSITE]['value'],
798
-						'websiteScope' => $data[AccountManager::PROPERTY_WEBSITE]['scope'],
799
-						'address' => $data[AccountManager::PROPERTY_ADDRESS]['value'],
800
-						'addressScope' => $data[AccountManager::PROPERTY_ADDRESS]['scope'],
801
-						'message' => (string)$this->l10n->t('Settings saved')
802
-					]
803
-				],
804
-				Http::STATUS_OK
805
-			);
806
-		} catch (ForbiddenException $e) {
807
-			return new DataResponse([
808
-				'status' => 'error',
809
-				'data' => [
810
-					'message' => $e->getMessage()
811
-				],
812
-			]);
813
-		}
814
-
815
-	}
816
-
817
-
818
-	/**
819
-	 * update account manager with new user data
820
-	 *
821
-	 * @param IUser $user
822
-	 * @param array $data
823
-	 * @throws ForbiddenException
824
-	 */
825
-	protected function saveUserSettings(IUser $user, $data) {
826
-
827
-		// keep the user back-end up-to-date with the latest display name and email
828
-		// address
829
-		$oldDisplayName = $user->getDisplayName();
830
-		$oldDisplayName = is_null($oldDisplayName) ? '' : $oldDisplayName;
831
-		if (isset($data[AccountManager::PROPERTY_DISPLAYNAME]['value'])
832
-			&& $oldDisplayName !== $data[AccountManager::PROPERTY_DISPLAYNAME]['value']
833
-		) {
834
-			$result = $user->setDisplayName($data[AccountManager::PROPERTY_DISPLAYNAME]['value']);
835
-			if ($result === false) {
836
-				throw new ForbiddenException($this->l10n->t('Unable to change full name'));
837
-			}
838
-		}
839
-
840
-		$oldEmailAddress = $user->getEMailAddress();
841
-		$oldEmailAddress = is_null($oldEmailAddress) ? '' : $oldEmailAddress;
842
-		if (isset($data[AccountManager::PROPERTY_EMAIL]['value'])
843
-			&& $oldEmailAddress !== $data[AccountManager::PROPERTY_EMAIL]['value']
844
-		) {
845
-			// this is the only permission a backend provides and is also used
846
-			// for the permission of setting a email address
847
-			if (!$user->canChangeDisplayName()) {
848
-				throw new ForbiddenException($this->l10n->t('Unable to change email address'));
849
-			}
850
-			$user->setEMailAddress($data[AccountManager::PROPERTY_EMAIL]['value']);
851
-		}
852
-
853
-		$this->accountManager->updateUser($user, $data);
854
-	}
855
-
856
-	/**
857
-	 * Count all unique users visible for the current admin/subadmin.
858
-	 *
859
-	 * @NoAdminRequired
860
-	 *
861
-	 * @return DataResponse
862
-	 */
863
-	public function stats() {
864
-		$userCount = 0;
865
-		if ($this->isAdmin) {
866
-			$countByBackend = $this->userManager->countUsers();
867
-
868
-			if (!empty($countByBackend)) {
869
-				foreach ($countByBackend as $count) {
870
-					$userCount += $count;
871
-				}
872
-			}
873
-		} else {
874
-			$groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($this->userSession->getUser());
875
-
876
-			$uniqueUsers = [];
877
-			foreach ($groups as $group) {
878
-				foreach ($group->getUsers() as $uid => $displayName) {
879
-					$uniqueUsers[$uid] = true;
880
-				}
881
-			}
882
-
883
-			$userCount = count($uniqueUsers);
884
-		}
885
-
886
-		return new DataResponse(
887
-			[
888
-				'totalUsers' => $userCount
889
-			]
890
-		);
891
-	}
892
-
893
-
894
-	/**
895
-	 * Set the displayName of a user
896
-	 *
897
-	 * @NoAdminRequired
898
-	 * @NoSubadminRequired
899
-	 * @PasswordConfirmationRequired
900
-	 * @todo merge into saveUserSettings
901
-	 *
902
-	 * @param string $username
903
-	 * @param string $displayName
904
-	 * @return DataResponse
905
-	 */
906
-	public function setDisplayName($username, $displayName) {
907
-		$currentUser = $this->userSession->getUser();
908
-		$user = $this->userManager->get($username);
909
-
910
-		if ($user === null ||
911
-			!$user->canChangeDisplayName() ||
912
-			(
913
-				!$this->groupManager->isAdmin($currentUser->getUID()) &&
914
-				!$this->groupManager->getSubAdmin()->isUserAccessible($currentUser, $user) &&
915
-				$currentUser->getUID() !== $username
916
-
917
-			)
918
-		) {
919
-			return new DataResponse([
920
-				'status' => 'error',
921
-				'data' => [
922
-					'message' => $this->l10n->t('Authentication error'),
923
-				],
924
-			]);
925
-		}
926
-
927
-		$userData = $this->accountManager->getUser($user);
928
-		$userData[AccountManager::PROPERTY_DISPLAYNAME]['value'] = $displayName;
929
-
930
-
931
-		try {
932
-			$this->saveUserSettings($user, $userData);
933
-			return new DataResponse([
934
-				'status' => 'success',
935
-				'data' => [
936
-					'message' => $this->l10n->t('Your full name has been changed.'),
937
-					'username' => $username,
938
-					'displayName' => $displayName,
939
-				],
940
-			]);
941
-		} catch (ForbiddenException $e) {
942
-			return new DataResponse([
943
-				'status' => 'error',
944
-				'data' => [
945
-					'message' => $e->getMessage(),
946
-					'displayName' => $user->getDisplayName(),
947
-				],
948
-			]);
949
-		}
950
-	}
951
-
952
-	/**
953
-	 * Set the mail address of a user
954
-	 *
955
-	 * @NoAdminRequired
956
-	 * @NoSubadminRequired
957
-	 * @PasswordConfirmationRequired
958
-	 *
959
-	 * @param string $id
960
-	 * @param string $mailAddress
961
-	 * @return DataResponse
962
-	 */
963
-	public function setEMailAddress($id, $mailAddress) {
964
-		$user = $this->userManager->get($id);
965
-		if (!$this->isAdmin
966
-			&& !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)
967
-		) {
968
-			return new DataResponse(
969
-				[
970
-					'status' => 'error',
971
-					'data' => [
972
-						'message' => (string)$this->l10n->t('Forbidden')
973
-					]
974
-				],
975
-				Http::STATUS_FORBIDDEN
976
-			);
977
-		}
978
-
979
-		if ($mailAddress !== '' && !$this->mailer->validateMailAddress($mailAddress)) {
980
-			return new DataResponse(
981
-				[
982
-					'status' => 'error',
983
-					'data' => [
984
-						'message' => (string)$this->l10n->t('Invalid mail address')
985
-					]
986
-				],
987
-				Http::STATUS_UNPROCESSABLE_ENTITY
988
-			);
989
-		}
990
-
991
-		if (!$user) {
992
-			return new DataResponse(
993
-				[
994
-					'status' => 'error',
995
-					'data' => [
996
-						'message' => (string)$this->l10n->t('Invalid user')
997
-					]
998
-				],
999
-				Http::STATUS_UNPROCESSABLE_ENTITY
1000
-			);
1001
-		}
1002
-		// this is the only permission a backend provides and is also used
1003
-		// for the permission of setting a email address
1004
-		if (!$user->canChangeDisplayName()) {
1005
-			return new DataResponse(
1006
-				[
1007
-					'status' => 'error',
1008
-					'data' => [
1009
-						'message' => (string)$this->l10n->t('Unable to change mail address')
1010
-					]
1011
-				],
1012
-				Http::STATUS_FORBIDDEN
1013
-			);
1014
-		}
1015
-
1016
-		$userData = $this->accountManager->getUser($user);
1017
-		$userData[AccountManager::PROPERTY_EMAIL]['value'] = $mailAddress;
1018
-
1019
-		try {
1020
-			$this->saveUserSettings($user, $userData);
1021
-			return new DataResponse(
1022
-				[
1023
-					'status' => 'success',
1024
-					'data' => [
1025
-						'username' => $id,
1026
-						'mailAddress' => $mailAddress,
1027
-						'message' => (string)$this->l10n->t('Email saved')
1028
-					]
1029
-				],
1030
-				Http::STATUS_OK
1031
-			);
1032
-		} catch (ForbiddenException $e) {
1033
-			return new DataResponse([
1034
-				'status' => 'error',
1035
-				'data' => [
1036
-					'message' => $e->getMessage()
1037
-				],
1038
-			]);
1039
-		}
1040
-	}
70
+    /** @var IL10N */
71
+    private $l10n;
72
+    /** @var IUserSession */
73
+    private $userSession;
74
+    /** @var bool */
75
+    private $isAdmin;
76
+    /** @var IUserManager */
77
+    private $userManager;
78
+    /** @var \OC\Group\Manager */
79
+    private $groupManager;
80
+    /** @var IConfig */
81
+    private $config;
82
+    /** @var ILogger */
83
+    private $log;
84
+    /** @var IMailer */
85
+    private $mailer;
86
+    /** @var bool contains the state of the encryption app */
87
+    private $isEncryptionAppEnabled;
88
+    /** @var bool contains the state of the admin recovery setting */
89
+    private $isRestoreEnabled = false;
90
+    /** @var IAppManager */
91
+    private $appManager;
92
+    /** @var IAvatarManager */
93
+    private $avatarManager;
94
+    /** @var AccountManager */
95
+    private $accountManager;
96
+    /** @var ISecureRandom */
97
+    private $secureRandom;
98
+    /** @var NewUserMailHelper */
99
+    private $newUserMailHelper;
100
+    /** @var Manager */
101
+    private $keyManager;
102
+    /** @var IJobList */
103
+    private $jobList;
104
+
105
+    /** @var IUserMountCache */
106
+    private $userMountCache;
107
+
108
+    /** @var IManager */
109
+    private $encryptionManager;
110
+
111
+
112
+    /**
113
+     * @param string $appName
114
+     * @param IRequest $request
115
+     * @param IUserManager $userManager
116
+     * @param \OC\Group\Manager $groupManager
117
+     * @param IUserSession $userSession
118
+     * @param IConfig $config
119
+     * @param bool $isAdmin
120
+     * @param IL10N $l10n
121
+     * @param ILogger $log
122
+     * @param IMailer $mailer
123
+     * @param IURLGenerator $urlGenerator
124
+     * @param IAppManager $appManager
125
+     * @param IAvatarManager $avatarManager
126
+     * @param AccountManager $accountManager
127
+     * @param ISecureRandom $secureRandom
128
+     * @param NewUserMailHelper $newUserMailHelper
129
+     * @param Manager $keyManager
130
+     * @param IJobList $jobList
131
+     * @param IUserMountCache $userMountCache
132
+     * @param IManager $encryptionManager
133
+     */
134
+    public function __construct($appName,
135
+                                IRequest $request,
136
+                                IUserManager $userManager,
137
+                                \OC\Group\Manager $groupManager,
138
+                                IUserSession $userSession,
139
+                                IConfig $config,
140
+                                $isAdmin,
141
+                                IL10N $l10n,
142
+                                ILogger $log,
143
+                                IMailer $mailer,
144
+                                IURLGenerator $urlGenerator,
145
+                                IAppManager $appManager,
146
+                                IAvatarManager $avatarManager,
147
+                                AccountManager $accountManager,
148
+                                ISecureRandom $secureRandom,
149
+                                NewUserMailHelper $newUserMailHelper,
150
+                                Manager $keyManager,
151
+                                IJobList $jobList,
152
+                                IUserMountCache $userMountCache,
153
+                                IManager $encryptionManager) {
154
+        parent::__construct($appName, $request);
155
+        $this->userManager = $userManager;
156
+        $this->groupManager = $groupManager;
157
+        $this->userSession = $userSession;
158
+        $this->config = $config;
159
+        $this->isAdmin = $isAdmin;
160
+        $this->l10n = $l10n;
161
+        $this->log = $log;
162
+        $this->mailer = $mailer;
163
+        $this->appManager = $appManager;
164
+        $this->avatarManager = $avatarManager;
165
+        $this->accountManager = $accountManager;
166
+        $this->secureRandom = $secureRandom;
167
+        $this->newUserMailHelper = $newUserMailHelper;
168
+        $this->keyManager = $keyManager;
169
+        $this->jobList = $jobList;
170
+        $this->userMountCache = $userMountCache;
171
+        $this->encryptionManager = $encryptionManager;
172
+
173
+        // check for encryption state - TODO see formatUserForIndex
174
+        $this->isEncryptionAppEnabled = $appManager->isEnabledForUser('encryption');
175
+        if ($this->isEncryptionAppEnabled) {
176
+            // putting this directly in empty is possible in PHP 5.5+
177
+            $result = $config->getAppValue('encryption', 'recoveryAdminEnabled', '0');
178
+            $this->isRestoreEnabled = !empty($result);
179
+        }
180
+    }
181
+
182
+    /**
183
+     * @param IUser $user
184
+     * @param array|null $userGroups
185
+     * @return array
186
+     */
187
+    private function formatUserForIndex(IUser $user, array $userGroups = null) {
188
+
189
+        // TODO: eliminate this encryption specific code below and somehow
190
+        // hook in additional user info from other apps
191
+
192
+        // recovery isn't possible if admin or user has it disabled and encryption
193
+        // is enabled - so we eliminate the else paths in the conditional tree
194
+        // below
195
+        $restorePossible = false;
196
+
197
+        if ($this->isEncryptionAppEnabled) {
198
+            if ($this->isRestoreEnabled) {
199
+                // check for the users recovery setting
200
+                $recoveryMode = $this->config->getUserValue($user->getUID(), 'encryption', 'recoveryEnabled', '0');
201
+                // method call inside empty is possible with PHP 5.5+
202
+                $recoveryModeEnabled = !empty($recoveryMode);
203
+                if ($recoveryModeEnabled) {
204
+                    // user also has recovery mode enabled
205
+                    $restorePossible = true;
206
+                }
207
+            } else {
208
+                $modules = $this->encryptionManager->getEncryptionModules();
209
+                $restorePossible = true;
210
+                foreach ($modules as $id => $module) {
211
+                    /* @var IEncryptionModule $instance */
212
+                    $instance = call_user_func($module['callback']);
213
+                    if ($instance->needDetailedAccessList()) {
214
+                        $restorePossible = false;
215
+                        break;
216
+                    }
217
+                }
218
+            }
219
+        } else {
220
+            // recovery is possible if encryption is disabled (plain files are
221
+            // available)
222
+            $restorePossible = true;
223
+        }
224
+
225
+        $subAdminGroups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($user);
226
+        foreach ($subAdminGroups as $key => $subAdminGroup) {
227
+            $subAdminGroups[$key] = $subAdminGroup->getGID();
228
+        }
229
+
230
+        $displayName = $user->getEMailAddress();
231
+        if (is_null($displayName)) {
232
+            $displayName = '';
233
+        }
234
+
235
+        $avatarAvailable = false;
236
+        try {
237
+            $avatarAvailable = $this->avatarManager->getAvatar($user->getUID())->exists();
238
+        } catch (\Exception $e) {
239
+            //No avatar yet
240
+        }
241
+
242
+        return [
243
+            'name' => $user->getUID(),
244
+            'displayname' => $user->getDisplayName(),
245
+            'groups' => empty($userGroups) ? $this->groupManager->getUserGroupIds($user) : $userGroups,
246
+            'subadmin' => $subAdminGroups,
247
+            'quota' => $user->getQuota(),
248
+            'quota_bytes' => Util::computerFileSize($user->getQuota()),
249
+            'storageLocation' => $user->getHome(),
250
+            'lastLogin' => $user->getLastLogin() * 1000,
251
+            'backend' => $user->getBackendClassName(),
252
+            'email' => $displayName,
253
+            'isRestoreDisabled' => !$restorePossible,
254
+            'isAvatarAvailable' => $avatarAvailable,
255
+            'isEnabled' => $user->isEnabled(),
256
+        ];
257
+    }
258
+
259
+    /**
260
+     * @param array $userIDs Array with schema [$uid => $displayName]
261
+     * @return IUser[]
262
+     */
263
+    private function getUsersForUID(array $userIDs) {
264
+        $users = [];
265
+        foreach ($userIDs as $uid => $displayName) {
266
+            $users[$uid] = $this->userManager->get($uid);
267
+        }
268
+        return $users;
269
+    }
270
+
271
+    /**
272
+     * @NoAdminRequired
273
+     *
274
+     * @param int $offset
275
+     * @param int $limit
276
+     * @param string $gid GID to filter for
277
+     * @param string $pattern Pattern to search for in the username
278
+     * @param string $backend Backend to filter for (class-name)
279
+     * @return DataResponse
280
+     *
281
+     * TODO: Tidy up and write unit tests - code is mainly static method calls
282
+     */
283
+    public function index($offset = 0, $limit = 10, $gid = '', $pattern = '', $backend = '') {
284
+        // Remove backends
285
+        if (!empty($backend)) {
286
+            $activeBackends = $this->userManager->getBackends();
287
+            $this->userManager->clearBackends();
288
+            foreach ($activeBackends as $singleActiveBackend) {
289
+                if ($backend === get_class($singleActiveBackend)) {
290
+                    $this->userManager->registerBackend($singleActiveBackend);
291
+                    break;
292
+                }
293
+            }
294
+        }
295
+
296
+        $userObjects = [];
297
+        $users = [];
298
+        if ($this->isAdmin) {
299
+            if ($gid !== '' && $gid !== '_disabledUsers' && $gid !== '_everyone') {
300
+                $batch = $this->getUsersForUID($this->groupManager->displayNamesInGroup($gid, $pattern, $limit, $offset));
301
+            } else {
302
+                $batch = $this->userManager->search($pattern, $limit, $offset);
303
+            }
304
+
305
+            foreach ($batch as $user) {
306
+                if (($gid !== '_disabledUsers' && $user->isEnabled()) ||
307
+                    ($gid === '_disabledUsers' && !$user->isEnabled())
308
+                ) {
309
+                    $userObjects[] = $user;
310
+                    $users[] = $this->formatUserForIndex($user);
311
+                }
312
+            }
313
+
314
+        } else {
315
+            $subAdminOfGroups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($this->userSession->getUser());
316
+            // New class returns IGroup[] so convert back
317
+            $gids = [];
318
+            foreach ($subAdminOfGroups as $group) {
319
+                $gids[] = $group->getGID();
320
+            }
321
+            $subAdminOfGroups = $gids;
322
+
323
+            // Set the $gid parameter to an empty value if the subadmin has no rights to access a specific group
324
+            if ($gid !== '' && $gid !== '_disabledUsers' && !in_array($gid, $subAdminOfGroups)) {
325
+                $gid = '';
326
+            }
327
+
328
+            // Batch all groups the user is subadmin of when a group is specified
329
+            $batch = [];
330
+            if ($gid !== '' && $gid !== '_disabledUsers' && $gid !== '_everyone') {
331
+                $batch = $this->groupManager->displayNamesInGroup($gid, $pattern, $limit, $offset);
332
+            } else {
333
+                foreach ($subAdminOfGroups as $group) {
334
+                    $groupUsers = $this->groupManager->displayNamesInGroup($group, $pattern, $limit, $offset);
335
+
336
+                    foreach ($groupUsers as $uid => $displayName) {
337
+                        $batch[$uid] = $displayName;
338
+                    }
339
+                }
340
+            }
341
+            $batch = $this->getUsersForUID($batch);
342
+
343
+            foreach ($batch as $user) {
344
+                // Only add the groups, this user is a subadmin of
345
+                $userGroups = array_values(array_intersect(
346
+                    $this->groupManager->getUserGroupIds($user),
347
+                    $subAdminOfGroups
348
+                ));
349
+                if (($gid !== '_disabledUsers' && $user->isEnabled()) ||
350
+                    ($gid === '_disabledUsers' && !$user->isEnabled())
351
+                ) {
352
+                    $userObjects[] = $user;
353
+                    $users[] = $this->formatUserForIndex($user, $userGroups);
354
+                }
355
+            }
356
+        }
357
+
358
+        $usedSpace = $this->userMountCache->getUsedSpaceForUsers($userObjects);
359
+
360
+        foreach ($users as &$userData) {
361
+            $userData['size'] = isset($usedSpace[$userData['name']]) ? $usedSpace[$userData['name']] : 0;
362
+        }
363
+
364
+        return new DataResponse($users);
365
+    }
366
+
367
+    /**
368
+     * @NoAdminRequired
369
+     * @PasswordConfirmationRequired
370
+     *
371
+     * @param string $username
372
+     * @param string $password
373
+     * @param array $groups
374
+     * @param string $email
375
+     * @return DataResponse
376
+     */
377
+    public function create($username, $password, array $groups = [], $email = '') {
378
+        if ($email !== '' && !$this->mailer->validateMailAddress($email)) {
379
+            return new DataResponse(
380
+                [
381
+                    'message' => (string)$this->l10n->t('Invalid mail address')
382
+                ],
383
+                Http::STATUS_UNPROCESSABLE_ENTITY
384
+            );
385
+        }
386
+
387
+        $currentUser = $this->userSession->getUser();
388
+
389
+        if (!$this->isAdmin) {
390
+            if (!empty($groups)) {
391
+                foreach ($groups as $key => $group) {
392
+                    $groupObject = $this->groupManager->get($group);
393
+                    if ($groupObject === null) {
394
+                        unset($groups[$key]);
395
+                        continue;
396
+                    }
397
+
398
+                    if (!$this->groupManager->getSubAdmin()->isSubAdminofGroup($currentUser, $groupObject)) {
399
+                        unset($groups[$key]);
400
+                    }
401
+                }
402
+            }
403
+
404
+            if (empty($groups)) {
405
+                return new DataResponse(
406
+                    [
407
+                        'message' => $this->l10n->t('No valid group selected'),
408
+                    ],
409
+                    Http::STATUS_FORBIDDEN
410
+                );
411
+            }
412
+        }
413
+
414
+        if ($this->userManager->userExists($username)) {
415
+            return new DataResponse(
416
+                [
417
+                    'message' => (string)$this->l10n->t('A user with that name already exists.')
418
+                ],
419
+                Http::STATUS_CONFLICT
420
+            );
421
+        }
422
+
423
+        $generatePasswordResetToken = false;
424
+        if ($password === '') {
425
+            if ($email === '') {
426
+                return new DataResponse(
427
+                    [
428
+                        'message' => (string)$this->l10n->t('To send a password link to the user an email address is required.')
429
+                    ],
430
+                    Http::STATUS_UNPROCESSABLE_ENTITY
431
+                );
432
+            }
433
+
434
+            $password = $this->secureRandom->generate(30);
435
+            // Make sure we pass the password_policy
436
+            $password .= $this->secureRandom->generate(2, '$!.,;:-~+*[]{}()');
437
+            $generatePasswordResetToken = true;
438
+        }
439
+
440
+        try {
441
+            $user = $this->userManager->createUser($username, $password);
442
+        } catch (\Exception $exception) {
443
+            $message = $exception->getMessage();
444
+            if ($exception instanceof HintException && $exception->getHint()) {
445
+                $message = $exception->getHint();
446
+            }
447
+            if (!$message) {
448
+                $message = $this->l10n->t('Unable to create user.');
449
+            }
450
+            return new DataResponse(
451
+                [
452
+                    'message' => (string)$message,
453
+                ],
454
+                Http::STATUS_FORBIDDEN
455
+            );
456
+        }
457
+
458
+        if ($user instanceof IUser) {
459
+            if ($groups !== null) {
460
+                foreach ($groups as $groupName) {
461
+                    $group = $this->groupManager->get($groupName);
462
+
463
+                    if (empty($group)) {
464
+                        $group = $this->groupManager->createGroup($groupName);
465
+                    }
466
+                    $group->addUser($user);
467
+                }
468
+            }
469
+            /**
470
+             * Send new user mail only if a mail is set
471
+             */
472
+            if ($email !== '') {
473
+                $user->setEMailAddress($email);
474
+                try {
475
+                    $emailTemplate = $this->newUserMailHelper->generateTemplate($user, $generatePasswordResetToken);
476
+                    $this->newUserMailHelper->sendMail($user, $emailTemplate);
477
+                } catch (\Exception $e) {
478
+                    $this->log->logException($e, [
479
+                        'message' => "Can't send new user mail to $email",
480
+                        'level' => \OCP\Util::ERROR,
481
+                        'app' => 'settings',
482
+                    ]);
483
+                }
484
+            }
485
+            // fetch users groups
486
+            $userGroups = $this->groupManager->getUserGroupIds($user);
487
+
488
+            return new DataResponse(
489
+                $this->formatUserForIndex($user, $userGroups),
490
+                Http::STATUS_CREATED
491
+            );
492
+        }
493
+
494
+        return new DataResponse(
495
+            [
496
+                'message' => (string)$this->l10n->t('Unable to create user.')
497
+            ],
498
+            Http::STATUS_FORBIDDEN
499
+        );
500
+
501
+    }
502
+
503
+    /**
504
+     * @NoAdminRequired
505
+     * @PasswordConfirmationRequired
506
+     *
507
+     * @param string $id
508
+     * @return DataResponse
509
+     */
510
+    public function destroy($id) {
511
+        $userId = $this->userSession->getUser()->getUID();
512
+        $user = $this->userManager->get($id);
513
+
514
+        if ($userId === $id) {
515
+            return new DataResponse(
516
+                [
517
+                    'status' => 'error',
518
+                    'data' => [
519
+                        'message' => (string)$this->l10n->t('Unable to delete user.')
520
+                    ]
521
+                ],
522
+                Http::STATUS_FORBIDDEN
523
+            );
524
+        }
525
+
526
+        if (!$this->isAdmin && !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)) {
527
+            return new DataResponse(
528
+                [
529
+                    'status' => 'error',
530
+                    'data' => [
531
+                        'message' => (string)$this->l10n->t('Authentication error')
532
+                    ]
533
+                ],
534
+                Http::STATUS_FORBIDDEN
535
+            );
536
+        }
537
+
538
+        if ($user) {
539
+            if ($user->delete()) {
540
+                return new DataResponse(
541
+                    [
542
+                        'status' => 'success',
543
+                        'data' => [
544
+                            'username' => $id
545
+                        ]
546
+                    ],
547
+                    Http::STATUS_NO_CONTENT
548
+                );
549
+            }
550
+        }
551
+
552
+        return new DataResponse(
553
+            [
554
+                'status' => 'error',
555
+                'data' => [
556
+                    'message' => (string)$this->l10n->t('Unable to delete user.')
557
+                ]
558
+            ],
559
+            Http::STATUS_FORBIDDEN
560
+        );
561
+    }
562
+
563
+    /**
564
+     * @NoAdminRequired
565
+     *
566
+     * @param string $id
567
+     * @param int $enabled
568
+     * @return DataResponse
569
+     */
570
+    public function setEnabled($id, $enabled) {
571
+        $enabled = (bool)$enabled;
572
+        if ($enabled) {
573
+            $errorMsgGeneral = (string)$this->l10n->t('Error while enabling user.');
574
+        } else {
575
+            $errorMsgGeneral = (string)$this->l10n->t('Error while disabling user.');
576
+        }
577
+
578
+        $userId = $this->userSession->getUser()->getUID();
579
+        $user = $this->userManager->get($id);
580
+
581
+        if ($userId === $id) {
582
+            return new DataResponse(
583
+                [
584
+                    'status' => 'error',
585
+                    'data' => [
586
+                        'message' => $errorMsgGeneral
587
+                    ]
588
+                ], Http::STATUS_FORBIDDEN
589
+            );
590
+        }
591
+
592
+        if ($user) {
593
+            if (!$this->isAdmin && !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)) {
594
+                return new DataResponse(
595
+                    [
596
+                        'status' => 'error',
597
+                        'data' => [
598
+                            'message' => (string)$this->l10n->t('Authentication error')
599
+                        ]
600
+                    ],
601
+                    Http::STATUS_FORBIDDEN
602
+                );
603
+            }
604
+
605
+            $user->setEnabled($enabled);
606
+            return new DataResponse(
607
+                [
608
+                    'status' => 'success',
609
+                    'data' => [
610
+                        'username' => $id,
611
+                        'enabled' => $enabled
612
+                    ]
613
+                ]
614
+            );
615
+        } else {
616
+            return new DataResponse(
617
+                [
618
+                    'status' => 'error',
619
+                    'data' => [
620
+                        'message' => $errorMsgGeneral
621
+                    ]
622
+                ],
623
+                Http::STATUS_FORBIDDEN
624
+            );
625
+        }
626
+
627
+    }
628
+
629
+    /**
630
+     * Set the mail address of a user
631
+     *
632
+     * @NoAdminRequired
633
+     * @NoSubadminRequired
634
+     * @PasswordConfirmationRequired
635
+     *
636
+     * @param string $account
637
+     * @param bool $onlyVerificationCode only return verification code without updating the data
638
+     * @return DataResponse
639
+     */
640
+    public function getVerificationCode($account, $onlyVerificationCode) {
641
+
642
+        $user = $this->userSession->getUser();
643
+
644
+        if ($user === null) {
645
+            return new DataResponse([], Http::STATUS_BAD_REQUEST);
646
+        }
647
+
648
+        $accountData = $this->accountManager->getUser($user);
649
+        $cloudId = $user->getCloudId();
650
+        $message = "Use my Federated Cloud ID to share with me: " . $cloudId;
651
+        $signature = $this->signMessage($user, $message);
652
+
653
+        $code = $message . ' ' . $signature;
654
+        $codeMd5 = $message . ' ' . md5($signature);
655
+
656
+        switch ($account) {
657
+            case 'verify-twitter':
658
+                $accountData[AccountManager::PROPERTY_TWITTER]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
659
+                $msg = $this->l10n->t('In order to verify your Twitter account, post the following tweet on Twitter (please make sure to post it without any line breaks):');
660
+                $code = $codeMd5;
661
+                $type = AccountManager::PROPERTY_TWITTER;
662
+                $data = $accountData[AccountManager::PROPERTY_TWITTER]['value'];
663
+                $accountData[AccountManager::PROPERTY_TWITTER]['signature'] = $signature;
664
+                break;
665
+            case 'verify-website':
666
+                $accountData[AccountManager::PROPERTY_WEBSITE]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
667
+                $msg = $this->l10n->t('In order to verify your Website, store the following content in your web-root at \'.well-known/CloudIdVerificationCode.txt\' (please make sure that the complete text is in one line):');
668
+                $type = AccountManager::PROPERTY_WEBSITE;
669
+                $data = $accountData[AccountManager::PROPERTY_WEBSITE]['value'];
670
+                $accountData[AccountManager::PROPERTY_WEBSITE]['signature'] = $signature;
671
+                break;
672
+            default:
673
+                return new DataResponse([], Http::STATUS_BAD_REQUEST);
674
+        }
675
+
676
+        if ($onlyVerificationCode === false) {
677
+            $this->accountManager->updateUser($user, $accountData);
678
+
679
+            $this->jobList->add(VerifyUserData::class,
680
+                [
681
+                    'verificationCode' => $code,
682
+                    'data' => $data,
683
+                    'type' => $type,
684
+                    'uid' => $user->getUID(),
685
+                    'try' => 0,
686
+                    'lastRun' => $this->getCurrentTime()
687
+                ]
688
+            );
689
+        }
690
+
691
+        return new DataResponse(['msg' => $msg, 'code' => $code]);
692
+    }
693
+
694
+    /**
695
+     * get current timestamp
696
+     *
697
+     * @return int
698
+     */
699
+    protected function getCurrentTime() {
700
+        return time();
701
+    }
702
+
703
+    /**
704
+     * sign message with users private key
705
+     *
706
+     * @param IUser $user
707
+     * @param string $message
708
+     *
709
+     * @return string base64 encoded signature
710
+     */
711
+    protected function signMessage(IUser $user, $message) {
712
+        $privateKey = $this->keyManager->getKey($user)->getPrivate();
713
+        openssl_sign(json_encode($message), $signature, $privateKey, OPENSSL_ALGO_SHA512);
714
+        return base64_encode($signature);
715
+    }
716
+
717
+    /**
718
+     * @NoAdminRequired
719
+     * @NoSubadminRequired
720
+     * @PasswordConfirmationRequired
721
+     *
722
+     * @param string $avatarScope
723
+     * @param string $displayname
724
+     * @param string $displaynameScope
725
+     * @param string $phone
726
+     * @param string $phoneScope
727
+     * @param string $email
728
+     * @param string $emailScope
729
+     * @param string $website
730
+     * @param string $websiteScope
731
+     * @param string $address
732
+     * @param string $addressScope
733
+     * @param string $twitter
734
+     * @param string $twitterScope
735
+     * @return DataResponse
736
+     */
737
+    public function setUserSettings($avatarScope,
738
+                                    $displayname,
739
+                                    $displaynameScope,
740
+                                    $phone,
741
+                                    $phoneScope,
742
+                                    $email,
743
+                                    $emailScope,
744
+                                    $website,
745
+                                    $websiteScope,
746
+                                    $address,
747
+                                    $addressScope,
748
+                                    $twitter,
749
+                                    $twitterScope
750
+    ) {
751
+
752
+        if (!empty($email) && !$this->mailer->validateMailAddress($email)) {
753
+            return new DataResponse(
754
+                [
755
+                    'status' => 'error',
756
+                    'data' => [
757
+                        'message' => (string)$this->l10n->t('Invalid mail address')
758
+                    ]
759
+                ],
760
+                Http::STATUS_UNPROCESSABLE_ENTITY
761
+            );
762
+        }
763
+
764
+        $user = $this->userSession->getUser();
765
+
766
+        $data = $this->accountManager->getUser($user);
767
+
768
+        $data[AccountManager::PROPERTY_AVATAR] = ['scope' => $avatarScope];
769
+        if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
770
+            $data[AccountManager::PROPERTY_DISPLAYNAME] = ['value' => $displayname, 'scope' => $displaynameScope];
771
+            $data[AccountManager::PROPERTY_EMAIL] = ['value' => $email, 'scope' => $emailScope];
772
+        }
773
+
774
+        if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
775
+            $federatedFileSharing = new \OCA\FederatedFileSharing\AppInfo\Application();
776
+            $shareProvider = $federatedFileSharing->getFederatedShareProvider();
777
+            if ($shareProvider->isLookupServerUploadEnabled()) {
778
+                $data[AccountManager::PROPERTY_WEBSITE] = ['value' => $website, 'scope' => $websiteScope];
779
+                $data[AccountManager::PROPERTY_ADDRESS] = ['value' => $address, 'scope' => $addressScope];
780
+                $data[AccountManager::PROPERTY_PHONE] = ['value' => $phone, 'scope' => $phoneScope];
781
+                $data[AccountManager::PROPERTY_TWITTER] = ['value' => $twitter, 'scope' => $twitterScope];
782
+            }
783
+        }
784
+
785
+        try {
786
+            $this->saveUserSettings($user, $data);
787
+            return new DataResponse(
788
+                [
789
+                    'status' => 'success',
790
+                    'data' => [
791
+                        'userId' => $user->getUID(),
792
+                        'avatarScope' => $data[AccountManager::PROPERTY_AVATAR]['scope'],
793
+                        'displayname' => $data[AccountManager::PROPERTY_DISPLAYNAME]['value'],
794
+                        'displaynameScope' => $data[AccountManager::PROPERTY_DISPLAYNAME]['scope'],
795
+                        'email' => $data[AccountManager::PROPERTY_EMAIL]['value'],
796
+                        'emailScope' => $data[AccountManager::PROPERTY_EMAIL]['scope'],
797
+                        'website' => $data[AccountManager::PROPERTY_WEBSITE]['value'],
798
+                        'websiteScope' => $data[AccountManager::PROPERTY_WEBSITE]['scope'],
799
+                        'address' => $data[AccountManager::PROPERTY_ADDRESS]['value'],
800
+                        'addressScope' => $data[AccountManager::PROPERTY_ADDRESS]['scope'],
801
+                        'message' => (string)$this->l10n->t('Settings saved')
802
+                    ]
803
+                ],
804
+                Http::STATUS_OK
805
+            );
806
+        } catch (ForbiddenException $e) {
807
+            return new DataResponse([
808
+                'status' => 'error',
809
+                'data' => [
810
+                    'message' => $e->getMessage()
811
+                ],
812
+            ]);
813
+        }
814
+
815
+    }
816
+
817
+
818
+    /**
819
+     * update account manager with new user data
820
+     *
821
+     * @param IUser $user
822
+     * @param array $data
823
+     * @throws ForbiddenException
824
+     */
825
+    protected function saveUserSettings(IUser $user, $data) {
826
+
827
+        // keep the user back-end up-to-date with the latest display name and email
828
+        // address
829
+        $oldDisplayName = $user->getDisplayName();
830
+        $oldDisplayName = is_null($oldDisplayName) ? '' : $oldDisplayName;
831
+        if (isset($data[AccountManager::PROPERTY_DISPLAYNAME]['value'])
832
+            && $oldDisplayName !== $data[AccountManager::PROPERTY_DISPLAYNAME]['value']
833
+        ) {
834
+            $result = $user->setDisplayName($data[AccountManager::PROPERTY_DISPLAYNAME]['value']);
835
+            if ($result === false) {
836
+                throw new ForbiddenException($this->l10n->t('Unable to change full name'));
837
+            }
838
+        }
839
+
840
+        $oldEmailAddress = $user->getEMailAddress();
841
+        $oldEmailAddress = is_null($oldEmailAddress) ? '' : $oldEmailAddress;
842
+        if (isset($data[AccountManager::PROPERTY_EMAIL]['value'])
843
+            && $oldEmailAddress !== $data[AccountManager::PROPERTY_EMAIL]['value']
844
+        ) {
845
+            // this is the only permission a backend provides and is also used
846
+            // for the permission of setting a email address
847
+            if (!$user->canChangeDisplayName()) {
848
+                throw new ForbiddenException($this->l10n->t('Unable to change email address'));
849
+            }
850
+            $user->setEMailAddress($data[AccountManager::PROPERTY_EMAIL]['value']);
851
+        }
852
+
853
+        $this->accountManager->updateUser($user, $data);
854
+    }
855
+
856
+    /**
857
+     * Count all unique users visible for the current admin/subadmin.
858
+     *
859
+     * @NoAdminRequired
860
+     *
861
+     * @return DataResponse
862
+     */
863
+    public function stats() {
864
+        $userCount = 0;
865
+        if ($this->isAdmin) {
866
+            $countByBackend = $this->userManager->countUsers();
867
+
868
+            if (!empty($countByBackend)) {
869
+                foreach ($countByBackend as $count) {
870
+                    $userCount += $count;
871
+                }
872
+            }
873
+        } else {
874
+            $groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($this->userSession->getUser());
875
+
876
+            $uniqueUsers = [];
877
+            foreach ($groups as $group) {
878
+                foreach ($group->getUsers() as $uid => $displayName) {
879
+                    $uniqueUsers[$uid] = true;
880
+                }
881
+            }
882
+
883
+            $userCount = count($uniqueUsers);
884
+        }
885
+
886
+        return new DataResponse(
887
+            [
888
+                'totalUsers' => $userCount
889
+            ]
890
+        );
891
+    }
892
+
893
+
894
+    /**
895
+     * Set the displayName of a user
896
+     *
897
+     * @NoAdminRequired
898
+     * @NoSubadminRequired
899
+     * @PasswordConfirmationRequired
900
+     * @todo merge into saveUserSettings
901
+     *
902
+     * @param string $username
903
+     * @param string $displayName
904
+     * @return DataResponse
905
+     */
906
+    public function setDisplayName($username, $displayName) {
907
+        $currentUser = $this->userSession->getUser();
908
+        $user = $this->userManager->get($username);
909
+
910
+        if ($user === null ||
911
+            !$user->canChangeDisplayName() ||
912
+            (
913
+                !$this->groupManager->isAdmin($currentUser->getUID()) &&
914
+                !$this->groupManager->getSubAdmin()->isUserAccessible($currentUser, $user) &&
915
+                $currentUser->getUID() !== $username
916
+
917
+            )
918
+        ) {
919
+            return new DataResponse([
920
+                'status' => 'error',
921
+                'data' => [
922
+                    'message' => $this->l10n->t('Authentication error'),
923
+                ],
924
+            ]);
925
+        }
926
+
927
+        $userData = $this->accountManager->getUser($user);
928
+        $userData[AccountManager::PROPERTY_DISPLAYNAME]['value'] = $displayName;
929
+
930
+
931
+        try {
932
+            $this->saveUserSettings($user, $userData);
933
+            return new DataResponse([
934
+                'status' => 'success',
935
+                'data' => [
936
+                    'message' => $this->l10n->t('Your full name has been changed.'),
937
+                    'username' => $username,
938
+                    'displayName' => $displayName,
939
+                ],
940
+            ]);
941
+        } catch (ForbiddenException $e) {
942
+            return new DataResponse([
943
+                'status' => 'error',
944
+                'data' => [
945
+                    'message' => $e->getMessage(),
946
+                    'displayName' => $user->getDisplayName(),
947
+                ],
948
+            ]);
949
+        }
950
+    }
951
+
952
+    /**
953
+     * Set the mail address of a user
954
+     *
955
+     * @NoAdminRequired
956
+     * @NoSubadminRequired
957
+     * @PasswordConfirmationRequired
958
+     *
959
+     * @param string $id
960
+     * @param string $mailAddress
961
+     * @return DataResponse
962
+     */
963
+    public function setEMailAddress($id, $mailAddress) {
964
+        $user = $this->userManager->get($id);
965
+        if (!$this->isAdmin
966
+            && !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)
967
+        ) {
968
+            return new DataResponse(
969
+                [
970
+                    'status' => 'error',
971
+                    'data' => [
972
+                        'message' => (string)$this->l10n->t('Forbidden')
973
+                    ]
974
+                ],
975
+                Http::STATUS_FORBIDDEN
976
+            );
977
+        }
978
+
979
+        if ($mailAddress !== '' && !$this->mailer->validateMailAddress($mailAddress)) {
980
+            return new DataResponse(
981
+                [
982
+                    'status' => 'error',
983
+                    'data' => [
984
+                        'message' => (string)$this->l10n->t('Invalid mail address')
985
+                    ]
986
+                ],
987
+                Http::STATUS_UNPROCESSABLE_ENTITY
988
+            );
989
+        }
990
+
991
+        if (!$user) {
992
+            return new DataResponse(
993
+                [
994
+                    'status' => 'error',
995
+                    'data' => [
996
+                        'message' => (string)$this->l10n->t('Invalid user')
997
+                    ]
998
+                ],
999
+                Http::STATUS_UNPROCESSABLE_ENTITY
1000
+            );
1001
+        }
1002
+        // this is the only permission a backend provides and is also used
1003
+        // for the permission of setting a email address
1004
+        if (!$user->canChangeDisplayName()) {
1005
+            return new DataResponse(
1006
+                [
1007
+                    'status' => 'error',
1008
+                    'data' => [
1009
+                        'message' => (string)$this->l10n->t('Unable to change mail address')
1010
+                    ]
1011
+                ],
1012
+                Http::STATUS_FORBIDDEN
1013
+            );
1014
+        }
1015
+
1016
+        $userData = $this->accountManager->getUser($user);
1017
+        $userData[AccountManager::PROPERTY_EMAIL]['value'] = $mailAddress;
1018
+
1019
+        try {
1020
+            $this->saveUserSettings($user, $userData);
1021
+            return new DataResponse(
1022
+                [
1023
+                    'status' => 'success',
1024
+                    'data' => [
1025
+                        'username' => $id,
1026
+                        'mailAddress' => $mailAddress,
1027
+                        'message' => (string)$this->l10n->t('Email saved')
1028
+                    ]
1029
+                ],
1030
+                Http::STATUS_OK
1031
+            );
1032
+        } catch (ForbiddenException $e) {
1033
+            return new DataResponse([
1034
+                'status' => 'error',
1035
+                'data' => [
1036
+                    'message' => $e->getMessage()
1037
+                ],
1038
+            ]);
1039
+        }
1040
+    }
1041 1041
 
1042 1042
 }
Please login to merge, or discard this patch.