Completed
Push — stable8.1 ( 1d6099...c6eee6 )
by Morris
88:22
created

EncryptionTest::testUpdateMissingPublicKey()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 32
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 32
ccs 24
cts 24
cp 1
rs 8.8571
cc 1
eloc 20
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 * @author Björn Schießle <[email protected]>
4
 * @author Joas Schilling <[email protected]>
5
 * @author Morris Jobke <[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\lib\Crypto;
26
27
use OCA\Encryption\Exceptions\PublicKeyMissingException;
28
use Test\TestCase;
29
use OCA\Encryption\Crypto\Encryption;
30
31
class EncryptionTest extends TestCase {
32
33
	/** @var Encryption */
34
	private $instance;
35
36
	/** @var \PHPUnit_Framework_MockObject_MockObject */
37
	private $keyManagerMock;
38
39
	/** @var \PHPUnit_Framework_MockObject_MockObject */
40
	private $cryptMock;
41
42
	/** @var \PHPUnit_Framework_MockObject_MockObject */
43
	private $utilMock;
44
45
	/** @var \PHPUnit_Framework_MockObject_MockObject */
46
	private $loggerMock;
47
48
	/** @var \PHPUnit_Framework_MockObject_MockObject */
49
	private $l10nMock;
50
51 22
	public function setUp() {
52 22
		parent::setUp();
53
54 22
		$this->cryptMock = $this->getMockBuilder('OCA\Encryption\Crypto\Crypt')
55 22
			->disableOriginalConstructor()
56 22
			->getMock();
57 22
		$this->utilMock = $this->getMockBuilder('OCA\Encryption\Util')
58 22
			->disableOriginalConstructor()
59 22
			->getMock();
60 22
		$this->keyManagerMock = $this->getMockBuilder('OCA\Encryption\KeyManager')
61 22
			->disableOriginalConstructor()
62 22
			->getMock();
63 22
		$this->loggerMock = $this->getMockBuilder('OCP\ILogger')
64 22
			->disableOriginalConstructor()
65 22
			->getMock();
66 22
		$this->l10nMock = $this->getMockBuilder('OCP\IL10N')
67 22
			->disableOriginalConstructor()
68 22
			->getMock();
69 22
		$this->l10nMock->expects($this->any())
70 22
			->method('t')
71 22
			->with($this->anything())
72 22
			->willReturnArgument(0);
73
74 22
		$this->instance = new Encryption(
75 22
			$this->cryptMock,
76 22
			$this->keyManagerMock,
77 22
			$this->utilMock,
78 22
			$this->loggerMock,
79 22
			$this->l10nMock
80 22
		);
81
82 22
	}
83
84
	/**
85
	 * test if public key from one of the recipients is missing
86
	 */
87 1
	public function testEndUser1() {
88 1
		$this->instance->begin('/foo/bar', 'user1', 'r', array(), array('users' => array('user1', 'user2', 'user3')));
89 1
		$this->endTest();
90 1
	}
91
92
	/**
93
	 * test if public key from owner is missing
94
	 *
95
	 * @expectedException \OCA\Encryption\Exceptions\PublicKeyMissingException
96
	 */
97 1
	public function testEndUser2() {
98 1
		$this->instance->begin('/foo/bar', 'user2', 'r', array(), array('users' => array('user1', 'user2', 'user3')));
99 1
		$this->endTest();
100
	}
101
102
	/**
103
	 * common part of testEndUser1 and testEndUser2
104
	 *
105
	 * @throws PublicKeyMissingException
106
	 */
107 2
	public function endTest() {
108
		// prepare internal variables
109 2
		self::invokePrivate($this->instance, 'isWriteOperation', [true]);
110 2
		self::invokePrivate($this->instance, 'writeCache', ['']);
111
112 2
		$this->keyManagerMock->expects($this->any())
113 2
			->method('getPublicKey')
114 2
			->will($this->returnCallback([$this, 'getPublicKeyCallback']));
115 2
		$this->keyManagerMock->expects($this->any())
116 2
			->method('addSystemKeys')
117 2
			->will($this->returnCallback([$this, 'addSystemKeysCallback']));
118 2
		$this->cryptMock->expects($this->any())
119 2
			->method('multiKeyEncrypt')
120 2
			->willReturn(true);
121 2
		$this->cryptMock->expects($this->any())
122 2
			->method('setAllFileKeys')
123 2
			->willReturn(true);
124
125 2
		$this->instance->end('/foo/bar');
126 1
	}
127
128
129 2
	public function getPublicKeyCallback($uid) {
130 2
		if ($uid === 'user2') {
131 2
			throw new PublicKeyMissingException($uid);
132
		}
133 2
		return $uid;
134
	}
135
136 1
	public function addSystemKeysCallback($accessList, $publicKeys) {
137 1
		$this->assertSame(2, count($publicKeys));
138 1
		$this->assertArrayHasKey('user1', $publicKeys);
139 1
		$this->assertArrayHasKey('user3', $publicKeys);
140 1
		return $publicKeys;
141
	}
142
143
	/**
144
	 * @dataProvider dataProviderForTestGetPathToRealFile
145
	 */
146 4
	public function testGetPathToRealFile($path, $expected) {
147 4
		$this->assertSame($expected,
148 4
			self::invokePrivate($this->instance, 'getPathToRealFile', array($path))
149 4
		);
150 4
	}
151
152 View Code Duplication
	public function dataProviderForTestGetPathToRealFile() {
153
		return array(
154
			array('/user/files/foo/bar.txt', '/user/files/foo/bar.txt'),
155
			array('/user/files/foo.txt', '/user/files/foo.txt'),
156
			array('/user/files_versions/foo.txt.v543534', '/user/files/foo.txt'),
157
			array('/user/files_versions/foo/bar.txt.v5454', '/user/files/foo/bar.txt'),
158
		);
159
	}
160
161
	/**
162
	 * @dataProvider dataTestBegin
163
	 */
164 4
	public function testBegin($mode, $header, $legacyCipher, $defaultCipher, $fileKey, $expected) {
165
166 4
		$this->cryptMock->expects($this->any())
167 4
			->method('getCipher')
168 4
			->willReturn($defaultCipher);
169 4
		$this->cryptMock->expects($this->any())
170 4
			->method('getLegacyCipher')
171 4
			->willReturn($legacyCipher);
172 4
		if (empty($fileKey)) {
173 1
			$this->cryptMock->expects($this->once())
174 1
				->method('generateFileKey')
175 1
				->willReturn('fileKey');
176 1
		} else {
177 3
			$this->cryptMock->expects($this->never())
178 3
				->method('generateFileKey');
179
		}
180
181 4
		$this->keyManagerMock->expects($this->once())
182 4
			->method('getFileKey')
183 4
			->willReturn($fileKey);
184
185 4
		$result = $this->instance->begin('/user/files/foo.txt', 'user', $mode, $header, []);
186
187 4
		$this->assertArrayHasKey('cipher', $result);
188 4
		$this->assertSame($expected, $result['cipher']);
189 4
		if ($mode === 'w') {
190 2
			$this->assertTrue(self::invokePrivate($this->instance, 'isWriteOperation'));
191 2
		} else {
192 2
			$this->assertFalse(self::invokePrivate($this->instance, 'isWriteOperation'));
193
		}
194 4
	}
195
196
	public function dataTestBegin() {
197
		return array(
198
			array('w', ['cipher' => 'myCipher'], 'legacyCipher', 'defaultCipher', 'fileKey', 'myCipher'),
199
			array('r', ['cipher' => 'myCipher'], 'legacyCipher', 'defaultCipher', 'fileKey', 'myCipher'),
200
			array('w', [], 'legacyCipher', 'defaultCipher', '', 'defaultCipher'),
201
			array('r', [], 'legacyCipher', 'defaultCipher', 'file_key', 'legacyCipher'),
202
		);
203
	}
204
205
	/**
206
	 * @dataProvider dataTestUpdate
207
	 *
208
	 * @param string $fileKey
209
	 * @param boolean $expected
210
	 */
211 2
	public function testUpdate($fileKey, $expected) {
212 2
		$this->keyManagerMock->expects($this->once())
213 2
			->method('getFileKey')->willReturn($fileKey);
214
215 2
		$this->keyManagerMock->expects($this->any())
216 2
			->method('getPublicKey')->willReturn('publicKey');
217
218 2
		$this->keyManagerMock->expects($this->any())
219 2
			->method('addSystemKeys')
220
			->willReturnCallback(function($accessList, $publicKeys) {
221 1
				return $publicKeys;
222 2
			});
223
224 2
		$this->assertSame($expected,
225 2
			$this->instance->update('path', 'user1', ['users' => ['user1']])
226 2
		);
227 2
	}
228
229
	public function dataTestUpdate() {
230
		return array(
231
			array('', false),
232
			array('fileKey', true)
233
		);
234
	}
235
236
	/**
237
	 * Test case if the public key is missing. ownCloud should still encrypt
238
	 * the file for the remaining users
239
	 */
240 1
	public function testUpdateMissingPublicKey() {
241 1
		$this->keyManagerMock->expects($this->once())
242 1
			->method('getFileKey')->willReturn('fileKey');
243
244 1
		$this->keyManagerMock->expects($this->any())
245 1
			->method('getPublicKey')->willReturnCallback(
246
				function($user) {
247 1
					throw new PublicKeyMissingException($user);
248
				}
249 1
			);
250
251 1
		$this->keyManagerMock->expects($this->any())
252 1
			->method('addSystemKeys')
253
			->willReturnCallback(function($accessList, $publicKeys) {
254 1
				return $publicKeys;
255 1
			});
256
257 1
		$this->cryptMock->expects($this->once())->method('multiKeyEncrypt')
258 1
			->willReturnCallback(
259 1
				function($fileKey, $publicKeys) {
260 1
					$this->assertEmpty($publicKeys);
261 1
					$this->assertSame('fileKey', $fileKey);
262 1
				}
263 1
			);
264
265 1
		$this->keyManagerMock->expects($this->never())->method('getVersion');
266 1
		$this->keyManagerMock->expects($this->never())->method('setVersion');
267
268 1
		$this->assertTrue(
269 1
			$this->instance->update('path', 'user1', ['users' => ['user1']])
270 1
		);
271 1
	}
272
273
	/**
274
	 * by default the encryption module should encrypt regular files, files in
275
	 * files_versions and files in files_trashbin
276
	 *
277
	 * @dataProvider dataTestShouldEncrypt
278
	 */
279 8
	public function testShouldEncrypt($path, $expected) {
280 8
		$this->assertSame($expected,
281 8
			$this->instance->shouldEncrypt($path)
282 8
		);
283 8
	}
284
285 1 View Code Duplication
	public function dataTestShouldEncrypt() {
286
		return array(
287
			array('/user1/files/foo.txt', true),
288
			array('/user1/files_versions/foo.txt', true),
289 1
			array('/user1/files_trashbin/foo.txt', true),
290
			array('/user1/some_folder/foo.txt', false),
291
			array('/user1/foo.txt', false),
292
			array('/user1/files', false),
293
			array('/user1/files_trashbin', false),
294
			array('/user1/files_versions', false),
295
		);
296
	}
297
298
	/**
299
	 * @expectedException \OC\Encryption\Exceptions\DecryptionFailedException
300
	 * @expectedExceptionMessage Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you.
301
	 */
302 1
	public function testDecrypt() {
303 1
		$this->instance->decrypt('abc');
304
	}
305
}
306