Passed
Push — master ( 5b0dfd...1f7cb0 )
by Christoph
14:50 queued 01:19
created
core/Migrations/Version16000Date20190212081545.php 1 patch
Indentation   +66 added lines, -66 removed lines patch added patch discarded remove patch
@@ -34,72 +34,72 @@
 block discarded – undo
34 34
 use OCP\Migration\SimpleMigrationStep;
35 35
 
36 36
 class Version16000Date20190212081545 extends SimpleMigrationStep {
37
-	/**
38
-	 * @param IOutput $output
39
-	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
40
-	 * @param array $options
41
-	 *
42
-	 * @return ISchemaWrapper
43
-	 */
44
-	public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ISchemaWrapper {
45
-		/** @var ISchemaWrapper $schema */
46
-		$schema = $schemaClosure();
37
+    /**
38
+     * @param IOutput $output
39
+     * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
40
+     * @param array $options
41
+     *
42
+     * @return ISchemaWrapper
43
+     */
44
+    public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ISchemaWrapper {
45
+        /** @var ISchemaWrapper $schema */
46
+        $schema = $schemaClosure();
47 47
 
48
-		$table = $schema->createTable('login_flow_v2');
49
-		$table->addColumn('id', Type::BIGINT, [
50
-			'autoincrement' => true,
51
-			'notnull' => true,
52
-			'length' => 20,
53
-			'unsigned' => true,
54
-		]);
55
-		$table->addColumn('timestamp', Type::BIGINT, [
56
-			'notnull' => true,
57
-			'length' => 20,
58
-			'unsigned' => true,
59
-		]);
60
-		$table->addColumn('started', Type::SMALLINT, [
61
-			'notnull' => true,
62
-			'length' => 1,
63
-			'unsigned' => true,
64
-			'default' => 0,
65
-		]);
66
-		$table->addColumn('poll_token', Type::STRING, [
67
-			'notnull' => true,
68
-			'length' => 255,
69
-		]);
70
-		$table->addColumn('login_token', Type::STRING, [
71
-			'notnull' => true,
72
-			'length' => 255,
73
-		]);
74
-		$table->addColumn('public_key', Type::TEXT, [
75
-			'notnull' => true,
76
-			'length' => 32768,
77
-		]);
78
-		$table->addColumn('private_key', Type::TEXT, [
79
-			'notnull' => true,
80
-			'length' => 32768,
81
-		]);
82
-		$table->addColumn('client_name', Type::STRING, [
83
-			'notnull' => true,
84
-			'length' => 255,
85
-		]);
86
-		$table->addColumn('login_name', Type::STRING, [
87
-			'notnull' => false,
88
-			'length' => 255,
89
-		]);
90
-		$table->addColumn('server', Type::STRING, [
91
-			'notnull' => false,
92
-			'length' => 255,
93
-		]);
94
-		$table->addColumn('app_password', Type::STRING, [
95
-			'notnull' => false,
96
-			'length' => 1024,
97
-		]);
98
-		$table->setPrimaryKey(['id']);
99
-		$table->addUniqueIndex(['poll_token'], 'poll_token');
100
-		$table->addUniqueIndex(['login_token'], 'login_token');
101
-		$table->addIndex(['timestamp'], 'timestamp');
48
+        $table = $schema->createTable('login_flow_v2');
49
+        $table->addColumn('id', Type::BIGINT, [
50
+            'autoincrement' => true,
51
+            'notnull' => true,
52
+            'length' => 20,
53
+            'unsigned' => true,
54
+        ]);
55
+        $table->addColumn('timestamp', Type::BIGINT, [
56
+            'notnull' => true,
57
+            'length' => 20,
58
+            'unsigned' => true,
59
+        ]);
60
+        $table->addColumn('started', Type::SMALLINT, [
61
+            'notnull' => true,
62
+            'length' => 1,
63
+            'unsigned' => true,
64
+            'default' => 0,
65
+        ]);
66
+        $table->addColumn('poll_token', Type::STRING, [
67
+            'notnull' => true,
68
+            'length' => 255,
69
+        ]);
70
+        $table->addColumn('login_token', Type::STRING, [
71
+            'notnull' => true,
72
+            'length' => 255,
73
+        ]);
74
+        $table->addColumn('public_key', Type::TEXT, [
75
+            'notnull' => true,
76
+            'length' => 32768,
77
+        ]);
78
+        $table->addColumn('private_key', Type::TEXT, [
79
+            'notnull' => true,
80
+            'length' => 32768,
81
+        ]);
82
+        $table->addColumn('client_name', Type::STRING, [
83
+            'notnull' => true,
84
+            'length' => 255,
85
+        ]);
86
+        $table->addColumn('login_name', Type::STRING, [
87
+            'notnull' => false,
88
+            'length' => 255,
89
+        ]);
90
+        $table->addColumn('server', Type::STRING, [
91
+            'notnull' => false,
92
+            'length' => 255,
93
+        ]);
94
+        $table->addColumn('app_password', Type::STRING, [
95
+            'notnull' => false,
96
+            'length' => 1024,
97
+        ]);
98
+        $table->setPrimaryKey(['id']);
99
+        $table->addUniqueIndex(['poll_token'], 'poll_token');
100
+        $table->addUniqueIndex(['login_token'], 'login_token');
101
+        $table->addIndex(['timestamp'], 'timestamp');
102 102
 
103
-		return $schema;
104
-	}
103
+        return $schema;
104
+    }
105 105
 }
Please login to merge, or discard this patch.
apps/files_versions/lib/Versions/IVersionBackend.php 1 patch
Indentation   +55 added lines, -55 removed lines patch added patch discarded remove patch
@@ -37,64 +37,64 @@
 block discarded – undo
37 37
  * @since 15.0.0
38 38
  */
39 39
 interface IVersionBackend {
40
-	/**
41
-	 * Whether or not this version backend should be used for a storage
42
-	 *
43
-	 * If false is returned then the next applicable backend will be used
44
-	 *
45
-	 * @param IStorage $storage
46
-	 * @return bool
47
-	 * @since 17.0.0
48
-	 */
49
-	public function useBackendForStorage(IStorage $storage): bool;
40
+    /**
41
+     * Whether or not this version backend should be used for a storage
42
+     *
43
+     * If false is returned then the next applicable backend will be used
44
+     *
45
+     * @param IStorage $storage
46
+     * @return bool
47
+     * @since 17.0.0
48
+     */
49
+    public function useBackendForStorage(IStorage $storage): bool;
50 50
 
51
-	/**
52
-	 * Get all versions for a file
53
-	 *
54
-	 * @param IUser $user
55
-	 * @param FileInfo $file
56
-	 * @return IVersion[]
57
-	 * @since 15.0.0
58
-	 */
59
-	public function getVersionsForFile(IUser $user, FileInfo $file): array;
51
+    /**
52
+     * Get all versions for a file
53
+     *
54
+     * @param IUser $user
55
+     * @param FileInfo $file
56
+     * @return IVersion[]
57
+     * @since 15.0.0
58
+     */
59
+    public function getVersionsForFile(IUser $user, FileInfo $file): array;
60 60
 
61
-	/**
62
-	 * Create a new version for a file
63
-	 *
64
-	 * @param IUser $user
65
-	 * @param FileInfo $file
66
-	 * @since 15.0.0
67
-	 */
68
-	public function createVersion(IUser $user, FileInfo $file);
61
+    /**
62
+     * Create a new version for a file
63
+     *
64
+     * @param IUser $user
65
+     * @param FileInfo $file
66
+     * @since 15.0.0
67
+     */
68
+    public function createVersion(IUser $user, FileInfo $file);
69 69
 
70
-	/**
71
-	 * Restore this version
72
-	 *
73
-	 * @param IVersion $version
74
-	 * @since 15.0.0
75
-	 */
76
-	public function rollback(IVersion $version);
70
+    /**
71
+     * Restore this version
72
+     *
73
+     * @param IVersion $version
74
+     * @since 15.0.0
75
+     */
76
+    public function rollback(IVersion $version);
77 77
 
78
-	/**
79
-	 * Open the file for reading
80
-	 *
81
-	 * @param IVersion $version
82
-	 * @return resource
83
-	 * @throws NotFoundException
84
-	 * @since 15.0.0
85
-	 */
86
-	public function read(IVersion $version);
78
+    /**
79
+     * Open the file for reading
80
+     *
81
+     * @param IVersion $version
82
+     * @return resource
83
+     * @throws NotFoundException
84
+     * @since 15.0.0
85
+     */
86
+    public function read(IVersion $version);
87 87
 
88
-	/**
89
-	 * Get the preview for a specific version of a file
90
-	 *
91
-	 * @param IUser $user
92
-	 * @param FileInfo $sourceFile
93
-	 * @param int|string $revision
94
-	 *
95
-	 * @return File
96
-	 *
97
-	 * @since 15.0.0
98
-	 */
99
-	public function getVersionFile(IUser $user, FileInfo $sourceFile, $revision): File;
88
+    /**
89
+     * Get the preview for a specific version of a file
90
+     *
91
+     * @param IUser $user
92
+     * @param FileInfo $sourceFile
93
+     * @param int|string $revision
94
+     *
95
+     * @return File
96
+     *
97
+     * @since 15.0.0
98
+     */
99
+    public function getVersionFile(IUser $user, FileInfo $sourceFile, $revision): File;
100 100
 }
Please login to merge, or discard this patch.
lib/private/Authentication/TwoFactorAuth/EnforcementState.php 1 patch
Indentation   +45 added lines, -45 removed lines patch added patch discarded remove patch
@@ -30,57 +30,57 @@
 block discarded – undo
30 30
 
31 31
 class EnforcementState implements JsonSerializable {
32 32
 
33
-	/** @var bool */
34
-	private $enforced;
33
+    /** @var bool */
34
+    private $enforced;
35 35
 
36
-	/** @var array */
37
-	private $enforcedGroups;
36
+    /** @var array */
37
+    private $enforcedGroups;
38 38
 
39
-	/** @var array */
40
-	private $excludedGroups;
39
+    /** @var array */
40
+    private $excludedGroups;
41 41
 
42
-	/**
43
-	 * EnforcementState constructor.
44
-	 *
45
-	 * @param bool $enforced
46
-	 * @param string[] $enforcedGroups
47
-	 * @param string[] $excludedGroups
48
-	 */
49
-	public function __construct(bool $enforced,
50
-								array $enforcedGroups = [],
51
-								array $excludedGroups = []) {
52
-		$this->enforced = $enforced;
53
-		$this->enforcedGroups = $enforcedGroups;
54
-		$this->excludedGroups = $excludedGroups;
55
-	}
42
+    /**
43
+     * EnforcementState constructor.
44
+     *
45
+     * @param bool $enforced
46
+     * @param string[] $enforcedGroups
47
+     * @param string[] $excludedGroups
48
+     */
49
+    public function __construct(bool $enforced,
50
+                                array $enforcedGroups = [],
51
+                                array $excludedGroups = []) {
52
+        $this->enforced = $enforced;
53
+        $this->enforcedGroups = $enforcedGroups;
54
+        $this->excludedGroups = $excludedGroups;
55
+    }
56 56
 
57
-	/**
58
-	 * @return bool
59
-	 */
60
-	public function isEnforced(): bool {
61
-		return $this->enforced;
62
-	}
57
+    /**
58
+     * @return bool
59
+     */
60
+    public function isEnforced(): bool {
61
+        return $this->enforced;
62
+    }
63 63
 
64
-	/**
65
-	 * @return string[]
66
-	 */
67
-	public function getEnforcedGroups(): array {
68
-		return $this->enforcedGroups;
69
-	}
64
+    /**
65
+     * @return string[]
66
+     */
67
+    public function getEnforcedGroups(): array {
68
+        return $this->enforcedGroups;
69
+    }
70 70
 
71
-	/**
72
-	 * @return string[]
73
-	 */
74
-	public function getExcludedGroups(): array {
75
-		return $this->excludedGroups;
76
-	}
71
+    /**
72
+     * @return string[]
73
+     */
74
+    public function getExcludedGroups(): array {
75
+        return $this->excludedGroups;
76
+    }
77 77
 
78
-	public function jsonSerialize(): array {
79
-		return [
80
-			'enforced' => $this->enforced,
81
-			'enforcedGroups' => $this->enforcedGroups,
82
-			'excludedGroups' => $this->excludedGroups,
83
-		];
84
-	}
78
+    public function jsonSerialize(): array {
79
+        return [
80
+            'enforced' => $this->enforced,
81
+            'enforcedGroups' => $this->enforcedGroups,
82
+            'excludedGroups' => $this->excludedGroups,
83
+        ];
84
+    }
85 85
 
86 86
 }
Please login to merge, or discard this patch.
lib/private/User/Session.php 1 patch
Indentation   +917 added lines, -917 removed lines patch added patch discarded remove patch
@@ -90,923 +90,923 @@
 block discarded – undo
90 90
  */
91 91
 class Session implements IUserSession, Emitter {
92 92
 
93
-	/** @var Manager|PublicEmitter $manager */
94
-	private $manager;
95
-
96
-	/** @var ISession $session */
97
-	private $session;
98
-
99
-	/** @var ITimeFactory */
100
-	private $timeFactory;
101
-
102
-	/** @var IProvider */
103
-	private $tokenProvider;
104
-
105
-	/** @var IConfig */
106
-	private $config;
107
-
108
-	/** @var User $activeUser */
109
-	protected $activeUser;
110
-
111
-	/** @var ISecureRandom */
112
-	private $random;
113
-
114
-	/** @var ILockdownManager  */
115
-	private $lockdownManager;
116
-
117
-	/** @var ILogger */
118
-	private $logger;
119
-	/** @var IEventDispatcher */
120
-	private $dispatcher;
121
-
122
-	/**
123
-	 * @param Manager $manager
124
-	 * @param ISession $session
125
-	 * @param ITimeFactory $timeFactory
126
-	 * @param IProvider $tokenProvider
127
-	 * @param IConfig $config
128
-	 * @param ISecureRandom $random
129
-	 * @param ILockdownManager $lockdownManager
130
-	 * @param ILogger $logger
131
-	 */
132
-	public function __construct(Manager $manager,
133
-								ISession $session,
134
-								ITimeFactory $timeFactory,
135
-								$tokenProvider,
136
-								IConfig $config,
137
-								ISecureRandom $random,
138
-								ILockdownManager $lockdownManager,
139
-								ILogger $logger,
140
-								IEventDispatcher $dispatcher) {
141
-		$this->manager = $manager;
142
-		$this->session = $session;
143
-		$this->timeFactory = $timeFactory;
144
-		$this->tokenProvider = $tokenProvider;
145
-		$this->config = $config;
146
-		$this->random = $random;
147
-		$this->lockdownManager = $lockdownManager;
148
-		$this->logger = $logger;
149
-		$this->dispatcher = $dispatcher;
150
-	}
151
-
152
-	/**
153
-	 * @param IProvider $provider
154
-	 */
155
-	public function setTokenProvider(IProvider $provider) {
156
-		$this->tokenProvider = $provider;
157
-	}
158
-
159
-	/**
160
-	 * @param string $scope
161
-	 * @param string $method
162
-	 * @param callable $callback
163
-	 */
164
-	public function listen($scope, $method, callable $callback) {
165
-		$this->manager->listen($scope, $method, $callback);
166
-	}
167
-
168
-	/**
169
-	 * @param string $scope optional
170
-	 * @param string $method optional
171
-	 * @param callable $callback optional
172
-	 */
173
-	public function removeListener($scope = null, $method = null, callable $callback = null) {
174
-		$this->manager->removeListener($scope, $method, $callback);
175
-	}
176
-
177
-	/**
178
-	 * get the manager object
179
-	 *
180
-	 * @return Manager|PublicEmitter
181
-	 */
182
-	public function getManager() {
183
-		return $this->manager;
184
-	}
185
-
186
-	/**
187
-	 * get the session object
188
-	 *
189
-	 * @return ISession
190
-	 */
191
-	public function getSession() {
192
-		return $this->session;
193
-	}
194
-
195
-	/**
196
-	 * set the session object
197
-	 *
198
-	 * @param ISession $session
199
-	 */
200
-	public function setSession(ISession $session) {
201
-		if ($this->session instanceof ISession) {
202
-			$this->session->close();
203
-		}
204
-		$this->session = $session;
205
-		$this->activeUser = null;
206
-	}
207
-
208
-	/**
209
-	 * set the currently active user
210
-	 *
211
-	 * @param IUser|null $user
212
-	 */
213
-	public function setUser($user) {
214
-		if (is_null($user)) {
215
-			$this->session->remove('user_id');
216
-		} else {
217
-			$this->session->set('user_id', $user->getUID());
218
-		}
219
-		$this->activeUser = $user;
220
-	}
221
-
222
-	/**
223
-	 * get the current active user
224
-	 *
225
-	 * @return IUser|null Current user, otherwise null
226
-	 */
227
-	public function getUser() {
228
-		// FIXME: This is a quick'n dirty work-around for the incognito mode as
229
-		// described at https://github.com/owncloud/core/pull/12912#issuecomment-67391155
230
-		if (OC_User::isIncognitoMode()) {
231
-			return null;
232
-		}
233
-		if (is_null($this->activeUser)) {
234
-			$uid = $this->session->get('user_id');
235
-			if (is_null($uid)) {
236
-				return null;
237
-			}
238
-			$this->activeUser = $this->manager->get($uid);
239
-			if (is_null($this->activeUser)) {
240
-				return null;
241
-			}
242
-			$this->validateSession();
243
-		}
244
-		return $this->activeUser;
245
-	}
246
-
247
-	/**
248
-	 * Validate whether the current session is valid
249
-	 *
250
-	 * - For token-authenticated clients, the token validity is checked
251
-	 * - For browsers, the session token validity is checked
252
-	 */
253
-	protected function validateSession() {
254
-		$token = null;
255
-		$appPassword = $this->session->get('app_password');
256
-
257
-		if (is_null($appPassword)) {
258
-			try {
259
-				$token = $this->session->getId();
260
-			} catch (SessionNotAvailableException $ex) {
261
-				return;
262
-			}
263
-		} else {
264
-			$token = $appPassword;
265
-		}
266
-
267
-		if (!$this->validateToken($token)) {
268
-			// Session was invalidated
269
-			$this->logout();
270
-		}
271
-	}
272
-
273
-	/**
274
-	 * Checks whether the user is logged in
275
-	 *
276
-	 * @return bool if logged in
277
-	 */
278
-	public function isLoggedIn() {
279
-		$user = $this->getUser();
280
-		if (is_null($user)) {
281
-			return false;
282
-		}
283
-
284
-		return $user->isEnabled();
285
-	}
286
-
287
-	/**
288
-	 * set the login name
289
-	 *
290
-	 * @param string|null $loginName for the logged in user
291
-	 */
292
-	public function setLoginName($loginName) {
293
-		if (is_null($loginName)) {
294
-			$this->session->remove('loginname');
295
-		} else {
296
-			$this->session->set('loginname', $loginName);
297
-		}
298
-	}
299
-
300
-	/**
301
-	 * get the login name of the current user
302
-	 *
303
-	 * @return string
304
-	 */
305
-	public function getLoginName() {
306
-		if ($this->activeUser) {
307
-			return $this->session->get('loginname');
308
-		}
309
-
310
-		$uid = $this->session->get('user_id');
311
-		if ($uid) {
312
-			$this->activeUser = $this->manager->get($uid);
313
-			return $this->session->get('loginname');
314
-		}
315
-
316
-		return null;
317
-	}
318
-
319
-	/**
320
-	 * @return null|string
321
-	 */
322
-	public function getImpersonatingUserID(): ?string {
323
-
324
-		return $this->session->get('oldUserId');
325
-
326
-	}
327
-
328
-	public function setImpersonatingUserID(bool $useCurrentUser = true): void {
329
-		if ($useCurrentUser === false) {
330
-			$this->session->remove('oldUserId');
331
-			return;
332
-		}
333
-
334
-		$currentUser = $this->getUser();
335
-
336
-		if ($currentUser === null) {
337
-			throw new \OC\User\NoUserException();
338
-		}
339
-		$this->session->set('oldUserId', $currentUser->getUID());
340
-
341
-	}
342
-	/**
343
-	 * set the token id
344
-	 *
345
-	 * @param int|null $token that was used to log in
346
-	 */
347
-	protected function setToken($token) {
348
-		if ($token === null) {
349
-			$this->session->remove('token-id');
350
-		} else {
351
-			$this->session->set('token-id', $token);
352
-		}
353
-	}
354
-
355
-	/**
356
-	 * try to log in with the provided credentials
357
-	 *
358
-	 * @param string $uid
359
-	 * @param string $password
360
-	 * @return boolean|null
361
-	 * @throws LoginException
362
-	 */
363
-	public function login($uid, $password) {
364
-		$this->session->regenerateId();
365
-		if ($this->validateToken($password, $uid)) {
366
-			return $this->loginWithToken($password);
367
-		}
368
-		return $this->loginWithPassword($uid, $password);
369
-	}
370
-
371
-	/**
372
-	 * @param IUser $user
373
-	 * @param array $loginDetails
374
-	 * @param bool $regenerateSessionId
375
-	 * @return true returns true if login successful or an exception otherwise
376
-	 * @throws LoginException
377
-	 */
378
-	public function completeLogin(IUser $user, array $loginDetails, $regenerateSessionId = true) {
379
-		if (!$user->isEnabled()) {
380
-			// disabled users can not log in
381
-			// injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory
382
-			$message = \OC::$server->getL10N('lib')->t('User disabled');
383
-			throw new LoginException($message);
384
-		}
385
-
386
-		if($regenerateSessionId) {
387
-			$this->session->regenerateId();
388
-		}
389
-
390
-		$this->setUser($user);
391
-		$this->setLoginName($loginDetails['loginName']);
392
-
393
-		$isToken = isset($loginDetails['token']) && $loginDetails['token'] instanceof IToken;
394
-		if ($isToken) {
395
-			$this->setToken($loginDetails['token']->getId());
396
-			$this->lockdownManager->setToken($loginDetails['token']);
397
-			$firstTimeLogin = false;
398
-		} else {
399
-			$this->setToken(null);
400
-			$firstTimeLogin = $user->updateLastLoginTimestamp();
401
-		}
402
-
403
-		$this->dispatcher->dispatchTyped(new PostLoginEvent(
404
-			$user,
405
-			$loginDetails['password'],
406
-			$isToken
407
-		));
408
-		$this->manager->emit('\OC\User', 'postLogin', [
409
-			$user,
410
-			$loginDetails['password'],
411
-			$isToken,
412
-		]);
413
-		if($this->isLoggedIn()) {
414
-			$this->prepareUserLogin($firstTimeLogin, $regenerateSessionId);
415
-			return true;
416
-		}
417
-
418
-		$message = \OC::$server->getL10N('lib')->t('Login canceled by app');
419
-		throw new LoginException($message);
420
-	}
421
-
422
-	/**
423
-	 * Tries to log in a client
424
-	 *
425
-	 * Checks token auth enforced
426
-	 * Checks 2FA enabled
427
-	 *
428
-	 * @param string $user
429
-	 * @param string $password
430
-	 * @param IRequest $request
431
-	 * @param OC\Security\Bruteforce\Throttler $throttler
432
-	 * @throws LoginException
433
-	 * @throws PasswordLoginForbiddenException
434
-	 * @return boolean
435
-	 */
436
-	public function logClientIn($user,
437
-								$password,
438
-								IRequest $request,
439
-								OC\Security\Bruteforce\Throttler $throttler) {
440
-		$currentDelay = $throttler->sleepDelay($request->getRemoteAddress(), 'login');
441
-
442
-		if ($this->manager instanceof PublicEmitter) {
443
-			$this->manager->emit('\OC\User', 'preLogin', array($user, $password));
444
-		}
445
-
446
-		try {
447
-			$isTokenPassword = $this->isTokenPassword($password);
448
-		} catch (ExpiredTokenException $e) {
449
-			// Just return on an expired token no need to check further or record a failed login
450
-			return false;
451
-		}
452
-
453
-		if (!$isTokenPassword && $this->isTokenAuthEnforced()) {
454
-			throw new PasswordLoginForbiddenException();
455
-		}
456
-		if (!$isTokenPassword && $this->isTwoFactorEnforced($user)) {
457
-			throw new PasswordLoginForbiddenException();
458
-		}
459
-
460
-		// Try to login with this username and password
461
-		if (!$this->login($user, $password) ) {
462
-
463
-			// Failed, maybe the user used their email address
464
-			$users = $this->manager->getByEmail($user);
465
-			if (!(\count($users) === 1 && $this->login($users[0]->getUID(), $password))) {
466
-
467
-				$this->logger->warning('Login failed: \'' . $user . '\' (Remote IP: \'' . \OC::$server->getRequest()->getRemoteAddress() . '\')', ['app' => 'core']);
468
-
469
-				$throttler->registerAttempt('login', $request->getRemoteAddress(), ['user' => $user]);
470
-				if ($currentDelay === 0) {
471
-					$throttler->sleepDelay($request->getRemoteAddress(), 'login');
472
-				}
473
-				return false;
474
-			}
475
-		}
476
-
477
-		if ($isTokenPassword) {
478
-			$this->session->set('app_password', $password);
479
-		} else if($this->supportsCookies($request)) {
480
-			// Password login, but cookies supported -> create (browser) session token
481
-			$this->createSessionToken($request, $this->getUser()->getUID(), $user, $password);
482
-		}
483
-
484
-		return true;
485
-	}
486
-
487
-	protected function supportsCookies(IRequest $request) {
488
-		if (!is_null($request->getCookie('cookie_test'))) {
489
-			return true;
490
-		}
491
-		setcookie('cookie_test', 'test', $this->timeFactory->getTime() + 3600);
492
-		return false;
493
-	}
494
-
495
-	private function isTokenAuthEnforced() {
496
-		return $this->config->getSystemValue('token_auth_enforced', false);
497
-	}
498
-
499
-	protected function isTwoFactorEnforced($username) {
500
-		Util::emitHook(
501
-			'\OCA\Files_Sharing\API\Server2Server',
502
-			'preLoginNameUsedAsUserName',
503
-			array('uid' => &$username)
504
-		);
505
-		$user = $this->manager->get($username);
506
-		if (is_null($user)) {
507
-			$users = $this->manager->getByEmail($username);
508
-			if (empty($users)) {
509
-				return false;
510
-			}
511
-			if (count($users) !== 1) {
512
-				return true;
513
-			}
514
-			$user = $users[0];
515
-		}
516
-		// DI not possible due to cyclic dependencies :'-/
517
-		return OC::$server->getTwoFactorAuthManager()->isTwoFactorAuthenticated($user);
518
-	}
519
-
520
-	/**
521
-	 * Check if the given 'password' is actually a device token
522
-	 *
523
-	 * @param string $password
524
-	 * @return boolean
525
-	 * @throws ExpiredTokenException
526
-	 */
527
-	public function isTokenPassword($password) {
528
-		try {
529
-			$this->tokenProvider->getToken($password);
530
-			return true;
531
-		} catch (ExpiredTokenException $e) {
532
-			throw $e;
533
-		} catch (InvalidTokenException $ex) {
534
-			return false;
535
-		}
536
-	}
537
-
538
-	protected function prepareUserLogin($firstTimeLogin, $refreshCsrfToken = true) {
539
-		if ($refreshCsrfToken) {
540
-			// TODO: mock/inject/use non-static
541
-			// Refresh the token
542
-			\OC::$server->getCsrfTokenManager()->refreshToken();
543
-		}
544
-
545
-		//we need to pass the user name, which may differ from login name
546
-		$user = $this->getUser()->getUID();
547
-		OC_Util::setupFS($user);
548
-
549
-		if ($firstTimeLogin) {
550
-			// TODO: lock necessary?
551
-			//trigger creation of user home and /files folder
552
-			$userFolder = \OC::$server->getUserFolder($user);
553
-
554
-			try {
555
-				// copy skeleton
556
-				\OC_Util::copySkeleton($user, $userFolder);
557
-			} catch (NotPermittedException $ex) {
558
-				// read only uses
559
-			}
560
-
561
-			// trigger any other initialization
562
-			\OC::$server->getEventDispatcher()->dispatch(IUser::class . '::firstLogin', new GenericEvent($this->getUser()));
563
-		}
564
-	}
565
-
566
-	/**
567
-	 * Tries to login the user with HTTP Basic Authentication
568
-	 *
569
-	 * @todo do not allow basic auth if the user is 2FA enforced
570
-	 * @param IRequest $request
571
-	 * @param OC\Security\Bruteforce\Throttler $throttler
572
-	 * @return boolean if the login was successful
573
-	 */
574
-	public function tryBasicAuthLogin(IRequest $request,
575
-									  OC\Security\Bruteforce\Throttler $throttler) {
576
-		if (!empty($request->server['PHP_AUTH_USER']) && !empty($request->server['PHP_AUTH_PW'])) {
577
-			try {
578
-				if ($this->logClientIn($request->server['PHP_AUTH_USER'], $request->server['PHP_AUTH_PW'], $request, $throttler)) {
579
-					/**
580
-					 * Add DAV authenticated. This should in an ideal world not be
581
-					 * necessary but the iOS App reads cookies from anywhere instead
582
-					 * only the DAV endpoint.
583
-					 * This makes sure that the cookies will be valid for the whole scope
584
-					 * @see https://github.com/owncloud/core/issues/22893
585
-					 */
586
-					$this->session->set(
587
-						Auth::DAV_AUTHENTICATED, $this->getUser()->getUID()
588
-					);
589
-
590
-					// Set the last-password-confirm session to make the sudo mode work
591
-					 $this->session->set('last-password-confirm', $this->timeFactory->getTime());
592
-
593
-					return true;
594
-				}
595
-			} catch (PasswordLoginForbiddenException $ex) {
596
-				// Nothing to do
597
-			}
598
-		}
599
-		return false;
600
-	}
601
-
602
-	/**
603
-	 * Log an user in via login name and password
604
-	 *
605
-	 * @param string $uid
606
-	 * @param string $password
607
-	 * @return boolean
608
-	 * @throws LoginException if an app canceld the login process or the user is not enabled
609
-	 */
610
-	private function loginWithPassword($uid, $password) {
611
-		$user = $this->manager->checkPasswordNoLogging($uid, $password);
612
-		if ($user === false) {
613
-			// Password check failed
614
-			return false;
615
-		}
616
-
617
-		return $this->completeLogin($user, ['loginName' => $uid, 'password' => $password], false);
618
-	}
619
-
620
-	/**
621
-	 * Log an user in with a given token (id)
622
-	 *
623
-	 * @param string $token
624
-	 * @return boolean
625
-	 * @throws LoginException if an app canceled the login process or the user is not enabled
626
-	 */
627
-	private function loginWithToken($token) {
628
-		try {
629
-			$dbToken = $this->tokenProvider->getToken($token);
630
-		} catch (InvalidTokenException $ex) {
631
-			return false;
632
-		}
633
-		$uid = $dbToken->getUID();
634
-
635
-		// When logging in with token, the password must be decrypted first before passing to login hook
636
-		$password = '';
637
-		try {
638
-			$password = $this->tokenProvider->getPassword($dbToken, $token);
639
-		} catch (PasswordlessTokenException $ex) {
640
-			// Ignore and use empty string instead
641
-		}
642
-
643
-		$this->manager->emit('\OC\User', 'preLogin', array($uid, $password));
644
-
645
-		$user = $this->manager->get($uid);
646
-		if (is_null($user)) {
647
-			// user does not exist
648
-			return false;
649
-		}
650
-
651
-		return $this->completeLogin(
652
-			$user,
653
-			[
654
-				'loginName' => $dbToken->getLoginName(),
655
-				'password' => $password,
656
-				'token' => $dbToken
657
-			],
658
-			false);
659
-	}
660
-
661
-	/**
662
-	 * Create a new session token for the given user credentials
663
-	 *
664
-	 * @param IRequest $request
665
-	 * @param string $uid user UID
666
-	 * @param string $loginName login name
667
-	 * @param string $password
668
-	 * @param int $remember
669
-	 * @return boolean
670
-	 */
671
-	public function createSessionToken(IRequest $request, $uid, $loginName, $password = null, $remember = IToken::DO_NOT_REMEMBER) {
672
-		if (is_null($this->manager->get($uid))) {
673
-			// User does not exist
674
-			return false;
675
-		}
676
-		$name = isset($request->server['HTTP_USER_AGENT']) ? $request->server['HTTP_USER_AGENT'] : 'unknown browser';
677
-		try {
678
-			$sessionId = $this->session->getId();
679
-			$pwd = $this->getPassword($password);
680
-			// Make sure the current sessionId has no leftover tokens
681
-			$this->tokenProvider->invalidateToken($sessionId);
682
-			$this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name, IToken::TEMPORARY_TOKEN, $remember);
683
-			return true;
684
-		} catch (SessionNotAvailableException $ex) {
685
-			// This can happen with OCC, where a memory session is used
686
-			// if a memory session is used, we shouldn't create a session token anyway
687
-			return false;
688
-		}
689
-	}
690
-
691
-	/**
692
-	 * Checks if the given password is a token.
693
-	 * If yes, the password is extracted from the token.
694
-	 * If no, the same password is returned.
695
-	 *
696
-	 * @param string $password either the login password or a device token
697
-	 * @return string|null the password or null if none was set in the token
698
-	 */
699
-	private function getPassword($password) {
700
-		if (is_null($password)) {
701
-			// This is surely no token ;-)
702
-			return null;
703
-		}
704
-		try {
705
-			$token = $this->tokenProvider->getToken($password);
706
-			try {
707
-				return $this->tokenProvider->getPassword($token, $password);
708
-			} catch (PasswordlessTokenException $ex) {
709
-				return null;
710
-			}
711
-		} catch (InvalidTokenException $ex) {
712
-			return $password;
713
-		}
714
-	}
715
-
716
-	/**
717
-	 * @param IToken $dbToken
718
-	 * @param string $token
719
-	 * @return boolean
720
-	 */
721
-	private function checkTokenCredentials(IToken $dbToken, $token) {
722
-		// Check whether login credentials are still valid and the user was not disabled
723
-		// This check is performed each 5 minutes
724
-		$lastCheck = $dbToken->getLastCheck() ? : 0;
725
-		$now = $this->timeFactory->getTime();
726
-		if ($lastCheck > ($now - 60 * 5)) {
727
-			// Checked performed recently, nothing to do now
728
-			return true;
729
-		}
730
-
731
-		try {
732
-			$pwd = $this->tokenProvider->getPassword($dbToken, $token);
733
-		} catch (InvalidTokenException $ex) {
734
-			// An invalid token password was used -> log user out
735
-			return false;
736
-		} catch (PasswordlessTokenException $ex) {
737
-			// Token has no password
738
-
739
-			if (!is_null($this->activeUser) && !$this->activeUser->isEnabled()) {
740
-				$this->tokenProvider->invalidateToken($token);
741
-				return false;
742
-			}
743
-
744
-			$dbToken->setLastCheck($now);
745
-			return true;
746
-		}
747
-
748
-		// Invalidate token if the user is no longer active
749
-		if (!is_null($this->activeUser) && !$this->activeUser->isEnabled()) {
750
-			$this->tokenProvider->invalidateToken($token);
751
-			return false;
752
-		}
753
-
754
-		// If the token password is no longer valid mark it as such
755
-		if ($this->manager->checkPassword($dbToken->getLoginName(), $pwd) === false) {
756
-			$this->tokenProvider->markPasswordInvalid($dbToken, $token);
757
-			// User is logged out
758
-			return false;
759
-		}
760
-
761
-		$dbToken->setLastCheck($now);
762
-		return true;
763
-	}
764
-
765
-	/**
766
-	 * Check if the given token exists and performs password/user-enabled checks
767
-	 *
768
-	 * Invalidates the token if checks fail
769
-	 *
770
-	 * @param string $token
771
-	 * @param string $user login name
772
-	 * @return boolean
773
-	 */
774
-	private function validateToken($token, $user = null) {
775
-		try {
776
-			$dbToken = $this->tokenProvider->getToken($token);
777
-		} catch (InvalidTokenException $ex) {
778
-			return false;
779
-		}
780
-
781
-		// Check if login names match
782
-		if (!is_null($user) && $dbToken->getLoginName() !== $user) {
783
-			// TODO: this makes it imposssible to use different login names on browser and client
784
-			// e.g. login by e-mail '[email protected]' on browser for generating the token will not
785
-			//      allow to use the client token with the login name 'user'.
786
-			return false;
787
-		}
788
-
789
-		if (!$this->checkTokenCredentials($dbToken, $token)) {
790
-			return false;
791
-		}
792
-
793
-		// Update token scope
794
-		$this->lockdownManager->setToken($dbToken);
795
-
796
-		$this->tokenProvider->updateTokenActivity($dbToken);
797
-
798
-		return true;
799
-	}
800
-
801
-	/**
802
-	 * Tries to login the user with auth token header
803
-	 *
804
-	 * @param IRequest $request
805
-	 * @todo check remember me cookie
806
-	 * @return boolean
807
-	 */
808
-	public function tryTokenLogin(IRequest $request) {
809
-		$authHeader = $request->getHeader('Authorization');
810
-		if (strpos($authHeader, 'Bearer ') === false) {
811
-			// No auth header, let's try session id
812
-			try {
813
-				$token = $this->session->getId();
814
-			} catch (SessionNotAvailableException $ex) {
815
-				return false;
816
-			}
817
-		} else {
818
-			$token = substr($authHeader, 7);
819
-		}
820
-
821
-		if (!$this->loginWithToken($token)) {
822
-			return false;
823
-		}
824
-		if(!$this->validateToken($token)) {
825
-			return false;
826
-		}
827
-
828
-		// Set the session variable so we know this is an app password
829
-		$this->session->set('app_password', $token);
830
-
831
-		return true;
832
-	}
833
-
834
-	/**
835
-	 * perform login using the magic cookie (remember login)
836
-	 *
837
-	 * @param string $uid the username
838
-	 * @param string $currentToken
839
-	 * @param string $oldSessionId
840
-	 * @return bool
841
-	 */
842
-	public function loginWithCookie($uid, $currentToken, $oldSessionId) {
843
-		$this->session->regenerateId();
844
-		$this->manager->emit('\OC\User', 'preRememberedLogin', array($uid));
845
-		$user = $this->manager->get($uid);
846
-		if (is_null($user)) {
847
-			// user does not exist
848
-			return false;
849
-		}
850
-
851
-		// get stored tokens
852
-		$tokens = $this->config->getUserKeys($uid, 'login_token');
853
-		// test cookies token against stored tokens
854
-		if (!in_array($currentToken, $tokens, true)) {
855
-			return false;
856
-		}
857
-		// replace successfully used token with a new one
858
-		$this->config->deleteUserValue($uid, 'login_token', $currentToken);
859
-		$newToken = $this->random->generate(32);
860
-		$this->config->setUserValue($uid, 'login_token', $newToken, $this->timeFactory->getTime());
861
-
862
-		try {
863
-			$sessionId = $this->session->getId();
864
-			$token = $this->tokenProvider->renewSessionToken($oldSessionId, $sessionId);
865
-		} catch (SessionNotAvailableException $ex) {
866
-			return false;
867
-		} catch (InvalidTokenException $ex) {
868
-			\OC::$server->getLogger()->warning('Renewing session token failed', ['app' => 'core']);
869
-			return false;
870
-		}
871
-
872
-		$this->setMagicInCookie($user->getUID(), $newToken);
873
-
874
-		//login
875
-		$this->setUser($user);
876
-		$this->setLoginName($token->getLoginName());
877
-		$this->setToken($token->getId());
878
-		$this->lockdownManager->setToken($token);
879
-		$user->updateLastLoginTimestamp();
880
-		$password = null;
881
-		try {
882
-			$password = $this->tokenProvider->getPassword($token, $sessionId);
883
-		} catch (PasswordlessTokenException $ex) {
884
-			// Ignore
885
-		}
886
-		$this->manager->emit('\OC\User', 'postRememberedLogin', [$user, $password]);
887
-		return true;
888
-	}
889
-
890
-	/**
891
-	 * @param IUser $user
892
-	 */
893
-	public function createRememberMeToken(IUser $user) {
894
-		$token = $this->random->generate(32);
895
-		$this->config->setUserValue($user->getUID(), 'login_token', $token, $this->timeFactory->getTime());
896
-		$this->setMagicInCookie($user->getUID(), $token);
897
-	}
898
-
899
-	/**
900
-	 * logout the user from the session
901
-	 */
902
-	public function logout() {
903
-		$user = $this->getUser();
904
-		$this->manager->emit('\OC\User', 'logout', [$user]);
905
-		if ($user !== null) {
906
-			try {
907
-				$this->tokenProvider->invalidateToken($this->session->getId());
908
-			} catch (SessionNotAvailableException $ex) {
909
-
910
-			}
911
-		}
912
-		$this->setUser(null);
913
-		$this->setLoginName(null);
914
-		$this->setToken(null);
915
-		$this->unsetMagicInCookie();
916
-		$this->session->clear();
917
-		$this->manager->emit('\OC\User', 'postLogout', [$user]);
918
-	}
919
-
920
-	/**
921
-	 * Set cookie value to use in next page load
922
-	 *
923
-	 * @param string $username username to be set
924
-	 * @param string $token
925
-	 */
926
-	public function setMagicInCookie($username, $token) {
927
-		$secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https';
928
-		$webRoot = \OC::$WEBROOT;
929
-		if ($webRoot === '') {
930
-			$webRoot = '/';
931
-		}
932
-
933
-		$maxAge = $this->config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
934
-		\OC\Http\CookieHelper::setCookie(
935
-			'nc_username',
936
-			$username,
937
-			$maxAge,
938
-			$webRoot,
939
-			'',
940
-			$secureCookie,
941
-			true,
942
-			\OC\Http\CookieHelper::SAMESITE_LAX
943
-		);
944
-		\OC\Http\CookieHelper::setCookie(
945
-			'nc_token',
946
-			$token,
947
-			$maxAge,
948
-			$webRoot,
949
-			'',
950
-			$secureCookie,
951
-			true,
952
-			\OC\Http\CookieHelper::SAMESITE_LAX
953
-		);
954
-		try {
955
-			\OC\Http\CookieHelper::setCookie(
956
-				'nc_session_id',
957
-				$this->session->getId(),
958
-				$maxAge,
959
-				$webRoot,
960
-				'',
961
-				$secureCookie,
962
-				true,
963
-				\OC\Http\CookieHelper::SAMESITE_LAX
964
-			);
965
-		} catch (SessionNotAvailableException $ex) {
966
-			// ignore
967
-		}
968
-	}
969
-
970
-	/**
971
-	 * Remove cookie for "remember username"
972
-	 */
973
-	public function unsetMagicInCookie() {
974
-		//TODO: DI for cookies and IRequest
975
-		$secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https';
976
-
977
-		unset($_COOKIE['nc_username']); //TODO: DI
978
-		unset($_COOKIE['nc_token']);
979
-		unset($_COOKIE['nc_session_id']);
980
-		setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true);
981
-		setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true);
982
-		setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true);
983
-		// old cookies might be stored under /webroot/ instead of /webroot
984
-		// and Firefox doesn't like it!
985
-		setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
986
-		setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
987
-		setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
988
-	}
989
-
990
-	/**
991
-	 * Update password of the browser session token if there is one
992
-	 *
993
-	 * @param string $password
994
-	 */
995
-	public function updateSessionTokenPassword($password) {
996
-		try {
997
-			$sessionId = $this->session->getId();
998
-			$token = $this->tokenProvider->getToken($sessionId);
999
-			$this->tokenProvider->setPassword($token, $sessionId, $password);
1000
-		} catch (SessionNotAvailableException $ex) {
1001
-			// Nothing to do
1002
-		} catch (InvalidTokenException $ex) {
1003
-			// Nothing to do
1004
-		}
1005
-	}
1006
-
1007
-	public function updateTokens(string $uid, string $password) {
1008
-		$this->tokenProvider->updatePasswords($uid, $password);
1009
-	}
93
+    /** @var Manager|PublicEmitter $manager */
94
+    private $manager;
95
+
96
+    /** @var ISession $session */
97
+    private $session;
98
+
99
+    /** @var ITimeFactory */
100
+    private $timeFactory;
101
+
102
+    /** @var IProvider */
103
+    private $tokenProvider;
104
+
105
+    /** @var IConfig */
106
+    private $config;
107
+
108
+    /** @var User $activeUser */
109
+    protected $activeUser;
110
+
111
+    /** @var ISecureRandom */
112
+    private $random;
113
+
114
+    /** @var ILockdownManager  */
115
+    private $lockdownManager;
116
+
117
+    /** @var ILogger */
118
+    private $logger;
119
+    /** @var IEventDispatcher */
120
+    private $dispatcher;
121
+
122
+    /**
123
+     * @param Manager $manager
124
+     * @param ISession $session
125
+     * @param ITimeFactory $timeFactory
126
+     * @param IProvider $tokenProvider
127
+     * @param IConfig $config
128
+     * @param ISecureRandom $random
129
+     * @param ILockdownManager $lockdownManager
130
+     * @param ILogger $logger
131
+     */
132
+    public function __construct(Manager $manager,
133
+                                ISession $session,
134
+                                ITimeFactory $timeFactory,
135
+                                $tokenProvider,
136
+                                IConfig $config,
137
+                                ISecureRandom $random,
138
+                                ILockdownManager $lockdownManager,
139
+                                ILogger $logger,
140
+                                IEventDispatcher $dispatcher) {
141
+        $this->manager = $manager;
142
+        $this->session = $session;
143
+        $this->timeFactory = $timeFactory;
144
+        $this->tokenProvider = $tokenProvider;
145
+        $this->config = $config;
146
+        $this->random = $random;
147
+        $this->lockdownManager = $lockdownManager;
148
+        $this->logger = $logger;
149
+        $this->dispatcher = $dispatcher;
150
+    }
151
+
152
+    /**
153
+     * @param IProvider $provider
154
+     */
155
+    public function setTokenProvider(IProvider $provider) {
156
+        $this->tokenProvider = $provider;
157
+    }
158
+
159
+    /**
160
+     * @param string $scope
161
+     * @param string $method
162
+     * @param callable $callback
163
+     */
164
+    public function listen($scope, $method, callable $callback) {
165
+        $this->manager->listen($scope, $method, $callback);
166
+    }
167
+
168
+    /**
169
+     * @param string $scope optional
170
+     * @param string $method optional
171
+     * @param callable $callback optional
172
+     */
173
+    public function removeListener($scope = null, $method = null, callable $callback = null) {
174
+        $this->manager->removeListener($scope, $method, $callback);
175
+    }
176
+
177
+    /**
178
+     * get the manager object
179
+     *
180
+     * @return Manager|PublicEmitter
181
+     */
182
+    public function getManager() {
183
+        return $this->manager;
184
+    }
185
+
186
+    /**
187
+     * get the session object
188
+     *
189
+     * @return ISession
190
+     */
191
+    public function getSession() {
192
+        return $this->session;
193
+    }
194
+
195
+    /**
196
+     * set the session object
197
+     *
198
+     * @param ISession $session
199
+     */
200
+    public function setSession(ISession $session) {
201
+        if ($this->session instanceof ISession) {
202
+            $this->session->close();
203
+        }
204
+        $this->session = $session;
205
+        $this->activeUser = null;
206
+    }
207
+
208
+    /**
209
+     * set the currently active user
210
+     *
211
+     * @param IUser|null $user
212
+     */
213
+    public function setUser($user) {
214
+        if (is_null($user)) {
215
+            $this->session->remove('user_id');
216
+        } else {
217
+            $this->session->set('user_id', $user->getUID());
218
+        }
219
+        $this->activeUser = $user;
220
+    }
221
+
222
+    /**
223
+     * get the current active user
224
+     *
225
+     * @return IUser|null Current user, otherwise null
226
+     */
227
+    public function getUser() {
228
+        // FIXME: This is a quick'n dirty work-around for the incognito mode as
229
+        // described at https://github.com/owncloud/core/pull/12912#issuecomment-67391155
230
+        if (OC_User::isIncognitoMode()) {
231
+            return null;
232
+        }
233
+        if (is_null($this->activeUser)) {
234
+            $uid = $this->session->get('user_id');
235
+            if (is_null($uid)) {
236
+                return null;
237
+            }
238
+            $this->activeUser = $this->manager->get($uid);
239
+            if (is_null($this->activeUser)) {
240
+                return null;
241
+            }
242
+            $this->validateSession();
243
+        }
244
+        return $this->activeUser;
245
+    }
246
+
247
+    /**
248
+     * Validate whether the current session is valid
249
+     *
250
+     * - For token-authenticated clients, the token validity is checked
251
+     * - For browsers, the session token validity is checked
252
+     */
253
+    protected function validateSession() {
254
+        $token = null;
255
+        $appPassword = $this->session->get('app_password');
256
+
257
+        if (is_null($appPassword)) {
258
+            try {
259
+                $token = $this->session->getId();
260
+            } catch (SessionNotAvailableException $ex) {
261
+                return;
262
+            }
263
+        } else {
264
+            $token = $appPassword;
265
+        }
266
+
267
+        if (!$this->validateToken($token)) {
268
+            // Session was invalidated
269
+            $this->logout();
270
+        }
271
+    }
272
+
273
+    /**
274
+     * Checks whether the user is logged in
275
+     *
276
+     * @return bool if logged in
277
+     */
278
+    public function isLoggedIn() {
279
+        $user = $this->getUser();
280
+        if (is_null($user)) {
281
+            return false;
282
+        }
283
+
284
+        return $user->isEnabled();
285
+    }
286
+
287
+    /**
288
+     * set the login name
289
+     *
290
+     * @param string|null $loginName for the logged in user
291
+     */
292
+    public function setLoginName($loginName) {
293
+        if (is_null($loginName)) {
294
+            $this->session->remove('loginname');
295
+        } else {
296
+            $this->session->set('loginname', $loginName);
297
+        }
298
+    }
299
+
300
+    /**
301
+     * get the login name of the current user
302
+     *
303
+     * @return string
304
+     */
305
+    public function getLoginName() {
306
+        if ($this->activeUser) {
307
+            return $this->session->get('loginname');
308
+        }
309
+
310
+        $uid = $this->session->get('user_id');
311
+        if ($uid) {
312
+            $this->activeUser = $this->manager->get($uid);
313
+            return $this->session->get('loginname');
314
+        }
315
+
316
+        return null;
317
+    }
318
+
319
+    /**
320
+     * @return null|string
321
+     */
322
+    public function getImpersonatingUserID(): ?string {
323
+
324
+        return $this->session->get('oldUserId');
325
+
326
+    }
327
+
328
+    public function setImpersonatingUserID(bool $useCurrentUser = true): void {
329
+        if ($useCurrentUser === false) {
330
+            $this->session->remove('oldUserId');
331
+            return;
332
+        }
333
+
334
+        $currentUser = $this->getUser();
335
+
336
+        if ($currentUser === null) {
337
+            throw new \OC\User\NoUserException();
338
+        }
339
+        $this->session->set('oldUserId', $currentUser->getUID());
340
+
341
+    }
342
+    /**
343
+     * set the token id
344
+     *
345
+     * @param int|null $token that was used to log in
346
+     */
347
+    protected function setToken($token) {
348
+        if ($token === null) {
349
+            $this->session->remove('token-id');
350
+        } else {
351
+            $this->session->set('token-id', $token);
352
+        }
353
+    }
354
+
355
+    /**
356
+     * try to log in with the provided credentials
357
+     *
358
+     * @param string $uid
359
+     * @param string $password
360
+     * @return boolean|null
361
+     * @throws LoginException
362
+     */
363
+    public function login($uid, $password) {
364
+        $this->session->regenerateId();
365
+        if ($this->validateToken($password, $uid)) {
366
+            return $this->loginWithToken($password);
367
+        }
368
+        return $this->loginWithPassword($uid, $password);
369
+    }
370
+
371
+    /**
372
+     * @param IUser $user
373
+     * @param array $loginDetails
374
+     * @param bool $regenerateSessionId
375
+     * @return true returns true if login successful or an exception otherwise
376
+     * @throws LoginException
377
+     */
378
+    public function completeLogin(IUser $user, array $loginDetails, $regenerateSessionId = true) {
379
+        if (!$user->isEnabled()) {
380
+            // disabled users can not log in
381
+            // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory
382
+            $message = \OC::$server->getL10N('lib')->t('User disabled');
383
+            throw new LoginException($message);
384
+        }
385
+
386
+        if($regenerateSessionId) {
387
+            $this->session->regenerateId();
388
+        }
389
+
390
+        $this->setUser($user);
391
+        $this->setLoginName($loginDetails['loginName']);
392
+
393
+        $isToken = isset($loginDetails['token']) && $loginDetails['token'] instanceof IToken;
394
+        if ($isToken) {
395
+            $this->setToken($loginDetails['token']->getId());
396
+            $this->lockdownManager->setToken($loginDetails['token']);
397
+            $firstTimeLogin = false;
398
+        } else {
399
+            $this->setToken(null);
400
+            $firstTimeLogin = $user->updateLastLoginTimestamp();
401
+        }
402
+
403
+        $this->dispatcher->dispatchTyped(new PostLoginEvent(
404
+            $user,
405
+            $loginDetails['password'],
406
+            $isToken
407
+        ));
408
+        $this->manager->emit('\OC\User', 'postLogin', [
409
+            $user,
410
+            $loginDetails['password'],
411
+            $isToken,
412
+        ]);
413
+        if($this->isLoggedIn()) {
414
+            $this->prepareUserLogin($firstTimeLogin, $regenerateSessionId);
415
+            return true;
416
+        }
417
+
418
+        $message = \OC::$server->getL10N('lib')->t('Login canceled by app');
419
+        throw new LoginException($message);
420
+    }
421
+
422
+    /**
423
+     * Tries to log in a client
424
+     *
425
+     * Checks token auth enforced
426
+     * Checks 2FA enabled
427
+     *
428
+     * @param string $user
429
+     * @param string $password
430
+     * @param IRequest $request
431
+     * @param OC\Security\Bruteforce\Throttler $throttler
432
+     * @throws LoginException
433
+     * @throws PasswordLoginForbiddenException
434
+     * @return boolean
435
+     */
436
+    public function logClientIn($user,
437
+                                $password,
438
+                                IRequest $request,
439
+                                OC\Security\Bruteforce\Throttler $throttler) {
440
+        $currentDelay = $throttler->sleepDelay($request->getRemoteAddress(), 'login');
441
+
442
+        if ($this->manager instanceof PublicEmitter) {
443
+            $this->manager->emit('\OC\User', 'preLogin', array($user, $password));
444
+        }
445
+
446
+        try {
447
+            $isTokenPassword = $this->isTokenPassword($password);
448
+        } catch (ExpiredTokenException $e) {
449
+            // Just return on an expired token no need to check further or record a failed login
450
+            return false;
451
+        }
452
+
453
+        if (!$isTokenPassword && $this->isTokenAuthEnforced()) {
454
+            throw new PasswordLoginForbiddenException();
455
+        }
456
+        if (!$isTokenPassword && $this->isTwoFactorEnforced($user)) {
457
+            throw new PasswordLoginForbiddenException();
458
+        }
459
+
460
+        // Try to login with this username and password
461
+        if (!$this->login($user, $password) ) {
462
+
463
+            // Failed, maybe the user used their email address
464
+            $users = $this->manager->getByEmail($user);
465
+            if (!(\count($users) === 1 && $this->login($users[0]->getUID(), $password))) {
466
+
467
+                $this->logger->warning('Login failed: \'' . $user . '\' (Remote IP: \'' . \OC::$server->getRequest()->getRemoteAddress() . '\')', ['app' => 'core']);
468
+
469
+                $throttler->registerAttempt('login', $request->getRemoteAddress(), ['user' => $user]);
470
+                if ($currentDelay === 0) {
471
+                    $throttler->sleepDelay($request->getRemoteAddress(), 'login');
472
+                }
473
+                return false;
474
+            }
475
+        }
476
+
477
+        if ($isTokenPassword) {
478
+            $this->session->set('app_password', $password);
479
+        } else if($this->supportsCookies($request)) {
480
+            // Password login, but cookies supported -> create (browser) session token
481
+            $this->createSessionToken($request, $this->getUser()->getUID(), $user, $password);
482
+        }
483
+
484
+        return true;
485
+    }
486
+
487
+    protected function supportsCookies(IRequest $request) {
488
+        if (!is_null($request->getCookie('cookie_test'))) {
489
+            return true;
490
+        }
491
+        setcookie('cookie_test', 'test', $this->timeFactory->getTime() + 3600);
492
+        return false;
493
+    }
494
+
495
+    private function isTokenAuthEnforced() {
496
+        return $this->config->getSystemValue('token_auth_enforced', false);
497
+    }
498
+
499
+    protected function isTwoFactorEnforced($username) {
500
+        Util::emitHook(
501
+            '\OCA\Files_Sharing\API\Server2Server',
502
+            'preLoginNameUsedAsUserName',
503
+            array('uid' => &$username)
504
+        );
505
+        $user = $this->manager->get($username);
506
+        if (is_null($user)) {
507
+            $users = $this->manager->getByEmail($username);
508
+            if (empty($users)) {
509
+                return false;
510
+            }
511
+            if (count($users) !== 1) {
512
+                return true;
513
+            }
514
+            $user = $users[0];
515
+        }
516
+        // DI not possible due to cyclic dependencies :'-/
517
+        return OC::$server->getTwoFactorAuthManager()->isTwoFactorAuthenticated($user);
518
+    }
519
+
520
+    /**
521
+     * Check if the given 'password' is actually a device token
522
+     *
523
+     * @param string $password
524
+     * @return boolean
525
+     * @throws ExpiredTokenException
526
+     */
527
+    public function isTokenPassword($password) {
528
+        try {
529
+            $this->tokenProvider->getToken($password);
530
+            return true;
531
+        } catch (ExpiredTokenException $e) {
532
+            throw $e;
533
+        } catch (InvalidTokenException $ex) {
534
+            return false;
535
+        }
536
+    }
537
+
538
+    protected function prepareUserLogin($firstTimeLogin, $refreshCsrfToken = true) {
539
+        if ($refreshCsrfToken) {
540
+            // TODO: mock/inject/use non-static
541
+            // Refresh the token
542
+            \OC::$server->getCsrfTokenManager()->refreshToken();
543
+        }
544
+
545
+        //we need to pass the user name, which may differ from login name
546
+        $user = $this->getUser()->getUID();
547
+        OC_Util::setupFS($user);
548
+
549
+        if ($firstTimeLogin) {
550
+            // TODO: lock necessary?
551
+            //trigger creation of user home and /files folder
552
+            $userFolder = \OC::$server->getUserFolder($user);
553
+
554
+            try {
555
+                // copy skeleton
556
+                \OC_Util::copySkeleton($user, $userFolder);
557
+            } catch (NotPermittedException $ex) {
558
+                // read only uses
559
+            }
560
+
561
+            // trigger any other initialization
562
+            \OC::$server->getEventDispatcher()->dispatch(IUser::class . '::firstLogin', new GenericEvent($this->getUser()));
563
+        }
564
+    }
565
+
566
+    /**
567
+     * Tries to login the user with HTTP Basic Authentication
568
+     *
569
+     * @todo do not allow basic auth if the user is 2FA enforced
570
+     * @param IRequest $request
571
+     * @param OC\Security\Bruteforce\Throttler $throttler
572
+     * @return boolean if the login was successful
573
+     */
574
+    public function tryBasicAuthLogin(IRequest $request,
575
+                                        OC\Security\Bruteforce\Throttler $throttler) {
576
+        if (!empty($request->server['PHP_AUTH_USER']) && !empty($request->server['PHP_AUTH_PW'])) {
577
+            try {
578
+                if ($this->logClientIn($request->server['PHP_AUTH_USER'], $request->server['PHP_AUTH_PW'], $request, $throttler)) {
579
+                    /**
580
+                     * Add DAV authenticated. This should in an ideal world not be
581
+                     * necessary but the iOS App reads cookies from anywhere instead
582
+                     * only the DAV endpoint.
583
+                     * This makes sure that the cookies will be valid for the whole scope
584
+                     * @see https://github.com/owncloud/core/issues/22893
585
+                     */
586
+                    $this->session->set(
587
+                        Auth::DAV_AUTHENTICATED, $this->getUser()->getUID()
588
+                    );
589
+
590
+                    // Set the last-password-confirm session to make the sudo mode work
591
+                        $this->session->set('last-password-confirm', $this->timeFactory->getTime());
592
+
593
+                    return true;
594
+                }
595
+            } catch (PasswordLoginForbiddenException $ex) {
596
+                // Nothing to do
597
+            }
598
+        }
599
+        return false;
600
+    }
601
+
602
+    /**
603
+     * Log an user in via login name and password
604
+     *
605
+     * @param string $uid
606
+     * @param string $password
607
+     * @return boolean
608
+     * @throws LoginException if an app canceld the login process or the user is not enabled
609
+     */
610
+    private function loginWithPassword($uid, $password) {
611
+        $user = $this->manager->checkPasswordNoLogging($uid, $password);
612
+        if ($user === false) {
613
+            // Password check failed
614
+            return false;
615
+        }
616
+
617
+        return $this->completeLogin($user, ['loginName' => $uid, 'password' => $password], false);
618
+    }
619
+
620
+    /**
621
+     * Log an user in with a given token (id)
622
+     *
623
+     * @param string $token
624
+     * @return boolean
625
+     * @throws LoginException if an app canceled the login process or the user is not enabled
626
+     */
627
+    private function loginWithToken($token) {
628
+        try {
629
+            $dbToken = $this->tokenProvider->getToken($token);
630
+        } catch (InvalidTokenException $ex) {
631
+            return false;
632
+        }
633
+        $uid = $dbToken->getUID();
634
+
635
+        // When logging in with token, the password must be decrypted first before passing to login hook
636
+        $password = '';
637
+        try {
638
+            $password = $this->tokenProvider->getPassword($dbToken, $token);
639
+        } catch (PasswordlessTokenException $ex) {
640
+            // Ignore and use empty string instead
641
+        }
642
+
643
+        $this->manager->emit('\OC\User', 'preLogin', array($uid, $password));
644
+
645
+        $user = $this->manager->get($uid);
646
+        if (is_null($user)) {
647
+            // user does not exist
648
+            return false;
649
+        }
650
+
651
+        return $this->completeLogin(
652
+            $user,
653
+            [
654
+                'loginName' => $dbToken->getLoginName(),
655
+                'password' => $password,
656
+                'token' => $dbToken
657
+            ],
658
+            false);
659
+    }
660
+
661
+    /**
662
+     * Create a new session token for the given user credentials
663
+     *
664
+     * @param IRequest $request
665
+     * @param string $uid user UID
666
+     * @param string $loginName login name
667
+     * @param string $password
668
+     * @param int $remember
669
+     * @return boolean
670
+     */
671
+    public function createSessionToken(IRequest $request, $uid, $loginName, $password = null, $remember = IToken::DO_NOT_REMEMBER) {
672
+        if (is_null($this->manager->get($uid))) {
673
+            // User does not exist
674
+            return false;
675
+        }
676
+        $name = isset($request->server['HTTP_USER_AGENT']) ? $request->server['HTTP_USER_AGENT'] : 'unknown browser';
677
+        try {
678
+            $sessionId = $this->session->getId();
679
+            $pwd = $this->getPassword($password);
680
+            // Make sure the current sessionId has no leftover tokens
681
+            $this->tokenProvider->invalidateToken($sessionId);
682
+            $this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name, IToken::TEMPORARY_TOKEN, $remember);
683
+            return true;
684
+        } catch (SessionNotAvailableException $ex) {
685
+            // This can happen with OCC, where a memory session is used
686
+            // if a memory session is used, we shouldn't create a session token anyway
687
+            return false;
688
+        }
689
+    }
690
+
691
+    /**
692
+     * Checks if the given password is a token.
693
+     * If yes, the password is extracted from the token.
694
+     * If no, the same password is returned.
695
+     *
696
+     * @param string $password either the login password or a device token
697
+     * @return string|null the password or null if none was set in the token
698
+     */
699
+    private function getPassword($password) {
700
+        if (is_null($password)) {
701
+            // This is surely no token ;-)
702
+            return null;
703
+        }
704
+        try {
705
+            $token = $this->tokenProvider->getToken($password);
706
+            try {
707
+                return $this->tokenProvider->getPassword($token, $password);
708
+            } catch (PasswordlessTokenException $ex) {
709
+                return null;
710
+            }
711
+        } catch (InvalidTokenException $ex) {
712
+            return $password;
713
+        }
714
+    }
715
+
716
+    /**
717
+     * @param IToken $dbToken
718
+     * @param string $token
719
+     * @return boolean
720
+     */
721
+    private function checkTokenCredentials(IToken $dbToken, $token) {
722
+        // Check whether login credentials are still valid and the user was not disabled
723
+        // This check is performed each 5 minutes
724
+        $lastCheck = $dbToken->getLastCheck() ? : 0;
725
+        $now = $this->timeFactory->getTime();
726
+        if ($lastCheck > ($now - 60 * 5)) {
727
+            // Checked performed recently, nothing to do now
728
+            return true;
729
+        }
730
+
731
+        try {
732
+            $pwd = $this->tokenProvider->getPassword($dbToken, $token);
733
+        } catch (InvalidTokenException $ex) {
734
+            // An invalid token password was used -> log user out
735
+            return false;
736
+        } catch (PasswordlessTokenException $ex) {
737
+            // Token has no password
738
+
739
+            if (!is_null($this->activeUser) && !$this->activeUser->isEnabled()) {
740
+                $this->tokenProvider->invalidateToken($token);
741
+                return false;
742
+            }
743
+
744
+            $dbToken->setLastCheck($now);
745
+            return true;
746
+        }
747
+
748
+        // Invalidate token if the user is no longer active
749
+        if (!is_null($this->activeUser) && !$this->activeUser->isEnabled()) {
750
+            $this->tokenProvider->invalidateToken($token);
751
+            return false;
752
+        }
753
+
754
+        // If the token password is no longer valid mark it as such
755
+        if ($this->manager->checkPassword($dbToken->getLoginName(), $pwd) === false) {
756
+            $this->tokenProvider->markPasswordInvalid($dbToken, $token);
757
+            // User is logged out
758
+            return false;
759
+        }
760
+
761
+        $dbToken->setLastCheck($now);
762
+        return true;
763
+    }
764
+
765
+    /**
766
+     * Check if the given token exists and performs password/user-enabled checks
767
+     *
768
+     * Invalidates the token if checks fail
769
+     *
770
+     * @param string $token
771
+     * @param string $user login name
772
+     * @return boolean
773
+     */
774
+    private function validateToken($token, $user = null) {
775
+        try {
776
+            $dbToken = $this->tokenProvider->getToken($token);
777
+        } catch (InvalidTokenException $ex) {
778
+            return false;
779
+        }
780
+
781
+        // Check if login names match
782
+        if (!is_null($user) && $dbToken->getLoginName() !== $user) {
783
+            // TODO: this makes it imposssible to use different login names on browser and client
784
+            // e.g. login by e-mail '[email protected]' on browser for generating the token will not
785
+            //      allow to use the client token with the login name 'user'.
786
+            return false;
787
+        }
788
+
789
+        if (!$this->checkTokenCredentials($dbToken, $token)) {
790
+            return false;
791
+        }
792
+
793
+        // Update token scope
794
+        $this->lockdownManager->setToken($dbToken);
795
+
796
+        $this->tokenProvider->updateTokenActivity($dbToken);
797
+
798
+        return true;
799
+    }
800
+
801
+    /**
802
+     * Tries to login the user with auth token header
803
+     *
804
+     * @param IRequest $request
805
+     * @todo check remember me cookie
806
+     * @return boolean
807
+     */
808
+    public function tryTokenLogin(IRequest $request) {
809
+        $authHeader = $request->getHeader('Authorization');
810
+        if (strpos($authHeader, 'Bearer ') === false) {
811
+            // No auth header, let's try session id
812
+            try {
813
+                $token = $this->session->getId();
814
+            } catch (SessionNotAvailableException $ex) {
815
+                return false;
816
+            }
817
+        } else {
818
+            $token = substr($authHeader, 7);
819
+        }
820
+
821
+        if (!$this->loginWithToken($token)) {
822
+            return false;
823
+        }
824
+        if(!$this->validateToken($token)) {
825
+            return false;
826
+        }
827
+
828
+        // Set the session variable so we know this is an app password
829
+        $this->session->set('app_password', $token);
830
+
831
+        return true;
832
+    }
833
+
834
+    /**
835
+     * perform login using the magic cookie (remember login)
836
+     *
837
+     * @param string $uid the username
838
+     * @param string $currentToken
839
+     * @param string $oldSessionId
840
+     * @return bool
841
+     */
842
+    public function loginWithCookie($uid, $currentToken, $oldSessionId) {
843
+        $this->session->regenerateId();
844
+        $this->manager->emit('\OC\User', 'preRememberedLogin', array($uid));
845
+        $user = $this->manager->get($uid);
846
+        if (is_null($user)) {
847
+            // user does not exist
848
+            return false;
849
+        }
850
+
851
+        // get stored tokens
852
+        $tokens = $this->config->getUserKeys($uid, 'login_token');
853
+        // test cookies token against stored tokens
854
+        if (!in_array($currentToken, $tokens, true)) {
855
+            return false;
856
+        }
857
+        // replace successfully used token with a new one
858
+        $this->config->deleteUserValue($uid, 'login_token', $currentToken);
859
+        $newToken = $this->random->generate(32);
860
+        $this->config->setUserValue($uid, 'login_token', $newToken, $this->timeFactory->getTime());
861
+
862
+        try {
863
+            $sessionId = $this->session->getId();
864
+            $token = $this->tokenProvider->renewSessionToken($oldSessionId, $sessionId);
865
+        } catch (SessionNotAvailableException $ex) {
866
+            return false;
867
+        } catch (InvalidTokenException $ex) {
868
+            \OC::$server->getLogger()->warning('Renewing session token failed', ['app' => 'core']);
869
+            return false;
870
+        }
871
+
872
+        $this->setMagicInCookie($user->getUID(), $newToken);
873
+
874
+        //login
875
+        $this->setUser($user);
876
+        $this->setLoginName($token->getLoginName());
877
+        $this->setToken($token->getId());
878
+        $this->lockdownManager->setToken($token);
879
+        $user->updateLastLoginTimestamp();
880
+        $password = null;
881
+        try {
882
+            $password = $this->tokenProvider->getPassword($token, $sessionId);
883
+        } catch (PasswordlessTokenException $ex) {
884
+            // Ignore
885
+        }
886
+        $this->manager->emit('\OC\User', 'postRememberedLogin', [$user, $password]);
887
+        return true;
888
+    }
889
+
890
+    /**
891
+     * @param IUser $user
892
+     */
893
+    public function createRememberMeToken(IUser $user) {
894
+        $token = $this->random->generate(32);
895
+        $this->config->setUserValue($user->getUID(), 'login_token', $token, $this->timeFactory->getTime());
896
+        $this->setMagicInCookie($user->getUID(), $token);
897
+    }
898
+
899
+    /**
900
+     * logout the user from the session
901
+     */
902
+    public function logout() {
903
+        $user = $this->getUser();
904
+        $this->manager->emit('\OC\User', 'logout', [$user]);
905
+        if ($user !== null) {
906
+            try {
907
+                $this->tokenProvider->invalidateToken($this->session->getId());
908
+            } catch (SessionNotAvailableException $ex) {
909
+
910
+            }
911
+        }
912
+        $this->setUser(null);
913
+        $this->setLoginName(null);
914
+        $this->setToken(null);
915
+        $this->unsetMagicInCookie();
916
+        $this->session->clear();
917
+        $this->manager->emit('\OC\User', 'postLogout', [$user]);
918
+    }
919
+
920
+    /**
921
+     * Set cookie value to use in next page load
922
+     *
923
+     * @param string $username username to be set
924
+     * @param string $token
925
+     */
926
+    public function setMagicInCookie($username, $token) {
927
+        $secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https';
928
+        $webRoot = \OC::$WEBROOT;
929
+        if ($webRoot === '') {
930
+            $webRoot = '/';
931
+        }
932
+
933
+        $maxAge = $this->config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
934
+        \OC\Http\CookieHelper::setCookie(
935
+            'nc_username',
936
+            $username,
937
+            $maxAge,
938
+            $webRoot,
939
+            '',
940
+            $secureCookie,
941
+            true,
942
+            \OC\Http\CookieHelper::SAMESITE_LAX
943
+        );
944
+        \OC\Http\CookieHelper::setCookie(
945
+            'nc_token',
946
+            $token,
947
+            $maxAge,
948
+            $webRoot,
949
+            '',
950
+            $secureCookie,
951
+            true,
952
+            \OC\Http\CookieHelper::SAMESITE_LAX
953
+        );
954
+        try {
955
+            \OC\Http\CookieHelper::setCookie(
956
+                'nc_session_id',
957
+                $this->session->getId(),
958
+                $maxAge,
959
+                $webRoot,
960
+                '',
961
+                $secureCookie,
962
+                true,
963
+                \OC\Http\CookieHelper::SAMESITE_LAX
964
+            );
965
+        } catch (SessionNotAvailableException $ex) {
966
+            // ignore
967
+        }
968
+    }
969
+
970
+    /**
971
+     * Remove cookie for "remember username"
972
+     */
973
+    public function unsetMagicInCookie() {
974
+        //TODO: DI for cookies and IRequest
975
+        $secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https';
976
+
977
+        unset($_COOKIE['nc_username']); //TODO: DI
978
+        unset($_COOKIE['nc_token']);
979
+        unset($_COOKIE['nc_session_id']);
980
+        setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true);
981
+        setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true);
982
+        setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true);
983
+        // old cookies might be stored under /webroot/ instead of /webroot
984
+        // and Firefox doesn't like it!
985
+        setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
986
+        setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
987
+        setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
988
+    }
989
+
990
+    /**
991
+     * Update password of the browser session token if there is one
992
+     *
993
+     * @param string $password
994
+     */
995
+    public function updateSessionTokenPassword($password) {
996
+        try {
997
+            $sessionId = $this->session->getId();
998
+            $token = $this->tokenProvider->getToken($sessionId);
999
+            $this->tokenProvider->setPassword($token, $sessionId, $password);
1000
+        } catch (SessionNotAvailableException $ex) {
1001
+            // Nothing to do
1002
+        } catch (InvalidTokenException $ex) {
1003
+            // Nothing to do
1004
+        }
1005
+    }
1006
+
1007
+    public function updateTokens(string $uid, string $password) {
1008
+        $this->tokenProvider->updatePasswords($uid, $password);
1009
+    }
1010 1010
 
1011 1011
 
1012 1012
 }
Please login to merge, or discard this patch.
lib/private/AllConfig.php 1 patch
Indentation   +497 added lines, -497 removed lines patch added patch discarded remove patch
@@ -38,501 +38,501 @@
 block discarded – undo
38 38
  * Class to combine all the configuration options ownCloud offers
39 39
  */
40 40
 class AllConfig implements \OCP\IConfig {
41
-	/** @var SystemConfig */
42
-	private $systemConfig;
43
-
44
-	/** @var IDBConnection */
45
-	private $connection;
46
-
47
-	/**
48
-	 * 3 dimensional array with the following structure:
49
-	 * [ $userId =>
50
-	 *     [ $appId =>
51
-	 *         [ $key => $value ]
52
-	 *     ]
53
-	 * ]
54
-	 *
55
-	 * database table: preferences
56
-	 *
57
-	 * methods that use this:
58
-	 *   - setUserValue
59
-	 *   - getUserValue
60
-	 *   - getUserKeys
61
-	 *   - deleteUserValue
62
-	 *   - deleteAllUserValues
63
-	 *   - deleteAppFromAllUsers
64
-	 *
65
-	 * @var CappedMemoryCache $userCache
66
-	 */
67
-	private $userCache;
68
-
69
-	/**
70
-	 * @param SystemConfig $systemConfig
71
-	 */
72
-	public function __construct(SystemConfig $systemConfig) {
73
-		$this->userCache = new CappedMemoryCache();
74
-		$this->systemConfig = $systemConfig;
75
-	}
76
-
77
-	/**
78
-	 * TODO - FIXME This fixes an issue with base.php that cause cyclic
79
-	 * dependencies, especially with autoconfig setup
80
-	 *
81
-	 * Replace this by properly injected database connection. Currently the
82
-	 * base.php triggers the getDatabaseConnection too early which causes in
83
-	 * autoconfig setup case a too early distributed database connection and
84
-	 * the autoconfig then needs to reinit all already initialized dependencies
85
-	 * that use the database connection.
86
-	 *
87
-	 * otherwise a SQLite database is created in the wrong directory
88
-	 * because the database connection was created with an uninitialized config
89
-	 */
90
-	private function fixDIInit() {
91
-		if($this->connection === null) {
92
-			$this->connection = \OC::$server->getDatabaseConnection();
93
-		}
94
-	}
95
-
96
-	/**
97
-	 * Sets and deletes system wide values
98
-	 *
99
-	 * @param array $configs Associative array with `key => value` pairs
100
-	 *                       If value is null, the config key will be deleted
101
-	 */
102
-	public function setSystemValues(array $configs) {
103
-		$this->systemConfig->setValues($configs);
104
-	}
105
-
106
-	/**
107
-	 * Sets a new system wide value
108
-	 *
109
-	 * @param string $key the key of the value, under which will be saved
110
-	 * @param mixed $value the value that should be stored
111
-	 */
112
-	public function setSystemValue($key, $value) {
113
-		$this->systemConfig->setValue($key, $value);
114
-	}
115
-
116
-	/**
117
-	 * Looks up a system wide defined value
118
-	 *
119
-	 * @param string $key the key of the value, under which it was saved
120
-	 * @param mixed $default the default value to be returned if the value isn't set
121
-	 * @return mixed the value or $default
122
-	 */
123
-	public function getSystemValue($key, $default = '') {
124
-		return $this->systemConfig->getValue($key, $default);
125
-	}
126
-
127
-	/**
128
-	 * Looks up a boolean system wide defined value
129
-	 *
130
-	 * @param string $key the key of the value, under which it was saved
131
-	 * @param mixed $default the default value to be returned if the value isn't set
132
-	 *
133
-	 * @return bool
134
-	 *
135
-	 * @since 16.0.0
136
-	 */
137
-	public function getSystemValueBool(string $key, bool $default = false): bool {
138
-		return (bool) $this->getSystemValue($key, $default);
139
-	}
140
-
141
-	/**
142
-	 * Looks up an integer system wide defined value
143
-	 *
144
-	 * @param string $key the key of the value, under which it was saved
145
-	 * @param mixed $default the default value to be returned if the value isn't set
146
-	 *
147
-	 * @return int
148
-	 *
149
-	 * @since 16.0.0
150
-	 */
151
-	public function getSystemValueInt(string $key, int $default = 0): int {
152
-		return (int) $this->getSystemValue($key, $default);
153
-	}
154
-
155
-	/**
156
-	 * Looks up a string system wide defined value
157
-	 *
158
-	 * @param string $key the key of the value, under which it was saved
159
-	 * @param mixed $default the default value to be returned if the value isn't set
160
-	 *
161
-	 * @return string
162
-	 *
163
-	 * @since 16.0.0
164
-	 */
165
-	public function getSystemValueString(string $key, string $default = ''): string {
166
-		return (string) $this->getSystemValue($key, $default);
167
-	}
168
-
169
-	/**
170
-	 * Looks up a system wide defined value and filters out sensitive data
171
-	 *
172
-	 * @param string $key the key of the value, under which it was saved
173
-	 * @param mixed $default the default value to be returned if the value isn't set
174
-	 * @return mixed the value or $default
175
-	 */
176
-	public function getFilteredSystemValue($key, $default = '') {
177
-		return $this->systemConfig->getFilteredValue($key, $default);
178
-	}
179
-
180
-	/**
181
-	 * Delete a system wide defined value
182
-	 *
183
-	 * @param string $key the key of the value, under which it was saved
184
-	 */
185
-	public function deleteSystemValue($key) {
186
-		$this->systemConfig->deleteValue($key);
187
-	}
188
-
189
-	/**
190
-	 * Get all keys stored for an app
191
-	 *
192
-	 * @param string $appName the appName that we stored the value under
193
-	 * @return string[] the keys stored for the app
194
-	 */
195
-	public function getAppKeys($appName) {
196
-		return \OC::$server->query(\OC\AppConfig::class)->getKeys($appName);
197
-	}
198
-
199
-	/**
200
-	 * Writes a new app wide value
201
-	 *
202
-	 * @param string $appName the appName that we want to store the value under
203
-	 * @param string $key the key of the value, under which will be saved
204
-	 * @param string|float|int $value the value that should be stored
205
-	 */
206
-	public function setAppValue($appName, $key, $value) {
207
-		\OC::$server->query(\OC\AppConfig::class)->setValue($appName, $key, $value);
208
-	}
209
-
210
-	/**
211
-	 * Looks up an app wide defined value
212
-	 *
213
-	 * @param string $appName the appName that we stored the value under
214
-	 * @param string $key the key of the value, under which it was saved
215
-	 * @param string $default the default value to be returned if the value isn't set
216
-	 * @return string the saved value
217
-	 */
218
-	public function getAppValue($appName, $key, $default = '') {
219
-		return \OC::$server->query(\OC\AppConfig::class)->getValue($appName, $key, $default);
220
-	}
221
-
222
-	/**
223
-	 * Delete an app wide defined value
224
-	 *
225
-	 * @param string $appName the appName that we stored the value under
226
-	 * @param string $key the key of the value, under which it was saved
227
-	 */
228
-	public function deleteAppValue($appName, $key) {
229
-		\OC::$server->query(\OC\AppConfig::class)->deleteKey($appName, $key);
230
-	}
231
-
232
-	/**
233
-	 * Removes all keys in appconfig belonging to the app
234
-	 *
235
-	 * @param string $appName the appName the configs are stored under
236
-	 */
237
-	public function deleteAppValues($appName) {
238
-		\OC::$server->query(\OC\AppConfig::class)->deleteApp($appName);
239
-	}
240
-
241
-
242
-	/**
243
-	 * Set a user defined value
244
-	 *
245
-	 * @param string $userId the userId of the user that we want to store the value under
246
-	 * @param string $appName the appName that we want to store the value under
247
-	 * @param string $key the key under which the value is being stored
248
-	 * @param string|float|int $value the value that you want to store
249
-	 * @param string $preCondition only update if the config value was previously the value passed as $preCondition
250
-	 * @throws \OCP\PreConditionNotMetException if a precondition is specified and is not met
251
-	 * @throws \UnexpectedValueException when trying to store an unexpected value
252
-	 */
253
-	public function setUserValue($userId, $appName, $key, $value, $preCondition = null) {
254
-		if (!is_int($value) && !is_float($value) && !is_string($value)) {
255
-			throw new \UnexpectedValueException('Only integers, floats and strings are allowed as value');
256
-		}
257
-
258
-		// TODO - FIXME
259
-		$this->fixDIInit();
260
-
261
-		$prevValue = $this->getUserValue($userId, $appName, $key, null);
262
-
263
-		if ($prevValue !== null) {
264
-			if ($prevValue === (string)$value) {
265
-				return;
266
-			} else if ($preCondition !== null && $prevValue !== (string)$preCondition) {
267
-				throw new PreConditionNotMetException();
268
-			} else {
269
-				$qb = $this->connection->getQueryBuilder();
270
-				$qb->update('preferences')
271
-					->set('configvalue', $qb->createNamedParameter($value))
272
-					->where($qb->expr()->eq('userid', $qb->createNamedParameter($userId)))
273
-					->andWhere($qb->expr()->eq('appid', $qb->createNamedParameter($appName)))
274
-					->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter($key)));
275
-				$qb->execute();
276
-
277
-				$this->userCache[$userId][$appName][$key] = (string)$value;
278
-				return;
279
-			}
280
-		}
281
-
282
-		$preconditionArray = [];
283
-		if (isset($preCondition)) {
284
-			$preconditionArray = [
285
-				'configvalue' => $preCondition,
286
-			];
287
-		}
288
-
289
-		$this->connection->setValues('preferences', [
290
-			'userid' => $userId,
291
-			'appid' => $appName,
292
-			'configkey' => $key,
293
-		], [
294
-			'configvalue' => $value,
295
-		], $preconditionArray);
296
-
297
-		// only add to the cache if we already loaded data for the user
298
-		if (isset($this->userCache[$userId])) {
299
-			if (!isset($this->userCache[$userId][$appName])) {
300
-				$this->userCache[$userId][$appName] = array();
301
-			}
302
-			$this->userCache[$userId][$appName][$key] = (string)$value;
303
-		}
304
-	}
305
-
306
-	/**
307
-	 * Getting a user defined value
308
-	 *
309
-	 * @param string $userId the userId of the user that we want to store the value under
310
-	 * @param string $appName the appName that we stored the value under
311
-	 * @param string $key the key under which the value is being stored
312
-	 * @param mixed $default the default value to be returned if the value isn't set
313
-	 * @return string
314
-	 */
315
-	public function getUserValue($userId, $appName, $key, $default = '') {
316
-		$data = $this->getUserValues($userId);
317
-		if (isset($data[$appName]) and isset($data[$appName][$key])) {
318
-			return $data[$appName][$key];
319
-		} else {
320
-			return $default;
321
-		}
322
-	}
323
-
324
-	/**
325
-	 * Get the keys of all stored by an app for the user
326
-	 *
327
-	 * @param string $userId the userId of the user that we want to store the value under
328
-	 * @param string $appName the appName that we stored the value under
329
-	 * @return string[]
330
-	 */
331
-	public function getUserKeys($userId, $appName) {
332
-		$data = $this->getUserValues($userId);
333
-		if (isset($data[$appName])) {
334
-			return array_keys($data[$appName]);
335
-		} else {
336
-			return array();
337
-		}
338
-	}
339
-
340
-	/**
341
-	 * Delete a user value
342
-	 *
343
-	 * @param string $userId the userId of the user that we want to store the value under
344
-	 * @param string $appName the appName that we stored the value under
345
-	 * @param string $key the key under which the value is being stored
346
-	 */
347
-	public function deleteUserValue($userId, $appName, $key) {
348
-		// TODO - FIXME
349
-		$this->fixDIInit();
350
-
351
-		$sql  = 'DELETE FROM `*PREFIX*preferences` '.
352
-				'WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?';
353
-		$this->connection->executeUpdate($sql, array($userId, $appName, $key));
354
-
355
-		if (isset($this->userCache[$userId]) and isset($this->userCache[$userId][$appName])) {
356
-			unset($this->userCache[$userId][$appName][$key]);
357
-		}
358
-	}
359
-
360
-	/**
361
-	 * Delete all user values
362
-	 *
363
-	 * @param string $userId the userId of the user that we want to remove all values from
364
-	 */
365
-	public function deleteAllUserValues($userId) {
366
-		// TODO - FIXME
367
-		$this->fixDIInit();
368
-
369
-		$sql  = 'DELETE FROM `*PREFIX*preferences` '.
370
-			'WHERE `userid` = ?';
371
-		$this->connection->executeUpdate($sql, array($userId));
372
-
373
-		unset($this->userCache[$userId]);
374
-	}
375
-
376
-	/**
377
-	 * Delete all user related values of one app
378
-	 *
379
-	 * @param string $appName the appName of the app that we want to remove all values from
380
-	 */
381
-	public function deleteAppFromAllUsers($appName) {
382
-		// TODO - FIXME
383
-		$this->fixDIInit();
384
-
385
-		$sql  = 'DELETE FROM `*PREFIX*preferences` '.
386
-				'WHERE `appid` = ?';
387
-		$this->connection->executeUpdate($sql, array($appName));
388
-
389
-		foreach ($this->userCache as &$userCache) {
390
-			unset($userCache[$appName]);
391
-		}
392
-	}
393
-
394
-	/**
395
-	 * Returns all user configs sorted by app of one user
396
-	 *
397
-	 * @param string $userId the user ID to get the app configs from
398
-	 * @return array[] - 2 dimensional array with the following structure:
399
-	 *     [ $appId =>
400
-	 *         [ $key => $value ]
401
-	 *     ]
402
-	 */
403
-	private function getUserValues($userId) {
404
-		if (isset($this->userCache[$userId])) {
405
-			return $this->userCache[$userId];
406
-		}
407
-		if ($userId === null || $userId === '') {
408
-			$this->userCache[$userId]=array();
409
-			return $this->userCache[$userId];
410
-		}
411
-
412
-		// TODO - FIXME
413
-		$this->fixDIInit();
414
-
415
-		$data = array();
416
-		$query = 'SELECT `appid`, `configkey`, `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ?';
417
-		$result = $this->connection->executeQuery($query, array($userId));
418
-		while ($row = $result->fetch()) {
419
-			$appId = $row['appid'];
420
-			if (!isset($data[$appId])) {
421
-				$data[$appId] = array();
422
-			}
423
-			$data[$appId][$row['configkey']] = $row['configvalue'];
424
-		}
425
-		$this->userCache[$userId] = $data;
426
-		return $data;
427
-	}
428
-
429
-	/**
430
-	 * Fetches a mapped list of userId -> value, for a specified app and key and a list of user IDs.
431
-	 *
432
-	 * @param string $appName app to get the value for
433
-	 * @param string $key the key to get the value for
434
-	 * @param array $userIds the user IDs to fetch the values for
435
-	 * @return array Mapped values: userId => value
436
-	 */
437
-	public function getUserValueForUsers($appName, $key, $userIds) {
438
-		// TODO - FIXME
439
-		$this->fixDIInit();
440
-
441
-		if (empty($userIds) || !is_array($userIds)) {
442
-			return array();
443
-		}
444
-
445
-		$chunkedUsers = array_chunk($userIds, 50, true);
446
-		$placeholders50 = implode(',', array_fill(0, 50, '?'));
447
-
448
-		$userValues = array();
449
-		foreach ($chunkedUsers as $chunk) {
450
-			$queryParams = $chunk;
451
-			// create [$app, $key, $chunkedUsers]
452
-			array_unshift($queryParams, $key);
453
-			array_unshift($queryParams, $appName);
454
-
455
-			$placeholders = (count($chunk) === 50) ? $placeholders50 :  implode(',', array_fill(0, count($chunk), '?'));
456
-
457
-			$query    = 'SELECT `userid`, `configvalue` ' .
458
-						'FROM `*PREFIX*preferences` ' .
459
-						'WHERE `appid` = ? AND `configkey` = ? ' .
460
-						'AND `userid` IN (' . $placeholders . ')';
461
-			$result = $this->connection->executeQuery($query, $queryParams);
462
-
463
-			while ($row = $result->fetch()) {
464
-				$userValues[$row['userid']] = $row['configvalue'];
465
-			}
466
-		}
467
-
468
-		return $userValues;
469
-	}
470
-
471
-	/**
472
-	 * Determines the users that have the given value set for a specific app-key-pair
473
-	 *
474
-	 * @param string $appName the app to get the user for
475
-	 * @param string $key the key to get the user for
476
-	 * @param string $value the value to get the user for
477
-	 * @return array of user IDs
478
-	 */
479
-	public function getUsersForUserValue($appName, $key, $value) {
480
-		// TODO - FIXME
481
-		$this->fixDIInit();
482
-
483
-		$sql  = 'SELECT `userid` FROM `*PREFIX*preferences` ' .
484
-				'WHERE `appid` = ? AND `configkey` = ? ';
485
-
486
-		if($this->getSystemValue('dbtype', 'sqlite') === 'oci') {
487
-			//oracle hack: need to explicitly cast CLOB to CHAR for comparison
488
-			$sql .= 'AND to_char(`configvalue`) = ?';
489
-		} else {
490
-			$sql .= 'AND `configvalue` = ?';
491
-		}
492
-
493
-		$result = $this->connection->executeQuery($sql, array($appName, $key, $value));
494
-
495
-		$userIDs = array();
496
-		while ($row = $result->fetch()) {
497
-			$userIDs[] = $row['userid'];
498
-		}
499
-
500
-		return $userIDs;
501
-	}
502
-
503
-	/**
504
-	 * Determines the users that have the given value set for a specific app-key-pair
505
-	 *
506
-	 * @param string $appName the app to get the user for
507
-	 * @param string $key the key to get the user for
508
-	 * @param string $value the value to get the user for
509
-	 * @return array of user IDs
510
-	 */
511
-	public function getUsersForUserValueCaseInsensitive($appName, $key, $value) {
512
-		// TODO - FIXME
513
-		$this->fixDIInit();
514
-
515
-		$sql  = 'SELECT `userid` FROM `*PREFIX*preferences` ' .
516
-			'WHERE `appid` = ? AND `configkey` = ? ';
517
-
518
-		if($this->getSystemValue('dbtype', 'sqlite') === 'oci') {
519
-			//oracle hack: need to explicitly cast CLOB to CHAR for comparison
520
-			$sql .= 'AND LOWER(to_char(`configvalue`)) = LOWER(?)';
521
-		} else {
522
-			$sql .= 'AND LOWER(`configvalue`) = LOWER(?)';
523
-		}
524
-
525
-		$result = $this->connection->executeQuery($sql, array($appName, $key, $value));
526
-
527
-		$userIDs = array();
528
-		while ($row = $result->fetch()) {
529
-			$userIDs[] = $row['userid'];
530
-		}
531
-
532
-		return $userIDs;
533
-	}
534
-
535
-	public function getSystemConfig() {
536
-		return $this->systemConfig;
537
-	}
41
+    /** @var SystemConfig */
42
+    private $systemConfig;
43
+
44
+    /** @var IDBConnection */
45
+    private $connection;
46
+
47
+    /**
48
+     * 3 dimensional array with the following structure:
49
+     * [ $userId =>
50
+     *     [ $appId =>
51
+     *         [ $key => $value ]
52
+     *     ]
53
+     * ]
54
+     *
55
+     * database table: preferences
56
+     *
57
+     * methods that use this:
58
+     *   - setUserValue
59
+     *   - getUserValue
60
+     *   - getUserKeys
61
+     *   - deleteUserValue
62
+     *   - deleteAllUserValues
63
+     *   - deleteAppFromAllUsers
64
+     *
65
+     * @var CappedMemoryCache $userCache
66
+     */
67
+    private $userCache;
68
+
69
+    /**
70
+     * @param SystemConfig $systemConfig
71
+     */
72
+    public function __construct(SystemConfig $systemConfig) {
73
+        $this->userCache = new CappedMemoryCache();
74
+        $this->systemConfig = $systemConfig;
75
+    }
76
+
77
+    /**
78
+     * TODO - FIXME This fixes an issue with base.php that cause cyclic
79
+     * dependencies, especially with autoconfig setup
80
+     *
81
+     * Replace this by properly injected database connection. Currently the
82
+     * base.php triggers the getDatabaseConnection too early which causes in
83
+     * autoconfig setup case a too early distributed database connection and
84
+     * the autoconfig then needs to reinit all already initialized dependencies
85
+     * that use the database connection.
86
+     *
87
+     * otherwise a SQLite database is created in the wrong directory
88
+     * because the database connection was created with an uninitialized config
89
+     */
90
+    private function fixDIInit() {
91
+        if($this->connection === null) {
92
+            $this->connection = \OC::$server->getDatabaseConnection();
93
+        }
94
+    }
95
+
96
+    /**
97
+     * Sets and deletes system wide values
98
+     *
99
+     * @param array $configs Associative array with `key => value` pairs
100
+     *                       If value is null, the config key will be deleted
101
+     */
102
+    public function setSystemValues(array $configs) {
103
+        $this->systemConfig->setValues($configs);
104
+    }
105
+
106
+    /**
107
+     * Sets a new system wide value
108
+     *
109
+     * @param string $key the key of the value, under which will be saved
110
+     * @param mixed $value the value that should be stored
111
+     */
112
+    public function setSystemValue($key, $value) {
113
+        $this->systemConfig->setValue($key, $value);
114
+    }
115
+
116
+    /**
117
+     * Looks up a system wide defined value
118
+     *
119
+     * @param string $key the key of the value, under which it was saved
120
+     * @param mixed $default the default value to be returned if the value isn't set
121
+     * @return mixed the value or $default
122
+     */
123
+    public function getSystemValue($key, $default = '') {
124
+        return $this->systemConfig->getValue($key, $default);
125
+    }
126
+
127
+    /**
128
+     * Looks up a boolean system wide defined value
129
+     *
130
+     * @param string $key the key of the value, under which it was saved
131
+     * @param mixed $default the default value to be returned if the value isn't set
132
+     *
133
+     * @return bool
134
+     *
135
+     * @since 16.0.0
136
+     */
137
+    public function getSystemValueBool(string $key, bool $default = false): bool {
138
+        return (bool) $this->getSystemValue($key, $default);
139
+    }
140
+
141
+    /**
142
+     * Looks up an integer system wide defined value
143
+     *
144
+     * @param string $key the key of the value, under which it was saved
145
+     * @param mixed $default the default value to be returned if the value isn't set
146
+     *
147
+     * @return int
148
+     *
149
+     * @since 16.0.0
150
+     */
151
+    public function getSystemValueInt(string $key, int $default = 0): int {
152
+        return (int) $this->getSystemValue($key, $default);
153
+    }
154
+
155
+    /**
156
+     * Looks up a string system wide defined value
157
+     *
158
+     * @param string $key the key of the value, under which it was saved
159
+     * @param mixed $default the default value to be returned if the value isn't set
160
+     *
161
+     * @return string
162
+     *
163
+     * @since 16.0.0
164
+     */
165
+    public function getSystemValueString(string $key, string $default = ''): string {
166
+        return (string) $this->getSystemValue($key, $default);
167
+    }
168
+
169
+    /**
170
+     * Looks up a system wide defined value and filters out sensitive data
171
+     *
172
+     * @param string $key the key of the value, under which it was saved
173
+     * @param mixed $default the default value to be returned if the value isn't set
174
+     * @return mixed the value or $default
175
+     */
176
+    public function getFilteredSystemValue($key, $default = '') {
177
+        return $this->systemConfig->getFilteredValue($key, $default);
178
+    }
179
+
180
+    /**
181
+     * Delete a system wide defined value
182
+     *
183
+     * @param string $key the key of the value, under which it was saved
184
+     */
185
+    public function deleteSystemValue($key) {
186
+        $this->systemConfig->deleteValue($key);
187
+    }
188
+
189
+    /**
190
+     * Get all keys stored for an app
191
+     *
192
+     * @param string $appName the appName that we stored the value under
193
+     * @return string[] the keys stored for the app
194
+     */
195
+    public function getAppKeys($appName) {
196
+        return \OC::$server->query(\OC\AppConfig::class)->getKeys($appName);
197
+    }
198
+
199
+    /**
200
+     * Writes a new app wide value
201
+     *
202
+     * @param string $appName the appName that we want to store the value under
203
+     * @param string $key the key of the value, under which will be saved
204
+     * @param string|float|int $value the value that should be stored
205
+     */
206
+    public function setAppValue($appName, $key, $value) {
207
+        \OC::$server->query(\OC\AppConfig::class)->setValue($appName, $key, $value);
208
+    }
209
+
210
+    /**
211
+     * Looks up an app wide defined value
212
+     *
213
+     * @param string $appName the appName that we stored the value under
214
+     * @param string $key the key of the value, under which it was saved
215
+     * @param string $default the default value to be returned if the value isn't set
216
+     * @return string the saved value
217
+     */
218
+    public function getAppValue($appName, $key, $default = '') {
219
+        return \OC::$server->query(\OC\AppConfig::class)->getValue($appName, $key, $default);
220
+    }
221
+
222
+    /**
223
+     * Delete an app wide defined value
224
+     *
225
+     * @param string $appName the appName that we stored the value under
226
+     * @param string $key the key of the value, under which it was saved
227
+     */
228
+    public function deleteAppValue($appName, $key) {
229
+        \OC::$server->query(\OC\AppConfig::class)->deleteKey($appName, $key);
230
+    }
231
+
232
+    /**
233
+     * Removes all keys in appconfig belonging to the app
234
+     *
235
+     * @param string $appName the appName the configs are stored under
236
+     */
237
+    public function deleteAppValues($appName) {
238
+        \OC::$server->query(\OC\AppConfig::class)->deleteApp($appName);
239
+    }
240
+
241
+
242
+    /**
243
+     * Set a user defined value
244
+     *
245
+     * @param string $userId the userId of the user that we want to store the value under
246
+     * @param string $appName the appName that we want to store the value under
247
+     * @param string $key the key under which the value is being stored
248
+     * @param string|float|int $value the value that you want to store
249
+     * @param string $preCondition only update if the config value was previously the value passed as $preCondition
250
+     * @throws \OCP\PreConditionNotMetException if a precondition is specified and is not met
251
+     * @throws \UnexpectedValueException when trying to store an unexpected value
252
+     */
253
+    public function setUserValue($userId, $appName, $key, $value, $preCondition = null) {
254
+        if (!is_int($value) && !is_float($value) && !is_string($value)) {
255
+            throw new \UnexpectedValueException('Only integers, floats and strings are allowed as value');
256
+        }
257
+
258
+        // TODO - FIXME
259
+        $this->fixDIInit();
260
+
261
+        $prevValue = $this->getUserValue($userId, $appName, $key, null);
262
+
263
+        if ($prevValue !== null) {
264
+            if ($prevValue === (string)$value) {
265
+                return;
266
+            } else if ($preCondition !== null && $prevValue !== (string)$preCondition) {
267
+                throw new PreConditionNotMetException();
268
+            } else {
269
+                $qb = $this->connection->getQueryBuilder();
270
+                $qb->update('preferences')
271
+                    ->set('configvalue', $qb->createNamedParameter($value))
272
+                    ->where($qb->expr()->eq('userid', $qb->createNamedParameter($userId)))
273
+                    ->andWhere($qb->expr()->eq('appid', $qb->createNamedParameter($appName)))
274
+                    ->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter($key)));
275
+                $qb->execute();
276
+
277
+                $this->userCache[$userId][$appName][$key] = (string)$value;
278
+                return;
279
+            }
280
+        }
281
+
282
+        $preconditionArray = [];
283
+        if (isset($preCondition)) {
284
+            $preconditionArray = [
285
+                'configvalue' => $preCondition,
286
+            ];
287
+        }
288
+
289
+        $this->connection->setValues('preferences', [
290
+            'userid' => $userId,
291
+            'appid' => $appName,
292
+            'configkey' => $key,
293
+        ], [
294
+            'configvalue' => $value,
295
+        ], $preconditionArray);
296
+
297
+        // only add to the cache if we already loaded data for the user
298
+        if (isset($this->userCache[$userId])) {
299
+            if (!isset($this->userCache[$userId][$appName])) {
300
+                $this->userCache[$userId][$appName] = array();
301
+            }
302
+            $this->userCache[$userId][$appName][$key] = (string)$value;
303
+        }
304
+    }
305
+
306
+    /**
307
+     * Getting a user defined value
308
+     *
309
+     * @param string $userId the userId of the user that we want to store the value under
310
+     * @param string $appName the appName that we stored the value under
311
+     * @param string $key the key under which the value is being stored
312
+     * @param mixed $default the default value to be returned if the value isn't set
313
+     * @return string
314
+     */
315
+    public function getUserValue($userId, $appName, $key, $default = '') {
316
+        $data = $this->getUserValues($userId);
317
+        if (isset($data[$appName]) and isset($data[$appName][$key])) {
318
+            return $data[$appName][$key];
319
+        } else {
320
+            return $default;
321
+        }
322
+    }
323
+
324
+    /**
325
+     * Get the keys of all stored by an app for the user
326
+     *
327
+     * @param string $userId the userId of the user that we want to store the value under
328
+     * @param string $appName the appName that we stored the value under
329
+     * @return string[]
330
+     */
331
+    public function getUserKeys($userId, $appName) {
332
+        $data = $this->getUserValues($userId);
333
+        if (isset($data[$appName])) {
334
+            return array_keys($data[$appName]);
335
+        } else {
336
+            return array();
337
+        }
338
+    }
339
+
340
+    /**
341
+     * Delete a user value
342
+     *
343
+     * @param string $userId the userId of the user that we want to store the value under
344
+     * @param string $appName the appName that we stored the value under
345
+     * @param string $key the key under which the value is being stored
346
+     */
347
+    public function deleteUserValue($userId, $appName, $key) {
348
+        // TODO - FIXME
349
+        $this->fixDIInit();
350
+
351
+        $sql  = 'DELETE FROM `*PREFIX*preferences` '.
352
+                'WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?';
353
+        $this->connection->executeUpdate($sql, array($userId, $appName, $key));
354
+
355
+        if (isset($this->userCache[$userId]) and isset($this->userCache[$userId][$appName])) {
356
+            unset($this->userCache[$userId][$appName][$key]);
357
+        }
358
+    }
359
+
360
+    /**
361
+     * Delete all user values
362
+     *
363
+     * @param string $userId the userId of the user that we want to remove all values from
364
+     */
365
+    public function deleteAllUserValues($userId) {
366
+        // TODO - FIXME
367
+        $this->fixDIInit();
368
+
369
+        $sql  = 'DELETE FROM `*PREFIX*preferences` '.
370
+            'WHERE `userid` = ?';
371
+        $this->connection->executeUpdate($sql, array($userId));
372
+
373
+        unset($this->userCache[$userId]);
374
+    }
375
+
376
+    /**
377
+     * Delete all user related values of one app
378
+     *
379
+     * @param string $appName the appName of the app that we want to remove all values from
380
+     */
381
+    public function deleteAppFromAllUsers($appName) {
382
+        // TODO - FIXME
383
+        $this->fixDIInit();
384
+
385
+        $sql  = 'DELETE FROM `*PREFIX*preferences` '.
386
+                'WHERE `appid` = ?';
387
+        $this->connection->executeUpdate($sql, array($appName));
388
+
389
+        foreach ($this->userCache as &$userCache) {
390
+            unset($userCache[$appName]);
391
+        }
392
+    }
393
+
394
+    /**
395
+     * Returns all user configs sorted by app of one user
396
+     *
397
+     * @param string $userId the user ID to get the app configs from
398
+     * @return array[] - 2 dimensional array with the following structure:
399
+     *     [ $appId =>
400
+     *         [ $key => $value ]
401
+     *     ]
402
+     */
403
+    private function getUserValues($userId) {
404
+        if (isset($this->userCache[$userId])) {
405
+            return $this->userCache[$userId];
406
+        }
407
+        if ($userId === null || $userId === '') {
408
+            $this->userCache[$userId]=array();
409
+            return $this->userCache[$userId];
410
+        }
411
+
412
+        // TODO - FIXME
413
+        $this->fixDIInit();
414
+
415
+        $data = array();
416
+        $query = 'SELECT `appid`, `configkey`, `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ?';
417
+        $result = $this->connection->executeQuery($query, array($userId));
418
+        while ($row = $result->fetch()) {
419
+            $appId = $row['appid'];
420
+            if (!isset($data[$appId])) {
421
+                $data[$appId] = array();
422
+            }
423
+            $data[$appId][$row['configkey']] = $row['configvalue'];
424
+        }
425
+        $this->userCache[$userId] = $data;
426
+        return $data;
427
+    }
428
+
429
+    /**
430
+     * Fetches a mapped list of userId -> value, for a specified app and key and a list of user IDs.
431
+     *
432
+     * @param string $appName app to get the value for
433
+     * @param string $key the key to get the value for
434
+     * @param array $userIds the user IDs to fetch the values for
435
+     * @return array Mapped values: userId => value
436
+     */
437
+    public function getUserValueForUsers($appName, $key, $userIds) {
438
+        // TODO - FIXME
439
+        $this->fixDIInit();
440
+
441
+        if (empty($userIds) || !is_array($userIds)) {
442
+            return array();
443
+        }
444
+
445
+        $chunkedUsers = array_chunk($userIds, 50, true);
446
+        $placeholders50 = implode(',', array_fill(0, 50, '?'));
447
+
448
+        $userValues = array();
449
+        foreach ($chunkedUsers as $chunk) {
450
+            $queryParams = $chunk;
451
+            // create [$app, $key, $chunkedUsers]
452
+            array_unshift($queryParams, $key);
453
+            array_unshift($queryParams, $appName);
454
+
455
+            $placeholders = (count($chunk) === 50) ? $placeholders50 :  implode(',', array_fill(0, count($chunk), '?'));
456
+
457
+            $query    = 'SELECT `userid`, `configvalue` ' .
458
+                        'FROM `*PREFIX*preferences` ' .
459
+                        'WHERE `appid` = ? AND `configkey` = ? ' .
460
+                        'AND `userid` IN (' . $placeholders . ')';
461
+            $result = $this->connection->executeQuery($query, $queryParams);
462
+
463
+            while ($row = $result->fetch()) {
464
+                $userValues[$row['userid']] = $row['configvalue'];
465
+            }
466
+        }
467
+
468
+        return $userValues;
469
+    }
470
+
471
+    /**
472
+     * Determines the users that have the given value set for a specific app-key-pair
473
+     *
474
+     * @param string $appName the app to get the user for
475
+     * @param string $key the key to get the user for
476
+     * @param string $value the value to get the user for
477
+     * @return array of user IDs
478
+     */
479
+    public function getUsersForUserValue($appName, $key, $value) {
480
+        // TODO - FIXME
481
+        $this->fixDIInit();
482
+
483
+        $sql  = 'SELECT `userid` FROM `*PREFIX*preferences` ' .
484
+                'WHERE `appid` = ? AND `configkey` = ? ';
485
+
486
+        if($this->getSystemValue('dbtype', 'sqlite') === 'oci') {
487
+            //oracle hack: need to explicitly cast CLOB to CHAR for comparison
488
+            $sql .= 'AND to_char(`configvalue`) = ?';
489
+        } else {
490
+            $sql .= 'AND `configvalue` = ?';
491
+        }
492
+
493
+        $result = $this->connection->executeQuery($sql, array($appName, $key, $value));
494
+
495
+        $userIDs = array();
496
+        while ($row = $result->fetch()) {
497
+            $userIDs[] = $row['userid'];
498
+        }
499
+
500
+        return $userIDs;
501
+    }
502
+
503
+    /**
504
+     * Determines the users that have the given value set for a specific app-key-pair
505
+     *
506
+     * @param string $appName the app to get the user for
507
+     * @param string $key the key to get the user for
508
+     * @param string $value the value to get the user for
509
+     * @return array of user IDs
510
+     */
511
+    public function getUsersForUserValueCaseInsensitive($appName, $key, $value) {
512
+        // TODO - FIXME
513
+        $this->fixDIInit();
514
+
515
+        $sql  = 'SELECT `userid` FROM `*PREFIX*preferences` ' .
516
+            'WHERE `appid` = ? AND `configkey` = ? ';
517
+
518
+        if($this->getSystemValue('dbtype', 'sqlite') === 'oci') {
519
+            //oracle hack: need to explicitly cast CLOB to CHAR for comparison
520
+            $sql .= 'AND LOWER(to_char(`configvalue`)) = LOWER(?)';
521
+        } else {
522
+            $sql .= 'AND LOWER(`configvalue`) = LOWER(?)';
523
+        }
524
+
525
+        $result = $this->connection->executeQuery($sql, array($appName, $key, $value));
526
+
527
+        $userIDs = array();
528
+        while ($row = $result->fetch()) {
529
+            $userIDs[] = $row['userid'];
530
+        }
531
+
532
+        return $userIDs;
533
+    }
534
+
535
+    public function getSystemConfig() {
536
+        return $this->systemConfig;
537
+    }
538 538
 }
Please login to merge, or discard this patch.
lib/private/Group/Database.php 1 patch
Indentation   +412 added lines, -412 removed lines patch added patch discarded remove patch
@@ -60,417 +60,417 @@
 block discarded – undo
60 60
  * Class for group management in a SQL Database (e.g. MySQL, SQLite)
61 61
  */
62 62
 class Database extends ABackend
63
-	implements IAddToGroupBackend,
64
-	           ICountDisabledInGroup,
65
-	           ICountUsersBackend,
66
-	           ICreateGroupBackend,
67
-	           IDeleteGroupBackend,
68
-	           IGetDisplayNameBackend,
69
-	           IGroupDetailsBackend,
70
-	           IRemoveFromGroupBackend,
71
-	           ISetDisplayNameBackend {
72
-
73
-	/** @var string[] */
74
-	private $groupCache = [];
75
-
76
-	/** @var IDBConnection */
77
-	private $dbConn;
78
-
79
-	/**
80
-	 * \OC\Group\Database constructor.
81
-	 *
82
-	 * @param IDBConnection|null $dbConn
83
-	 */
84
-	public function __construct(IDBConnection $dbConn = null) {
85
-		$this->dbConn = $dbConn;
86
-	}
87
-
88
-	/**
89
-	 * FIXME: This function should not be required!
90
-	 */
91
-	private function fixDI() {
92
-		if ($this->dbConn === null) {
93
-			$this->dbConn = \OC::$server->getDatabaseConnection();
94
-		}
95
-	}
96
-
97
-	/**
98
-	 * Try to create a new group
99
-	 * @param string $gid The name of the group to create
100
-	 * @return bool
101
-	 *
102
-	 * Tries to create a new group. If the group name already exists, false will
103
-	 * be returned.
104
-	 */
105
-	public function createGroup(string $gid): bool {
106
-		$this->fixDI();
107
-
108
-		try {
109
-			// Add group
110
-			$builder = $this->dbConn->getQueryBuilder();
111
-			$result = $builder->insert('groups')
112
-				->setValue('gid', $builder->createNamedParameter($gid))
113
-				->setValue('displayname', $builder->createNamedParameter($gid))
114
-				->execute();
115
-		} catch(UniqueConstraintViolationException $e) {
116
-			$result = 0;
117
-		}
118
-
119
-		// Add to cache
120
-		$this->groupCache[$gid] = $gid;
121
-
122
-		return $result === 1;
123
-	}
124
-
125
-	/**
126
-	 * delete a group
127
-	 * @param string $gid gid of the group to delete
128
-	 * @return bool
129
-	 *
130
-	 * Deletes a group and removes it from the group_user-table
131
-	 */
132
-	public function deleteGroup(string $gid): bool {
133
-		$this->fixDI();
134
-
135
-		// Delete the group
136
-		$qb = $this->dbConn->getQueryBuilder();
137
-		$qb->delete('groups')
138
-			->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
139
-			->execute();
140
-
141
-		// Delete the group-user relation
142
-		$qb = $this->dbConn->getQueryBuilder();
143
-		$qb->delete('group_user')
144
-			->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
145
-			->execute();
146
-
147
-		// Delete the group-groupadmin relation
148
-		$qb = $this->dbConn->getQueryBuilder();
149
-		$qb->delete('group_admin')
150
-			->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
151
-			->execute();
152
-
153
-		// Delete from cache
154
-		unset($this->groupCache[$gid]);
155
-
156
-		return true;
157
-	}
158
-
159
-	/**
160
-	 * is user in group?
161
-	 * @param string $uid uid of the user
162
-	 * @param string $gid gid of the group
163
-	 * @return bool
164
-	 *
165
-	 * Checks whether the user is member of a group or not.
166
-	 */
167
-	public function inGroup( $uid, $gid ) {
168
-		$this->fixDI();
169
-
170
-		// check
171
-		$qb = $this->dbConn->getQueryBuilder();
172
-		$cursor = $qb->select('uid')
173
-			->from('group_user')
174
-			->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
175
-			->andWhere($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
176
-			->execute();
177
-
178
-		$result = $cursor->fetch();
179
-		$cursor->closeCursor();
180
-
181
-		return $result ? true : false;
182
-	}
183
-
184
-	/**
185
-	 * Add a user to a group
186
-	 * @param string $uid Name of the user to add to group
187
-	 * @param string $gid Name of the group in which add the user
188
-	 * @return bool
189
-	 *
190
-	 * Adds a user to a group.
191
-	 */
192
-	public function addToGroup(string $uid, string $gid): bool {
193
-		$this->fixDI();
194
-
195
-		// No duplicate entries!
196
-		if( !$this->inGroup( $uid, $gid )) {
197
-			$qb = $this->dbConn->getQueryBuilder();
198
-			$qb->insert('group_user')
199
-				->setValue('uid', $qb->createNamedParameter($uid))
200
-				->setValue('gid', $qb->createNamedParameter($gid))
201
-				->execute();
202
-			return true;
203
-		}else{
204
-			return false;
205
-		}
206
-	}
207
-
208
-	/**
209
-	 * Removes a user from a group
210
-	 * @param string $uid Name of the user to remove from group
211
-	 * @param string $gid Name of the group from which remove the user
212
-	 * @return bool
213
-	 *
214
-	 * removes the user from a group.
215
-	 */
216
-	public function removeFromGroup(string $uid, string $gid): bool {
217
-		$this->fixDI();
218
-
219
-		$qb = $this->dbConn->getQueryBuilder();
220
-		$qb->delete('group_user')
221
-			->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
222
-			->andWhere($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
223
-			->execute();
224
-
225
-		return true;
226
-	}
227
-
228
-	/**
229
-	 * Get all groups a user belongs to
230
-	 * @param string $uid Name of the user
231
-	 * @return array an array of group names
232
-	 *
233
-	 * This function fetches all groups a user belongs to. It does not check
234
-	 * if the user exists at all.
235
-	 */
236
-	public function getUserGroups( $uid ) {
237
-		//guests has empty or null $uid
238
-		if ($uid === null || $uid === '') {
239
-			return [];
240
-		}
241
-
242
-		$this->fixDI();
243
-
244
-		// No magic!
245
-		$qb = $this->dbConn->getQueryBuilder();
246
-		$cursor = $qb->select('gid')
247
-			->from('group_user')
248
-			->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
249
-			->execute();
250
-
251
-		$groups = [];
252
-		while( $row = $cursor->fetch()) {
253
-			$groups[] = $row['gid'];
254
-			$this->groupCache[$row['gid']] = $row['gid'];
255
-		}
256
-		$cursor->closeCursor();
257
-
258
-		return $groups;
259
-	}
260
-
261
-	/**
262
-	 * get a list of all groups
263
-	 * @param string $search
264
-	 * @param int $limit
265
-	 * @param int $offset
266
-	 * @return array an array of group names
267
-	 *
268
-	 * Returns a list with all groups
269
-	 */
270
-	public function getGroups($search = '', $limit = null, $offset = null) {
271
-		$this->fixDI();
272
-
273
-		$query = $this->dbConn->getQueryBuilder();
274
-		$query->select('gid')
275
-			->from('groups')
276
-			->orderBy('gid', 'ASC');
277
-
278
-		if ($search !== '') {
279
-			$query->where($query->expr()->iLike('gid', $query->createNamedParameter(
280
-				'%' . $this->dbConn->escapeLikeParameter($search) . '%'
281
-			)));
282
-		}
283
-
284
-		$query->setMaxResults($limit)
285
-			->setFirstResult($offset);
286
-		$result = $query->execute();
287
-
288
-		$groups = [];
289
-		while ($row = $result->fetch()) {
290
-			$groups[] = $row['gid'];
291
-		}
292
-		$result->closeCursor();
293
-
294
-		return $groups;
295
-	}
296
-
297
-	/**
298
-	 * check if a group exists
299
-	 * @param string $gid
300
-	 * @return bool
301
-	 */
302
-	public function groupExists($gid) {
303
-		$this->fixDI();
304
-
305
-		// Check cache first
306
-		if (isset($this->groupCache[$gid])) {
307
-			return true;
308
-		}
309
-
310
-		$qb = $this->dbConn->getQueryBuilder();
311
-		$cursor = $qb->select('gid')
312
-			->from('groups')
313
-			->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
314
-			->execute();
315
-		$result = $cursor->fetch();
316
-		$cursor->closeCursor();
317
-
318
-		if ($result !== false) {
319
-			$this->groupCache[$gid] = $gid;
320
-			return true;
321
-		}
322
-		return false;
323
-	}
324
-
325
-	/**
326
-	 * get a list of all users in a group
327
-	 * @param string $gid
328
-	 * @param string $search
329
-	 * @param int $limit
330
-	 * @param int $offset
331
-	 * @return array an array of user ids
332
-	 */
333
-	public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0) {
334
-		$this->fixDI();
335
-
336
-		$query = $this->dbConn->getQueryBuilder();
337
-		$query->select('uid')
338
-			->from('group_user')
339
-			->where($query->expr()->eq('gid', $query->createNamedParameter($gid)))
340
-			->orderBy('uid', 'ASC');
341
-
342
-		if ($search !== '') {
343
-			$query->andWhere($query->expr()->like('uid', $query->createNamedParameter(
344
-				'%' . $this->dbConn->escapeLikeParameter($search) . '%'
345
-			)));
346
-		}
347
-
348
-		if ($limit !== -1) {
349
-			$query->setMaxResults($limit);
350
-		}
351
-		if ($offset !== 0) {
352
-			$query->setFirstResult($offset);
353
-		}
354
-
355
-		$result = $query->execute();
356
-
357
-		$users = [];
358
-		while ($row = $result->fetch()) {
359
-			$users[] = $row['uid'];
360
-		}
361
-		$result->closeCursor();
362
-
363
-		return $users;
364
-	}
365
-
366
-	/**
367
-	 * get the number of all users matching the search string in a group
368
-	 * @param string $gid
369
-	 * @param string $search
370
-	 * @return int
371
-	 */
372
-	public function countUsersInGroup(string $gid, string $search = ''): int {
373
-		$this->fixDI();
374
-
375
-		$query = $this->dbConn->getQueryBuilder();
376
-		$query->select($query->func()->count('*', 'num_users'))
377
-			->from('group_user')
378
-			->where($query->expr()->eq('gid', $query->createNamedParameter($gid)));
379
-
380
-		if ($search !== '') {
381
-			$query->andWhere($query->expr()->like('uid', $query->createNamedParameter(
382
-				'%' . $this->dbConn->escapeLikeParameter($search) . '%'
383
-			)));
384
-		}
385
-
386
-		$result = $query->execute();
387
-		$count = $result->fetchColumn();
388
-		$result->closeCursor();
389
-
390
-		if ($count !== false) {
391
-			$count = (int)$count;
392
-		} else {
393
-			$count = 0;
394
-		}
395
-
396
-		return $count;
397
-	}
398
-
399
-	/**
400
-	 * get the number of disabled users in a group
401
-	 *
402
-	 * @param string $search
403
-	 *
404
-	 * @return int
405
-	 */
406
-	public function countDisabledInGroup(string $gid): int {
407
-		$this->fixDI();
408
-
409
-		$query = $this->dbConn->getQueryBuilder();
410
-		$query->select($query->createFunction('COUNT(DISTINCT ' . $query->getColumnName('uid') . ')'))
411
-			->from('preferences', 'p')
412
-			->innerJoin('p', 'group_user', 'g', $query->expr()->eq('p.userid', 'g.uid'))
413
-			->where($query->expr()->eq('appid', $query->createNamedParameter('core')))
414
-			->andWhere($query->expr()->eq('configkey', $query->createNamedParameter('enabled')))
415
-			->andWhere($query->expr()->eq('configvalue', $query->createNamedParameter('false'), IQueryBuilder::PARAM_STR))
416
-			->andWhere($query->expr()->eq('gid', $query->createNamedParameter($gid), IQueryBuilder::PARAM_STR));
417
-
418
-		$result = $query->execute();
419
-		$count = $result->fetchColumn();
420
-		$result->closeCursor();
421
-
422
-		if ($count !== false) {
423
-			$count = (int)$count;
424
-		} else {
425
-			$count = 0;
426
-		}
427
-
428
-		return $count;
429
-	}
430
-
431
-	public function getDisplayName(string $gid): string {
432
-		$this->fixDI();
433
-
434
-		$query = $this->dbConn->getQueryBuilder();
435
-		$query->select('displayname')
436
-			->from('groups')
437
-			->where($query->expr()->eq('gid', $query->createNamedParameter($gid)));
438
-
439
-		$result = $query->execute();
440
-		$displayName = $result->fetchColumn();
441
-		$result->closeCursor();
442
-
443
-		return (string) $displayName;
444
-	}
445
-
446
-	public function getGroupDetails(string $gid): array {
447
-		$displayName = $this->getDisplayName($gid);
448
-		if ($displayName !== '') {
449
-			return ['displayName' => $displayName];
450
-		}
451
-
452
-		return [];
453
-	}
454
-
455
-	public function setDisplayName(string $gid, string $displayName): bool {
456
-		if (!$this->groupExists($gid)) {
457
-			return false;
458
-		}
459
-
460
-		$this->fixDI();
461
-
462
-		$displayName = trim($displayName);
463
-		if ($displayName === '') {
464
-			$displayName = $gid;
465
-		}
466
-
467
-		$query = $this->dbConn->getQueryBuilder();
468
-		$query->update('groups')
469
-			->set('displayname', $query->createNamedParameter($displayName))
470
-			->where($query->expr()->eq('gid', $query->createNamedParameter($gid)));
471
-		$query->execute();
472
-
473
-		return true;
474
-	}
63
+    implements IAddToGroupBackend,
64
+                ICountDisabledInGroup,
65
+                ICountUsersBackend,
66
+                ICreateGroupBackend,
67
+                IDeleteGroupBackend,
68
+                IGetDisplayNameBackend,
69
+                IGroupDetailsBackend,
70
+                IRemoveFromGroupBackend,
71
+                ISetDisplayNameBackend {
72
+
73
+    /** @var string[] */
74
+    private $groupCache = [];
75
+
76
+    /** @var IDBConnection */
77
+    private $dbConn;
78
+
79
+    /**
80
+     * \OC\Group\Database constructor.
81
+     *
82
+     * @param IDBConnection|null $dbConn
83
+     */
84
+    public function __construct(IDBConnection $dbConn = null) {
85
+        $this->dbConn = $dbConn;
86
+    }
87
+
88
+    /**
89
+     * FIXME: This function should not be required!
90
+     */
91
+    private function fixDI() {
92
+        if ($this->dbConn === null) {
93
+            $this->dbConn = \OC::$server->getDatabaseConnection();
94
+        }
95
+    }
96
+
97
+    /**
98
+     * Try to create a new group
99
+     * @param string $gid The name of the group to create
100
+     * @return bool
101
+     *
102
+     * Tries to create a new group. If the group name already exists, false will
103
+     * be returned.
104
+     */
105
+    public function createGroup(string $gid): bool {
106
+        $this->fixDI();
107
+
108
+        try {
109
+            // Add group
110
+            $builder = $this->dbConn->getQueryBuilder();
111
+            $result = $builder->insert('groups')
112
+                ->setValue('gid', $builder->createNamedParameter($gid))
113
+                ->setValue('displayname', $builder->createNamedParameter($gid))
114
+                ->execute();
115
+        } catch(UniqueConstraintViolationException $e) {
116
+            $result = 0;
117
+        }
118
+
119
+        // Add to cache
120
+        $this->groupCache[$gid] = $gid;
121
+
122
+        return $result === 1;
123
+    }
124
+
125
+    /**
126
+     * delete a group
127
+     * @param string $gid gid of the group to delete
128
+     * @return bool
129
+     *
130
+     * Deletes a group and removes it from the group_user-table
131
+     */
132
+    public function deleteGroup(string $gid): bool {
133
+        $this->fixDI();
134
+
135
+        // Delete the group
136
+        $qb = $this->dbConn->getQueryBuilder();
137
+        $qb->delete('groups')
138
+            ->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
139
+            ->execute();
140
+
141
+        // Delete the group-user relation
142
+        $qb = $this->dbConn->getQueryBuilder();
143
+        $qb->delete('group_user')
144
+            ->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
145
+            ->execute();
146
+
147
+        // Delete the group-groupadmin relation
148
+        $qb = $this->dbConn->getQueryBuilder();
149
+        $qb->delete('group_admin')
150
+            ->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
151
+            ->execute();
152
+
153
+        // Delete from cache
154
+        unset($this->groupCache[$gid]);
155
+
156
+        return true;
157
+    }
158
+
159
+    /**
160
+     * is user in group?
161
+     * @param string $uid uid of the user
162
+     * @param string $gid gid of the group
163
+     * @return bool
164
+     *
165
+     * Checks whether the user is member of a group or not.
166
+     */
167
+    public function inGroup( $uid, $gid ) {
168
+        $this->fixDI();
169
+
170
+        // check
171
+        $qb = $this->dbConn->getQueryBuilder();
172
+        $cursor = $qb->select('uid')
173
+            ->from('group_user')
174
+            ->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
175
+            ->andWhere($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
176
+            ->execute();
177
+
178
+        $result = $cursor->fetch();
179
+        $cursor->closeCursor();
180
+
181
+        return $result ? true : false;
182
+    }
183
+
184
+    /**
185
+     * Add a user to a group
186
+     * @param string $uid Name of the user to add to group
187
+     * @param string $gid Name of the group in which add the user
188
+     * @return bool
189
+     *
190
+     * Adds a user to a group.
191
+     */
192
+    public function addToGroup(string $uid, string $gid): bool {
193
+        $this->fixDI();
194
+
195
+        // No duplicate entries!
196
+        if( !$this->inGroup( $uid, $gid )) {
197
+            $qb = $this->dbConn->getQueryBuilder();
198
+            $qb->insert('group_user')
199
+                ->setValue('uid', $qb->createNamedParameter($uid))
200
+                ->setValue('gid', $qb->createNamedParameter($gid))
201
+                ->execute();
202
+            return true;
203
+        }else{
204
+            return false;
205
+        }
206
+    }
207
+
208
+    /**
209
+     * Removes a user from a group
210
+     * @param string $uid Name of the user to remove from group
211
+     * @param string $gid Name of the group from which remove the user
212
+     * @return bool
213
+     *
214
+     * removes the user from a group.
215
+     */
216
+    public function removeFromGroup(string $uid, string $gid): bool {
217
+        $this->fixDI();
218
+
219
+        $qb = $this->dbConn->getQueryBuilder();
220
+        $qb->delete('group_user')
221
+            ->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
222
+            ->andWhere($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
223
+            ->execute();
224
+
225
+        return true;
226
+    }
227
+
228
+    /**
229
+     * Get all groups a user belongs to
230
+     * @param string $uid Name of the user
231
+     * @return array an array of group names
232
+     *
233
+     * This function fetches all groups a user belongs to. It does not check
234
+     * if the user exists at all.
235
+     */
236
+    public function getUserGroups( $uid ) {
237
+        //guests has empty or null $uid
238
+        if ($uid === null || $uid === '') {
239
+            return [];
240
+        }
241
+
242
+        $this->fixDI();
243
+
244
+        // No magic!
245
+        $qb = $this->dbConn->getQueryBuilder();
246
+        $cursor = $qb->select('gid')
247
+            ->from('group_user')
248
+            ->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
249
+            ->execute();
250
+
251
+        $groups = [];
252
+        while( $row = $cursor->fetch()) {
253
+            $groups[] = $row['gid'];
254
+            $this->groupCache[$row['gid']] = $row['gid'];
255
+        }
256
+        $cursor->closeCursor();
257
+
258
+        return $groups;
259
+    }
260
+
261
+    /**
262
+     * get a list of all groups
263
+     * @param string $search
264
+     * @param int $limit
265
+     * @param int $offset
266
+     * @return array an array of group names
267
+     *
268
+     * Returns a list with all groups
269
+     */
270
+    public function getGroups($search = '', $limit = null, $offset = null) {
271
+        $this->fixDI();
272
+
273
+        $query = $this->dbConn->getQueryBuilder();
274
+        $query->select('gid')
275
+            ->from('groups')
276
+            ->orderBy('gid', 'ASC');
277
+
278
+        if ($search !== '') {
279
+            $query->where($query->expr()->iLike('gid', $query->createNamedParameter(
280
+                '%' . $this->dbConn->escapeLikeParameter($search) . '%'
281
+            )));
282
+        }
283
+
284
+        $query->setMaxResults($limit)
285
+            ->setFirstResult($offset);
286
+        $result = $query->execute();
287
+
288
+        $groups = [];
289
+        while ($row = $result->fetch()) {
290
+            $groups[] = $row['gid'];
291
+        }
292
+        $result->closeCursor();
293
+
294
+        return $groups;
295
+    }
296
+
297
+    /**
298
+     * check if a group exists
299
+     * @param string $gid
300
+     * @return bool
301
+     */
302
+    public function groupExists($gid) {
303
+        $this->fixDI();
304
+
305
+        // Check cache first
306
+        if (isset($this->groupCache[$gid])) {
307
+            return true;
308
+        }
309
+
310
+        $qb = $this->dbConn->getQueryBuilder();
311
+        $cursor = $qb->select('gid')
312
+            ->from('groups')
313
+            ->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
314
+            ->execute();
315
+        $result = $cursor->fetch();
316
+        $cursor->closeCursor();
317
+
318
+        if ($result !== false) {
319
+            $this->groupCache[$gid] = $gid;
320
+            return true;
321
+        }
322
+        return false;
323
+    }
324
+
325
+    /**
326
+     * get a list of all users in a group
327
+     * @param string $gid
328
+     * @param string $search
329
+     * @param int $limit
330
+     * @param int $offset
331
+     * @return array an array of user ids
332
+     */
333
+    public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0) {
334
+        $this->fixDI();
335
+
336
+        $query = $this->dbConn->getQueryBuilder();
337
+        $query->select('uid')
338
+            ->from('group_user')
339
+            ->where($query->expr()->eq('gid', $query->createNamedParameter($gid)))
340
+            ->orderBy('uid', 'ASC');
341
+
342
+        if ($search !== '') {
343
+            $query->andWhere($query->expr()->like('uid', $query->createNamedParameter(
344
+                '%' . $this->dbConn->escapeLikeParameter($search) . '%'
345
+            )));
346
+        }
347
+
348
+        if ($limit !== -1) {
349
+            $query->setMaxResults($limit);
350
+        }
351
+        if ($offset !== 0) {
352
+            $query->setFirstResult($offset);
353
+        }
354
+
355
+        $result = $query->execute();
356
+
357
+        $users = [];
358
+        while ($row = $result->fetch()) {
359
+            $users[] = $row['uid'];
360
+        }
361
+        $result->closeCursor();
362
+
363
+        return $users;
364
+    }
365
+
366
+    /**
367
+     * get the number of all users matching the search string in a group
368
+     * @param string $gid
369
+     * @param string $search
370
+     * @return int
371
+     */
372
+    public function countUsersInGroup(string $gid, string $search = ''): int {
373
+        $this->fixDI();
374
+
375
+        $query = $this->dbConn->getQueryBuilder();
376
+        $query->select($query->func()->count('*', 'num_users'))
377
+            ->from('group_user')
378
+            ->where($query->expr()->eq('gid', $query->createNamedParameter($gid)));
379
+
380
+        if ($search !== '') {
381
+            $query->andWhere($query->expr()->like('uid', $query->createNamedParameter(
382
+                '%' . $this->dbConn->escapeLikeParameter($search) . '%'
383
+            )));
384
+        }
385
+
386
+        $result = $query->execute();
387
+        $count = $result->fetchColumn();
388
+        $result->closeCursor();
389
+
390
+        if ($count !== false) {
391
+            $count = (int)$count;
392
+        } else {
393
+            $count = 0;
394
+        }
395
+
396
+        return $count;
397
+    }
398
+
399
+    /**
400
+     * get the number of disabled users in a group
401
+     *
402
+     * @param string $search
403
+     *
404
+     * @return int
405
+     */
406
+    public function countDisabledInGroup(string $gid): int {
407
+        $this->fixDI();
408
+
409
+        $query = $this->dbConn->getQueryBuilder();
410
+        $query->select($query->createFunction('COUNT(DISTINCT ' . $query->getColumnName('uid') . ')'))
411
+            ->from('preferences', 'p')
412
+            ->innerJoin('p', 'group_user', 'g', $query->expr()->eq('p.userid', 'g.uid'))
413
+            ->where($query->expr()->eq('appid', $query->createNamedParameter('core')))
414
+            ->andWhere($query->expr()->eq('configkey', $query->createNamedParameter('enabled')))
415
+            ->andWhere($query->expr()->eq('configvalue', $query->createNamedParameter('false'), IQueryBuilder::PARAM_STR))
416
+            ->andWhere($query->expr()->eq('gid', $query->createNamedParameter($gid), IQueryBuilder::PARAM_STR));
417
+
418
+        $result = $query->execute();
419
+        $count = $result->fetchColumn();
420
+        $result->closeCursor();
421
+
422
+        if ($count !== false) {
423
+            $count = (int)$count;
424
+        } else {
425
+            $count = 0;
426
+        }
427
+
428
+        return $count;
429
+    }
430
+
431
+    public function getDisplayName(string $gid): string {
432
+        $this->fixDI();
433
+
434
+        $query = $this->dbConn->getQueryBuilder();
435
+        $query->select('displayname')
436
+            ->from('groups')
437
+            ->where($query->expr()->eq('gid', $query->createNamedParameter($gid)));
438
+
439
+        $result = $query->execute();
440
+        $displayName = $result->fetchColumn();
441
+        $result->closeCursor();
442
+
443
+        return (string) $displayName;
444
+    }
445
+
446
+    public function getGroupDetails(string $gid): array {
447
+        $displayName = $this->getDisplayName($gid);
448
+        if ($displayName !== '') {
449
+            return ['displayName' => $displayName];
450
+        }
451
+
452
+        return [];
453
+    }
454
+
455
+    public function setDisplayName(string $gid, string $displayName): bool {
456
+        if (!$this->groupExists($gid)) {
457
+            return false;
458
+        }
459
+
460
+        $this->fixDI();
461
+
462
+        $displayName = trim($displayName);
463
+        if ($displayName === '') {
464
+            $displayName = $gid;
465
+        }
466
+
467
+        $query = $this->dbConn->getQueryBuilder();
468
+        $query->update('groups')
469
+            ->set('displayname', $query->createNamedParameter($displayName))
470
+            ->where($query->expr()->eq('gid', $query->createNamedParameter($gid)));
471
+        $query->execute();
472
+
473
+        return true;
474
+    }
475 475
 
476 476
 }
Please login to merge, or discard this patch.