Completed
Push — stable8.1 ( c01ad6...6cfe33 )
by
unknown
67:28
created

UserHooks::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 1
Metric Value
dl 0
loc 20
ccs 11
cts 11
cp 1
rs 9.4285
cc 1
eloc 18
nc 1
nop 9
crap 1

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * @author Björn Schießle <[email protected]>
4
 * @author Clark Tomlinson <[email protected]>
5
 * @author Thomas Müller <[email protected]>
6
 *
7
 * @copyright Copyright (c) 2015, ownCloud, Inc.
8
 * @license AGPL-3.0
9
 *
10
 * This code is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU Affero General Public License, version 3,
12
 * as published by the Free Software Foundation.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License, version 3,
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
21
 *
22
 */
23
24
namespace OCA\Encryption\Hooks;
25
26
27
use OC\Files\Filesystem;
28
use OCP\IUserManager;
29
use OCP\Util as OCUtil;
30
use OCA\Encryption\Hooks\Contracts\IHook;
31
use OCA\Encryption\KeyManager;
32
use OCA\Encryption\Crypto\Crypt;
33
use OCA\Encryption\Users\Setup;
34
use OCP\App;
35
use OCP\ILogger;
36
use OCP\IUserSession;
37
use OCA\Encryption\Util;
38
use OCA\Encryption\Session;
39
use OCA\Encryption\Recovery;
40
41
class UserHooks implements IHook {
42
	/**
43
	 * @var KeyManager
44
	 */
45
	private $keyManager;
46
	/**
47
	 * @var IUserManager
48
	 */
49
	private $userManager;
50
	/**
51
	 * @var ILogger
52
	 */
53
	private $logger;
54
	/**
55
	 * @var Setup
56
	 */
57
	private $userSetup;
58
	/**
59
	 * @var IUserSession
60
	 */
61
	private $user;
62
	/**
63
	 * @var Util
64
	 */
65
	private $util;
66
	/**
67
	 * @var Session
68
	 */
69
	private $session;
70
	/**
71
	 * @var Recovery
72
	 */
73
	private $recovery;
74
	/**
75
	 * @var Crypt
76
	 */
77
	private $crypt;
78
79
	/**
80
	 * UserHooks constructor.
81
	 *
82
	 * @param KeyManager $keyManager
83
	 * @param IUserManager $userManager
84
	 * @param ILogger $logger
85
	 * @param Setup $userSetup
86
	 * @param IUserSession $user
87
	 * @param Util $util
88
	 * @param Session $session
89
	 * @param Crypt $crypt
90
	 * @param Recovery $recovery
91
	 */
92 9
	public function __construct(KeyManager $keyManager,
93
								IUserManager $userManager,
94
								ILogger $logger,
95
								Setup $userSetup,
96
								IUserSession $user,
97
								Util $util,
98
								Session $session,
99
								Crypt $crypt,
100
								Recovery $recovery) {
101
102 9
		$this->keyManager = $keyManager;
103 9
		$this->userManager = $userManager;
104 9
		$this->logger = $logger;
105 9
		$this->userSetup = $userSetup;
106 9
		$this->user = $user;
107 9
		$this->util = $util;
108 9
		$this->session = $session;
109 9
		$this->recovery = $recovery;
110 9
		$this->crypt = $crypt;
111 9
	}
112
113
	/**
114
	 * Connects Hooks
115
	 *
116
	 * @return null
117
	 */
118
	public function addHooks() {
119
		OCUtil::connectHook('OC_User', 'post_login', $this, 'login');
120
		OCUtil::connectHook('OC_User', 'logout', $this, 'logout');
121
		OCUtil::connectHook('OC_User',
122
			'post_setPassword',
123
			$this,
124
			'setPassphrase');
125
		OCUtil::connectHook('OC_User',
126
			'pre_setPassword',
127
			$this,
128
			'preSetPassphrase');
129
		OCUtil::connectHook('OC_User',
130
			'post_createUser',
131
			$this,
132
			'postCreateUser');
133
		OCUtil::connectHook('OC_User',
134
			'post_deleteUser',
135
			$this,
136
			'postDeleteUser');
137
	}
138
139
140
	/**
141
	 * Startup encryption backend upon user login
142
	 *
143
	 * @note This method should never be called for users using client side encryption
144
	 * @param array $params
145
	 * @return bool
146
	 */
147 1
	public function login($params) {
148
149 1
		if (!App::isEnabled('encryption')) {
150
			return true;
151
		}
152
153
		// ensure filesystem is loaded
154 1
		if (!\OC\Files\Filesystem::$loaded) {
155
			\OC_Util::setupFS($params['uid']);
156
		}
157
158
		// setup user, if user not ready force relogin
159 1
		if (!$this->userSetup->setupUser($params['uid'], $params['password'])) {
160 1
			return false;
161
		}
162
163 1
		$this->keyManager->init($params['uid'], $params['password']);
164 1
	}
165
166
	/**
167
	 * remove keys from session during logout
168
	 */
169 1
	public function logout() {
170 1
		$this->session->clear();
171 1
	}
172
173
	/**
174
	 * setup encryption backend upon user created
175
	 *
176
	 * @note This method should never be called for users using client side encryption
177
	 * @param array $params
178
	 */
179 1
	public function postCreateUser($params) {
180
181 1
		if (App::isEnabled('encryption')) {
182 1
			$this->userSetup->setupUser($params['uid'], $params['password']);
183 1
		}
184 1
	}
185
186
	/**
187
	 * cleanup encryption backend upon user deleted
188
	 *
189
	 * @param array $params : uid, password
190
	 * @note This method should never be called for users using client side encryption
191
	 */
192 1
	public function postDeleteUser($params) {
193
194 1
		if (App::isEnabled('encryption')) {
195 1
			$this->keyManager->deletePublicKey($params['uid']);
196 1
		}
197 1
	}
198
199
	/**
200
	 * If the password can't be changed within ownCloud, than update the key password in advance.
201
	 *
202
	 * @param array $params : uid, password
203
	 * @return bool
204
	 */
205 2
	public function preSetPassphrase($params) {
206 2
		if (App::isEnabled('encryption')) {
207
208 2
			$user = $this->userManager->get($params['uid']);
209
210 2
			if ($user && !$user->canChangePassword()) {
211 1
				$this->setPassphrase($params);
212 1
			}
213 2
		}
214 2
	}
215
216
	/**
217
	 * Change a user's encryption passphrase
218
	 *
219
	 * @param array $params keys: uid, password
220
	 * @return bool
221
	 */
222 2
	public function setPassphrase($params) {
223
224
		// Get existing decrypted private key
225 2
		$privateKey = $this->session->getPrivateKey();
226 2
		$user = $this->user->getUser();
227
228
		// current logged in user changes his own password
229 2
		if ($user && $params['uid'] === $user->getUID() && $privateKey) {
230
231
			// Encrypt private key with new user pwd as passphrase
232 1
			$encryptedPrivateKey = $this->crypt->symmetricEncryptFileContent($privateKey,
233 1
				$params['password']);
234
235
			// Save private key
236 1
			if ($encryptedPrivateKey) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $encryptedPrivateKey of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
237 1
				$this->keyManager->setPrivateKey($this->user->getUser()->getUID(),
238 1
					$this->crypt->generateHeader() . $encryptedPrivateKey);
239 1
			} else {
240
				$this->logger->error('Encryption could not update users encryption password');
241
			}
242
243
			// NOTE: Session does not need to be updated as the
244
			// private key has not changed, only the passphrase
245
			// used to decrypt it has changed
246 1
		} else { // admin changed the password for a different user, create new keys and re-encrypt file keys
247 2
			$user = $params['uid'];
248 2
			$this->initMountPoints($user);
249 2
			$recoveryPassword = isset($params['recoveryPassword']) ? $params['recoveryPassword'] : null;
250
251
			// we generate new keys if...
252
			// ...we have a recovery password and the user enabled the recovery key
253
			// ...encryption was activated for the first time (no keys exists)
254
			// ...the user doesn't have any files
255
			if (
256 2
				($this->recovery->isRecoveryEnabledForUser($user) && $recoveryPassword)
257 2
				|| !$this->keyManager->userHasKeys($user)
258 2
				|| !$this->util->userHasFiles($user)
259 2
			) {
260
261
				// backup old keys
262
				//$this->backupAllKeys('recovery');
263
264 2
				$newUserPassword = $params['password'];
265
266 2
				$keyPair = $this->crypt->createKeyPair();
267
268
				// Save public key
269 2
				$this->keyManager->setPublicKey($user, $keyPair['publicKey']);
270
271
				// Encrypt private key with new password
272 2
				$encryptedKey = $this->crypt->symmetricEncryptFileContent($keyPair['privateKey'],
273 2
					$newUserPassword);
274
275 2
				if ($encryptedKey) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $encryptedKey of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
276 1
					$this->keyManager->setPrivateKey($user, $this->crypt->generateHeader() . $encryptedKey);
277
278 1
					if ($recoveryPassword) { // if recovery key is set we can re-encrypt the key files
279 1
						$this->recovery->recoverUsersFiles($recoveryPassword, $user);
280 1
					}
281 1
				} else {
282 1
					$this->logger->error('Encryption Could not update users encryption password');
283
				}
284 2
			}
285
		}
286 2
	}
287
288
	/**
289
	 * init mount points for given user
290
	 *
291
	 * @param string $user
292
	 * @throws \OC\User\NoUserException
293
	 */
294
	protected function initMountPoints($user) {
295
		Filesystem::initMountPoints($user);
296
	}
297
298
299
	/**
300
	 * after password reset we create a new key pair for the user
301
	 *
302
	 * @param array $params
303
	 */
304 1
	public function postPasswordReset($params) {
305 1
		$password = $params['password'];
306
307 1
		$this->keyManager->replaceUserKeys($params['uid']);
308 1
		$this->userSetup->setupServerSide($params['uid'], $password);
309 1
	}
310
}
311