Completed
Push — stable8.2 ( 458a90...47a1fb )
by Morris
115:41
created

KeyManagerTest::testGetFileKey()   B

Complexity

Conditions 4
Paths 8

Size

Total Lines 51
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 32
CRAP Score 4.0925

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 51
ccs 32
cts 39
cp 0.8205
rs 8.8983
cc 4
eloc 37
nc 8
nop 4
crap 4.0925

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @author Björn Schießle <[email protected]>
4
 * @author Clark Tomlinson <[email protected]>
5
 * @author Joas Schilling <[email protected]>
6
 * @author Thomas Müller <[email protected]>
7
 *
8
 * @copyright Copyright (c) 2015, ownCloud, Inc.
9
 * @license AGPL-3.0
10
 *
11
 * This code is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU Affero General Public License, version 3,
13
 * as published by the Free Software Foundation.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU Affero General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public License, version 3,
21
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
22
 *
23
 */
24
25
namespace OCA\Encryption\Tests;
26
27
28
use OCA\Encryption\KeyManager;
29
use OCA\Encryption\Session;
30
use Test\TestCase;
31
32
class KeyManagerTest extends TestCase {
33
	/**
34
	 * @var KeyManager
35
	 */
36
	private $instance;
37
	/**
38
	 * @var string
39
	 */
40
	private $userId;
41
42
	/** @var string */
43
	private $systemKeyId;
44
45
	/** @var \PHPUnit_Framework_MockObject_MockObject */
46
	private $keyStorageMock;
47
48
	/** @var \PHPUnit_Framework_MockObject_MockObject */
49
	private $cryptMock;
50
51
	/** @var \PHPUnit_Framework_MockObject_MockObject */
52
	private $userMock;
53
54
	/** @var \PHPUnit_Framework_MockObject_MockObject */
55
	private $sessionMock;
56
57
	/** @var \PHPUnit_Framework_MockObject_MockObject */
58
	private $logMock;
59
60
	/** @var \PHPUnit_Framework_MockObject_MockObject */
61
	private $utilMock;
62
63
	/** @var \PHPUnit_Framework_MockObject_MockObject */
64
	private $configMock;
65
66 37
	public function setUp() {
67 37
		parent::setUp();
68 37
		$this->userId = 'user1';
69 37
		$this->systemKeyId = 'systemKeyId';
70 37
		$this->keyStorageMock = $this->getMock('OCP\Encryption\Keys\IStorage');
71 37
		$this->cryptMock = $this->getMockBuilder('OCA\Encryption\Crypto\Crypt')
72 37
			->disableOriginalConstructor()
73 37
			->getMock();
74 37
		$this->configMock = $this->getMock('OCP\IConfig');
75 37
		$this->configMock->expects($this->any())
76 37
			->method('getAppValue')
77 37
			->willReturn($this->systemKeyId);
78 37
		$this->userMock = $this->getMock('OCP\IUserSession');
79 37
		$this->sessionMock = $this->getMockBuilder('OCA\Encryption\Session')
80 37
			->disableOriginalConstructor()
81 37
			->getMock();
82 37
		$this->logMock = $this->getMock('OCP\ILogger');
83 37
		$this->utilMock = $this->getMockBuilder('OCA\Encryption\Util')
84 37
			->disableOriginalConstructor()
85 37
			->getMock();
86
87 37
		$this->instance = new KeyManager(
88 37
			$this->keyStorageMock,
89 37
			$this->cryptMock,
90 37
			$this->configMock,
91 37
			$this->userMock,
92 37
			$this->sessionMock,
93 37
			$this->logMock,
94 37
			$this->utilMock);
95 37
	}
96
97 1 View Code Duplication
	public function testDeleteShareKey() {
98 1
		$this->keyStorageMock->expects($this->any())
99 1
			->method('deleteFileKey')
100 1
			->with($this->equalTo('/path'), $this->equalTo('keyId.shareKey'))
101 1
			->willReturn(true);
102
103 1
		$this->assertTrue(
104 1
			$this->instance->deleteShareKey('/path', 'keyId')
105 1
		);
106 1
	}
107
108 1 View Code Duplication
	public function testGetPrivateKey() {
109 1
		$this->keyStorageMock->expects($this->any())
110 1
			->method('getUserKey')
111 1
			->with($this->equalTo($this->userId), $this->equalTo('privateKey'))
112 1
			->willReturn('privateKey');
113
114
115 1
		$this->assertSame('privateKey',
116 1
			$this->instance->getPrivateKey($this->userId)
117 1
		);
118 1
	}
119
120 1 View Code Duplication
	public function testGetPublicKey() {
121 1
		$this->keyStorageMock->expects($this->any())
122 1
			->method('getUserKey')
123 1
			->with($this->equalTo($this->userId), $this->equalTo('publicKey'))
124 1
			->willReturn('publicKey');
125
126
127 1
		$this->assertSame('publicKey',
128 1
			$this->instance->getPublicKey($this->userId)
129 1
		);
130 1
	}
131
132 1 View Code Duplication
	public function testRecoveryKeyExists() {
133 1
		$this->keyStorageMock->expects($this->any())
134 1
			->method('getSystemUserKey')
135 1
			->with($this->equalTo($this->systemKeyId . '.publicKey'))
136 1
			->willReturn('recoveryKey');
137
138
139 1
		$this->assertTrue($this->instance->recoveryKeyExists());
140 1
	}
141
142 1 View Code Duplication
	public function testCheckRecoveryKeyPassword() {
143 1
		$this->keyStorageMock->expects($this->any())
144 1
			->method('getSystemUserKey')
145 1
			->with($this->equalTo($this->systemKeyId . '.privateKey'))
146 1
			->willReturn('recoveryKey');
147 1
		$this->cryptMock->expects($this->any())
148 1
			->method('decryptPrivateKey')
149 1
			->with($this->equalTo('recoveryKey'), $this->equalTo('pass'))
150 1
			->willReturn('decryptedRecoveryKey');
151
152 1
		$this->assertTrue($this->instance->checkRecoveryPassword('pass'));
153 1
	}
154
155 1 View Code Duplication
	public function testSetPublicKey() {
156 1
		$this->keyStorageMock->expects($this->any())
157 1
			->method('setUserKey')
158 1
			->with(
159 1
				$this->equalTo($this->userId),
160 1
				$this->equalTo('publicKey'),
161 1
				$this->equalTo('key'))
162 1
			->willReturn(true);
163
164
165 1
		$this->assertTrue(
166 1
			$this->instance->setPublicKey($this->userId, 'key')
167 1
		);
168 1
	}
169
170 1 View Code Duplication
	public function testSetPrivateKey() {
171 1
		$this->keyStorageMock->expects($this->any())
172 1
			->method('setUserKey')
173 1
			->with(
174 1
				$this->equalTo($this->userId),
175 1
				$this->equalTo('privateKey'),
176 1
				$this->equalTo('key'))
177 1
			->willReturn(true);
178
179
180 1
		$this->assertTrue(
181 1
			$this->instance->setPrivateKey($this->userId, 'key')
182 1
		);
183 1
	}
184
185
	/**
186
	 * @dataProvider dataTestUserHasKeys
187
	 */
188 2 View Code Duplication
	public function testUserHasKeys($key, $expected) {
189 2
		$this->keyStorageMock->expects($this->exactly(2))
190 2
			->method('getUserKey')
191 2
			->with($this->equalTo($this->userId), $this->anything())
192 2
			->willReturn($key);
193
194
195 2
		$this->assertSame($expected,
196 2
			$this->instance->userHasKeys($this->userId)
197 2
		);
198 2
	}
199
200
	public function dataTestUserHasKeys() {
201
		return [
202
			['key', true],
203
			['', false]
204
		];
205
	}
206
207
	/**
208
	 * @expectedException \OCA\Encryption\Exceptions\PrivateKeyMissingException
209
	 */
210 1 View Code Duplication
	public function testUserHasKeysMissingPrivateKey() {
211 1
		$this->keyStorageMock->expects($this->exactly(2))
212 1
			->method('getUserKey')
213
			->willReturnCallback(function ($uid, $keyID, $encryptionModuleId) {
0 ignored issues
show
Unused Code introduced by
The parameter $encryptionModuleId is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
214 1
				if ($keyID=== 'privateKey') {
215 1
					return '';
216
				}
217 1
				return 'key';
218 1
			});
219
220 1
		$this->instance->userHasKeys($this->userId);
221
	}
222
223
	/**
224
	 * @expectedException \OCA\Encryption\Exceptions\PublicKeyMissingException
225
	 */
226 1 View Code Duplication
	public function testUserHasKeysMissingPublicKey() {
227 1
		$this->keyStorageMock->expects($this->exactly(2))
228 1
			->method('getUserKey')
229
			->willReturnCallback(function ($uid, $keyID, $encryptionModuleId){
0 ignored issues
show
Unused Code introduced by
The parameter $encryptionModuleId is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
230 1
				if ($keyID === 'publicKey') {
231 1
					return '';
232
				}
233 1
				return 'key';
234 1
			});
235
236 1
		$this->instance->userHasKeys($this->userId);
237
238
	}
239
240
	/**
241
	 * @dataProvider dataTestInit
242
	 *
243
	 * @param bool $useMasterKey
244
	 */
245 2 View Code Duplication
	public function testInit($useMasterKey) {
246
247 2
		$instance = $this->getMockBuilder('OCA\Encryption\KeyManager')
248 2
			->setConstructorArgs(
249
				[
250 2
					$this->keyStorageMock,
251 2
					$this->cryptMock,
252 2
					$this->configMock,
253 2
					$this->userMock,
254 2
					$this->sessionMock,
255 2
					$this->logMock,
256 2
					$this->utilMock
257 2
				]
258 2
			)->setMethods(['getMasterKeyId', 'getMasterKeyPassword', 'getSystemPrivateKey', 'getPrivateKey'])
259 2
			->getMock();
260
261 2
		$this->utilMock->expects($this->once())->method('isMasterKeyEnabled')
262 2
			->willReturn($useMasterKey);
263
264 2
		$this->sessionMock->expects($this->at(0))->method('setStatus')
265 2
			->with(Session::INIT_EXECUTED);
266
267 2
		$instance->expects($this->any())->method('getMasterKeyId')->willReturn('masterKeyId');
268 2
		$instance->expects($this->any())->method('getMasterKeyPassword')->willReturn('masterKeyPassword');
269 2
		$instance->expects($this->any())->method('getSystemPrivateKey')->with('masterKeyId')->willReturn('privateMasterKey');
270 2
		$instance->expects($this->any())->method('getPrivateKey')->with($this->userId)->willReturn('privateUserKey');
271
272 2
		if($useMasterKey) {
273 1
			$this->cryptMock->expects($this->once())->method('decryptPrivateKey')
274 1
				->with('privateMasterKey', 'masterKeyPassword', 'masterKeyId')
275 1
				->willReturn('key');
276 1
		} else {
277 1
			$this->cryptMock->expects($this->once())->method('decryptPrivateKey')
278 1
				->with('privateUserKey', 'pass', $this->userId)
279 1
				->willReturn('key');
280
		}
281
282 2
		$this->sessionMock->expects($this->once())->method('setPrivateKey')
283 2
			->with('key');
284
285 2
		$this->assertTrue($instance->init($this->userId, 'pass'));
286 2
	}
287
288
	public function dataTestInit() {
289
		return [
290
			[true],
291
			[false]
292
		];
293
	}
294
295
296 1
	public function testSetRecoveryKey() {
297 1
		$this->keyStorageMock->expects($this->exactly(2))
298 1
			->method('setSystemUserKey')
299 1
			->willReturn(true);
300 1
		$this->cryptMock->expects($this->any())
301 1
			->method('encryptPrivateKey')
302 1
			->with($this->equalTo('privateKey'), $this->equalTo('pass'))
303 1
			->willReturn('decryptedPrivateKey');
304
305
306 1
		$this->assertTrue(
307 1
			$this->instance->setRecoveryKey('pass',
308 1
				array('publicKey' => 'publicKey', 'privateKey' => 'privateKey'))
309 1
		);
310 1
	}
311
312 1 View Code Duplication
	public function testSetSystemPrivateKey() {
313 1
		$this->keyStorageMock->expects($this->exactly(1))
314 1
			->method('setSystemUserKey')
315 1
			->with($this->equalTo('keyId.privateKey'), $this->equalTo('key'))
316 1
			->willReturn(true);
317
318
319 1
		$this->assertTrue(
320 1
			$this->instance->setSystemPrivateKey('keyId', 'key')
321 1
		);
322 1
	}
323
324 1 View Code Duplication
	public function testGetSystemPrivateKey() {
325 1
		$this->keyStorageMock->expects($this->exactly(1))
326 1
			->method('getSystemUserKey')
327 1
			->with($this->equalTo('keyId.privateKey'))
328 1
			->willReturn('systemPrivateKey');
329
330
331 1
		$this->assertSame('systemPrivateKey',
332 1
			$this->instance->getSystemPrivateKey('keyId')
333 1
		);
334 1
	}
335
336 1 View Code Duplication
	public function testGetEncryptedFileKey() {
337 1
		$this->keyStorageMock->expects($this->once())
338 1
			->method('getFileKey')
339 1
			->with('/', 'fileKey')
340 1
			->willReturn(true);
341
342 1
		$this->assertTrue($this->instance->getEncryptedFileKey('/'));
343 1
	}
344
345
	/**
346
	 * @dataProvider dataTestGetFileKey
347
	 *
348
	 * @param $uid
349
	 * @param $isMasterKeyEnabled
350
	 * @param $privateKey
351
	 * @param $expected
352
	 */
353 8
	public function testGetFileKey($uid, $isMasterKeyEnabled, $privateKey, $expected) {
354
355 8
		$path = '/foo.txt';
356
357 8
		if ($isMasterKeyEnabled) {
358 4
			$expectedUid = 'masterKeyId';
359 4
		} else {
360 4
			$expectedUid = $uid;
361
		}
362
363 8
		$this->invokePrivate($this->instance, 'masterKeyId', ['masterKeyId']);
364
365 8
		$this->keyStorageMock->expects($this->at(0))
366 8
			->method('getFileKey')
367 8
			->with($path, 'fileKey', 'OC_DEFAULT_MODULE')
368 8
			->willReturn(true);
369
370 8
		$this->keyStorageMock->expects($this->at(1))
371 8
			->method('getFileKey')
372 8
			->with($path, $expectedUid . '.shareKey', 'OC_DEFAULT_MODULE')
373 8
			->willReturn(true);
374
375 8
		if (is_null($uid)) {
376
			$this->keyStorageMock->expects($this->once())
377
				->method('getSystemUserKey')
378
				->willReturn(true);
379
			$this->cryptMock->expects($this->once())
380
				->method('decryptPrivateKey')
381
				->willReturn($privateKey);
382
		} else {
383 8
			$this->keyStorageMock->expects($this->never())
384 8
				->method('getSystemUserKey');
385 8
			$this->utilMock->expects($this->once())->method('isMasterKeyEnabled')
386 8
				->willReturn($isMasterKeyEnabled);
387 8
			$this->sessionMock->expects($this->once())->method('getPrivateKey')->willReturn($privateKey);
388
		}
389
390 8
		if($privateKey) {
391 4
			$this->cryptMock->expects($this->once())
392 4
				->method('multiKeyDecrypt')
393 4
				->willReturn(true);
394 4
		} else {
395 4
			$this->cryptMock->expects($this->never())
396 4
				->method('multiKeyDecrypt');
397
		}
398
399 8
		$this->assertSame($expected,
400 8
			$this->instance->getFileKey($path, $uid)
401 8
		);
402
403 8
	}
404
405
	public function dataTestGetFileKey() {
406
		return [
407
			['user1', false, 'privateKey', true],
408
			['user1', false, false, ''],
409
			['user1', true, 'privateKey', true],
410
			['user1', true, false, ''],
411
			['', false, 'privateKey', true],
412
			['', false, false, ''],
413
			['', true, 'privateKey', true],
414
			['', true, false, '']
415
		];
416
	}
417
418 1
	public function testDeletePrivateKey() {
419 1
		$this->keyStorageMock->expects($this->once())
420 1
			->method('deleteUserKey')
421 1
			->with('user1', 'privateKey')
422 1
			->willReturn(true);
423
424 1
		$this->assertTrue(self::invokePrivate($this->instance,
425 1
			'deletePrivateKey',
426 1
			[$this->userId]));
427 1
	}
428
429 1 View Code Duplication
	public function testDeleteAllFileKeys() {
430 1
		$this->keyStorageMock->expects($this->once())
431 1
			->method('deleteAllFileKeys')
432 1
			->willReturn(true);
433
434 1
		$this->assertTrue($this->instance->deleteAllFileKeys('/'));
435 1
	}
436
437
	/**
438
	 * test add public share key and or recovery key to the list of public keys
439
	 *
440
	 * @dataProvider dataTestAddSystemKeys
441
	 *
442
	 * @param array $accessList
443
	 * @param array $publicKeys
444
	 * @param string $uid
445
	 * @param array $expectedKeys
446
	 */
447 4
	public function testAddSystemKeys($accessList, $publicKeys, $uid, $expectedKeys) {
448
449 4
		$publicShareKeyId = 'publicShareKey';
450 4
		$recoveryKeyId = 'recoveryKey';
451
452 4
		$this->keyStorageMock->expects($this->any())
453 4
			->method('getSystemUserKey')
454
			->willReturnCallback(function($keyId, $encryptionModuleId) {
0 ignored issues
show
Unused Code introduced by
The parameter $encryptionModuleId is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
455 4
				return $keyId;
456 4
			});
457
458 4
		$this->utilMock->expects($this->any())
459 4
			->method('isRecoveryEnabledForUser')
460 4
			->willReturnCallback(function($uid) {
461 4
				if ($uid === 'user1') {
462 2
					return true;
463
				}
464 2
				return false;
465 4
			});
466
467
		// set key IDs
468 4
		self::invokePrivate($this->instance, 'publicShareKeyId', [$publicShareKeyId]);
469 4
		self::invokePrivate($this->instance, 'recoveryKeyId', [$recoveryKeyId]);
470
471 4
		$result = $this->instance->addSystemKeys($accessList, $publicKeys, $uid);
472
473 4
		foreach ($expectedKeys as $expected) {
474 3
			$this->assertArrayHasKey($expected, $result);
475 4
		}
476
477 4
		$this->assertSameSize($expectedKeys, $result);
478 4
	}
479
480
	/**
481
	 * data provider for testAddSystemKeys()
482
	 *
483
	 * @return array
484
	 */
485
	public function dataTestAddSystemKeys() {
486
		return array(
487
			array(['public' => true],[], 'user1', ['publicShareKey', 'recoveryKey']),
488
			array(['public' => false], [], 'user1', ['recoveryKey']),
489
			array(['public' => true],[], 'user2', ['publicShareKey']),
490
			array(['public' => false], [], 'user2', []),
491
		);
492
	}
493
494 1
	public function testGetMasterKeyId() {
495 1
		$this->assertSame('systemKeyId', $this->instance->getMasterKeyId());
496 1
	}
497
498 1
	public function testGetPublicMasterKey() {
499 1
		$this->keyStorageMock->expects($this->once())->method('getSystemUserKey')
500 1
			->with('systemKeyId.publicKey', \OCA\Encryption\Crypto\Encryption::ID)
501 1
			->willReturn(true);
502
503 1
		$this->assertTrue(
504 1
			$this->instance->getPublicMasterKey()
505 1
		);
506 1
	}
507
508 1 View Code Duplication
	public function testGetMasterKeyPassword() {
509 1
		$this->configMock->expects($this->once())->method('getSystemValue')->with('secret')
510 1
			->willReturn('password');
511
512 1
		$this->assertSame('password',
513 1
			$this->invokePrivate($this->instance, 'getMasterKeyPassword', [])
514 1
		);
515 1
	}
516
517
	/**
518
	 * @expectedException \Exception
519
	 */
520 1
	public function testGetMasterKeyPasswordException() {
521 1
		$this->configMock->expects($this->once())->method('getSystemValue')->with('secret')
522 1
			->willReturn('');
523
524 1
		$this->invokePrivate($this->instance, 'getMasterKeyPassword', []);
525
	}
526
527
	/**
528
	 * @dataProvider dataTestValidateMasterKey
529
	 *
530
	 * @param $masterKey
531
	 */
532 2 View Code Duplication
	public function testValidateMasterKey($masterKey) {
533
534
		/** @var \OCA\Encryption\KeyManager | \PHPUnit_Framework_MockObject_MockObject $instance */
535 2
		$instance = $this->getMockBuilder('OCA\Encryption\KeyManager')
536 2
			->setConstructorArgs(
537
				[
538 2
					$this->keyStorageMock,
539 2
					$this->cryptMock,
540 2
					$this->configMock,
541 2
					$this->userMock,
542 2
					$this->sessionMock,
543 2
					$this->logMock,
544 2
					$this->utilMock
545 2
				]
546 2
			)->setMethods(['getPublicMasterKey', 'setSystemPrivateKey', 'getMasterKeyPassword'])
547 2
			->getMock();
548
549 2
		$instance->expects($this->once())->method('getPublicMasterKey')
550 2
			->willReturn($masterKey);
551
552 2
		$instance->expects($this->any())->method('getMasterKeyPassword')->willReturn('masterKeyPassword');
553 2
		$this->cryptMock->expects($this->any())->method('generateHeader')->willReturn('header');
554
555 2
		if(empty($masterKey)) {
556 1
			$this->cryptMock->expects($this->once())->method('createKeyPair')
557 1
				->willReturn(['publicKey' => 'public', 'privateKey' => 'private']);
558 1
			$this->keyStorageMock->expects($this->once())->method('setSystemUserKey')
559 1
				->with('systemKeyId.publicKey', 'public', \OCA\Encryption\Crypto\Encryption::ID);
560 1
			$this->cryptMock->expects($this->once())->method('encryptPrivateKey')
561 1
				->with('private', 'masterKeyPassword', 'systemKeyId')
562 1
				->willReturn('EncryptedKey');
563 1
			$instance->expects($this->once())->method('setSystemPrivateKey')
564 1
				->with('systemKeyId', 'headerEncryptedKey');
565 1
		} else {
566 1
			$this->cryptMock->expects($this->never())->method('createKeyPair');
567 1
			$this->keyStorageMock->expects($this->never())->method('setSystemUserKey');
568 1
			$this->cryptMock->expects($this->never())->method('encryptPrivateKey');
569 1
			$instance->expects($this->never())->method('setSystemPrivateKey');
570
		}
571
572 2
		$instance->validateMasterKey();
573 2
	}
574
575
	public function dataTestValidateMasterKey() {
576
		return [
577
			['masterKey'],
578
			['']
579
		];
580
	}
581
582
}
583