Completed
Push — stable8.2 ( b54faa...3a8391 )
by
unknown
37:04
created

UserHooks::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 18

Duplication

Lines 20
Ratio 100 %

Code Coverage

Tests 10
CRAP Score 1
Metric Value
dl 20
loc 20
ccs 10
cts 10
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 9
	 */
92 View Code Duplication
	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 9
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
	}
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 1
	 */
147
	public function login($params) {
148 1
149
		if (!App::isEnabled('encryption')) {
150
			return true;
151
		}
152
153 1
		// ensure filesystem is loaded
154
		if (!\OC\Files\Filesystem::$loaded) {
155
			\OC_Util::setupFS($params['uid']);
156
		}
157
158 1
		// setup user, if user not ready force relogin
159 1
		if (!$this->userSetup->setupUser($params['uid'], $params['password'])) {
160
			return false;
161
		}
162 1
163 1
		$this->keyManager->init($params['uid'], $params['password']);
164
	}
165
166
	/**
167
	 * remove keys from session during logout
168 1
	 */
169 1
	public function logout() {
170 1
		$this->session->clear();
171
	}
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 1
	 */
179
	public function postCreateUser($params) {
180 1
181 1
		if (App::isEnabled('encryption')) {
182 1
			$this->userSetup->setupUser($params['uid'], $params['password']);
183 1
		}
184
	}
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 1
	 */
192
	public function postDeleteUser($params) {
193 1
194 1
		if (App::isEnabled('encryption')) {
195 1
			$this->keyManager->deletePublicKey($params['uid']);
196 1
		}
197
	}
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 2
	 */
205 2
	public function preSetPassphrase($params) {
206
		if (App::isEnabled('encryption')) {
207 2
208
			$user = $this->userManager->get($params['uid']);
209 2
210 1
			if ($user && !$user->canChangePassword()) {
211 1
				$this->setPassphrase($params);
212 2
			}
213 2
		}
214
	}
215
216
	/**
217
	 * Change a user's encryption passphrase
218
	 *
219
	 * @param array $params keys: uid, password
220
	 * @return bool
221 2
	 */
222
	public function setPassphrase($params) {
223
224 2
		// Get existing decrypted private key
225 2
		$privateKey = $this->session->getPrivateKey();
226
		$user = $this->user->getUser();
227
228 2
		// current logged in user changes his own password
229
		if ($user && $params['uid'] === $user->getUID() && $privateKey) {
230
231 1
			// Encrypt private key with new user pwd as passphrase
232
			$encryptedPrivateKey = $this->crypt->encryptPrivateKey($privateKey, $params['password'], $params['uid']);
233
234 1
			// Save private key
235 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...
236 1
				$this->keyManager->setPrivateKey($this->user->getUser()->getUID(),
237 1
					$this->crypt->generateHeader() . $encryptedPrivateKey);
238
			} else {
239
				$this->logger->error('Encryption could not update users encryption password');
240
			}
241
242
			// NOTE: Session does not need to be updated as the
243
			// private key has not changed, only the passphrase
244 1
			// used to decrypt it has changed
245 2
		} else { // admin changed the password for a different user, create new keys and re-encrypt file keys
246 2
			$user = $params['uid'];
247
			$this->initMountPoints($user);
248
			$recoveryPassword = isset($params['recoveryPassword']) ? $params['recoveryPassword'] : null;
249
250
			// we generate new keys if...
251
			// ...we have a recovery password and the user enabled the recovery key
252
			// ...encryption was activated for the first time (no keys exists)
253 2
			// ...the user doesn't have any files
254 2
			if (
255 2
				($this->recovery->isRecoveryEnabledForUser($user) && $recoveryPassword)
256 2
				|| !$this->keyManager->userHasKeys($user)
257
				|| !$this->util->userHasFiles($user)
258
			) {
259
260
				// backup old keys
261 2
				//$this->backupAllKeys('recovery');
262
263 2
				$newUserPassword = $params['password'];
264
265
				$keyPair = $this->crypt->createKeyPair();
266 2
267
				// Save public key
268
				$this->keyManager->setPublicKey($user, $keyPair['publicKey']);
269 2
270
				// Encrypt private key with new password
271 2
				$encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], $newUserPassword, $user);
272 1
273
				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...
274 1
					$this->keyManager->setPrivateKey($user, $this->crypt->generateHeader() . $encryptedKey);
275 1
276 1
					if ($recoveryPassword) { // if recovery key is set we can re-encrypt the key files
277 1
						$this->recovery->recoverUsersFiles($recoveryPassword, $user);
278 1
					}
279
				} else {
280 2
					$this->logger->error('Encryption Could not update users encryption password');
281
				}
282 2
			}
283
		}
284
	}
285
286
	/**
287
	 * init mount points for given user
288
	 *
289
	 * @param string $user
290
	 * @throws \OC\User\NoUserException
291 1
	 */
292 1
	protected function initMountPoints($user) {
293
		Filesystem::initMountPoints($user);
294 1
	}
295 1
296 1
297
	/**
298
	 * after password reset we create a new key pair for the user
299
	 *
300
	 * @param array $params
301
	 */
302
	public function postPasswordReset($params) {
303
		$password = $params['password'];
304
305
		$this->keyManager->replaceUserKeys($params['uid']);
306
		$this->userSetup->setupServerSide($params['uid'], $password);
307
	}
308
}
309