Passed
Push — master ( d78829...05edd1 )
by Roeland
26:57 queued 10s
created
lib/private/Group/MetaData.php 1 patch
Indentation   +171 added lines, -171 removed lines patch added patch discarded remove patch
@@ -35,175 +35,175 @@
 block discarded – undo
35 35
 use OCP\IUserSession;
36 36
 
37 37
 class MetaData {
38
-	public const SORT_NONE = 0;
39
-	public const SORT_USERCOUNT = 1; // May have performance issues on LDAP backends
40
-	public const SORT_GROUPNAME = 2;
41
-
42
-	/** @var string */
43
-	protected $user;
44
-	/** @var bool */
45
-	protected $isAdmin;
46
-	/** @var array */
47
-	protected $metaData = [];
48
-	/** @var GroupManager */
49
-	protected $groupManager;
50
-	/** @var bool */
51
-	protected $sorting = false;
52
-	/** @var IUserSession */
53
-	protected $userSession;
54
-
55
-	/**
56
-	 * @param string $user the uid of the current user
57
-	 * @param bool $isAdmin whether the current users is an admin
58
-	 * @param IGroupManager $groupManager
59
-	 * @param IUserSession $userSession
60
-	 */
61
-	public function __construct(
62
-			$user,
63
-			$isAdmin,
64
-			IGroupManager $groupManager,
65
-			IUserSession $userSession
66
-			) {
67
-		$this->user = $user;
68
-		$this->isAdmin = (bool)$isAdmin;
69
-		$this->groupManager = $groupManager;
70
-		$this->userSession = $userSession;
71
-	}
72
-
73
-	/**
74
-	 * returns an array with meta data about all available groups
75
-	 * the array is structured as follows:
76
-	 * [0] array containing meta data about admin groups
77
-	 * [1] array containing meta data about unprivileged groups
78
-	 * @param string $groupSearch only effective when instance was created with
79
-	 * isAdmin being true
80
-	 * @param string $userSearch the pattern users are search for
81
-	 * @return array
82
-	 */
83
-	public function get($groupSearch = '', $userSearch = '') {
84
-		$key = $groupSearch . '::' . $userSearch;
85
-		if (isset($this->metaData[$key])) {
86
-			return $this->metaData[$key];
87
-		}
88
-
89
-		$adminGroups = [];
90
-		$groups = [];
91
-		$sortGroupsIndex = 0;
92
-		$sortGroupsKeys = [];
93
-		$sortAdminGroupsIndex = 0;
94
-		$sortAdminGroupsKeys = [];
95
-
96
-		foreach ($this->getGroups($groupSearch) as $group) {
97
-			$groupMetaData = $this->generateGroupMetaData($group, $userSearch);
98
-			if (strtolower($group->getGID()) !== 'admin') {
99
-				$this->addEntry(
100
-					$groups,
101
-					$sortGroupsKeys,
102
-					$sortGroupsIndex,
103
-					$groupMetaData);
104
-			} else {
105
-				//admin group is hard coded to 'admin' for now. In future,
106
-				//backends may define admin groups too. Then the if statement
107
-				//has to be adjusted accordingly.
108
-				$this->addEntry(
109
-					$adminGroups,
110
-					$sortAdminGroupsKeys,
111
-					$sortAdminGroupsIndex,
112
-					$groupMetaData);
113
-			}
114
-		}
115
-
116
-		//whether sorting is necessary is will be checked in sort()
117
-		$this->sort($groups, $sortGroupsKeys);
118
-		$this->sort($adminGroups, $sortAdminGroupsKeys);
119
-
120
-		$this->metaData[$key] = [$adminGroups, $groups];
121
-		return $this->metaData[$key];
122
-	}
123
-
124
-	/**
125
-	 * sets the sort mode, see SORT_* constants for supported modes
126
-	 *
127
-	 * @param int $sortMode
128
-	 */
129
-	public function setSorting($sortMode) {
130
-		switch ($sortMode) {
131
-			case self::SORT_USERCOUNT:
132
-			case self::SORT_GROUPNAME:
133
-				$this->sorting = $sortMode;
134
-				break;
135
-
136
-			default:
137
-				$this->sorting = self::SORT_NONE;
138
-		}
139
-	}
140
-
141
-	/**
142
-	 * adds an group entry to the resulting array
143
-	 * @param array $entries the resulting array, by reference
144
-	 * @param array $sortKeys the sort key array, by reference
145
-	 * @param int $sortIndex the sort key index, by reference
146
-	 * @param array $data the group's meta data as returned by generateGroupMetaData()
147
-	 */
148
-	private function addEntry(&$entries, &$sortKeys, &$sortIndex, $data) {
149
-		$entries[] = $data;
150
-		if ($this->sorting === self::SORT_USERCOUNT) {
151
-			$sortKeys[$sortIndex] = $data['usercount'];
152
-			$sortIndex++;
153
-		} elseif ($this->sorting === self::SORT_GROUPNAME) {
154
-			$sortKeys[$sortIndex] = $data['name'];
155
-			$sortIndex++;
156
-		}
157
-	}
158
-
159
-	/**
160
-	 * creates an array containing the group meta data
161
-	 * @param \OCP\IGroup $group
162
-	 * @param string $userSearch
163
-	 * @return array with the keys 'id', 'name', 'usercount' and 'disabled'
164
-	 */
165
-	private function generateGroupMetaData(\OCP\IGroup $group, $userSearch) {
166
-		return [
167
-			'id' => $group->getGID(),
168
-			'name' => $group->getDisplayName(),
169
-			'usercount' => $this->sorting === self::SORT_USERCOUNT ? $group->count($userSearch) : 0,
170
-			'disabled' => $group->countDisabled(),
171
-			'canAdd' => $group->canAddUser(),
172
-			'canRemove' => $group->canRemoveUser(),
173
-		];
174
-	}
175
-
176
-	/**
177
-	 * sorts the result array, if applicable
178
-	 * @param array $entries the result array, by reference
179
-	 * @param array $sortKeys the array containing the sort keys
180
-	 * @param return null
181
-	 */
182
-	private function sort(&$entries, $sortKeys) {
183
-		if ($this->sorting === self::SORT_USERCOUNT) {
184
-			array_multisort($sortKeys, SORT_DESC, $entries);
185
-		} elseif ($this->sorting === self::SORT_GROUPNAME) {
186
-			array_multisort($sortKeys, SORT_ASC, $entries);
187
-		}
188
-	}
189
-
190
-	/**
191
-	 * returns the available groups
192
-	 * @param string $search a search string
193
-	 * @return \OCP\IGroup[]
194
-	 */
195
-	public function getGroups($search = '') {
196
-		if ($this->isAdmin) {
197
-			return $this->groupManager->search($search);
198
-		} else {
199
-			$userObject = $this->userSession->getUser();
200
-			if ($userObject !== null) {
201
-				$groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($userObject);
202
-			} else {
203
-				$groups = [];
204
-			}
205
-
206
-			return $groups;
207
-		}
208
-	}
38
+    public const SORT_NONE = 0;
39
+    public const SORT_USERCOUNT = 1; // May have performance issues on LDAP backends
40
+    public const SORT_GROUPNAME = 2;
41
+
42
+    /** @var string */
43
+    protected $user;
44
+    /** @var bool */
45
+    protected $isAdmin;
46
+    /** @var array */
47
+    protected $metaData = [];
48
+    /** @var GroupManager */
49
+    protected $groupManager;
50
+    /** @var bool */
51
+    protected $sorting = false;
52
+    /** @var IUserSession */
53
+    protected $userSession;
54
+
55
+    /**
56
+     * @param string $user the uid of the current user
57
+     * @param bool $isAdmin whether the current users is an admin
58
+     * @param IGroupManager $groupManager
59
+     * @param IUserSession $userSession
60
+     */
61
+    public function __construct(
62
+            $user,
63
+            $isAdmin,
64
+            IGroupManager $groupManager,
65
+            IUserSession $userSession
66
+            ) {
67
+        $this->user = $user;
68
+        $this->isAdmin = (bool)$isAdmin;
69
+        $this->groupManager = $groupManager;
70
+        $this->userSession = $userSession;
71
+    }
72
+
73
+    /**
74
+     * returns an array with meta data about all available groups
75
+     * the array is structured as follows:
76
+     * [0] array containing meta data about admin groups
77
+     * [1] array containing meta data about unprivileged groups
78
+     * @param string $groupSearch only effective when instance was created with
79
+     * isAdmin being true
80
+     * @param string $userSearch the pattern users are search for
81
+     * @return array
82
+     */
83
+    public function get($groupSearch = '', $userSearch = '') {
84
+        $key = $groupSearch . '::' . $userSearch;
85
+        if (isset($this->metaData[$key])) {
86
+            return $this->metaData[$key];
87
+        }
88
+
89
+        $adminGroups = [];
90
+        $groups = [];
91
+        $sortGroupsIndex = 0;
92
+        $sortGroupsKeys = [];
93
+        $sortAdminGroupsIndex = 0;
94
+        $sortAdminGroupsKeys = [];
95
+
96
+        foreach ($this->getGroups($groupSearch) as $group) {
97
+            $groupMetaData = $this->generateGroupMetaData($group, $userSearch);
98
+            if (strtolower($group->getGID()) !== 'admin') {
99
+                $this->addEntry(
100
+                    $groups,
101
+                    $sortGroupsKeys,
102
+                    $sortGroupsIndex,
103
+                    $groupMetaData);
104
+            } else {
105
+                //admin group is hard coded to 'admin' for now. In future,
106
+                //backends may define admin groups too. Then the if statement
107
+                //has to be adjusted accordingly.
108
+                $this->addEntry(
109
+                    $adminGroups,
110
+                    $sortAdminGroupsKeys,
111
+                    $sortAdminGroupsIndex,
112
+                    $groupMetaData);
113
+            }
114
+        }
115
+
116
+        //whether sorting is necessary is will be checked in sort()
117
+        $this->sort($groups, $sortGroupsKeys);
118
+        $this->sort($adminGroups, $sortAdminGroupsKeys);
119
+
120
+        $this->metaData[$key] = [$adminGroups, $groups];
121
+        return $this->metaData[$key];
122
+    }
123
+
124
+    /**
125
+     * sets the sort mode, see SORT_* constants for supported modes
126
+     *
127
+     * @param int $sortMode
128
+     */
129
+    public function setSorting($sortMode) {
130
+        switch ($sortMode) {
131
+            case self::SORT_USERCOUNT:
132
+            case self::SORT_GROUPNAME:
133
+                $this->sorting = $sortMode;
134
+                break;
135
+
136
+            default:
137
+                $this->sorting = self::SORT_NONE;
138
+        }
139
+    }
140
+
141
+    /**
142
+     * adds an group entry to the resulting array
143
+     * @param array $entries the resulting array, by reference
144
+     * @param array $sortKeys the sort key array, by reference
145
+     * @param int $sortIndex the sort key index, by reference
146
+     * @param array $data the group's meta data as returned by generateGroupMetaData()
147
+     */
148
+    private function addEntry(&$entries, &$sortKeys, &$sortIndex, $data) {
149
+        $entries[] = $data;
150
+        if ($this->sorting === self::SORT_USERCOUNT) {
151
+            $sortKeys[$sortIndex] = $data['usercount'];
152
+            $sortIndex++;
153
+        } elseif ($this->sorting === self::SORT_GROUPNAME) {
154
+            $sortKeys[$sortIndex] = $data['name'];
155
+            $sortIndex++;
156
+        }
157
+    }
158
+
159
+    /**
160
+     * creates an array containing the group meta data
161
+     * @param \OCP\IGroup $group
162
+     * @param string $userSearch
163
+     * @return array with the keys 'id', 'name', 'usercount' and 'disabled'
164
+     */
165
+    private function generateGroupMetaData(\OCP\IGroup $group, $userSearch) {
166
+        return [
167
+            'id' => $group->getGID(),
168
+            'name' => $group->getDisplayName(),
169
+            'usercount' => $this->sorting === self::SORT_USERCOUNT ? $group->count($userSearch) : 0,
170
+            'disabled' => $group->countDisabled(),
171
+            'canAdd' => $group->canAddUser(),
172
+            'canRemove' => $group->canRemoveUser(),
173
+        ];
174
+    }
175
+
176
+    /**
177
+     * sorts the result array, if applicable
178
+     * @param array $entries the result array, by reference
179
+     * @param array $sortKeys the array containing the sort keys
180
+     * @param return null
181
+     */
182
+    private function sort(&$entries, $sortKeys) {
183
+        if ($this->sorting === self::SORT_USERCOUNT) {
184
+            array_multisort($sortKeys, SORT_DESC, $entries);
185
+        } elseif ($this->sorting === self::SORT_GROUPNAME) {
186
+            array_multisort($sortKeys, SORT_ASC, $entries);
187
+        }
188
+    }
189
+
190
+    /**
191
+     * returns the available groups
192
+     * @param string $search a search string
193
+     * @return \OCP\IGroup[]
194
+     */
195
+    public function getGroups($search = '') {
196
+        if ($this->isAdmin) {
197
+            return $this->groupManager->search($search);
198
+        } else {
199
+            $userObject = $this->userSession->getUser();
200
+            if ($userObject !== null) {
201
+                $groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($userObject);
202
+            } else {
203
+                $groups = [];
204
+            }
205
+
206
+            return $groups;
207
+        }
208
+    }
209 209
 }
Please login to merge, or discard this patch.
apps/settings/lib/Controller/UsersController.php 1 patch
Indentation   +472 added lines, -472 removed lines patch added patch discarded remove patch
@@ -66,476 +66,476 @@
 block discarded – undo
66 66
 use function in_array;
67 67
 
68 68
 class UsersController extends Controller {
69
-	/** @var UserManager */
70
-	private $userManager;
71
-	/** @var GroupManager */
72
-	private $groupManager;
73
-	/** @var IUserSession */
74
-	private $userSession;
75
-	/** @var IConfig */
76
-	private $config;
77
-	/** @var bool */
78
-	private $isAdmin;
79
-	/** @var IL10N */
80
-	private $l10n;
81
-	/** @var IMailer */
82
-	private $mailer;
83
-	/** @var Factory */
84
-	private $l10nFactory;
85
-	/** @var IAppManager */
86
-	private $appManager;
87
-	/** @var AccountManager */
88
-	private $accountManager;
89
-	/** @var Manager */
90
-	private $keyManager;
91
-	/** @var IJobList */
92
-	private $jobList;
93
-	/** @var IManager */
94
-	private $encryptionManager;
95
-	/** @var IEventDispatcher */
96
-	private $dispatcher;
97
-
98
-
99
-	public function __construct(
100
-		string $appName,
101
-		IRequest $request,
102
-		IUserManager $userManager,
103
-		IGroupManager $groupManager,
104
-		IUserSession $userSession,
105
-		IConfig $config,
106
-		bool $isAdmin,
107
-		IL10N $l10n,
108
-		IMailer $mailer,
109
-		IFactory $l10nFactory,
110
-		IAppManager $appManager,
111
-		AccountManager $accountManager,
112
-		Manager $keyManager,
113
-		IJobList $jobList,
114
-		IManager $encryptionManager,
115
-		IEventDispatcher $dispatcher
116
-	) {
117
-		parent::__construct($appName, $request);
118
-		$this->userManager = $userManager;
119
-		$this->groupManager = $groupManager;
120
-		$this->userSession = $userSession;
121
-		$this->config = $config;
122
-		$this->isAdmin = $isAdmin;
123
-		$this->l10n = $l10n;
124
-		$this->mailer = $mailer;
125
-		$this->l10nFactory = $l10nFactory;
126
-		$this->appManager = $appManager;
127
-		$this->accountManager = $accountManager;
128
-		$this->keyManager = $keyManager;
129
-		$this->jobList = $jobList;
130
-		$this->encryptionManager = $encryptionManager;
131
-		$this->dispatcher = $dispatcher;
132
-	}
133
-
134
-
135
-	/**
136
-	 * @NoCSRFRequired
137
-	 * @NoAdminRequired
138
-	 *
139
-	 * Display users list template
140
-	 *
141
-	 * @return TemplateResponse
142
-	 */
143
-	public function usersListByGroup() {
144
-		return $this->usersList();
145
-	}
146
-
147
-	/**
148
-	 * @NoCSRFRequired
149
-	 * @NoAdminRequired
150
-	 *
151
-	 * Display users list template
152
-	 *
153
-	 * @return TemplateResponse
154
-	 */
155
-	public function usersList() {
156
-		$user = $this->userSession->getUser();
157
-		$uid = $user->getUID();
158
-
159
-		\OC::$server->getNavigationManager()->setActiveEntry('core_users');
160
-
161
-		/* SORT OPTION: SORT_USERCOUNT or SORT_GROUPNAME */
162
-		$sortGroupsBy = \OC\Group\MetaData::SORT_USERCOUNT;
163
-		$isLDAPUsed = false;
164
-		if ($this->config->getSystemValue('sort_groups_by_name', false)) {
165
-			$sortGroupsBy = \OC\Group\MetaData::SORT_GROUPNAME;
166
-		} else {
167
-			if ($this->appManager->isEnabledForUser('user_ldap')) {
168
-				$isLDAPUsed =
169
-					$this->groupManager->isBackendUsed('\OCA\User_LDAP\Group_Proxy');
170
-				if ($isLDAPUsed) {
171
-					// LDAP user count can be slow, so we sort by group name here
172
-					$sortGroupsBy = \OC\Group\MetaData::SORT_GROUPNAME;
173
-				}
174
-			}
175
-		}
176
-
177
-		$canChangePassword = $this->canAdminChangeUserPasswords();
178
-
179
-		/* GROUPS */
180
-		$groupsInfo = new \OC\Group\MetaData(
181
-			$uid,
182
-			$this->isAdmin,
183
-			$this->groupManager,
184
-			$this->userSession
185
-		);
186
-
187
-		$groupsInfo->setSorting($sortGroupsBy);
188
-		list($adminGroup, $groups) = $groupsInfo->get();
189
-
190
-		if (!$isLDAPUsed && $this->appManager->isEnabledForUser('user_ldap')) {
191
-			$isLDAPUsed = (bool)array_reduce($this->userManager->getBackends(), function ($ldapFound, $backend) {
192
-				return $ldapFound || $backend instanceof User_Proxy;
193
-			});
194
-		}
195
-
196
-		$disabledUsers = -1;
197
-		$userCount = 0;
198
-
199
-		if (!$isLDAPUsed) {
200
-			if ($this->isAdmin) {
201
-				$disabledUsers = $this->userManager->countDisabledUsers();
202
-				$userCount = array_reduce($this->userManager->countUsers(), function ($v, $w) {
203
-					return $v + (int)$w;
204
-				}, 0);
205
-			} else {
206
-				// User is subadmin !
207
-				// Map group list to names to retrieve the countDisabledUsersOfGroups
208
-				$userGroups = $this->groupManager->getUserGroups($user);
209
-				$groupsNames = [];
210
-
211
-				foreach ($groups as $key => $group) {
212
-					// $userCount += (int)$group['usercount'];
213
-					array_push($groupsNames, $group['name']);
214
-					// we prevent subadmins from looking up themselves
215
-					// so we lower the count of the groups he belongs to
216
-					if (array_key_exists($group['id'], $userGroups)) {
217
-						$groups[$key]['usercount']--;
218
-						$userCount -= 1; // we also lower from one the total count
219
-					}
220
-				}
221
-				$userCount += $this->userManager->countUsersOfGroups($groupsInfo->getGroups());
222
-				$disabledUsers = $this->userManager->countDisabledUsersOfGroups($groupsNames);
223
-			}
224
-
225
-			$userCount -= $disabledUsers;
226
-		}
227
-
228
-		$disabledUsersGroup = [
229
-			'id' => 'disabled',
230
-			'name' => 'Disabled users',
231
-			'usercount' => $disabledUsers
232
-		];
233
-
234
-		/* QUOTAS PRESETS */
235
-		$quotaPreset = $this->parseQuotaPreset($this->config->getAppValue('files', 'quota_preset', '1 GB, 5 GB, 10 GB'));
236
-		$defaultQuota = $this->config->getAppValue('files', 'default_quota', 'none');
237
-
238
-		$event = new BeforeTemplateRenderedEvent();
239
-		$this->dispatcher->dispatch('OC\Settings\Users::loadAdditionalScripts', $event);
240
-		$this->dispatcher->dispatchTyped($event);
241
-
242
-		/* LANGUAGES */
243
-		$languages = $this->l10nFactory->getLanguages();
244
-
245
-		/* FINAL DATA */
246
-		$serverData = [];
247
-		// groups
248
-		$serverData['groups'] = array_merge_recursive($adminGroup, [$disabledUsersGroup], $groups);
249
-		// Various data
250
-		$serverData['isAdmin'] = $this->isAdmin;
251
-		$serverData['sortGroups'] = $sortGroupsBy;
252
-		$serverData['quotaPreset'] = $quotaPreset;
253
-		$serverData['userCount'] = $userCount;
254
-		$serverData['languages'] = $languages;
255
-		$serverData['defaultLanguage'] = $this->config->getSystemValue('default_language', 'en');
256
-		$serverData['forceLanguage'] = $this->config->getSystemValue('force_language', false);
257
-		// Settings
258
-		$serverData['defaultQuota'] = $defaultQuota;
259
-		$serverData['canChangePassword'] = $canChangePassword;
260
-		$serverData['newUserGenerateUserID'] = $this->config->getAppValue('core', 'newUser.generateUserID', 'no') === 'yes';
261
-		$serverData['newUserRequireEmail'] = $this->config->getAppValue('core', 'newUser.requireEmail', 'no') === 'yes';
262
-		$serverData['newUserSendEmail'] = $this->config->getAppValue('core', 'newUser.sendEmail', 'yes') === 'yes';
263
-
264
-		return new TemplateResponse('settings', 'settings-vue', ['serverData' => $serverData]);
265
-	}
266
-
267
-	/**
268
-	 * @param string $key
269
-	 * @param string $value
270
-	 *
271
-	 * @return JSONResponse
272
-	 */
273
-	public function setPreference(string $key, string $value): JSONResponse {
274
-		$allowed = ['newUser.sendEmail'];
275
-		if (!in_array($key, $allowed, true)) {
276
-			return new JSONResponse([], Http::STATUS_FORBIDDEN);
277
-		}
278
-
279
-		$this->config->setAppValue('core', $key, $value);
280
-
281
-		return new JSONResponse([]);
282
-	}
283
-
284
-	/**
285
-	 * Parse the app value for quota_present
286
-	 *
287
-	 * @param string $quotaPreset
288
-	 * @return array
289
-	 */
290
-	protected function parseQuotaPreset(string $quotaPreset): array {
291
-		// 1 GB, 5 GB, 10 GB => [1 GB, 5 GB, 10 GB]
292
-		$presets = array_filter(array_map('trim', explode(',', $quotaPreset)));
293
-		// Drop default and none, Make array indexes numerically
294
-		return array_values(array_diff($presets, ['default', 'none']));
295
-	}
296
-
297
-	/**
298
-	 * check if the admin can change the users password
299
-	 *
300
-	 * The admin can change the passwords if:
301
-	 *
302
-	 *   - no encryption module is loaded and encryption is disabled
303
-	 *   - encryption module is loaded but it doesn't require per user keys
304
-	 *
305
-	 * The admin can not change the passwords if:
306
-	 *
307
-	 *   - an encryption module is loaded and it uses per-user keys
308
-	 *   - encryption is enabled but no encryption modules are loaded
309
-	 *
310
-	 * @return bool
311
-	 */
312
-	protected function canAdminChangeUserPasswords() {
313
-		$isEncryptionEnabled = $this->encryptionManager->isEnabled();
314
-		try {
315
-			$noUserSpecificEncryptionKeys =!$this->encryptionManager->getEncryptionModule()->needDetailedAccessList();
316
-			$isEncryptionModuleLoaded = true;
317
-		} catch (ModuleDoesNotExistsException $e) {
318
-			$noUserSpecificEncryptionKeys = true;
319
-			$isEncryptionModuleLoaded = false;
320
-		}
321
-
322
-		$canChangePassword = ($isEncryptionEnabled && $isEncryptionModuleLoaded  && $noUserSpecificEncryptionKeys)
323
-			|| (!$isEncryptionEnabled && !$isEncryptionModuleLoaded)
324
-			|| (!$isEncryptionEnabled && $isEncryptionModuleLoaded && $noUserSpecificEncryptionKeys);
325
-
326
-		return $canChangePassword;
327
-	}
328
-
329
-	/**
330
-	 * @NoAdminRequired
331
-	 * @NoSubAdminRequired
332
-	 * @PasswordConfirmationRequired
333
-	 *
334
-	 * @param string $avatarScope
335
-	 * @param string $displayname
336
-	 * @param string $displaynameScope
337
-	 * @param string $phone
338
-	 * @param string $phoneScope
339
-	 * @param string $email
340
-	 * @param string $emailScope
341
-	 * @param string $website
342
-	 * @param string $websiteScope
343
-	 * @param string $address
344
-	 * @param string $addressScope
345
-	 * @param string $twitter
346
-	 * @param string $twitterScope
347
-	 * @return DataResponse
348
-	 */
349
-	public function setUserSettings($avatarScope,
350
-									$displayname,
351
-									$displaynameScope,
352
-									$phone,
353
-									$phoneScope,
354
-									$email,
355
-									$emailScope,
356
-									$website,
357
-									$websiteScope,
358
-									$address,
359
-									$addressScope,
360
-									$twitter,
361
-									$twitterScope
362
-	) {
363
-		if (!empty($email) && !$this->mailer->validateMailAddress($email)) {
364
-			return new DataResponse(
365
-				[
366
-					'status' => 'error',
367
-					'data' => [
368
-						'message' => $this->l10n->t('Invalid mail address')
369
-					]
370
-				],
371
-				Http::STATUS_UNPROCESSABLE_ENTITY
372
-			);
373
-		}
374
-		$user = $this->userSession->getUser();
375
-		$data = $this->accountManager->getUser($user);
376
-		$data[AccountManager::PROPERTY_AVATAR] = ['scope' => $avatarScope];
377
-		if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
378
-			$data[AccountManager::PROPERTY_DISPLAYNAME] = ['value' => $displayname, 'scope' => $displaynameScope];
379
-			$data[AccountManager::PROPERTY_EMAIL] = ['value' => $email, 'scope' => $emailScope];
380
-		}
381
-		if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
382
-			$shareProvider = \OC::$server->query(FederatedShareProvider::class);
383
-			if ($shareProvider->isLookupServerUploadEnabled()) {
384
-				$data[AccountManager::PROPERTY_WEBSITE] = ['value' => $website, 'scope' => $websiteScope];
385
-				$data[AccountManager::PROPERTY_ADDRESS] = ['value' => $address, 'scope' => $addressScope];
386
-				$data[AccountManager::PROPERTY_PHONE] = ['value' => $phone, 'scope' => $phoneScope];
387
-				$data[AccountManager::PROPERTY_TWITTER] = ['value' => $twitter, 'scope' => $twitterScope];
388
-			}
389
-		}
390
-		try {
391
-			$this->saveUserSettings($user, $data);
392
-			return new DataResponse(
393
-				[
394
-					'status' => 'success',
395
-					'data' => [
396
-						'userId' => $user->getUID(),
397
-						'avatarScope' => $data[AccountManager::PROPERTY_AVATAR]['scope'],
398
-						'displayname' => $data[AccountManager::PROPERTY_DISPLAYNAME]['value'],
399
-						'displaynameScope' => $data[AccountManager::PROPERTY_DISPLAYNAME]['scope'],
400
-						'email' => $data[AccountManager::PROPERTY_EMAIL]['value'],
401
-						'emailScope' => $data[AccountManager::PROPERTY_EMAIL]['scope'],
402
-						'website' => $data[AccountManager::PROPERTY_WEBSITE]['value'],
403
-						'websiteScope' => $data[AccountManager::PROPERTY_WEBSITE]['scope'],
404
-						'address' => $data[AccountManager::PROPERTY_ADDRESS]['value'],
405
-						'addressScope' => $data[AccountManager::PROPERTY_ADDRESS]['scope'],
406
-						'message' => $this->l10n->t('Settings saved')
407
-					]
408
-				],
409
-				Http::STATUS_OK
410
-			);
411
-		} catch (ForbiddenException $e) {
412
-			return new DataResponse([
413
-				'status' => 'error',
414
-				'data' => [
415
-					'message' => $e->getMessage()
416
-				],
417
-			]);
418
-		}
419
-	}
420
-	/**
421
-	 * update account manager with new user data
422
-	 *
423
-	 * @param IUser $user
424
-	 * @param array $data
425
-	 * @throws ForbiddenException
426
-	 */
427
-	protected function saveUserSettings(IUser $user, array $data) {
428
-		// keep the user back-end up-to-date with the latest display name and email
429
-		// address
430
-		$oldDisplayName = $user->getDisplayName();
431
-		$oldDisplayName = is_null($oldDisplayName) ? '' : $oldDisplayName;
432
-		if (isset($data[AccountManager::PROPERTY_DISPLAYNAME]['value'])
433
-			&& $oldDisplayName !== $data[AccountManager::PROPERTY_DISPLAYNAME]['value']
434
-		) {
435
-			$result = $user->setDisplayName($data[AccountManager::PROPERTY_DISPLAYNAME]['value']);
436
-			if ($result === false) {
437
-				throw new ForbiddenException($this->l10n->t('Unable to change full name'));
438
-			}
439
-		}
440
-		$oldEmailAddress = $user->getEMailAddress();
441
-		$oldEmailAddress = is_null($oldEmailAddress) ? '' : $oldEmailAddress;
442
-		if (isset($data[AccountManager::PROPERTY_EMAIL]['value'])
443
-			&& $oldEmailAddress !== $data[AccountManager::PROPERTY_EMAIL]['value']
444
-		) {
445
-			// this is the only permission a backend provides and is also used
446
-			// for the permission of setting a email address
447
-			if (!$user->canChangeDisplayName()) {
448
-				throw new ForbiddenException($this->l10n->t('Unable to change email address'));
449
-			}
450
-			$user->setEMailAddress($data[AccountManager::PROPERTY_EMAIL]['value']);
451
-		}
452
-		$this->accountManager->updateUser($user, $data);
453
-	}
454
-
455
-	/**
456
-	 * Set the mail address of a user
457
-	 *
458
-	 * @NoAdminRequired
459
-	 * @NoSubAdminRequired
460
-	 * @PasswordConfirmationRequired
461
-	 *
462
-	 * @param string $account
463
-	 * @param bool $onlyVerificationCode only return verification code without updating the data
464
-	 * @return DataResponse
465
-	 */
466
-	public function getVerificationCode(string $account, bool $onlyVerificationCode): DataResponse {
467
-		$user = $this->userSession->getUser();
468
-
469
-		if ($user === null) {
470
-			return new DataResponse([], Http::STATUS_BAD_REQUEST);
471
-		}
472
-
473
-		$accountData = $this->accountManager->getUser($user);
474
-		$cloudId = $user->getCloudId();
475
-		$message = 'Use my Federated Cloud ID to share with me: ' . $cloudId;
476
-		$signature = $this->signMessage($user, $message);
477
-
478
-		$code = $message . ' ' . $signature;
479
-		$codeMd5 = $message . ' ' . md5($signature);
480
-
481
-		switch ($account) {
482
-			case 'verify-twitter':
483
-				$accountData[AccountManager::PROPERTY_TWITTER]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
484
-				$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):');
485
-				$code = $codeMd5;
486
-				$type = AccountManager::PROPERTY_TWITTER;
487
-				$data = $accountData[AccountManager::PROPERTY_TWITTER]['value'];
488
-				$accountData[AccountManager::PROPERTY_TWITTER]['signature'] = $signature;
489
-				break;
490
-			case 'verify-website':
491
-				$accountData[AccountManager::PROPERTY_WEBSITE]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
492
-				$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):');
493
-				$type = AccountManager::PROPERTY_WEBSITE;
494
-				$data = $accountData[AccountManager::PROPERTY_WEBSITE]['value'];
495
-				$accountData[AccountManager::PROPERTY_WEBSITE]['signature'] = $signature;
496
-				break;
497
-			default:
498
-				return new DataResponse([], Http::STATUS_BAD_REQUEST);
499
-		}
500
-
501
-		if ($onlyVerificationCode === false) {
502
-			$this->accountManager->updateUser($user, $accountData);
503
-
504
-			$this->jobList->add(VerifyUserData::class,
505
-				[
506
-					'verificationCode' => $code,
507
-					'data' => $data,
508
-					'type' => $type,
509
-					'uid' => $user->getUID(),
510
-					'try' => 0,
511
-					'lastRun' => $this->getCurrentTime()
512
-				]
513
-			);
514
-		}
515
-
516
-		return new DataResponse(['msg' => $msg, 'code' => $code]);
517
-	}
518
-
519
-	/**
520
-	 * get current timestamp
521
-	 *
522
-	 * @return int
523
-	 */
524
-	protected function getCurrentTime(): int {
525
-		return time();
526
-	}
527
-
528
-	/**
529
-	 * sign message with users private key
530
-	 *
531
-	 * @param IUser $user
532
-	 * @param string $message
533
-	 *
534
-	 * @return string base64 encoded signature
535
-	 */
536
-	protected function signMessage(IUser $user, string $message): string {
537
-		$privateKey = $this->keyManager->getKey($user)->getPrivate();
538
-		openssl_sign(json_encode($message), $signature, $privateKey, OPENSSL_ALGO_SHA512);
539
-		return base64_encode($signature);
540
-	}
69
+    /** @var UserManager */
70
+    private $userManager;
71
+    /** @var GroupManager */
72
+    private $groupManager;
73
+    /** @var IUserSession */
74
+    private $userSession;
75
+    /** @var IConfig */
76
+    private $config;
77
+    /** @var bool */
78
+    private $isAdmin;
79
+    /** @var IL10N */
80
+    private $l10n;
81
+    /** @var IMailer */
82
+    private $mailer;
83
+    /** @var Factory */
84
+    private $l10nFactory;
85
+    /** @var IAppManager */
86
+    private $appManager;
87
+    /** @var AccountManager */
88
+    private $accountManager;
89
+    /** @var Manager */
90
+    private $keyManager;
91
+    /** @var IJobList */
92
+    private $jobList;
93
+    /** @var IManager */
94
+    private $encryptionManager;
95
+    /** @var IEventDispatcher */
96
+    private $dispatcher;
97
+
98
+
99
+    public function __construct(
100
+        string $appName,
101
+        IRequest $request,
102
+        IUserManager $userManager,
103
+        IGroupManager $groupManager,
104
+        IUserSession $userSession,
105
+        IConfig $config,
106
+        bool $isAdmin,
107
+        IL10N $l10n,
108
+        IMailer $mailer,
109
+        IFactory $l10nFactory,
110
+        IAppManager $appManager,
111
+        AccountManager $accountManager,
112
+        Manager $keyManager,
113
+        IJobList $jobList,
114
+        IManager $encryptionManager,
115
+        IEventDispatcher $dispatcher
116
+    ) {
117
+        parent::__construct($appName, $request);
118
+        $this->userManager = $userManager;
119
+        $this->groupManager = $groupManager;
120
+        $this->userSession = $userSession;
121
+        $this->config = $config;
122
+        $this->isAdmin = $isAdmin;
123
+        $this->l10n = $l10n;
124
+        $this->mailer = $mailer;
125
+        $this->l10nFactory = $l10nFactory;
126
+        $this->appManager = $appManager;
127
+        $this->accountManager = $accountManager;
128
+        $this->keyManager = $keyManager;
129
+        $this->jobList = $jobList;
130
+        $this->encryptionManager = $encryptionManager;
131
+        $this->dispatcher = $dispatcher;
132
+    }
133
+
134
+
135
+    /**
136
+     * @NoCSRFRequired
137
+     * @NoAdminRequired
138
+     *
139
+     * Display users list template
140
+     *
141
+     * @return TemplateResponse
142
+     */
143
+    public function usersListByGroup() {
144
+        return $this->usersList();
145
+    }
146
+
147
+    /**
148
+     * @NoCSRFRequired
149
+     * @NoAdminRequired
150
+     *
151
+     * Display users list template
152
+     *
153
+     * @return TemplateResponse
154
+     */
155
+    public function usersList() {
156
+        $user = $this->userSession->getUser();
157
+        $uid = $user->getUID();
158
+
159
+        \OC::$server->getNavigationManager()->setActiveEntry('core_users');
160
+
161
+        /* SORT OPTION: SORT_USERCOUNT or SORT_GROUPNAME */
162
+        $sortGroupsBy = \OC\Group\MetaData::SORT_USERCOUNT;
163
+        $isLDAPUsed = false;
164
+        if ($this->config->getSystemValue('sort_groups_by_name', false)) {
165
+            $sortGroupsBy = \OC\Group\MetaData::SORT_GROUPNAME;
166
+        } else {
167
+            if ($this->appManager->isEnabledForUser('user_ldap')) {
168
+                $isLDAPUsed =
169
+                    $this->groupManager->isBackendUsed('\OCA\User_LDAP\Group_Proxy');
170
+                if ($isLDAPUsed) {
171
+                    // LDAP user count can be slow, so we sort by group name here
172
+                    $sortGroupsBy = \OC\Group\MetaData::SORT_GROUPNAME;
173
+                }
174
+            }
175
+        }
176
+
177
+        $canChangePassword = $this->canAdminChangeUserPasswords();
178
+
179
+        /* GROUPS */
180
+        $groupsInfo = new \OC\Group\MetaData(
181
+            $uid,
182
+            $this->isAdmin,
183
+            $this->groupManager,
184
+            $this->userSession
185
+        );
186
+
187
+        $groupsInfo->setSorting($sortGroupsBy);
188
+        list($adminGroup, $groups) = $groupsInfo->get();
189
+
190
+        if (!$isLDAPUsed && $this->appManager->isEnabledForUser('user_ldap')) {
191
+            $isLDAPUsed = (bool)array_reduce($this->userManager->getBackends(), function ($ldapFound, $backend) {
192
+                return $ldapFound || $backend instanceof User_Proxy;
193
+            });
194
+        }
195
+
196
+        $disabledUsers = -1;
197
+        $userCount = 0;
198
+
199
+        if (!$isLDAPUsed) {
200
+            if ($this->isAdmin) {
201
+                $disabledUsers = $this->userManager->countDisabledUsers();
202
+                $userCount = array_reduce($this->userManager->countUsers(), function ($v, $w) {
203
+                    return $v + (int)$w;
204
+                }, 0);
205
+            } else {
206
+                // User is subadmin !
207
+                // Map group list to names to retrieve the countDisabledUsersOfGroups
208
+                $userGroups = $this->groupManager->getUserGroups($user);
209
+                $groupsNames = [];
210
+
211
+                foreach ($groups as $key => $group) {
212
+                    // $userCount += (int)$group['usercount'];
213
+                    array_push($groupsNames, $group['name']);
214
+                    // we prevent subadmins from looking up themselves
215
+                    // so we lower the count of the groups he belongs to
216
+                    if (array_key_exists($group['id'], $userGroups)) {
217
+                        $groups[$key]['usercount']--;
218
+                        $userCount -= 1; // we also lower from one the total count
219
+                    }
220
+                }
221
+                $userCount += $this->userManager->countUsersOfGroups($groupsInfo->getGroups());
222
+                $disabledUsers = $this->userManager->countDisabledUsersOfGroups($groupsNames);
223
+            }
224
+
225
+            $userCount -= $disabledUsers;
226
+        }
227
+
228
+        $disabledUsersGroup = [
229
+            'id' => 'disabled',
230
+            'name' => 'Disabled users',
231
+            'usercount' => $disabledUsers
232
+        ];
233
+
234
+        /* QUOTAS PRESETS */
235
+        $quotaPreset = $this->parseQuotaPreset($this->config->getAppValue('files', 'quota_preset', '1 GB, 5 GB, 10 GB'));
236
+        $defaultQuota = $this->config->getAppValue('files', 'default_quota', 'none');
237
+
238
+        $event = new BeforeTemplateRenderedEvent();
239
+        $this->dispatcher->dispatch('OC\Settings\Users::loadAdditionalScripts', $event);
240
+        $this->dispatcher->dispatchTyped($event);
241
+
242
+        /* LANGUAGES */
243
+        $languages = $this->l10nFactory->getLanguages();
244
+
245
+        /* FINAL DATA */
246
+        $serverData = [];
247
+        // groups
248
+        $serverData['groups'] = array_merge_recursive($adminGroup, [$disabledUsersGroup], $groups);
249
+        // Various data
250
+        $serverData['isAdmin'] = $this->isAdmin;
251
+        $serverData['sortGroups'] = $sortGroupsBy;
252
+        $serverData['quotaPreset'] = $quotaPreset;
253
+        $serverData['userCount'] = $userCount;
254
+        $serverData['languages'] = $languages;
255
+        $serverData['defaultLanguage'] = $this->config->getSystemValue('default_language', 'en');
256
+        $serverData['forceLanguage'] = $this->config->getSystemValue('force_language', false);
257
+        // Settings
258
+        $serverData['defaultQuota'] = $defaultQuota;
259
+        $serverData['canChangePassword'] = $canChangePassword;
260
+        $serverData['newUserGenerateUserID'] = $this->config->getAppValue('core', 'newUser.generateUserID', 'no') === 'yes';
261
+        $serverData['newUserRequireEmail'] = $this->config->getAppValue('core', 'newUser.requireEmail', 'no') === 'yes';
262
+        $serverData['newUserSendEmail'] = $this->config->getAppValue('core', 'newUser.sendEmail', 'yes') === 'yes';
263
+
264
+        return new TemplateResponse('settings', 'settings-vue', ['serverData' => $serverData]);
265
+    }
266
+
267
+    /**
268
+     * @param string $key
269
+     * @param string $value
270
+     *
271
+     * @return JSONResponse
272
+     */
273
+    public function setPreference(string $key, string $value): JSONResponse {
274
+        $allowed = ['newUser.sendEmail'];
275
+        if (!in_array($key, $allowed, true)) {
276
+            return new JSONResponse([], Http::STATUS_FORBIDDEN);
277
+        }
278
+
279
+        $this->config->setAppValue('core', $key, $value);
280
+
281
+        return new JSONResponse([]);
282
+    }
283
+
284
+    /**
285
+     * Parse the app value for quota_present
286
+     *
287
+     * @param string $quotaPreset
288
+     * @return array
289
+     */
290
+    protected function parseQuotaPreset(string $quotaPreset): array {
291
+        // 1 GB, 5 GB, 10 GB => [1 GB, 5 GB, 10 GB]
292
+        $presets = array_filter(array_map('trim', explode(',', $quotaPreset)));
293
+        // Drop default and none, Make array indexes numerically
294
+        return array_values(array_diff($presets, ['default', 'none']));
295
+    }
296
+
297
+    /**
298
+     * check if the admin can change the users password
299
+     *
300
+     * The admin can change the passwords if:
301
+     *
302
+     *   - no encryption module is loaded and encryption is disabled
303
+     *   - encryption module is loaded but it doesn't require per user keys
304
+     *
305
+     * The admin can not change the passwords if:
306
+     *
307
+     *   - an encryption module is loaded and it uses per-user keys
308
+     *   - encryption is enabled but no encryption modules are loaded
309
+     *
310
+     * @return bool
311
+     */
312
+    protected function canAdminChangeUserPasswords() {
313
+        $isEncryptionEnabled = $this->encryptionManager->isEnabled();
314
+        try {
315
+            $noUserSpecificEncryptionKeys =!$this->encryptionManager->getEncryptionModule()->needDetailedAccessList();
316
+            $isEncryptionModuleLoaded = true;
317
+        } catch (ModuleDoesNotExistsException $e) {
318
+            $noUserSpecificEncryptionKeys = true;
319
+            $isEncryptionModuleLoaded = false;
320
+        }
321
+
322
+        $canChangePassword = ($isEncryptionEnabled && $isEncryptionModuleLoaded  && $noUserSpecificEncryptionKeys)
323
+            || (!$isEncryptionEnabled && !$isEncryptionModuleLoaded)
324
+            || (!$isEncryptionEnabled && $isEncryptionModuleLoaded && $noUserSpecificEncryptionKeys);
325
+
326
+        return $canChangePassword;
327
+    }
328
+
329
+    /**
330
+     * @NoAdminRequired
331
+     * @NoSubAdminRequired
332
+     * @PasswordConfirmationRequired
333
+     *
334
+     * @param string $avatarScope
335
+     * @param string $displayname
336
+     * @param string $displaynameScope
337
+     * @param string $phone
338
+     * @param string $phoneScope
339
+     * @param string $email
340
+     * @param string $emailScope
341
+     * @param string $website
342
+     * @param string $websiteScope
343
+     * @param string $address
344
+     * @param string $addressScope
345
+     * @param string $twitter
346
+     * @param string $twitterScope
347
+     * @return DataResponse
348
+     */
349
+    public function setUserSettings($avatarScope,
350
+                                    $displayname,
351
+                                    $displaynameScope,
352
+                                    $phone,
353
+                                    $phoneScope,
354
+                                    $email,
355
+                                    $emailScope,
356
+                                    $website,
357
+                                    $websiteScope,
358
+                                    $address,
359
+                                    $addressScope,
360
+                                    $twitter,
361
+                                    $twitterScope
362
+    ) {
363
+        if (!empty($email) && !$this->mailer->validateMailAddress($email)) {
364
+            return new DataResponse(
365
+                [
366
+                    'status' => 'error',
367
+                    'data' => [
368
+                        'message' => $this->l10n->t('Invalid mail address')
369
+                    ]
370
+                ],
371
+                Http::STATUS_UNPROCESSABLE_ENTITY
372
+            );
373
+        }
374
+        $user = $this->userSession->getUser();
375
+        $data = $this->accountManager->getUser($user);
376
+        $data[AccountManager::PROPERTY_AVATAR] = ['scope' => $avatarScope];
377
+        if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
378
+            $data[AccountManager::PROPERTY_DISPLAYNAME] = ['value' => $displayname, 'scope' => $displaynameScope];
379
+            $data[AccountManager::PROPERTY_EMAIL] = ['value' => $email, 'scope' => $emailScope];
380
+        }
381
+        if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
382
+            $shareProvider = \OC::$server->query(FederatedShareProvider::class);
383
+            if ($shareProvider->isLookupServerUploadEnabled()) {
384
+                $data[AccountManager::PROPERTY_WEBSITE] = ['value' => $website, 'scope' => $websiteScope];
385
+                $data[AccountManager::PROPERTY_ADDRESS] = ['value' => $address, 'scope' => $addressScope];
386
+                $data[AccountManager::PROPERTY_PHONE] = ['value' => $phone, 'scope' => $phoneScope];
387
+                $data[AccountManager::PROPERTY_TWITTER] = ['value' => $twitter, 'scope' => $twitterScope];
388
+            }
389
+        }
390
+        try {
391
+            $this->saveUserSettings($user, $data);
392
+            return new DataResponse(
393
+                [
394
+                    'status' => 'success',
395
+                    'data' => [
396
+                        'userId' => $user->getUID(),
397
+                        'avatarScope' => $data[AccountManager::PROPERTY_AVATAR]['scope'],
398
+                        'displayname' => $data[AccountManager::PROPERTY_DISPLAYNAME]['value'],
399
+                        'displaynameScope' => $data[AccountManager::PROPERTY_DISPLAYNAME]['scope'],
400
+                        'email' => $data[AccountManager::PROPERTY_EMAIL]['value'],
401
+                        'emailScope' => $data[AccountManager::PROPERTY_EMAIL]['scope'],
402
+                        'website' => $data[AccountManager::PROPERTY_WEBSITE]['value'],
403
+                        'websiteScope' => $data[AccountManager::PROPERTY_WEBSITE]['scope'],
404
+                        'address' => $data[AccountManager::PROPERTY_ADDRESS]['value'],
405
+                        'addressScope' => $data[AccountManager::PROPERTY_ADDRESS]['scope'],
406
+                        'message' => $this->l10n->t('Settings saved')
407
+                    ]
408
+                ],
409
+                Http::STATUS_OK
410
+            );
411
+        } catch (ForbiddenException $e) {
412
+            return new DataResponse([
413
+                'status' => 'error',
414
+                'data' => [
415
+                    'message' => $e->getMessage()
416
+                ],
417
+            ]);
418
+        }
419
+    }
420
+    /**
421
+     * update account manager with new user data
422
+     *
423
+     * @param IUser $user
424
+     * @param array $data
425
+     * @throws ForbiddenException
426
+     */
427
+    protected function saveUserSettings(IUser $user, array $data) {
428
+        // keep the user back-end up-to-date with the latest display name and email
429
+        // address
430
+        $oldDisplayName = $user->getDisplayName();
431
+        $oldDisplayName = is_null($oldDisplayName) ? '' : $oldDisplayName;
432
+        if (isset($data[AccountManager::PROPERTY_DISPLAYNAME]['value'])
433
+            && $oldDisplayName !== $data[AccountManager::PROPERTY_DISPLAYNAME]['value']
434
+        ) {
435
+            $result = $user->setDisplayName($data[AccountManager::PROPERTY_DISPLAYNAME]['value']);
436
+            if ($result === false) {
437
+                throw new ForbiddenException($this->l10n->t('Unable to change full name'));
438
+            }
439
+        }
440
+        $oldEmailAddress = $user->getEMailAddress();
441
+        $oldEmailAddress = is_null($oldEmailAddress) ? '' : $oldEmailAddress;
442
+        if (isset($data[AccountManager::PROPERTY_EMAIL]['value'])
443
+            && $oldEmailAddress !== $data[AccountManager::PROPERTY_EMAIL]['value']
444
+        ) {
445
+            // this is the only permission a backend provides and is also used
446
+            // for the permission of setting a email address
447
+            if (!$user->canChangeDisplayName()) {
448
+                throw new ForbiddenException($this->l10n->t('Unable to change email address'));
449
+            }
450
+            $user->setEMailAddress($data[AccountManager::PROPERTY_EMAIL]['value']);
451
+        }
452
+        $this->accountManager->updateUser($user, $data);
453
+    }
454
+
455
+    /**
456
+     * Set the mail address of a user
457
+     *
458
+     * @NoAdminRequired
459
+     * @NoSubAdminRequired
460
+     * @PasswordConfirmationRequired
461
+     *
462
+     * @param string $account
463
+     * @param bool $onlyVerificationCode only return verification code without updating the data
464
+     * @return DataResponse
465
+     */
466
+    public function getVerificationCode(string $account, bool $onlyVerificationCode): DataResponse {
467
+        $user = $this->userSession->getUser();
468
+
469
+        if ($user === null) {
470
+            return new DataResponse([], Http::STATUS_BAD_REQUEST);
471
+        }
472
+
473
+        $accountData = $this->accountManager->getUser($user);
474
+        $cloudId = $user->getCloudId();
475
+        $message = 'Use my Federated Cloud ID to share with me: ' . $cloudId;
476
+        $signature = $this->signMessage($user, $message);
477
+
478
+        $code = $message . ' ' . $signature;
479
+        $codeMd5 = $message . ' ' . md5($signature);
480
+
481
+        switch ($account) {
482
+            case 'verify-twitter':
483
+                $accountData[AccountManager::PROPERTY_TWITTER]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
484
+                $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):');
485
+                $code = $codeMd5;
486
+                $type = AccountManager::PROPERTY_TWITTER;
487
+                $data = $accountData[AccountManager::PROPERTY_TWITTER]['value'];
488
+                $accountData[AccountManager::PROPERTY_TWITTER]['signature'] = $signature;
489
+                break;
490
+            case 'verify-website':
491
+                $accountData[AccountManager::PROPERTY_WEBSITE]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
492
+                $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):');
493
+                $type = AccountManager::PROPERTY_WEBSITE;
494
+                $data = $accountData[AccountManager::PROPERTY_WEBSITE]['value'];
495
+                $accountData[AccountManager::PROPERTY_WEBSITE]['signature'] = $signature;
496
+                break;
497
+            default:
498
+                return new DataResponse([], Http::STATUS_BAD_REQUEST);
499
+        }
500
+
501
+        if ($onlyVerificationCode === false) {
502
+            $this->accountManager->updateUser($user, $accountData);
503
+
504
+            $this->jobList->add(VerifyUserData::class,
505
+                [
506
+                    'verificationCode' => $code,
507
+                    'data' => $data,
508
+                    'type' => $type,
509
+                    'uid' => $user->getUID(),
510
+                    'try' => 0,
511
+                    'lastRun' => $this->getCurrentTime()
512
+                ]
513
+            );
514
+        }
515
+
516
+        return new DataResponse(['msg' => $msg, 'code' => $code]);
517
+    }
518
+
519
+    /**
520
+     * get current timestamp
521
+     *
522
+     * @return int
523
+     */
524
+    protected function getCurrentTime(): int {
525
+        return time();
526
+    }
527
+
528
+    /**
529
+     * sign message with users private key
530
+     *
531
+     * @param IUser $user
532
+     * @param string $message
533
+     *
534
+     * @return string base64 encoded signature
535
+     */
536
+    protected function signMessage(IUser $user, string $message): string {
537
+        $privateKey = $this->keyManager->getKey($user)->getPrivate();
538
+        openssl_sign(json_encode($message), $signature, $privateKey, OPENSSL_ALGO_SHA512);
539
+        return base64_encode($signature);
540
+    }
541 541
 }
Please login to merge, or discard this patch.
apps/settings/lib/Controller/ChangePasswordController.php 1 patch
Indentation   +212 added lines, -212 removed lines patch added patch discarded remove patch
@@ -50,234 +50,234 @@
 block discarded – undo
50 50
 
51 51
 class ChangePasswordController extends Controller {
52 52
 
53
-	/** @var string */
54
-	private $userId;
53
+    /** @var string */
54
+    private $userId;
55 55
 
56
-	/** @var IUserManager */
57
-	private $userManager;
56
+    /** @var IUserManager */
57
+    private $userManager;
58 58
 
59
-	/** @var IL10N */
60
-	private $l;
59
+    /** @var IL10N */
60
+    private $l;
61 61
 
62
-	/** @var GroupManager */
63
-	private $groupManager;
62
+    /** @var GroupManager */
63
+    private $groupManager;
64 64
 
65
-	/** @var Session */
66
-	private $userSession;
65
+    /** @var Session */
66
+    private $userSession;
67 67
 
68
-	/** @var IAppManager */
69
-	private $appManager;
68
+    /** @var IAppManager */
69
+    private $appManager;
70 70
 
71
-	public function __construct(string $appName,
72
-								IRequest $request,
73
-								string $userId,
74
-								IUserManager $userManager,
75
-								IUserSession $userSession,
76
-								IGroupManager $groupManager,
77
-								IAppManager $appManager,
78
-								IL10N $l) {
79
-		parent::__construct($appName, $request);
71
+    public function __construct(string $appName,
72
+                                IRequest $request,
73
+                                string $userId,
74
+                                IUserManager $userManager,
75
+                                IUserSession $userSession,
76
+                                IGroupManager $groupManager,
77
+                                IAppManager $appManager,
78
+                                IL10N $l) {
79
+        parent::__construct($appName, $request);
80 80
 
81
-		$this->userId = $userId;
82
-		$this->userManager = $userManager;
83
-		$this->userSession = $userSession;
84
-		$this->groupManager = $groupManager;
85
-		$this->appManager = $appManager;
86
-		$this->l = $l;
87
-	}
81
+        $this->userId = $userId;
82
+        $this->userManager = $userManager;
83
+        $this->userSession = $userSession;
84
+        $this->groupManager = $groupManager;
85
+        $this->appManager = $appManager;
86
+        $this->l = $l;
87
+    }
88 88
 
89
-	/**
90
-	 * @NoAdminRequired
91
-	 * @NoSubAdminRequired
92
-	 * @BruteForceProtection(action=changePersonalPassword)
93
-	 */
94
-	public function changePersonalPassword(string $oldpassword = '', string $newpassword = null): JSONResponse {
95
-		$loginName = $this->userSession->getLoginName();
96
-		/** @var IUser $user */
97
-		$user = $this->userManager->checkPassword($loginName, $oldpassword);
98
-		if ($user === false) {
99
-			$response = new JSONResponse([
100
-				'status' => 'error',
101
-				'data' => [
102
-					'message' => $this->l->t('Wrong password'),
103
-				],
104
-			]);
105
-			$response->throttle();
106
-			return $response;
107
-		}
89
+    /**
90
+     * @NoAdminRequired
91
+     * @NoSubAdminRequired
92
+     * @BruteForceProtection(action=changePersonalPassword)
93
+     */
94
+    public function changePersonalPassword(string $oldpassword = '', string $newpassword = null): JSONResponse {
95
+        $loginName = $this->userSession->getLoginName();
96
+        /** @var IUser $user */
97
+        $user = $this->userManager->checkPassword($loginName, $oldpassword);
98
+        if ($user === false) {
99
+            $response = new JSONResponse([
100
+                'status' => 'error',
101
+                'data' => [
102
+                    'message' => $this->l->t('Wrong password'),
103
+                ],
104
+            ]);
105
+            $response->throttle();
106
+            return $response;
107
+        }
108 108
 
109
-		try {
110
-			if ($newpassword === null || $user->setPassword($newpassword) === false) {
111
-				return new JSONResponse([
112
-					'status' => 'error'
113
-				]);
114
-			}
115
-			// password policy app throws exception
116
-		} catch (HintException $e) {
117
-			return new JSONResponse([
118
-				'status' => 'error',
119
-				'data' => [
120
-					'message' => $e->getHint(),
121
-				],
122
-			]);
123
-		}
109
+        try {
110
+            if ($newpassword === null || $user->setPassword($newpassword) === false) {
111
+                return new JSONResponse([
112
+                    'status' => 'error'
113
+                ]);
114
+            }
115
+            // password policy app throws exception
116
+        } catch (HintException $e) {
117
+            return new JSONResponse([
118
+                'status' => 'error',
119
+                'data' => [
120
+                    'message' => $e->getHint(),
121
+                ],
122
+            ]);
123
+        }
124 124
 
125
-		$this->userSession->updateSessionTokenPassword($newpassword);
125
+        $this->userSession->updateSessionTokenPassword($newpassword);
126 126
 
127
-		return new JSONResponse([
128
-			'status' => 'success',
129
-			'data' => [
130
-				'message' => $this->l->t('Saved'),
131
-			],
132
-		]);
133
-	}
127
+        return new JSONResponse([
128
+            'status' => 'success',
129
+            'data' => [
130
+                'message' => $this->l->t('Saved'),
131
+            ],
132
+        ]);
133
+    }
134 134
 
135
-	/**
136
-	 * @NoAdminRequired
137
-	 * @PasswordConfirmationRequired
138
-	 */
139
-	public function changeUserPassword(string $username = null, string $password = null, string $recoveryPassword = null): JSONResponse {
140
-		if ($username === null) {
141
-			return new JSONResponse([
142
-				'status' => 'error',
143
-				'data' => [
144
-					'message' => $this->l->t('No user supplied'),
145
-				],
146
-			]);
147
-		}
135
+    /**
136
+     * @NoAdminRequired
137
+     * @PasswordConfirmationRequired
138
+     */
139
+    public function changeUserPassword(string $username = null, string $password = null, string $recoveryPassword = null): JSONResponse {
140
+        if ($username === null) {
141
+            return new JSONResponse([
142
+                'status' => 'error',
143
+                'data' => [
144
+                    'message' => $this->l->t('No user supplied'),
145
+                ],
146
+            ]);
147
+        }
148 148
 
149
-		if ($password === null) {
150
-			return new JSONResponse([
151
-				'status' => 'error',
152
-				'data' => [
153
-					'message' => $this->l->t('Unable to change password'),
154
-				],
155
-			]);
156
-		}
149
+        if ($password === null) {
150
+            return new JSONResponse([
151
+                'status' => 'error',
152
+                'data' => [
153
+                    'message' => $this->l->t('Unable to change password'),
154
+                ],
155
+            ]);
156
+        }
157 157
 
158
-		$currentUser = $this->userSession->getUser();
159
-		$targetUser = $this->userManager->get($username);
160
-		if ($currentUser === null || $targetUser === null ||
161
-			!($this->groupManager->isAdmin($this->userId) ||
162
-			 $this->groupManager->getSubAdmin()->isUserAccessible($currentUser, $targetUser))
163
-		) {
164
-			return new JSONResponse([
165
-				'status' => 'error',
166
-				'data' => [
167
-					'message' => $this->l->t('Authentication error'),
168
-				],
169
-			]);
170
-		}
158
+        $currentUser = $this->userSession->getUser();
159
+        $targetUser = $this->userManager->get($username);
160
+        if ($currentUser === null || $targetUser === null ||
161
+            !($this->groupManager->isAdmin($this->userId) ||
162
+             $this->groupManager->getSubAdmin()->isUserAccessible($currentUser, $targetUser))
163
+        ) {
164
+            return new JSONResponse([
165
+                'status' => 'error',
166
+                'data' => [
167
+                    'message' => $this->l->t('Authentication error'),
168
+                ],
169
+            ]);
170
+        }
171 171
 
172
-		if ($this->appManager->isEnabledForUser('encryption')) {
173
-			//handle the recovery case
174
-			$crypt = new \OCA\Encryption\Crypto\Crypt(
175
-				\OC::$server->getLogger(),
176
-				\OC::$server->getUserSession(),
177
-				\OC::$server->getConfig(),
178
-				\OC::$server->getL10N('encryption'));
179
-			$keyStorage = \OC::$server->getEncryptionKeyStorage();
180
-			$util = new \OCA\Encryption\Util(
181
-				new \OC\Files\View(),
182
-				$crypt,
183
-				\OC::$server->getLogger(),
184
-				\OC::$server->getUserSession(),
185
-				\OC::$server->getConfig(),
186
-				\OC::$server->getUserManager());
187
-			$keyManager = new \OCA\Encryption\KeyManager(
188
-				$keyStorage,
189
-				$crypt,
190
-				\OC::$server->getConfig(),
191
-				\OC::$server->getUserSession(),
192
-				new \OCA\Encryption\Session(\OC::$server->getSession()),
193
-				\OC::$server->getLogger(),
194
-				$util,
195
-				\OC::$server->getLockingProvider()
196
-			);
197
-			$recovery = new \OCA\Encryption\Recovery(
198
-				\OC::$server->getUserSession(),
199
-				$crypt,
200
-				$keyManager,
201
-				\OC::$server->getConfig(),
202
-				\OC::$server->getEncryptionFilesHelper(),
203
-				new \OC\Files\View());
204
-			$recoveryAdminEnabled = $recovery->isRecoveryKeyEnabled();
172
+        if ($this->appManager->isEnabledForUser('encryption')) {
173
+            //handle the recovery case
174
+            $crypt = new \OCA\Encryption\Crypto\Crypt(
175
+                \OC::$server->getLogger(),
176
+                \OC::$server->getUserSession(),
177
+                \OC::$server->getConfig(),
178
+                \OC::$server->getL10N('encryption'));
179
+            $keyStorage = \OC::$server->getEncryptionKeyStorage();
180
+            $util = new \OCA\Encryption\Util(
181
+                new \OC\Files\View(),
182
+                $crypt,
183
+                \OC::$server->getLogger(),
184
+                \OC::$server->getUserSession(),
185
+                \OC::$server->getConfig(),
186
+                \OC::$server->getUserManager());
187
+            $keyManager = new \OCA\Encryption\KeyManager(
188
+                $keyStorage,
189
+                $crypt,
190
+                \OC::$server->getConfig(),
191
+                \OC::$server->getUserSession(),
192
+                new \OCA\Encryption\Session(\OC::$server->getSession()),
193
+                \OC::$server->getLogger(),
194
+                $util,
195
+                \OC::$server->getLockingProvider()
196
+            );
197
+            $recovery = new \OCA\Encryption\Recovery(
198
+                \OC::$server->getUserSession(),
199
+                $crypt,
200
+                $keyManager,
201
+                \OC::$server->getConfig(),
202
+                \OC::$server->getEncryptionFilesHelper(),
203
+                new \OC\Files\View());
204
+            $recoveryAdminEnabled = $recovery->isRecoveryKeyEnabled();
205 205
 
206
-			$validRecoveryPassword = false;
207
-			$recoveryEnabledForUser = false;
208
-			if ($recoveryAdminEnabled) {
209
-				$validRecoveryPassword = $keyManager->checkRecoveryPassword($recoveryPassword);
210
-				$recoveryEnabledForUser = $recovery->isRecoveryEnabledForUser($username);
211
-			}
206
+            $validRecoveryPassword = false;
207
+            $recoveryEnabledForUser = false;
208
+            if ($recoveryAdminEnabled) {
209
+                $validRecoveryPassword = $keyManager->checkRecoveryPassword($recoveryPassword);
210
+                $recoveryEnabledForUser = $recovery->isRecoveryEnabledForUser($username);
211
+            }
212 212
 
213
-			if ($recoveryEnabledForUser && $recoveryPassword === '') {
214
-				return new JSONResponse([
215
-					'status' => 'error',
216
-					'data' => [
217
-						'message' => $this->l->t('Please provide an admin recovery password; otherwise, all user data will be lost.'),
218
-					]
219
-				]);
220
-			} elseif ($recoveryEnabledForUser && ! $validRecoveryPassword) {
221
-				return new JSONResponse([
222
-					'status' => 'error',
223
-					'data' => [
224
-						'message' => $this->l->t('Wrong admin recovery password. Please check the password and try again.'),
225
-					]
226
-				]);
227
-			} else { // now we know that everything is fine regarding the recovery password, let's try to change the password
228
-				try {
229
-					$result = $targetUser->setPassword($password, $recoveryPassword);
230
-					// password policy app throws exception
231
-				} catch (HintException $e) {
232
-					return new JSONResponse([
233
-						'status' => 'error',
234
-						'data' => [
235
-							'message' => $e->getHint(),
236
-						],
237
-					]);
238
-				}
239
-				if (!$result && $recoveryEnabledForUser) {
240
-					return new JSONResponse([
241
-						'status' => 'error',
242
-						'data' => [
243
-							'message' => $this->l->t('Backend doesn\'t support password change, but the user\'s encryption key was updated.'),
244
-						]
245
-					]);
246
-				} elseif (!$result && !$recoveryEnabledForUser) {
247
-					return new JSONResponse([
248
-						'status' => 'error',
249
-						'data' => [
250
-							'message' => $this->l->t('Unable to change password'),
251
-						]
252
-					]);
253
-				}
254
-			}
255
-		} else {
256
-			try {
257
-				if ($targetUser->setPassword($password) === false) {
258
-					return new JSONResponse([
259
-						'status' => 'error',
260
-						'data' => [
261
-							'message' => $this->l->t('Unable to change password'),
262
-						],
263
-					]);
264
-				}
265
-				// password policy app throws exception
266
-			} catch (HintException $e) {
267
-				return new JSONResponse([
268
-					'status' => 'error',
269
-					'data' => [
270
-						'message' => $e->getHint(),
271
-					],
272
-				]);
273
-			}
274
-		}
213
+            if ($recoveryEnabledForUser && $recoveryPassword === '') {
214
+                return new JSONResponse([
215
+                    'status' => 'error',
216
+                    'data' => [
217
+                        'message' => $this->l->t('Please provide an admin recovery password; otherwise, all user data will be lost.'),
218
+                    ]
219
+                ]);
220
+            } elseif ($recoveryEnabledForUser && ! $validRecoveryPassword) {
221
+                return new JSONResponse([
222
+                    'status' => 'error',
223
+                    'data' => [
224
+                        'message' => $this->l->t('Wrong admin recovery password. Please check the password and try again.'),
225
+                    ]
226
+                ]);
227
+            } else { // now we know that everything is fine regarding the recovery password, let's try to change the password
228
+                try {
229
+                    $result = $targetUser->setPassword($password, $recoveryPassword);
230
+                    // password policy app throws exception
231
+                } catch (HintException $e) {
232
+                    return new JSONResponse([
233
+                        'status' => 'error',
234
+                        'data' => [
235
+                            'message' => $e->getHint(),
236
+                        ],
237
+                    ]);
238
+                }
239
+                if (!$result && $recoveryEnabledForUser) {
240
+                    return new JSONResponse([
241
+                        'status' => 'error',
242
+                        'data' => [
243
+                            'message' => $this->l->t('Backend doesn\'t support password change, but the user\'s encryption key was updated.'),
244
+                        ]
245
+                    ]);
246
+                } elseif (!$result && !$recoveryEnabledForUser) {
247
+                    return new JSONResponse([
248
+                        'status' => 'error',
249
+                        'data' => [
250
+                            'message' => $this->l->t('Unable to change password'),
251
+                        ]
252
+                    ]);
253
+                }
254
+            }
255
+        } else {
256
+            try {
257
+                if ($targetUser->setPassword($password) === false) {
258
+                    return new JSONResponse([
259
+                        'status' => 'error',
260
+                        'data' => [
261
+                            'message' => $this->l->t('Unable to change password'),
262
+                        ],
263
+                    ]);
264
+                }
265
+                // password policy app throws exception
266
+            } catch (HintException $e) {
267
+                return new JSONResponse([
268
+                    'status' => 'error',
269
+                    'data' => [
270
+                        'message' => $e->getHint(),
271
+                    ],
272
+                ]);
273
+            }
274
+        }
275 275
 
276
-		return new JSONResponse([
277
-			'status' => 'success',
278
-			'data' => [
279
-				'username' => $username,
280
-			],
281
-		]);
282
-	}
276
+        return new JSONResponse([
277
+            'status' => 'success',
278
+            'data' => [
279
+                'username' => $username,
280
+            ],
281
+        ]);
282
+    }
283 283
 }
Please login to merge, or discard this patch.
apps/admin_audit/lib/AppInfo/Application.php 1 patch
Indentation   +205 added lines, -205 removed lines patch added patch discarded remove patch
@@ -69,216 +69,216 @@
 block discarded – undo
69 69
 
70 70
 class Application extends App implements IBootstrap {
71 71
 
72
-	/** @var ILogger */
73
-	protected $logger;
72
+    /** @var ILogger */
73
+    protected $logger;
74 74
 
75
-	public function __construct() {
76
-		parent::__construct('admin_audit');
77
-	}
75
+    public function __construct() {
76
+        parent::__construct('admin_audit');
77
+    }
78 78
 
79
-	public function register(IRegistrationContext $context): void {
80
-	}
79
+    public function register(IRegistrationContext $context): void {
80
+    }
81 81
 
82
-	public function boot(IBootContext $context): void {
83
-		/** @var ILogger $logger */
84
-		$logger = $context->injectFn(
85
-			Closure::fromCallable([$this, 'getLogger'])
86
-		);
82
+    public function boot(IBootContext $context): void {
83
+        /** @var ILogger $logger */
84
+        $logger = $context->injectFn(
85
+            Closure::fromCallable([$this, 'getLogger'])
86
+        );
87 87
 
88
-		/*
88
+        /*
89 89
 		 * TODO: once the hooks are migrated to lazy events, this should be done
90 90
 		 *       in \OCA\AdminAudit\AppInfo\Application::register
91 91
 		 */
92
-		$this->registerHooks($logger, $context->getServerContainer());
93
-	}
94
-
95
-	private function getLogger(IConfig $config,
96
-							   ILogger $logger,
97
-							   ILogFactory $logFactory): ILogger {
98
-		$default = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/audit.log';
99
-		$logFile = $config->getAppValue('admin_audit', 'logfile', $default);
100
-
101
-		if ($logFile === null) {
102
-			return $logger;
103
-		}
104
-		return $logFactory->getCustomLogger($logFile);
105
-	}
106
-
107
-	/**
108
-	 * Register hooks in order to log them
109
-	 */
110
-	private function registerHooks(ILogger $logger,
111
-									 IServerContainer $serverContainer) {
112
-		$this->userManagementHooks($logger, $serverContainer->get(IUserSession::class));
113
-		$this->groupHooks($logger, $serverContainer->get(IGroupManager::class));
114
-		$this->authHooks($logger);
115
-
116
-		/** @var EventDispatcherInterface $eventDispatcher */
117
-		$eventDispatcher = $serverContainer->get(EventDispatcherInterface::class);
118
-		$this->consoleHooks($logger, $eventDispatcher);
119
-		$this->appHooks($logger, $eventDispatcher);
120
-
121
-		$this->sharingHooks($logger);
122
-
123
-		$this->fileHooks($logger, $eventDispatcher);
124
-		$this->trashbinHooks($logger);
125
-		$this->versionsHooks($logger);
126
-
127
-		$this->securityHooks($logger, $eventDispatcher);
128
-	}
129
-
130
-	private function userManagementHooks(ILogger $logger,
131
-										 IUserSession $userSession) {
132
-		$userActions = new UserManagement($logger);
133
-
134
-		Util::connectHook('OC_User', 'post_createUser', $userActions, 'create');
135
-		Util::connectHook('OC_User', 'post_deleteUser', $userActions, 'delete');
136
-		Util::connectHook('OC_User', 'changeUser', $userActions, 'change');
137
-
138
-		assert($userSession instanceof UserSession);
139
-		$userSession->listen('\OC\User', 'postSetPassword', [$userActions, 'setPassword']);
140
-		$userSession->listen('\OC\User', 'assignedUserId', [$userActions, 'assign']);
141
-		$userSession->listen('\OC\User', 'postUnassignedUserId', [$userActions, 'unassign']);
142
-	}
143
-
144
-	private function groupHooks(ILogger $logger,
145
-								IGroupManager $groupManager) {
146
-		$groupActions = new GroupManagement($logger);
147
-
148
-		assert($groupManager instanceof GroupManager);
149
-		$groupManager->listen('\OC\Group', 'postRemoveUser', [$groupActions, 'removeUser']);
150
-		$groupManager->listen('\OC\Group', 'postAddUser', [$groupActions, 'addUser']);
151
-		$groupManager->listen('\OC\Group', 'postDelete', [$groupActions, 'deleteGroup']);
152
-		$groupManager->listen('\OC\Group', 'postCreate', [$groupActions, 'createGroup']);
153
-	}
154
-
155
-	private function sharingHooks(ILogger $logger) {
156
-		$shareActions = new Sharing($logger);
157
-
158
-		Util::connectHook(Share::class, 'post_shared', $shareActions, 'shared');
159
-		Util::connectHook(Share::class, 'post_unshare', $shareActions, 'unshare');
160
-		Util::connectHook(Share::class, 'post_unshareFromSelf', $shareActions, 'unshare');
161
-		Util::connectHook(Share::class, 'post_update_permissions', $shareActions, 'updatePermissions');
162
-		Util::connectHook(Share::class, 'post_update_password', $shareActions, 'updatePassword');
163
-		Util::connectHook(Share::class, 'post_set_expiration_date', $shareActions, 'updateExpirationDate');
164
-		Util::connectHook(Share::class, 'share_link_access', $shareActions, 'shareAccessed');
165
-	}
166
-
167
-	private function authHooks(ILogger $logger) {
168
-		$authActions = new Auth($logger);
169
-
170
-		Util::connectHook('OC_User', 'pre_login', $authActions, 'loginAttempt');
171
-		Util::connectHook('OC_User', 'post_login', $authActions, 'loginSuccessful');
172
-		Util::connectHook('OC_User', 'logout', $authActions, 'logout');
173
-	}
174
-
175
-	private function appHooks(ILogger $logger,
176
-							  EventDispatcherInterface $eventDispatcher) {
177
-		$eventDispatcher->addListener(ManagerEvent::EVENT_APP_ENABLE, function (ManagerEvent $event) use ($logger) {
178
-			$appActions = new AppManagement($logger);
179
-			$appActions->enableApp($event->getAppID());
180
-		});
181
-		$eventDispatcher->addListener(ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, function (ManagerEvent $event) use ($logger) {
182
-			$appActions = new AppManagement($logger);
183
-			$appActions->enableAppForGroups($event->getAppID(), $event->getGroups());
184
-		});
185
-		$eventDispatcher->addListener(ManagerEvent::EVENT_APP_DISABLE, function (ManagerEvent $event) use ($logger) {
186
-			$appActions = new AppManagement($logger);
187
-			$appActions->disableApp($event->getAppID());
188
-		});
189
-	}
190
-
191
-	private function consoleHooks(ILogger $logger,
192
-								  EventDispatcherInterface $eventDispatcher) {
193
-		$eventDispatcher->addListener(ConsoleEvent::EVENT_RUN, function (ConsoleEvent $event) use ($logger) {
194
-			$appActions = new Console($logger);
195
-			$appActions->runCommand($event->getArguments());
196
-		});
197
-	}
198
-
199
-	private function fileHooks(ILogger $logger,
200
-							   EventDispatcherInterface $eventDispatcher) {
201
-		$fileActions = new Files($logger);
202
-		$eventDispatcher->addListener(
203
-			IPreview::EVENT,
204
-			function (GenericEvent $event) use ($fileActions) {
205
-				/** @var File $file */
206
-				$file = $event->getSubject();
207
-				$fileActions->preview([
208
-					'path' => mb_substr($file->getInternalPath(), 5),
209
-					'width' => $event->getArguments()['width'],
210
-					'height' => $event->getArguments()['height'],
211
-					'crop' => $event->getArguments()['crop'],
212
-					'mode' => $event->getArguments()['mode']
213
-				]);
214
-			}
215
-		);
216
-
217
-		Util::connectHook(
218
-			Filesystem::CLASSNAME,
219
-			Filesystem::signal_post_rename,
220
-			$fileActions,
221
-			'rename'
222
-		);
223
-		Util::connectHook(
224
-			Filesystem::CLASSNAME,
225
-			Filesystem::signal_post_create,
226
-			$fileActions,
227
-			'create'
228
-		);
229
-		Util::connectHook(
230
-			Filesystem::CLASSNAME,
231
-			Filesystem::signal_post_copy,
232
-			$fileActions,
233
-			'copy'
234
-		);
235
-		Util::connectHook(
236
-			Filesystem::CLASSNAME,
237
-			Filesystem::signal_post_write,
238
-			$fileActions,
239
-			'write'
240
-		);
241
-		Util::connectHook(
242
-			Filesystem::CLASSNAME,
243
-			Filesystem::signal_post_update,
244
-			$fileActions,
245
-			'update'
246
-		);
247
-		Util::connectHook(
248
-			Filesystem::CLASSNAME,
249
-			Filesystem::signal_read,
250
-			$fileActions,
251
-			'read'
252
-		);
253
-		Util::connectHook(
254
-			Filesystem::CLASSNAME,
255
-			Filesystem::signal_delete,
256
-			$fileActions,
257
-			'delete'
258
-		);
259
-	}
260
-
261
-	private function versionsHooks(ILogger $logger) {
262
-		$versionsActions = new Versions($logger);
263
-		Util::connectHook('\OCP\Versions', 'rollback', $versionsActions, 'rollback');
264
-		Util::connectHook('\OCP\Versions', 'delete', $versionsActions, 'delete');
265
-	}
266
-
267
-	private function trashbinHooks(ILogger $logger) {
268
-		$trashActions = new Trashbin($logger);
269
-		Util::connectHook('\OCP\Trashbin', 'preDelete', $trashActions, 'delete');
270
-		Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', $trashActions, 'restore');
271
-	}
272
-
273
-	private function securityHooks(ILogger $logger,
274
-								   EventDispatcherInterface $eventDispatcher) {
275
-		$eventDispatcher->addListener(IProvider::EVENT_SUCCESS, function (GenericEvent $event) use ($logger) {
276
-			$security = new Security($logger);
277
-			$security->twofactorSuccess($event->getSubject(), $event->getArguments());
278
-		});
279
-		$eventDispatcher->addListener(IProvider::EVENT_FAILED, function (GenericEvent $event) use ($logger) {
280
-			$security = new Security($logger);
281
-			$security->twofactorFailed($event->getSubject(), $event->getArguments());
282
-		});
283
-	}
92
+        $this->registerHooks($logger, $context->getServerContainer());
93
+    }
94
+
95
+    private function getLogger(IConfig $config,
96
+                                ILogger $logger,
97
+                                ILogFactory $logFactory): ILogger {
98
+        $default = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/audit.log';
99
+        $logFile = $config->getAppValue('admin_audit', 'logfile', $default);
100
+
101
+        if ($logFile === null) {
102
+            return $logger;
103
+        }
104
+        return $logFactory->getCustomLogger($logFile);
105
+    }
106
+
107
+    /**
108
+     * Register hooks in order to log them
109
+     */
110
+    private function registerHooks(ILogger $logger,
111
+                                        IServerContainer $serverContainer) {
112
+        $this->userManagementHooks($logger, $serverContainer->get(IUserSession::class));
113
+        $this->groupHooks($logger, $serverContainer->get(IGroupManager::class));
114
+        $this->authHooks($logger);
115
+
116
+        /** @var EventDispatcherInterface $eventDispatcher */
117
+        $eventDispatcher = $serverContainer->get(EventDispatcherInterface::class);
118
+        $this->consoleHooks($logger, $eventDispatcher);
119
+        $this->appHooks($logger, $eventDispatcher);
120
+
121
+        $this->sharingHooks($logger);
122
+
123
+        $this->fileHooks($logger, $eventDispatcher);
124
+        $this->trashbinHooks($logger);
125
+        $this->versionsHooks($logger);
126
+
127
+        $this->securityHooks($logger, $eventDispatcher);
128
+    }
129
+
130
+    private function userManagementHooks(ILogger $logger,
131
+                                            IUserSession $userSession) {
132
+        $userActions = new UserManagement($logger);
133
+
134
+        Util::connectHook('OC_User', 'post_createUser', $userActions, 'create');
135
+        Util::connectHook('OC_User', 'post_deleteUser', $userActions, 'delete');
136
+        Util::connectHook('OC_User', 'changeUser', $userActions, 'change');
137
+
138
+        assert($userSession instanceof UserSession);
139
+        $userSession->listen('\OC\User', 'postSetPassword', [$userActions, 'setPassword']);
140
+        $userSession->listen('\OC\User', 'assignedUserId', [$userActions, 'assign']);
141
+        $userSession->listen('\OC\User', 'postUnassignedUserId', [$userActions, 'unassign']);
142
+    }
143
+
144
+    private function groupHooks(ILogger $logger,
145
+                                IGroupManager $groupManager) {
146
+        $groupActions = new GroupManagement($logger);
147
+
148
+        assert($groupManager instanceof GroupManager);
149
+        $groupManager->listen('\OC\Group', 'postRemoveUser', [$groupActions, 'removeUser']);
150
+        $groupManager->listen('\OC\Group', 'postAddUser', [$groupActions, 'addUser']);
151
+        $groupManager->listen('\OC\Group', 'postDelete', [$groupActions, 'deleteGroup']);
152
+        $groupManager->listen('\OC\Group', 'postCreate', [$groupActions, 'createGroup']);
153
+    }
154
+
155
+    private function sharingHooks(ILogger $logger) {
156
+        $shareActions = new Sharing($logger);
157
+
158
+        Util::connectHook(Share::class, 'post_shared', $shareActions, 'shared');
159
+        Util::connectHook(Share::class, 'post_unshare', $shareActions, 'unshare');
160
+        Util::connectHook(Share::class, 'post_unshareFromSelf', $shareActions, 'unshare');
161
+        Util::connectHook(Share::class, 'post_update_permissions', $shareActions, 'updatePermissions');
162
+        Util::connectHook(Share::class, 'post_update_password', $shareActions, 'updatePassword');
163
+        Util::connectHook(Share::class, 'post_set_expiration_date', $shareActions, 'updateExpirationDate');
164
+        Util::connectHook(Share::class, 'share_link_access', $shareActions, 'shareAccessed');
165
+    }
166
+
167
+    private function authHooks(ILogger $logger) {
168
+        $authActions = new Auth($logger);
169
+
170
+        Util::connectHook('OC_User', 'pre_login', $authActions, 'loginAttempt');
171
+        Util::connectHook('OC_User', 'post_login', $authActions, 'loginSuccessful');
172
+        Util::connectHook('OC_User', 'logout', $authActions, 'logout');
173
+    }
174
+
175
+    private function appHooks(ILogger $logger,
176
+                                EventDispatcherInterface $eventDispatcher) {
177
+        $eventDispatcher->addListener(ManagerEvent::EVENT_APP_ENABLE, function (ManagerEvent $event) use ($logger) {
178
+            $appActions = new AppManagement($logger);
179
+            $appActions->enableApp($event->getAppID());
180
+        });
181
+        $eventDispatcher->addListener(ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, function (ManagerEvent $event) use ($logger) {
182
+            $appActions = new AppManagement($logger);
183
+            $appActions->enableAppForGroups($event->getAppID(), $event->getGroups());
184
+        });
185
+        $eventDispatcher->addListener(ManagerEvent::EVENT_APP_DISABLE, function (ManagerEvent $event) use ($logger) {
186
+            $appActions = new AppManagement($logger);
187
+            $appActions->disableApp($event->getAppID());
188
+        });
189
+    }
190
+
191
+    private function consoleHooks(ILogger $logger,
192
+                                    EventDispatcherInterface $eventDispatcher) {
193
+        $eventDispatcher->addListener(ConsoleEvent::EVENT_RUN, function (ConsoleEvent $event) use ($logger) {
194
+            $appActions = new Console($logger);
195
+            $appActions->runCommand($event->getArguments());
196
+        });
197
+    }
198
+
199
+    private function fileHooks(ILogger $logger,
200
+                                EventDispatcherInterface $eventDispatcher) {
201
+        $fileActions = new Files($logger);
202
+        $eventDispatcher->addListener(
203
+            IPreview::EVENT,
204
+            function (GenericEvent $event) use ($fileActions) {
205
+                /** @var File $file */
206
+                $file = $event->getSubject();
207
+                $fileActions->preview([
208
+                    'path' => mb_substr($file->getInternalPath(), 5),
209
+                    'width' => $event->getArguments()['width'],
210
+                    'height' => $event->getArguments()['height'],
211
+                    'crop' => $event->getArguments()['crop'],
212
+                    'mode' => $event->getArguments()['mode']
213
+                ]);
214
+            }
215
+        );
216
+
217
+        Util::connectHook(
218
+            Filesystem::CLASSNAME,
219
+            Filesystem::signal_post_rename,
220
+            $fileActions,
221
+            'rename'
222
+        );
223
+        Util::connectHook(
224
+            Filesystem::CLASSNAME,
225
+            Filesystem::signal_post_create,
226
+            $fileActions,
227
+            'create'
228
+        );
229
+        Util::connectHook(
230
+            Filesystem::CLASSNAME,
231
+            Filesystem::signal_post_copy,
232
+            $fileActions,
233
+            'copy'
234
+        );
235
+        Util::connectHook(
236
+            Filesystem::CLASSNAME,
237
+            Filesystem::signal_post_write,
238
+            $fileActions,
239
+            'write'
240
+        );
241
+        Util::connectHook(
242
+            Filesystem::CLASSNAME,
243
+            Filesystem::signal_post_update,
244
+            $fileActions,
245
+            'update'
246
+        );
247
+        Util::connectHook(
248
+            Filesystem::CLASSNAME,
249
+            Filesystem::signal_read,
250
+            $fileActions,
251
+            'read'
252
+        );
253
+        Util::connectHook(
254
+            Filesystem::CLASSNAME,
255
+            Filesystem::signal_delete,
256
+            $fileActions,
257
+            'delete'
258
+        );
259
+    }
260
+
261
+    private function versionsHooks(ILogger $logger) {
262
+        $versionsActions = new Versions($logger);
263
+        Util::connectHook('\OCP\Versions', 'rollback', $versionsActions, 'rollback');
264
+        Util::connectHook('\OCP\Versions', 'delete', $versionsActions, 'delete');
265
+    }
266
+
267
+    private function trashbinHooks(ILogger $logger) {
268
+        $trashActions = new Trashbin($logger);
269
+        Util::connectHook('\OCP\Trashbin', 'preDelete', $trashActions, 'delete');
270
+        Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', $trashActions, 'restore');
271
+    }
272
+
273
+    private function securityHooks(ILogger $logger,
274
+                                    EventDispatcherInterface $eventDispatcher) {
275
+        $eventDispatcher->addListener(IProvider::EVENT_SUCCESS, function (GenericEvent $event) use ($logger) {
276
+            $security = new Security($logger);
277
+            $security->twofactorSuccess($event->getSubject(), $event->getArguments());
278
+        });
279
+        $eventDispatcher->addListener(IProvider::EVENT_FAILED, function (GenericEvent $event) use ($logger) {
280
+            $security = new Security($logger);
281
+            $security->twofactorFailed($event->getSubject(), $event->getArguments());
282
+        });
283
+    }
284 284
 }
Please login to merge, or discard this patch.