@@ -21,62 +21,62 @@ |
||
21 | 21 | |
22 | 22 | class AdminTest extends TestCase { |
23 | 23 | |
24 | - protected Admin $admin; |
|
24 | + protected Admin $admin; |
|
25 | 25 | |
26 | - protected IL10N&MockObject $l; |
|
27 | - protected LoggerInterface&MockObject $logger; |
|
28 | - protected IUserSession&MockObject $userSession; |
|
29 | - protected IConfig&MockObject $config; |
|
30 | - protected IUserManager&MockObject $userManager; |
|
31 | - protected ISession&MockObject $session; |
|
26 | + protected IL10N&MockObject $l; |
|
27 | + protected LoggerInterface&MockObject $logger; |
|
28 | + protected IUserSession&MockObject $userSession; |
|
29 | + protected IConfig&MockObject $config; |
|
30 | + protected IUserManager&MockObject $userManager; |
|
31 | + protected ISession&MockObject $session; |
|
32 | 32 | |
33 | - protected function setUp(): void { |
|
34 | - parent::setUp(); |
|
33 | + protected function setUp(): void { |
|
34 | + parent::setUp(); |
|
35 | 35 | |
36 | - $this->l = $this->getMockBuilder(IL10N::class)->getMock(); |
|
37 | - $this->logger = $this->getMockBuilder(LoggerInterface::class)->getMock(); |
|
38 | - $this->userSession = $this->getMockBuilder(IUserSession::class)->getMock(); |
|
39 | - $this->config = $this->getMockBuilder(IConfig::class)->getMock(); |
|
40 | - $this->userManager = $this->getMockBuilder(IUserManager::class)->getMock(); |
|
41 | - $this->session = $this->getMockBuilder(ISession::class)->getMock(); |
|
36 | + $this->l = $this->getMockBuilder(IL10N::class)->getMock(); |
|
37 | + $this->logger = $this->getMockBuilder(LoggerInterface::class)->getMock(); |
|
38 | + $this->userSession = $this->getMockBuilder(IUserSession::class)->getMock(); |
|
39 | + $this->config = $this->getMockBuilder(IConfig::class)->getMock(); |
|
40 | + $this->userManager = $this->getMockBuilder(IUserManager::class)->getMock(); |
|
41 | + $this->session = $this->getMockBuilder(ISession::class)->getMock(); |
|
42 | 42 | |
43 | - $this->admin = new Admin( |
|
44 | - $this->l, |
|
45 | - $this->logger, |
|
46 | - $this->userSession, |
|
47 | - $this->config, |
|
48 | - $this->userManager, |
|
49 | - $this->session |
|
50 | - ); |
|
51 | - } |
|
43 | + $this->admin = new Admin( |
|
44 | + $this->l, |
|
45 | + $this->logger, |
|
46 | + $this->userSession, |
|
47 | + $this->config, |
|
48 | + $this->userManager, |
|
49 | + $this->session |
|
50 | + ); |
|
51 | + } |
|
52 | 52 | |
53 | - public function testGetForm(): void { |
|
54 | - $this->config |
|
55 | - ->method('getAppValue') |
|
56 | - ->will($this->returnCallback(function ($app, $key, $default) { |
|
57 | - if ($app === 'encryption' && $key === 'recoveryAdminEnabled' && $default === '0') { |
|
58 | - return '1'; |
|
59 | - } |
|
60 | - if ($app === 'encryption' && $key === 'encryptHomeStorage' && $default === '1') { |
|
61 | - return '1'; |
|
62 | - } |
|
63 | - return $default; |
|
64 | - })); |
|
65 | - $params = [ |
|
66 | - 'recoveryEnabled' => '1', |
|
67 | - 'initStatus' => '0', |
|
68 | - 'encryptHomeStorage' => true, |
|
69 | - 'masterKeyEnabled' => true |
|
70 | - ]; |
|
71 | - $expected = new TemplateResponse('encryption', 'settings-admin', $params, ''); |
|
72 | - $this->assertEquals($expected, $this->admin->getForm()); |
|
73 | - } |
|
53 | + public function testGetForm(): void { |
|
54 | + $this->config |
|
55 | + ->method('getAppValue') |
|
56 | + ->will($this->returnCallback(function ($app, $key, $default) { |
|
57 | + if ($app === 'encryption' && $key === 'recoveryAdminEnabled' && $default === '0') { |
|
58 | + return '1'; |
|
59 | + } |
|
60 | + if ($app === 'encryption' && $key === 'encryptHomeStorage' && $default === '1') { |
|
61 | + return '1'; |
|
62 | + } |
|
63 | + return $default; |
|
64 | + })); |
|
65 | + $params = [ |
|
66 | + 'recoveryEnabled' => '1', |
|
67 | + 'initStatus' => '0', |
|
68 | + 'encryptHomeStorage' => true, |
|
69 | + 'masterKeyEnabled' => true |
|
70 | + ]; |
|
71 | + $expected = new TemplateResponse('encryption', 'settings-admin', $params, ''); |
|
72 | + $this->assertEquals($expected, $this->admin->getForm()); |
|
73 | + } |
|
74 | 74 | |
75 | - public function testGetSection(): void { |
|
76 | - $this->assertSame('security', $this->admin->getSection()); |
|
77 | - } |
|
75 | + public function testGetSection(): void { |
|
76 | + $this->assertSame('security', $this->admin->getSection()); |
|
77 | + } |
|
78 | 78 | |
79 | - public function testGetPriority(): void { |
|
80 | - $this->assertSame(11, $this->admin->getPriority()); |
|
81 | - } |
|
79 | + public function testGetPriority(): void { |
|
80 | + $this->assertSame(11, $this->admin->getPriority()); |
|
81 | + } |
|
82 | 82 | } |
@@ -17,61 +17,61 @@ |
||
17 | 17 | |
18 | 18 | class SetupTest extends TestCase { |
19 | 19 | |
20 | - protected Setup $instance; |
|
21 | - |
|
22 | - protected KeyManager&MockObject $keyManagerMock; |
|
23 | - protected Crypt&MockObject $cryptMock; |
|
24 | - |
|
25 | - protected function setUp(): void { |
|
26 | - parent::setUp(); |
|
27 | - $this->cryptMock = $this->getMockBuilder(Crypt::class) |
|
28 | - ->disableOriginalConstructor() |
|
29 | - ->getMock(); |
|
30 | - |
|
31 | - $this->keyManagerMock = $this->getMockBuilder(KeyManager::class) |
|
32 | - ->disableOriginalConstructor() |
|
33 | - ->getMock(); |
|
34 | - |
|
35 | - $this->instance = new Setup( |
|
36 | - $this->cryptMock, |
|
37 | - $this->keyManagerMock); |
|
38 | - } |
|
39 | - |
|
40 | - |
|
41 | - public function testSetupSystem(): void { |
|
42 | - $this->keyManagerMock->expects($this->once())->method('validateShareKey'); |
|
43 | - $this->keyManagerMock->expects($this->once())->method('validateMasterKey'); |
|
44 | - |
|
45 | - $this->instance->setupSystem(); |
|
46 | - } |
|
47 | - |
|
48 | - /** |
|
49 | - * @dataProvider dataTestSetupUser |
|
50 | - * |
|
51 | - * @param bool $hasKeys |
|
52 | - * @param bool $expected |
|
53 | - */ |
|
54 | - public function testSetupUser($hasKeys, $expected): void { |
|
55 | - $this->keyManagerMock->expects($this->once())->method('userHasKeys') |
|
56 | - ->with('uid')->willReturn($hasKeys); |
|
57 | - |
|
58 | - if ($hasKeys) { |
|
59 | - $this->keyManagerMock->expects($this->never())->method('storeKeyPair'); |
|
60 | - } else { |
|
61 | - $this->cryptMock->expects($this->once())->method('createKeyPair')->willReturn(['publicKey' => 'publicKey', 'privateKey' => 'privateKey']); |
|
62 | - $this->keyManagerMock->expects($this->once())->method('storeKeyPair') |
|
63 | - ->with('uid', 'password', ['publicKey' => 'publicKey', 'privateKey' => 'privateKey'])->willReturn(true); |
|
64 | - } |
|
65 | - |
|
66 | - $this->assertSame($expected, |
|
67 | - $this->instance->setupUser('uid', 'password') |
|
68 | - ); |
|
69 | - } |
|
70 | - |
|
71 | - public static function dataTestSetupUser(): array { |
|
72 | - return [ |
|
73 | - [true, true], |
|
74 | - [false, true] |
|
75 | - ]; |
|
76 | - } |
|
20 | + protected Setup $instance; |
|
21 | + |
|
22 | + protected KeyManager&MockObject $keyManagerMock; |
|
23 | + protected Crypt&MockObject $cryptMock; |
|
24 | + |
|
25 | + protected function setUp(): void { |
|
26 | + parent::setUp(); |
|
27 | + $this->cryptMock = $this->getMockBuilder(Crypt::class) |
|
28 | + ->disableOriginalConstructor() |
|
29 | + ->getMock(); |
|
30 | + |
|
31 | + $this->keyManagerMock = $this->getMockBuilder(KeyManager::class) |
|
32 | + ->disableOriginalConstructor() |
|
33 | + ->getMock(); |
|
34 | + |
|
35 | + $this->instance = new Setup( |
|
36 | + $this->cryptMock, |
|
37 | + $this->keyManagerMock); |
|
38 | + } |
|
39 | + |
|
40 | + |
|
41 | + public function testSetupSystem(): void { |
|
42 | + $this->keyManagerMock->expects($this->once())->method('validateShareKey'); |
|
43 | + $this->keyManagerMock->expects($this->once())->method('validateMasterKey'); |
|
44 | + |
|
45 | + $this->instance->setupSystem(); |
|
46 | + } |
|
47 | + |
|
48 | + /** |
|
49 | + * @dataProvider dataTestSetupUser |
|
50 | + * |
|
51 | + * @param bool $hasKeys |
|
52 | + * @param bool $expected |
|
53 | + */ |
|
54 | + public function testSetupUser($hasKeys, $expected): void { |
|
55 | + $this->keyManagerMock->expects($this->once())->method('userHasKeys') |
|
56 | + ->with('uid')->willReturn($hasKeys); |
|
57 | + |
|
58 | + if ($hasKeys) { |
|
59 | + $this->keyManagerMock->expects($this->never())->method('storeKeyPair'); |
|
60 | + } else { |
|
61 | + $this->cryptMock->expects($this->once())->method('createKeyPair')->willReturn(['publicKey' => 'publicKey', 'privateKey' => 'privateKey']); |
|
62 | + $this->keyManagerMock->expects($this->once())->method('storeKeyPair') |
|
63 | + ->with('uid', 'password', ['publicKey' => 'publicKey', 'privateKey' => 'privateKey'])->willReturn(true); |
|
64 | + } |
|
65 | + |
|
66 | + $this->assertSame($expected, |
|
67 | + $this->instance->setupUser('uid', 'password') |
|
68 | + ); |
|
69 | + } |
|
70 | + |
|
71 | + public static function dataTestSetupUser(): array { |
|
72 | + return [ |
|
73 | + [true, true], |
|
74 | + [false, true] |
|
75 | + ]; |
|
76 | + } |
|
77 | 77 | } |
@@ -31,682 +31,682 @@ |
||
31 | 31 | |
32 | 32 | class KeyManagerTest extends TestCase { |
33 | 33 | |
34 | - protected KeyManager $instance; |
|
35 | - |
|
36 | - protected string $userId; |
|
37 | - protected string $systemKeyId; |
|
38 | - protected IStorage&MockObject $keyStorageMock; |
|
39 | - protected Crypt&MockObject $cryptMock; |
|
40 | - protected IUserSession&MockObject $userMock; |
|
41 | - protected Session&MockObject $sessionMock; |
|
42 | - protected LoggerInterface&MockObject $logMock; |
|
43 | - protected Util&MockObject $utilMock; |
|
44 | - protected IConfig&MockObject $configMock; |
|
45 | - protected ILockingProvider&MockObject $lockingProviderMock; |
|
46 | - |
|
47 | - protected function setUp(): void { |
|
48 | - parent::setUp(); |
|
49 | - $this->userId = 'user1'; |
|
50 | - $this->systemKeyId = 'systemKeyId'; |
|
51 | - $this->keyStorageMock = $this->createMock(IStorage::class); |
|
52 | - $this->cryptMock = $this->getMockBuilder(Crypt::class) |
|
53 | - ->disableOriginalConstructor() |
|
54 | - ->getMock(); |
|
55 | - $this->configMock = $this->createMock(IConfig::class); |
|
56 | - $this->configMock->expects($this->any()) |
|
57 | - ->method('getAppValue') |
|
58 | - ->willReturn($this->systemKeyId); |
|
59 | - $this->userMock = $this->createMock(IUserSession::class); |
|
60 | - $this->sessionMock = $this->getMockBuilder(Session::class) |
|
61 | - ->disableOriginalConstructor() |
|
62 | - ->getMock(); |
|
63 | - $this->logMock = $this->createMock(LoggerInterface::class); |
|
64 | - $this->utilMock = $this->getMockBuilder(Util::class) |
|
65 | - ->disableOriginalConstructor() |
|
66 | - ->getMock(); |
|
67 | - $this->lockingProviderMock = $this->createMock(ILockingProvider::class); |
|
68 | - |
|
69 | - $this->instance = new KeyManager( |
|
70 | - $this->keyStorageMock, |
|
71 | - $this->cryptMock, |
|
72 | - $this->configMock, |
|
73 | - $this->userMock, |
|
74 | - $this->sessionMock, |
|
75 | - $this->logMock, |
|
76 | - $this->utilMock, |
|
77 | - $this->lockingProviderMock |
|
78 | - ); |
|
79 | - } |
|
80 | - |
|
81 | - public function testDeleteShareKey(): void { |
|
82 | - $this->keyStorageMock->expects($this->any()) |
|
83 | - ->method('deleteFileKey') |
|
84 | - ->with($this->equalTo('/path'), $this->equalTo('keyId.shareKey')) |
|
85 | - ->willReturn(true); |
|
86 | - |
|
87 | - $this->assertTrue( |
|
88 | - $this->instance->deleteShareKey('/path', 'keyId') |
|
89 | - ); |
|
90 | - } |
|
91 | - |
|
92 | - public function testGetPrivateKey(): void { |
|
93 | - $this->keyStorageMock->expects($this->any()) |
|
94 | - ->method('getUserKey') |
|
95 | - ->with($this->equalTo($this->userId), $this->equalTo('privateKey')) |
|
96 | - ->willReturn('privateKey'); |
|
97 | - |
|
98 | - |
|
99 | - $this->assertSame('privateKey', |
|
100 | - $this->instance->getPrivateKey($this->userId) |
|
101 | - ); |
|
102 | - } |
|
103 | - |
|
104 | - public function testGetPublicKey(): void { |
|
105 | - $this->keyStorageMock->expects($this->any()) |
|
106 | - ->method('getUserKey') |
|
107 | - ->with($this->equalTo($this->userId), $this->equalTo('publicKey')) |
|
108 | - ->willReturn('publicKey'); |
|
109 | - |
|
110 | - |
|
111 | - $this->assertSame('publicKey', |
|
112 | - $this->instance->getPublicKey($this->userId) |
|
113 | - ); |
|
114 | - } |
|
115 | - |
|
116 | - public function testRecoveryKeyExists(): void { |
|
117 | - $this->keyStorageMock->expects($this->any()) |
|
118 | - ->method('getSystemUserKey') |
|
119 | - ->with($this->equalTo($this->systemKeyId . '.publicKey')) |
|
120 | - ->willReturn('recoveryKey'); |
|
121 | - |
|
122 | - |
|
123 | - $this->assertTrue($this->instance->recoveryKeyExists()); |
|
124 | - } |
|
125 | - |
|
126 | - public function testCheckRecoveryKeyPassword(): void { |
|
127 | - $this->keyStorageMock->expects($this->any()) |
|
128 | - ->method('getSystemUserKey') |
|
129 | - ->with($this->equalTo($this->systemKeyId . '.privateKey')) |
|
130 | - ->willReturn('recoveryKey'); |
|
131 | - $this->cryptMock->expects($this->any()) |
|
132 | - ->method('decryptPrivateKey') |
|
133 | - ->with($this->equalTo('recoveryKey'), $this->equalTo('pass')) |
|
134 | - ->willReturn('decryptedRecoveryKey'); |
|
135 | - |
|
136 | - $this->assertTrue($this->instance->checkRecoveryPassword('pass')); |
|
137 | - } |
|
138 | - |
|
139 | - public function testSetPublicKey(): void { |
|
140 | - $this->keyStorageMock->expects($this->any()) |
|
141 | - ->method('setUserKey') |
|
142 | - ->with( |
|
143 | - $this->equalTo($this->userId), |
|
144 | - $this->equalTo('publicKey'), |
|
145 | - $this->equalTo('key')) |
|
146 | - ->willReturn(true); |
|
147 | - |
|
148 | - |
|
149 | - $this->assertTrue( |
|
150 | - $this->instance->setPublicKey($this->userId, 'key') |
|
151 | - ); |
|
152 | - } |
|
153 | - |
|
154 | - public function testSetPrivateKey(): void { |
|
155 | - $this->keyStorageMock->expects($this->any()) |
|
156 | - ->method('setUserKey') |
|
157 | - ->with( |
|
158 | - $this->equalTo($this->userId), |
|
159 | - $this->equalTo('privateKey'), |
|
160 | - $this->equalTo('key')) |
|
161 | - ->willReturn(true); |
|
162 | - |
|
163 | - |
|
164 | - $this->assertTrue( |
|
165 | - $this->instance->setPrivateKey($this->userId, 'key') |
|
166 | - ); |
|
167 | - } |
|
168 | - |
|
169 | - /** |
|
170 | - * @dataProvider dataTestUserHasKeys |
|
171 | - */ |
|
172 | - public function testUserHasKeys($key, $expected): void { |
|
173 | - $this->keyStorageMock->expects($this->exactly(2)) |
|
174 | - ->method('getUserKey') |
|
175 | - ->with($this->equalTo($this->userId), $this->anything()) |
|
176 | - ->willReturn($key); |
|
177 | - |
|
178 | - |
|
179 | - $this->assertSame($expected, |
|
180 | - $this->instance->userHasKeys($this->userId) |
|
181 | - ); |
|
182 | - } |
|
183 | - |
|
184 | - public static function dataTestUserHasKeys(): array { |
|
185 | - return [ |
|
186 | - ['key', true], |
|
187 | - ['', false] |
|
188 | - ]; |
|
189 | - } |
|
190 | - |
|
191 | - |
|
192 | - public function testUserHasKeysMissingPrivateKey(): void { |
|
193 | - $this->expectException(PrivateKeyMissingException::class); |
|
194 | - |
|
195 | - $this->keyStorageMock->expects($this->exactly(2)) |
|
196 | - ->method('getUserKey') |
|
197 | - ->willReturnCallback(function ($uid, $keyID, $encryptionModuleId) { |
|
198 | - if ($keyID === 'privateKey') { |
|
199 | - return ''; |
|
200 | - } |
|
201 | - return 'key'; |
|
202 | - }); |
|
203 | - |
|
204 | - $this->instance->userHasKeys($this->userId); |
|
205 | - } |
|
206 | - |
|
207 | - |
|
208 | - public function testUserHasKeysMissingPublicKey(): void { |
|
209 | - $this->expectException(PublicKeyMissingException::class); |
|
210 | - |
|
211 | - $this->keyStorageMock->expects($this->exactly(2)) |
|
212 | - ->method('getUserKey') |
|
213 | - ->willReturnCallback(function ($uid, $keyID, $encryptionModuleId) { |
|
214 | - if ($keyID === 'publicKey') { |
|
215 | - return ''; |
|
216 | - } |
|
217 | - return 'key'; |
|
218 | - }); |
|
219 | - |
|
220 | - $this->instance->userHasKeys($this->userId); |
|
221 | - } |
|
222 | - |
|
223 | - /** |
|
224 | - * @dataProvider dataTestInit |
|
225 | - * |
|
226 | - * @param bool $useMasterKey |
|
227 | - */ |
|
228 | - public function testInit($useMasterKey): void { |
|
229 | - /** @var KeyManager&MockObject $instance */ |
|
230 | - $instance = $this->getMockBuilder(KeyManager::class) |
|
231 | - ->setConstructorArgs( |
|
232 | - [ |
|
233 | - $this->keyStorageMock, |
|
234 | - $this->cryptMock, |
|
235 | - $this->configMock, |
|
236 | - $this->userMock, |
|
237 | - $this->sessionMock, |
|
238 | - $this->logMock, |
|
239 | - $this->utilMock, |
|
240 | - $this->lockingProviderMock |
|
241 | - ] |
|
242 | - )->onlyMethods(['getMasterKeyId', 'getMasterKeyPassword', 'getSystemPrivateKey', 'getPrivateKey']) |
|
243 | - ->getMock(); |
|
244 | - |
|
245 | - $this->utilMock->expects($this->once())->method('isMasterKeyEnabled') |
|
246 | - ->willReturn($useMasterKey); |
|
247 | - |
|
248 | - $sessionSetStatusCalls = []; |
|
249 | - $this->sessionMock->expects($this->exactly(2)) |
|
250 | - ->method('setStatus') |
|
251 | - ->willReturnCallback(function (string $status) use (&$sessionSetStatusCalls) { |
|
252 | - $sessionSetStatusCalls[] = $status; |
|
253 | - }); |
|
254 | - |
|
255 | - $instance->expects($this->any())->method('getMasterKeyId')->willReturn('masterKeyId'); |
|
256 | - $instance->expects($this->any())->method('getMasterKeyPassword')->willReturn('masterKeyPassword'); |
|
257 | - $instance->expects($this->any())->method('getSystemPrivateKey')->with('masterKeyId')->willReturn('privateMasterKey'); |
|
258 | - $instance->expects($this->any())->method('getPrivateKey')->with($this->userId)->willReturn('privateUserKey'); |
|
259 | - |
|
260 | - if ($useMasterKey) { |
|
261 | - $this->cryptMock->expects($this->once())->method('decryptPrivateKey') |
|
262 | - ->with('privateMasterKey', 'masterKeyPassword', 'masterKeyId') |
|
263 | - ->willReturn('key'); |
|
264 | - } else { |
|
265 | - $this->cryptMock->expects($this->once())->method('decryptPrivateKey') |
|
266 | - ->with('privateUserKey', 'pass', $this->userId) |
|
267 | - ->willReturn('key'); |
|
268 | - } |
|
269 | - |
|
270 | - $this->sessionMock->expects($this->once())->method('setPrivateKey') |
|
271 | - ->with('key'); |
|
272 | - |
|
273 | - $this->assertTrue($instance->init($this->userId, 'pass')); |
|
274 | - self::assertEquals([ |
|
275 | - Session::INIT_EXECUTED, |
|
276 | - Session::INIT_SUCCESSFUL, |
|
277 | - ], $sessionSetStatusCalls); |
|
278 | - } |
|
279 | - |
|
280 | - public static function dataTestInit(): array { |
|
281 | - return [ |
|
282 | - [true], |
|
283 | - [false] |
|
284 | - ]; |
|
285 | - } |
|
286 | - |
|
287 | - |
|
288 | - public function testSetRecoveryKey(): void { |
|
289 | - $this->keyStorageMock->expects($this->exactly(2)) |
|
290 | - ->method('setSystemUserKey') |
|
291 | - ->willReturn(true); |
|
292 | - $this->cryptMock->expects($this->any()) |
|
293 | - ->method('encryptPrivateKey') |
|
294 | - ->with($this->equalTo('privateKey'), $this->equalTo('pass')) |
|
295 | - ->willReturn('decryptedPrivateKey'); |
|
296 | - |
|
297 | - |
|
298 | - $this->assertTrue( |
|
299 | - $this->instance->setRecoveryKey('pass', |
|
300 | - ['publicKey' => 'publicKey', 'privateKey' => 'privateKey']) |
|
301 | - ); |
|
302 | - } |
|
303 | - |
|
304 | - public function testSetSystemPrivateKey(): void { |
|
305 | - $this->keyStorageMock->expects($this->exactly(1)) |
|
306 | - ->method('setSystemUserKey') |
|
307 | - ->with($this->equalTo('keyId.privateKey'), $this->equalTo('key')) |
|
308 | - ->willReturn(true); |
|
309 | - |
|
310 | - |
|
311 | - $this->assertTrue( |
|
312 | - $this->instance->setSystemPrivateKey('keyId', 'key') |
|
313 | - ); |
|
314 | - } |
|
315 | - |
|
316 | - public function testGetSystemPrivateKey(): void { |
|
317 | - $this->keyStorageMock->expects($this->exactly(1)) |
|
318 | - ->method('getSystemUserKey') |
|
319 | - ->with($this->equalTo('keyId.privateKey')) |
|
320 | - ->willReturn('systemPrivateKey'); |
|
321 | - |
|
322 | - |
|
323 | - $this->assertSame('systemPrivateKey', |
|
324 | - $this->instance->getSystemPrivateKey('keyId') |
|
325 | - ); |
|
326 | - } |
|
327 | - |
|
328 | - public function testGetEncryptedFileKey(): void { |
|
329 | - $this->keyStorageMock->expects($this->once()) |
|
330 | - ->method('getFileKey') |
|
331 | - ->with('/', 'fileKey') |
|
332 | - ->willReturn(true); |
|
333 | - |
|
334 | - $this->assertTrue($this->instance->getEncryptedFileKey('/')); |
|
335 | - } |
|
336 | - |
|
337 | - public static function dataTestGetFileKey(): array { |
|
338 | - return [ |
|
339 | - ['user1', false, 'privateKey', 'legacyKey', 'multiKeyDecryptResult'], |
|
340 | - ['user1', false, 'privateKey', '', 'multiKeyDecryptResult'], |
|
341 | - ['user1', false, false, 'legacyKey', ''], |
|
342 | - ['user1', false, false, '', ''], |
|
343 | - ['user1', true, 'privateKey', 'legacyKey', 'multiKeyDecryptResult'], |
|
344 | - ['user1', true, 'privateKey', '', 'multiKeyDecryptResult'], |
|
345 | - ['user1', true, false, 'legacyKey', ''], |
|
346 | - ['user1', true, false, '', ''], |
|
347 | - [null, false, 'privateKey', 'legacyKey', 'multiKeyDecryptResult'], |
|
348 | - [null, false, 'privateKey', '', 'multiKeyDecryptResult'], |
|
349 | - [null, false, false, 'legacyKey', ''], |
|
350 | - [null, false, false, '', ''], |
|
351 | - [null, true, 'privateKey', 'legacyKey', 'multiKeyDecryptResult'], |
|
352 | - [null, true, 'privateKey', '', 'multiKeyDecryptResult'], |
|
353 | - [null, true, false, 'legacyKey', ''], |
|
354 | - [null, true, false, '', ''], |
|
355 | - ]; |
|
356 | - } |
|
357 | - |
|
358 | - /** |
|
359 | - * @dataProvider dataTestGetFileKey |
|
360 | - * |
|
361 | - * @param $uid |
|
362 | - * @param $isMasterKeyEnabled |
|
363 | - * @param $privateKey |
|
364 | - * @param $expected |
|
365 | - */ |
|
366 | - public function testGetFileKey($uid, $isMasterKeyEnabled, $privateKey, $encryptedFileKey, $expected): void { |
|
367 | - $path = '/foo.txt'; |
|
368 | - |
|
369 | - if ($isMasterKeyEnabled) { |
|
370 | - $expectedUid = 'masterKeyId'; |
|
371 | - $this->configMock->expects($this->any())->method('getSystemValue')->with('secret') |
|
372 | - ->willReturn('password'); |
|
373 | - } elseif (!$uid) { |
|
374 | - $expectedUid = 'systemKeyId'; |
|
375 | - } else { |
|
376 | - $expectedUid = $uid; |
|
377 | - } |
|
378 | - |
|
379 | - $this->invokePrivate($this->instance, 'masterKeyId', ['masterKeyId']); |
|
380 | - |
|
381 | - $this->keyStorageMock->expects($this->exactly(2)) |
|
382 | - ->method('getFileKey') |
|
383 | - ->willReturnMap([ |
|
384 | - [$path, 'fileKey', 'OC_DEFAULT_MODULE', $encryptedFileKey], |
|
385 | - [$path, $expectedUid . '.shareKey', 'OC_DEFAULT_MODULE', 'fileKey'], |
|
386 | - ]); |
|
387 | - |
|
388 | - $this->utilMock->expects($this->any())->method('isMasterKeyEnabled') |
|
389 | - ->willReturn($isMasterKeyEnabled); |
|
390 | - |
|
391 | - if (is_null($uid)) { |
|
392 | - $this->keyStorageMock->expects($this->once()) |
|
393 | - ->method('getSystemUserKey') |
|
394 | - ->willReturn(true); |
|
395 | - $this->cryptMock->expects($this->once()) |
|
396 | - ->method('decryptPrivateKey') |
|
397 | - ->willReturn($privateKey); |
|
398 | - } else { |
|
399 | - $this->keyStorageMock->expects($this->never()) |
|
400 | - ->method('getSystemUserKey'); |
|
401 | - $this->sessionMock->expects($this->once())->method('getPrivateKey')->willReturn($privateKey); |
|
402 | - } |
|
403 | - |
|
404 | - if (!empty($encryptedFileKey)) { |
|
405 | - $this->cryptMock->expects($this->never()) |
|
406 | - ->method('multiKeyDecrypt'); |
|
407 | - if ($privateKey) { |
|
408 | - $this->cryptMock->expects($this->once()) |
|
409 | - ->method('multiKeyDecryptLegacy') |
|
410 | - ->willReturn('multiKeyDecryptResult'); |
|
411 | - } else { |
|
412 | - $this->cryptMock->expects($this->never()) |
|
413 | - ->method('multiKeyDecryptLegacy'); |
|
414 | - } |
|
415 | - } else { |
|
416 | - $this->cryptMock->expects($this->never()) |
|
417 | - ->method('multiKeyDecryptLegacy'); |
|
418 | - if ($privateKey) { |
|
419 | - $this->cryptMock->expects($this->once()) |
|
420 | - ->method('multiKeyDecrypt') |
|
421 | - ->willReturn('multiKeyDecryptResult'); |
|
422 | - } else { |
|
423 | - $this->cryptMock->expects($this->never()) |
|
424 | - ->method('multiKeyDecrypt'); |
|
425 | - } |
|
426 | - } |
|
427 | - |
|
428 | - $this->assertSame($expected, |
|
429 | - $this->instance->getFileKey($path, $uid, null) |
|
430 | - ); |
|
431 | - } |
|
432 | - |
|
433 | - public function testDeletePrivateKey(): void { |
|
434 | - $this->keyStorageMock->expects($this->once()) |
|
435 | - ->method('deleteUserKey') |
|
436 | - ->with('user1', 'privateKey') |
|
437 | - ->willReturn(true); |
|
438 | - |
|
439 | - $this->assertTrue(self::invokePrivate($this->instance, |
|
440 | - 'deletePrivateKey', |
|
441 | - [$this->userId])); |
|
442 | - } |
|
443 | - |
|
444 | - public function testDeleteAllFileKeys(): void { |
|
445 | - $this->keyStorageMock->expects($this->once()) |
|
446 | - ->method('deleteAllFileKeys') |
|
447 | - ->willReturn(true); |
|
448 | - |
|
449 | - $this->assertTrue($this->instance->deleteAllFileKeys('/')); |
|
450 | - } |
|
451 | - |
|
452 | - /** |
|
453 | - * test add public share key and or recovery key to the list of public keys |
|
454 | - * |
|
455 | - * @dataProvider dataTestAddSystemKeys |
|
456 | - * |
|
457 | - * @param array $accessList |
|
458 | - * @param array $publicKeys |
|
459 | - * @param string $uid |
|
460 | - * @param array $expectedKeys |
|
461 | - */ |
|
462 | - public function testAddSystemKeys($accessList, $publicKeys, $uid, $expectedKeys): void { |
|
463 | - $publicShareKeyId = 'publicShareKey'; |
|
464 | - $recoveryKeyId = 'recoveryKey'; |
|
465 | - |
|
466 | - $this->keyStorageMock->expects($this->any()) |
|
467 | - ->method('getSystemUserKey') |
|
468 | - ->willReturnCallback(function ($keyId, $encryptionModuleId) { |
|
469 | - return $keyId; |
|
470 | - }); |
|
471 | - |
|
472 | - $this->utilMock->expects($this->any()) |
|
473 | - ->method('isRecoveryEnabledForUser') |
|
474 | - ->willReturnCallback(function ($uid) { |
|
475 | - if ($uid === 'user1') { |
|
476 | - return true; |
|
477 | - } |
|
478 | - return false; |
|
479 | - }); |
|
480 | - |
|
481 | - // set key IDs |
|
482 | - self::invokePrivate($this->instance, 'publicShareKeyId', [$publicShareKeyId]); |
|
483 | - self::invokePrivate($this->instance, 'recoveryKeyId', [$recoveryKeyId]); |
|
484 | - |
|
485 | - $result = $this->instance->addSystemKeys($accessList, $publicKeys, $uid); |
|
486 | - |
|
487 | - foreach ($expectedKeys as $expected) { |
|
488 | - $this->assertArrayHasKey($expected, $result); |
|
489 | - } |
|
490 | - |
|
491 | - $this->assertSameSize($expectedKeys, $result); |
|
492 | - } |
|
493 | - |
|
494 | - /** |
|
495 | - * data provider for testAddSystemKeys() |
|
496 | - * |
|
497 | - * @return array |
|
498 | - */ |
|
499 | - public static function dataTestAddSystemKeys(): array { |
|
500 | - return [ |
|
501 | - [['public' => true],[], 'user1', ['publicShareKey', 'recoveryKey']], |
|
502 | - [['public' => false], [], 'user1', ['recoveryKey']], |
|
503 | - [['public' => true],[], 'user2', ['publicShareKey']], |
|
504 | - [['public' => false], [], 'user2', []], |
|
505 | - ]; |
|
506 | - } |
|
507 | - |
|
508 | - public function testGetMasterKeyId(): void { |
|
509 | - $this->assertSame('systemKeyId', $this->instance->getMasterKeyId()); |
|
510 | - } |
|
511 | - |
|
512 | - public function testGetPublicMasterKey(): void { |
|
513 | - $this->keyStorageMock->expects($this->once())->method('getSystemUserKey') |
|
514 | - ->with('systemKeyId.publicKey', Encryption::ID) |
|
515 | - ->willReturn(true); |
|
516 | - |
|
517 | - $this->assertTrue( |
|
518 | - $this->instance->getPublicMasterKey() |
|
519 | - ); |
|
520 | - } |
|
521 | - |
|
522 | - public function testGetMasterKeyPassword(): void { |
|
523 | - $this->configMock->expects($this->once())->method('getSystemValue')->with('secret') |
|
524 | - ->willReturn('password'); |
|
525 | - |
|
526 | - $this->assertSame('password', |
|
527 | - $this->invokePrivate($this->instance, 'getMasterKeyPassword', []) |
|
528 | - ); |
|
529 | - } |
|
530 | - |
|
531 | - |
|
532 | - public function testGetMasterKeyPasswordException(): void { |
|
533 | - $this->expectException(\Exception::class); |
|
534 | - |
|
535 | - $this->configMock->expects($this->once())->method('getSystemValue')->with('secret') |
|
536 | - ->willReturn(''); |
|
537 | - |
|
538 | - $this->invokePrivate($this->instance, 'getMasterKeyPassword', []); |
|
539 | - } |
|
540 | - |
|
541 | - /** |
|
542 | - * @dataProvider dataTestValidateMasterKey |
|
543 | - * |
|
544 | - * @param $masterKey |
|
545 | - */ |
|
546 | - public function testValidateMasterKey($masterKey): void { |
|
547 | - /** @var KeyManager&MockObject $instance */ |
|
548 | - $instance = $this->getMockBuilder(KeyManager::class) |
|
549 | - ->setConstructorArgs( |
|
550 | - [ |
|
551 | - $this->keyStorageMock, |
|
552 | - $this->cryptMock, |
|
553 | - $this->configMock, |
|
554 | - $this->userMock, |
|
555 | - $this->sessionMock, |
|
556 | - $this->logMock, |
|
557 | - $this->utilMock, |
|
558 | - $this->lockingProviderMock |
|
559 | - ] |
|
560 | - )->onlyMethods(['getPublicMasterKey', 'setSystemPrivateKey', 'getMasterKeyPassword']) |
|
561 | - ->getMock(); |
|
562 | - |
|
563 | - $this->utilMock->expects($this->once())->method('isMasterKeyEnabled') |
|
564 | - ->willReturn(true); |
|
565 | - |
|
566 | - $instance->expects($this->once())->method('getPublicMasterKey') |
|
567 | - ->willReturn($masterKey); |
|
568 | - |
|
569 | - $instance->expects($this->any())->method('getMasterKeyPassword')->willReturn('masterKeyPassword'); |
|
570 | - $this->cryptMock->expects($this->any())->method('generateHeader')->willReturn('header'); |
|
571 | - |
|
572 | - if (empty($masterKey)) { |
|
573 | - $this->cryptMock->expects($this->once())->method('createKeyPair') |
|
574 | - ->willReturn(['publicKey' => 'public', 'privateKey' => 'private']); |
|
575 | - $this->keyStorageMock->expects($this->once())->method('setSystemUserKey') |
|
576 | - ->with('systemKeyId.publicKey', 'public', Encryption::ID); |
|
577 | - $this->cryptMock->expects($this->once())->method('encryptPrivateKey') |
|
578 | - ->with('private', 'masterKeyPassword', 'systemKeyId') |
|
579 | - ->willReturn('EncryptedKey'); |
|
580 | - $this->lockingProviderMock->expects($this->once()) |
|
581 | - ->method('acquireLock'); |
|
582 | - $instance->expects($this->once())->method('setSystemPrivateKey') |
|
583 | - ->with('systemKeyId', 'headerEncryptedKey'); |
|
584 | - } else { |
|
585 | - $this->cryptMock->expects($this->never())->method('createKeyPair'); |
|
586 | - $this->keyStorageMock->expects($this->never())->method('setSystemUserKey'); |
|
587 | - $this->cryptMock->expects($this->never())->method('encryptPrivateKey'); |
|
588 | - $instance->expects($this->never())->method('setSystemPrivateKey'); |
|
589 | - } |
|
590 | - |
|
591 | - $instance->validateMasterKey(); |
|
592 | - } |
|
593 | - |
|
594 | - public function testValidateMasterKeyLocked(): void { |
|
595 | - /** @var KeyManager&MockObject $instance */ |
|
596 | - $instance = $this->getMockBuilder(KeyManager::class) |
|
597 | - ->setConstructorArgs([ |
|
598 | - $this->keyStorageMock, |
|
599 | - $this->cryptMock, |
|
600 | - $this->configMock, |
|
601 | - $this->userMock, |
|
602 | - $this->sessionMock, |
|
603 | - $this->logMock, |
|
604 | - $this->utilMock, |
|
605 | - $this->lockingProviderMock |
|
606 | - ]) |
|
607 | - ->onlyMethods(['getPublicMasterKey', 'getPrivateMasterKey', 'setSystemPrivateKey', 'getMasterKeyPassword']) |
|
608 | - ->getMock(); |
|
609 | - |
|
610 | - $this->utilMock->expects($this->once())->method('isMasterKeyEnabled') |
|
611 | - ->willReturn(true); |
|
612 | - |
|
613 | - $instance->expects($this->once())->method('getPublicMasterKey') |
|
614 | - ->willReturn(''); |
|
615 | - $instance->expects($this->once())->method('getPrivateMasterKey') |
|
616 | - ->willReturn(''); |
|
617 | - |
|
618 | - $instance->expects($this->any())->method('getMasterKeyPassword')->willReturn('masterKeyPassword'); |
|
619 | - $this->cryptMock->expects($this->any())->method('generateHeader')->willReturn('header'); |
|
620 | - |
|
621 | - $this->lockingProviderMock->expects($this->once()) |
|
622 | - ->method('acquireLock') |
|
623 | - ->willThrowException(new LockedException('encryption-generateMasterKey')); |
|
624 | - |
|
625 | - $this->expectException(LockedException::class); |
|
626 | - $instance->validateMasterKey(); |
|
627 | - } |
|
628 | - |
|
629 | - public static function dataTestValidateMasterKey(): array { |
|
630 | - return [ |
|
631 | - ['masterKey'], |
|
632 | - [''] |
|
633 | - ]; |
|
634 | - } |
|
635 | - |
|
636 | - public function testGetVersionWithoutFileInfo(): void { |
|
637 | - $view = $this->getMockBuilder(View::class) |
|
638 | - ->disableOriginalConstructor()->getMock(); |
|
639 | - $view->expects($this->once()) |
|
640 | - ->method('getFileInfo') |
|
641 | - ->with('/admin/files/myfile.txt') |
|
642 | - ->willReturn(false); |
|
643 | - |
|
644 | - /** @var View $view */ |
|
645 | - $this->assertSame(0, $this->instance->getVersion('/admin/files/myfile.txt', $view)); |
|
646 | - } |
|
647 | - |
|
648 | - public function testGetVersionWithFileInfo(): void { |
|
649 | - $view = $this->getMockBuilder(View::class) |
|
650 | - ->disableOriginalConstructor()->getMock(); |
|
651 | - $fileInfo = $this->getMockBuilder(FileInfo::class) |
|
652 | - ->disableOriginalConstructor()->getMock(); |
|
653 | - $fileInfo->expects($this->once()) |
|
654 | - ->method('getEncryptedVersion') |
|
655 | - ->willReturn(1337); |
|
656 | - $view->expects($this->once()) |
|
657 | - ->method('getFileInfo') |
|
658 | - ->with('/admin/files/myfile.txt') |
|
659 | - ->willReturn($fileInfo); |
|
660 | - |
|
661 | - /** @var View $view */ |
|
662 | - $this->assertSame(1337, $this->instance->getVersion('/admin/files/myfile.txt', $view)); |
|
663 | - } |
|
664 | - |
|
665 | - public function testSetVersionWithFileInfo(): void { |
|
666 | - $view = $this->getMockBuilder(View::class) |
|
667 | - ->disableOriginalConstructor()->getMock(); |
|
668 | - $cache = $this->getMockBuilder(ICache::class) |
|
669 | - ->disableOriginalConstructor()->getMock(); |
|
670 | - $cache->expects($this->once()) |
|
671 | - ->method('update') |
|
672 | - ->with(123, ['encrypted' => 5, 'encryptedVersion' => 5]); |
|
673 | - $storage = $this->getMockBuilder(FilesIStorage::class) |
|
674 | - ->disableOriginalConstructor()->getMock(); |
|
675 | - $storage->expects($this->once()) |
|
676 | - ->method('getCache') |
|
677 | - ->willReturn($cache); |
|
678 | - $fileInfo = $this->getMockBuilder(FileInfo::class) |
|
679 | - ->disableOriginalConstructor()->getMock(); |
|
680 | - $fileInfo->expects($this->once()) |
|
681 | - ->method('getStorage') |
|
682 | - ->willReturn($storage); |
|
683 | - $fileInfo->expects($this->once()) |
|
684 | - ->method('getId') |
|
685 | - ->willReturn(123); |
|
686 | - $view->expects($this->once()) |
|
687 | - ->method('getFileInfo') |
|
688 | - ->with('/admin/files/myfile.txt') |
|
689 | - ->willReturn($fileInfo); |
|
690 | - |
|
691 | - /** @var View $view */ |
|
692 | - $this->instance->setVersion('/admin/files/myfile.txt', 5, $view); |
|
693 | - } |
|
694 | - |
|
695 | - public function testSetVersionWithoutFileInfo(): void { |
|
696 | - $view = $this->getMockBuilder(View::class) |
|
697 | - ->disableOriginalConstructor()->getMock(); |
|
698 | - $view->expects($this->once()) |
|
699 | - ->method('getFileInfo') |
|
700 | - ->with('/admin/files/myfile.txt') |
|
701 | - ->willReturn(false); |
|
702 | - |
|
703 | - /** @var View $view */ |
|
704 | - $this->instance->setVersion('/admin/files/myfile.txt', 5, $view); |
|
705 | - } |
|
706 | - |
|
707 | - public function testBackupUserKeys(): void { |
|
708 | - $this->keyStorageMock->expects($this->once())->method('backupUserKeys') |
|
709 | - ->with('OC_DEFAULT_MODULE', 'test', 'user1'); |
|
710 | - $this->instance->backupUserKeys('test', 'user1'); |
|
711 | - } |
|
34 | + protected KeyManager $instance; |
|
35 | + |
|
36 | + protected string $userId; |
|
37 | + protected string $systemKeyId; |
|
38 | + protected IStorage&MockObject $keyStorageMock; |
|
39 | + protected Crypt&MockObject $cryptMock; |
|
40 | + protected IUserSession&MockObject $userMock; |
|
41 | + protected Session&MockObject $sessionMock; |
|
42 | + protected LoggerInterface&MockObject $logMock; |
|
43 | + protected Util&MockObject $utilMock; |
|
44 | + protected IConfig&MockObject $configMock; |
|
45 | + protected ILockingProvider&MockObject $lockingProviderMock; |
|
46 | + |
|
47 | + protected function setUp(): void { |
|
48 | + parent::setUp(); |
|
49 | + $this->userId = 'user1'; |
|
50 | + $this->systemKeyId = 'systemKeyId'; |
|
51 | + $this->keyStorageMock = $this->createMock(IStorage::class); |
|
52 | + $this->cryptMock = $this->getMockBuilder(Crypt::class) |
|
53 | + ->disableOriginalConstructor() |
|
54 | + ->getMock(); |
|
55 | + $this->configMock = $this->createMock(IConfig::class); |
|
56 | + $this->configMock->expects($this->any()) |
|
57 | + ->method('getAppValue') |
|
58 | + ->willReturn($this->systemKeyId); |
|
59 | + $this->userMock = $this->createMock(IUserSession::class); |
|
60 | + $this->sessionMock = $this->getMockBuilder(Session::class) |
|
61 | + ->disableOriginalConstructor() |
|
62 | + ->getMock(); |
|
63 | + $this->logMock = $this->createMock(LoggerInterface::class); |
|
64 | + $this->utilMock = $this->getMockBuilder(Util::class) |
|
65 | + ->disableOriginalConstructor() |
|
66 | + ->getMock(); |
|
67 | + $this->lockingProviderMock = $this->createMock(ILockingProvider::class); |
|
68 | + |
|
69 | + $this->instance = new KeyManager( |
|
70 | + $this->keyStorageMock, |
|
71 | + $this->cryptMock, |
|
72 | + $this->configMock, |
|
73 | + $this->userMock, |
|
74 | + $this->sessionMock, |
|
75 | + $this->logMock, |
|
76 | + $this->utilMock, |
|
77 | + $this->lockingProviderMock |
|
78 | + ); |
|
79 | + } |
|
80 | + |
|
81 | + public function testDeleteShareKey(): void { |
|
82 | + $this->keyStorageMock->expects($this->any()) |
|
83 | + ->method('deleteFileKey') |
|
84 | + ->with($this->equalTo('/path'), $this->equalTo('keyId.shareKey')) |
|
85 | + ->willReturn(true); |
|
86 | + |
|
87 | + $this->assertTrue( |
|
88 | + $this->instance->deleteShareKey('/path', 'keyId') |
|
89 | + ); |
|
90 | + } |
|
91 | + |
|
92 | + public function testGetPrivateKey(): void { |
|
93 | + $this->keyStorageMock->expects($this->any()) |
|
94 | + ->method('getUserKey') |
|
95 | + ->with($this->equalTo($this->userId), $this->equalTo('privateKey')) |
|
96 | + ->willReturn('privateKey'); |
|
97 | + |
|
98 | + |
|
99 | + $this->assertSame('privateKey', |
|
100 | + $this->instance->getPrivateKey($this->userId) |
|
101 | + ); |
|
102 | + } |
|
103 | + |
|
104 | + public function testGetPublicKey(): void { |
|
105 | + $this->keyStorageMock->expects($this->any()) |
|
106 | + ->method('getUserKey') |
|
107 | + ->with($this->equalTo($this->userId), $this->equalTo('publicKey')) |
|
108 | + ->willReturn('publicKey'); |
|
109 | + |
|
110 | + |
|
111 | + $this->assertSame('publicKey', |
|
112 | + $this->instance->getPublicKey($this->userId) |
|
113 | + ); |
|
114 | + } |
|
115 | + |
|
116 | + public function testRecoveryKeyExists(): void { |
|
117 | + $this->keyStorageMock->expects($this->any()) |
|
118 | + ->method('getSystemUserKey') |
|
119 | + ->with($this->equalTo($this->systemKeyId . '.publicKey')) |
|
120 | + ->willReturn('recoveryKey'); |
|
121 | + |
|
122 | + |
|
123 | + $this->assertTrue($this->instance->recoveryKeyExists()); |
|
124 | + } |
|
125 | + |
|
126 | + public function testCheckRecoveryKeyPassword(): void { |
|
127 | + $this->keyStorageMock->expects($this->any()) |
|
128 | + ->method('getSystemUserKey') |
|
129 | + ->with($this->equalTo($this->systemKeyId . '.privateKey')) |
|
130 | + ->willReturn('recoveryKey'); |
|
131 | + $this->cryptMock->expects($this->any()) |
|
132 | + ->method('decryptPrivateKey') |
|
133 | + ->with($this->equalTo('recoveryKey'), $this->equalTo('pass')) |
|
134 | + ->willReturn('decryptedRecoveryKey'); |
|
135 | + |
|
136 | + $this->assertTrue($this->instance->checkRecoveryPassword('pass')); |
|
137 | + } |
|
138 | + |
|
139 | + public function testSetPublicKey(): void { |
|
140 | + $this->keyStorageMock->expects($this->any()) |
|
141 | + ->method('setUserKey') |
|
142 | + ->with( |
|
143 | + $this->equalTo($this->userId), |
|
144 | + $this->equalTo('publicKey'), |
|
145 | + $this->equalTo('key')) |
|
146 | + ->willReturn(true); |
|
147 | + |
|
148 | + |
|
149 | + $this->assertTrue( |
|
150 | + $this->instance->setPublicKey($this->userId, 'key') |
|
151 | + ); |
|
152 | + } |
|
153 | + |
|
154 | + public function testSetPrivateKey(): void { |
|
155 | + $this->keyStorageMock->expects($this->any()) |
|
156 | + ->method('setUserKey') |
|
157 | + ->with( |
|
158 | + $this->equalTo($this->userId), |
|
159 | + $this->equalTo('privateKey'), |
|
160 | + $this->equalTo('key')) |
|
161 | + ->willReturn(true); |
|
162 | + |
|
163 | + |
|
164 | + $this->assertTrue( |
|
165 | + $this->instance->setPrivateKey($this->userId, 'key') |
|
166 | + ); |
|
167 | + } |
|
168 | + |
|
169 | + /** |
|
170 | + * @dataProvider dataTestUserHasKeys |
|
171 | + */ |
|
172 | + public function testUserHasKeys($key, $expected): void { |
|
173 | + $this->keyStorageMock->expects($this->exactly(2)) |
|
174 | + ->method('getUserKey') |
|
175 | + ->with($this->equalTo($this->userId), $this->anything()) |
|
176 | + ->willReturn($key); |
|
177 | + |
|
178 | + |
|
179 | + $this->assertSame($expected, |
|
180 | + $this->instance->userHasKeys($this->userId) |
|
181 | + ); |
|
182 | + } |
|
183 | + |
|
184 | + public static function dataTestUserHasKeys(): array { |
|
185 | + return [ |
|
186 | + ['key', true], |
|
187 | + ['', false] |
|
188 | + ]; |
|
189 | + } |
|
190 | + |
|
191 | + |
|
192 | + public function testUserHasKeysMissingPrivateKey(): void { |
|
193 | + $this->expectException(PrivateKeyMissingException::class); |
|
194 | + |
|
195 | + $this->keyStorageMock->expects($this->exactly(2)) |
|
196 | + ->method('getUserKey') |
|
197 | + ->willReturnCallback(function ($uid, $keyID, $encryptionModuleId) { |
|
198 | + if ($keyID === 'privateKey') { |
|
199 | + return ''; |
|
200 | + } |
|
201 | + return 'key'; |
|
202 | + }); |
|
203 | + |
|
204 | + $this->instance->userHasKeys($this->userId); |
|
205 | + } |
|
206 | + |
|
207 | + |
|
208 | + public function testUserHasKeysMissingPublicKey(): void { |
|
209 | + $this->expectException(PublicKeyMissingException::class); |
|
210 | + |
|
211 | + $this->keyStorageMock->expects($this->exactly(2)) |
|
212 | + ->method('getUserKey') |
|
213 | + ->willReturnCallback(function ($uid, $keyID, $encryptionModuleId) { |
|
214 | + if ($keyID === 'publicKey') { |
|
215 | + return ''; |
|
216 | + } |
|
217 | + return 'key'; |
|
218 | + }); |
|
219 | + |
|
220 | + $this->instance->userHasKeys($this->userId); |
|
221 | + } |
|
222 | + |
|
223 | + /** |
|
224 | + * @dataProvider dataTestInit |
|
225 | + * |
|
226 | + * @param bool $useMasterKey |
|
227 | + */ |
|
228 | + public function testInit($useMasterKey): void { |
|
229 | + /** @var KeyManager&MockObject $instance */ |
|
230 | + $instance = $this->getMockBuilder(KeyManager::class) |
|
231 | + ->setConstructorArgs( |
|
232 | + [ |
|
233 | + $this->keyStorageMock, |
|
234 | + $this->cryptMock, |
|
235 | + $this->configMock, |
|
236 | + $this->userMock, |
|
237 | + $this->sessionMock, |
|
238 | + $this->logMock, |
|
239 | + $this->utilMock, |
|
240 | + $this->lockingProviderMock |
|
241 | + ] |
|
242 | + )->onlyMethods(['getMasterKeyId', 'getMasterKeyPassword', 'getSystemPrivateKey', 'getPrivateKey']) |
|
243 | + ->getMock(); |
|
244 | + |
|
245 | + $this->utilMock->expects($this->once())->method('isMasterKeyEnabled') |
|
246 | + ->willReturn($useMasterKey); |
|
247 | + |
|
248 | + $sessionSetStatusCalls = []; |
|
249 | + $this->sessionMock->expects($this->exactly(2)) |
|
250 | + ->method('setStatus') |
|
251 | + ->willReturnCallback(function (string $status) use (&$sessionSetStatusCalls) { |
|
252 | + $sessionSetStatusCalls[] = $status; |
|
253 | + }); |
|
254 | + |
|
255 | + $instance->expects($this->any())->method('getMasterKeyId')->willReturn('masterKeyId'); |
|
256 | + $instance->expects($this->any())->method('getMasterKeyPassword')->willReturn('masterKeyPassword'); |
|
257 | + $instance->expects($this->any())->method('getSystemPrivateKey')->with('masterKeyId')->willReturn('privateMasterKey'); |
|
258 | + $instance->expects($this->any())->method('getPrivateKey')->with($this->userId)->willReturn('privateUserKey'); |
|
259 | + |
|
260 | + if ($useMasterKey) { |
|
261 | + $this->cryptMock->expects($this->once())->method('decryptPrivateKey') |
|
262 | + ->with('privateMasterKey', 'masterKeyPassword', 'masterKeyId') |
|
263 | + ->willReturn('key'); |
|
264 | + } else { |
|
265 | + $this->cryptMock->expects($this->once())->method('decryptPrivateKey') |
|
266 | + ->with('privateUserKey', 'pass', $this->userId) |
|
267 | + ->willReturn('key'); |
|
268 | + } |
|
269 | + |
|
270 | + $this->sessionMock->expects($this->once())->method('setPrivateKey') |
|
271 | + ->with('key'); |
|
272 | + |
|
273 | + $this->assertTrue($instance->init($this->userId, 'pass')); |
|
274 | + self::assertEquals([ |
|
275 | + Session::INIT_EXECUTED, |
|
276 | + Session::INIT_SUCCESSFUL, |
|
277 | + ], $sessionSetStatusCalls); |
|
278 | + } |
|
279 | + |
|
280 | + public static function dataTestInit(): array { |
|
281 | + return [ |
|
282 | + [true], |
|
283 | + [false] |
|
284 | + ]; |
|
285 | + } |
|
286 | + |
|
287 | + |
|
288 | + public function testSetRecoveryKey(): void { |
|
289 | + $this->keyStorageMock->expects($this->exactly(2)) |
|
290 | + ->method('setSystemUserKey') |
|
291 | + ->willReturn(true); |
|
292 | + $this->cryptMock->expects($this->any()) |
|
293 | + ->method('encryptPrivateKey') |
|
294 | + ->with($this->equalTo('privateKey'), $this->equalTo('pass')) |
|
295 | + ->willReturn('decryptedPrivateKey'); |
|
296 | + |
|
297 | + |
|
298 | + $this->assertTrue( |
|
299 | + $this->instance->setRecoveryKey('pass', |
|
300 | + ['publicKey' => 'publicKey', 'privateKey' => 'privateKey']) |
|
301 | + ); |
|
302 | + } |
|
303 | + |
|
304 | + public function testSetSystemPrivateKey(): void { |
|
305 | + $this->keyStorageMock->expects($this->exactly(1)) |
|
306 | + ->method('setSystemUserKey') |
|
307 | + ->with($this->equalTo('keyId.privateKey'), $this->equalTo('key')) |
|
308 | + ->willReturn(true); |
|
309 | + |
|
310 | + |
|
311 | + $this->assertTrue( |
|
312 | + $this->instance->setSystemPrivateKey('keyId', 'key') |
|
313 | + ); |
|
314 | + } |
|
315 | + |
|
316 | + public function testGetSystemPrivateKey(): void { |
|
317 | + $this->keyStorageMock->expects($this->exactly(1)) |
|
318 | + ->method('getSystemUserKey') |
|
319 | + ->with($this->equalTo('keyId.privateKey')) |
|
320 | + ->willReturn('systemPrivateKey'); |
|
321 | + |
|
322 | + |
|
323 | + $this->assertSame('systemPrivateKey', |
|
324 | + $this->instance->getSystemPrivateKey('keyId') |
|
325 | + ); |
|
326 | + } |
|
327 | + |
|
328 | + public function testGetEncryptedFileKey(): void { |
|
329 | + $this->keyStorageMock->expects($this->once()) |
|
330 | + ->method('getFileKey') |
|
331 | + ->with('/', 'fileKey') |
|
332 | + ->willReturn(true); |
|
333 | + |
|
334 | + $this->assertTrue($this->instance->getEncryptedFileKey('/')); |
|
335 | + } |
|
336 | + |
|
337 | + public static function dataTestGetFileKey(): array { |
|
338 | + return [ |
|
339 | + ['user1', false, 'privateKey', 'legacyKey', 'multiKeyDecryptResult'], |
|
340 | + ['user1', false, 'privateKey', '', 'multiKeyDecryptResult'], |
|
341 | + ['user1', false, false, 'legacyKey', ''], |
|
342 | + ['user1', false, false, '', ''], |
|
343 | + ['user1', true, 'privateKey', 'legacyKey', 'multiKeyDecryptResult'], |
|
344 | + ['user1', true, 'privateKey', '', 'multiKeyDecryptResult'], |
|
345 | + ['user1', true, false, 'legacyKey', ''], |
|
346 | + ['user1', true, false, '', ''], |
|
347 | + [null, false, 'privateKey', 'legacyKey', 'multiKeyDecryptResult'], |
|
348 | + [null, false, 'privateKey', '', 'multiKeyDecryptResult'], |
|
349 | + [null, false, false, 'legacyKey', ''], |
|
350 | + [null, false, false, '', ''], |
|
351 | + [null, true, 'privateKey', 'legacyKey', 'multiKeyDecryptResult'], |
|
352 | + [null, true, 'privateKey', '', 'multiKeyDecryptResult'], |
|
353 | + [null, true, false, 'legacyKey', ''], |
|
354 | + [null, true, false, '', ''], |
|
355 | + ]; |
|
356 | + } |
|
357 | + |
|
358 | + /** |
|
359 | + * @dataProvider dataTestGetFileKey |
|
360 | + * |
|
361 | + * @param $uid |
|
362 | + * @param $isMasterKeyEnabled |
|
363 | + * @param $privateKey |
|
364 | + * @param $expected |
|
365 | + */ |
|
366 | + public function testGetFileKey($uid, $isMasterKeyEnabled, $privateKey, $encryptedFileKey, $expected): void { |
|
367 | + $path = '/foo.txt'; |
|
368 | + |
|
369 | + if ($isMasterKeyEnabled) { |
|
370 | + $expectedUid = 'masterKeyId'; |
|
371 | + $this->configMock->expects($this->any())->method('getSystemValue')->with('secret') |
|
372 | + ->willReturn('password'); |
|
373 | + } elseif (!$uid) { |
|
374 | + $expectedUid = 'systemKeyId'; |
|
375 | + } else { |
|
376 | + $expectedUid = $uid; |
|
377 | + } |
|
378 | + |
|
379 | + $this->invokePrivate($this->instance, 'masterKeyId', ['masterKeyId']); |
|
380 | + |
|
381 | + $this->keyStorageMock->expects($this->exactly(2)) |
|
382 | + ->method('getFileKey') |
|
383 | + ->willReturnMap([ |
|
384 | + [$path, 'fileKey', 'OC_DEFAULT_MODULE', $encryptedFileKey], |
|
385 | + [$path, $expectedUid . '.shareKey', 'OC_DEFAULT_MODULE', 'fileKey'], |
|
386 | + ]); |
|
387 | + |
|
388 | + $this->utilMock->expects($this->any())->method('isMasterKeyEnabled') |
|
389 | + ->willReturn($isMasterKeyEnabled); |
|
390 | + |
|
391 | + if (is_null($uid)) { |
|
392 | + $this->keyStorageMock->expects($this->once()) |
|
393 | + ->method('getSystemUserKey') |
|
394 | + ->willReturn(true); |
|
395 | + $this->cryptMock->expects($this->once()) |
|
396 | + ->method('decryptPrivateKey') |
|
397 | + ->willReturn($privateKey); |
|
398 | + } else { |
|
399 | + $this->keyStorageMock->expects($this->never()) |
|
400 | + ->method('getSystemUserKey'); |
|
401 | + $this->sessionMock->expects($this->once())->method('getPrivateKey')->willReturn($privateKey); |
|
402 | + } |
|
403 | + |
|
404 | + if (!empty($encryptedFileKey)) { |
|
405 | + $this->cryptMock->expects($this->never()) |
|
406 | + ->method('multiKeyDecrypt'); |
|
407 | + if ($privateKey) { |
|
408 | + $this->cryptMock->expects($this->once()) |
|
409 | + ->method('multiKeyDecryptLegacy') |
|
410 | + ->willReturn('multiKeyDecryptResult'); |
|
411 | + } else { |
|
412 | + $this->cryptMock->expects($this->never()) |
|
413 | + ->method('multiKeyDecryptLegacy'); |
|
414 | + } |
|
415 | + } else { |
|
416 | + $this->cryptMock->expects($this->never()) |
|
417 | + ->method('multiKeyDecryptLegacy'); |
|
418 | + if ($privateKey) { |
|
419 | + $this->cryptMock->expects($this->once()) |
|
420 | + ->method('multiKeyDecrypt') |
|
421 | + ->willReturn('multiKeyDecryptResult'); |
|
422 | + } else { |
|
423 | + $this->cryptMock->expects($this->never()) |
|
424 | + ->method('multiKeyDecrypt'); |
|
425 | + } |
|
426 | + } |
|
427 | + |
|
428 | + $this->assertSame($expected, |
|
429 | + $this->instance->getFileKey($path, $uid, null) |
|
430 | + ); |
|
431 | + } |
|
432 | + |
|
433 | + public function testDeletePrivateKey(): void { |
|
434 | + $this->keyStorageMock->expects($this->once()) |
|
435 | + ->method('deleteUserKey') |
|
436 | + ->with('user1', 'privateKey') |
|
437 | + ->willReturn(true); |
|
438 | + |
|
439 | + $this->assertTrue(self::invokePrivate($this->instance, |
|
440 | + 'deletePrivateKey', |
|
441 | + [$this->userId])); |
|
442 | + } |
|
443 | + |
|
444 | + public function testDeleteAllFileKeys(): void { |
|
445 | + $this->keyStorageMock->expects($this->once()) |
|
446 | + ->method('deleteAllFileKeys') |
|
447 | + ->willReturn(true); |
|
448 | + |
|
449 | + $this->assertTrue($this->instance->deleteAllFileKeys('/')); |
|
450 | + } |
|
451 | + |
|
452 | + /** |
|
453 | + * test add public share key and or recovery key to the list of public keys |
|
454 | + * |
|
455 | + * @dataProvider dataTestAddSystemKeys |
|
456 | + * |
|
457 | + * @param array $accessList |
|
458 | + * @param array $publicKeys |
|
459 | + * @param string $uid |
|
460 | + * @param array $expectedKeys |
|
461 | + */ |
|
462 | + public function testAddSystemKeys($accessList, $publicKeys, $uid, $expectedKeys): void { |
|
463 | + $publicShareKeyId = 'publicShareKey'; |
|
464 | + $recoveryKeyId = 'recoveryKey'; |
|
465 | + |
|
466 | + $this->keyStorageMock->expects($this->any()) |
|
467 | + ->method('getSystemUserKey') |
|
468 | + ->willReturnCallback(function ($keyId, $encryptionModuleId) { |
|
469 | + return $keyId; |
|
470 | + }); |
|
471 | + |
|
472 | + $this->utilMock->expects($this->any()) |
|
473 | + ->method('isRecoveryEnabledForUser') |
|
474 | + ->willReturnCallback(function ($uid) { |
|
475 | + if ($uid === 'user1') { |
|
476 | + return true; |
|
477 | + } |
|
478 | + return false; |
|
479 | + }); |
|
480 | + |
|
481 | + // set key IDs |
|
482 | + self::invokePrivate($this->instance, 'publicShareKeyId', [$publicShareKeyId]); |
|
483 | + self::invokePrivate($this->instance, 'recoveryKeyId', [$recoveryKeyId]); |
|
484 | + |
|
485 | + $result = $this->instance->addSystemKeys($accessList, $publicKeys, $uid); |
|
486 | + |
|
487 | + foreach ($expectedKeys as $expected) { |
|
488 | + $this->assertArrayHasKey($expected, $result); |
|
489 | + } |
|
490 | + |
|
491 | + $this->assertSameSize($expectedKeys, $result); |
|
492 | + } |
|
493 | + |
|
494 | + /** |
|
495 | + * data provider for testAddSystemKeys() |
|
496 | + * |
|
497 | + * @return array |
|
498 | + */ |
|
499 | + public static function dataTestAddSystemKeys(): array { |
|
500 | + return [ |
|
501 | + [['public' => true],[], 'user1', ['publicShareKey', 'recoveryKey']], |
|
502 | + [['public' => false], [], 'user1', ['recoveryKey']], |
|
503 | + [['public' => true],[], 'user2', ['publicShareKey']], |
|
504 | + [['public' => false], [], 'user2', []], |
|
505 | + ]; |
|
506 | + } |
|
507 | + |
|
508 | + public function testGetMasterKeyId(): void { |
|
509 | + $this->assertSame('systemKeyId', $this->instance->getMasterKeyId()); |
|
510 | + } |
|
511 | + |
|
512 | + public function testGetPublicMasterKey(): void { |
|
513 | + $this->keyStorageMock->expects($this->once())->method('getSystemUserKey') |
|
514 | + ->with('systemKeyId.publicKey', Encryption::ID) |
|
515 | + ->willReturn(true); |
|
516 | + |
|
517 | + $this->assertTrue( |
|
518 | + $this->instance->getPublicMasterKey() |
|
519 | + ); |
|
520 | + } |
|
521 | + |
|
522 | + public function testGetMasterKeyPassword(): void { |
|
523 | + $this->configMock->expects($this->once())->method('getSystemValue')->with('secret') |
|
524 | + ->willReturn('password'); |
|
525 | + |
|
526 | + $this->assertSame('password', |
|
527 | + $this->invokePrivate($this->instance, 'getMasterKeyPassword', []) |
|
528 | + ); |
|
529 | + } |
|
530 | + |
|
531 | + |
|
532 | + public function testGetMasterKeyPasswordException(): void { |
|
533 | + $this->expectException(\Exception::class); |
|
534 | + |
|
535 | + $this->configMock->expects($this->once())->method('getSystemValue')->with('secret') |
|
536 | + ->willReturn(''); |
|
537 | + |
|
538 | + $this->invokePrivate($this->instance, 'getMasterKeyPassword', []); |
|
539 | + } |
|
540 | + |
|
541 | + /** |
|
542 | + * @dataProvider dataTestValidateMasterKey |
|
543 | + * |
|
544 | + * @param $masterKey |
|
545 | + */ |
|
546 | + public function testValidateMasterKey($masterKey): void { |
|
547 | + /** @var KeyManager&MockObject $instance */ |
|
548 | + $instance = $this->getMockBuilder(KeyManager::class) |
|
549 | + ->setConstructorArgs( |
|
550 | + [ |
|
551 | + $this->keyStorageMock, |
|
552 | + $this->cryptMock, |
|
553 | + $this->configMock, |
|
554 | + $this->userMock, |
|
555 | + $this->sessionMock, |
|
556 | + $this->logMock, |
|
557 | + $this->utilMock, |
|
558 | + $this->lockingProviderMock |
|
559 | + ] |
|
560 | + )->onlyMethods(['getPublicMasterKey', 'setSystemPrivateKey', 'getMasterKeyPassword']) |
|
561 | + ->getMock(); |
|
562 | + |
|
563 | + $this->utilMock->expects($this->once())->method('isMasterKeyEnabled') |
|
564 | + ->willReturn(true); |
|
565 | + |
|
566 | + $instance->expects($this->once())->method('getPublicMasterKey') |
|
567 | + ->willReturn($masterKey); |
|
568 | + |
|
569 | + $instance->expects($this->any())->method('getMasterKeyPassword')->willReturn('masterKeyPassword'); |
|
570 | + $this->cryptMock->expects($this->any())->method('generateHeader')->willReturn('header'); |
|
571 | + |
|
572 | + if (empty($masterKey)) { |
|
573 | + $this->cryptMock->expects($this->once())->method('createKeyPair') |
|
574 | + ->willReturn(['publicKey' => 'public', 'privateKey' => 'private']); |
|
575 | + $this->keyStorageMock->expects($this->once())->method('setSystemUserKey') |
|
576 | + ->with('systemKeyId.publicKey', 'public', Encryption::ID); |
|
577 | + $this->cryptMock->expects($this->once())->method('encryptPrivateKey') |
|
578 | + ->with('private', 'masterKeyPassword', 'systemKeyId') |
|
579 | + ->willReturn('EncryptedKey'); |
|
580 | + $this->lockingProviderMock->expects($this->once()) |
|
581 | + ->method('acquireLock'); |
|
582 | + $instance->expects($this->once())->method('setSystemPrivateKey') |
|
583 | + ->with('systemKeyId', 'headerEncryptedKey'); |
|
584 | + } else { |
|
585 | + $this->cryptMock->expects($this->never())->method('createKeyPair'); |
|
586 | + $this->keyStorageMock->expects($this->never())->method('setSystemUserKey'); |
|
587 | + $this->cryptMock->expects($this->never())->method('encryptPrivateKey'); |
|
588 | + $instance->expects($this->never())->method('setSystemPrivateKey'); |
|
589 | + } |
|
590 | + |
|
591 | + $instance->validateMasterKey(); |
|
592 | + } |
|
593 | + |
|
594 | + public function testValidateMasterKeyLocked(): void { |
|
595 | + /** @var KeyManager&MockObject $instance */ |
|
596 | + $instance = $this->getMockBuilder(KeyManager::class) |
|
597 | + ->setConstructorArgs([ |
|
598 | + $this->keyStorageMock, |
|
599 | + $this->cryptMock, |
|
600 | + $this->configMock, |
|
601 | + $this->userMock, |
|
602 | + $this->sessionMock, |
|
603 | + $this->logMock, |
|
604 | + $this->utilMock, |
|
605 | + $this->lockingProviderMock |
|
606 | + ]) |
|
607 | + ->onlyMethods(['getPublicMasterKey', 'getPrivateMasterKey', 'setSystemPrivateKey', 'getMasterKeyPassword']) |
|
608 | + ->getMock(); |
|
609 | + |
|
610 | + $this->utilMock->expects($this->once())->method('isMasterKeyEnabled') |
|
611 | + ->willReturn(true); |
|
612 | + |
|
613 | + $instance->expects($this->once())->method('getPublicMasterKey') |
|
614 | + ->willReturn(''); |
|
615 | + $instance->expects($this->once())->method('getPrivateMasterKey') |
|
616 | + ->willReturn(''); |
|
617 | + |
|
618 | + $instance->expects($this->any())->method('getMasterKeyPassword')->willReturn('masterKeyPassword'); |
|
619 | + $this->cryptMock->expects($this->any())->method('generateHeader')->willReturn('header'); |
|
620 | + |
|
621 | + $this->lockingProviderMock->expects($this->once()) |
|
622 | + ->method('acquireLock') |
|
623 | + ->willThrowException(new LockedException('encryption-generateMasterKey')); |
|
624 | + |
|
625 | + $this->expectException(LockedException::class); |
|
626 | + $instance->validateMasterKey(); |
|
627 | + } |
|
628 | + |
|
629 | + public static function dataTestValidateMasterKey(): array { |
|
630 | + return [ |
|
631 | + ['masterKey'], |
|
632 | + [''] |
|
633 | + ]; |
|
634 | + } |
|
635 | + |
|
636 | + public function testGetVersionWithoutFileInfo(): void { |
|
637 | + $view = $this->getMockBuilder(View::class) |
|
638 | + ->disableOriginalConstructor()->getMock(); |
|
639 | + $view->expects($this->once()) |
|
640 | + ->method('getFileInfo') |
|
641 | + ->with('/admin/files/myfile.txt') |
|
642 | + ->willReturn(false); |
|
643 | + |
|
644 | + /** @var View $view */ |
|
645 | + $this->assertSame(0, $this->instance->getVersion('/admin/files/myfile.txt', $view)); |
|
646 | + } |
|
647 | + |
|
648 | + public function testGetVersionWithFileInfo(): void { |
|
649 | + $view = $this->getMockBuilder(View::class) |
|
650 | + ->disableOriginalConstructor()->getMock(); |
|
651 | + $fileInfo = $this->getMockBuilder(FileInfo::class) |
|
652 | + ->disableOriginalConstructor()->getMock(); |
|
653 | + $fileInfo->expects($this->once()) |
|
654 | + ->method('getEncryptedVersion') |
|
655 | + ->willReturn(1337); |
|
656 | + $view->expects($this->once()) |
|
657 | + ->method('getFileInfo') |
|
658 | + ->with('/admin/files/myfile.txt') |
|
659 | + ->willReturn($fileInfo); |
|
660 | + |
|
661 | + /** @var View $view */ |
|
662 | + $this->assertSame(1337, $this->instance->getVersion('/admin/files/myfile.txt', $view)); |
|
663 | + } |
|
664 | + |
|
665 | + public function testSetVersionWithFileInfo(): void { |
|
666 | + $view = $this->getMockBuilder(View::class) |
|
667 | + ->disableOriginalConstructor()->getMock(); |
|
668 | + $cache = $this->getMockBuilder(ICache::class) |
|
669 | + ->disableOriginalConstructor()->getMock(); |
|
670 | + $cache->expects($this->once()) |
|
671 | + ->method('update') |
|
672 | + ->with(123, ['encrypted' => 5, 'encryptedVersion' => 5]); |
|
673 | + $storage = $this->getMockBuilder(FilesIStorage::class) |
|
674 | + ->disableOriginalConstructor()->getMock(); |
|
675 | + $storage->expects($this->once()) |
|
676 | + ->method('getCache') |
|
677 | + ->willReturn($cache); |
|
678 | + $fileInfo = $this->getMockBuilder(FileInfo::class) |
|
679 | + ->disableOriginalConstructor()->getMock(); |
|
680 | + $fileInfo->expects($this->once()) |
|
681 | + ->method('getStorage') |
|
682 | + ->willReturn($storage); |
|
683 | + $fileInfo->expects($this->once()) |
|
684 | + ->method('getId') |
|
685 | + ->willReturn(123); |
|
686 | + $view->expects($this->once()) |
|
687 | + ->method('getFileInfo') |
|
688 | + ->with('/admin/files/myfile.txt') |
|
689 | + ->willReturn($fileInfo); |
|
690 | + |
|
691 | + /** @var View $view */ |
|
692 | + $this->instance->setVersion('/admin/files/myfile.txt', 5, $view); |
|
693 | + } |
|
694 | + |
|
695 | + public function testSetVersionWithoutFileInfo(): void { |
|
696 | + $view = $this->getMockBuilder(View::class) |
|
697 | + ->disableOriginalConstructor()->getMock(); |
|
698 | + $view->expects($this->once()) |
|
699 | + ->method('getFileInfo') |
|
700 | + ->with('/admin/files/myfile.txt') |
|
701 | + ->willReturn(false); |
|
702 | + |
|
703 | + /** @var View $view */ |
|
704 | + $this->instance->setVersion('/admin/files/myfile.txt', 5, $view); |
|
705 | + } |
|
706 | + |
|
707 | + public function testBackupUserKeys(): void { |
|
708 | + $this->keyStorageMock->expects($this->once())->method('backupUserKeys') |
|
709 | + ->with('OC_DEFAULT_MODULE', 'test', 'user1'); |
|
710 | + $this->instance->backupUserKeys('test', 'user1'); |
|
711 | + } |
|
712 | 712 | } |
@@ -26,486 +26,486 @@ |
||
26 | 26 | |
27 | 27 | class FilenameValidatorTest extends TestCase { |
28 | 28 | |
29 | - protected IFactory&MockObject $l10n; |
|
30 | - protected IConfig&MockObject $config; |
|
31 | - protected IDBConnection&MockObject $database; |
|
32 | - protected LoggerInterface&MockObject $logger; |
|
33 | - |
|
34 | - protected function setUp(): void { |
|
35 | - parent::setUp(); |
|
36 | - $l10n = $this->createMock(IL10N::class); |
|
37 | - $l10n->method('t') |
|
38 | - ->willReturnCallback(fn ($string, $params) => sprintf($string, ...$params)); |
|
39 | - $this->l10n = $this->createMock(IFactory::class); |
|
40 | - $this->l10n |
|
41 | - ->method('get') |
|
42 | - ->with('core') |
|
43 | - ->willReturn($l10n); |
|
44 | - |
|
45 | - $this->config = $this->createMock(IConfig::class); |
|
46 | - $this->logger = $this->createMock(LoggerInterface::class); |
|
47 | - $this->database = $this->createMock(IDBConnection::class); |
|
48 | - $this->database->method('supports4ByteText')->willReturn(true); |
|
49 | - } |
|
50 | - |
|
51 | - /** |
|
52 | - * @dataProvider dataValidateFilename |
|
53 | - */ |
|
54 | - public function testValidateFilename( |
|
55 | - string $filename, |
|
56 | - array $forbiddenNames, |
|
57 | - array $forbiddenBasenames, |
|
58 | - array $forbiddenExtensions, |
|
59 | - array $forbiddenCharacters, |
|
60 | - ?string $exception, |
|
61 | - ): void { |
|
62 | - /** @var FilenameValidator&MockObject */ |
|
63 | - $validator = $this->getMockBuilder(FilenameValidator::class) |
|
64 | - ->onlyMethods([ |
|
65 | - 'getForbiddenBasenames', |
|
66 | - 'getForbiddenCharacters', |
|
67 | - 'getForbiddenExtensions', |
|
68 | - 'getForbiddenFilenames', |
|
69 | - ]) |
|
70 | - ->setConstructorArgs([$this->l10n, $this->database, $this->config, $this->logger]) |
|
71 | - ->getMock(); |
|
72 | - |
|
73 | - $validator->method('getForbiddenBasenames') |
|
74 | - ->willReturn($forbiddenBasenames); |
|
75 | - $validator->method('getForbiddenCharacters') |
|
76 | - ->willReturn($forbiddenCharacters); |
|
77 | - $validator->method('getForbiddenExtensions') |
|
78 | - ->willReturn($forbiddenExtensions); |
|
79 | - $validator->method('getForbiddenFilenames') |
|
80 | - ->willReturn($forbiddenNames); |
|
81 | - |
|
82 | - if ($exception !== null) { |
|
83 | - $this->expectException($exception); |
|
84 | - } else { |
|
85 | - $this->expectNotToPerformAssertions(); |
|
86 | - } |
|
87 | - $validator->validateFilename($filename); |
|
88 | - } |
|
89 | - |
|
90 | - /** |
|
91 | - * @dataProvider dataValidateFilename |
|
92 | - */ |
|
93 | - public function testIsFilenameValid( |
|
94 | - string $filename, |
|
95 | - array $forbiddenNames, |
|
96 | - array $forbiddenBasenames, |
|
97 | - array $forbiddenExtensions, |
|
98 | - array $forbiddenCharacters, |
|
99 | - ?string $exception, |
|
100 | - ): void { |
|
101 | - /** @var FilenameValidator&MockObject */ |
|
102 | - $validator = $this->getMockBuilder(FilenameValidator::class) |
|
103 | - ->onlyMethods([ |
|
104 | - 'getForbiddenBasenames', |
|
105 | - 'getForbiddenExtensions', |
|
106 | - 'getForbiddenFilenames', |
|
107 | - 'getForbiddenCharacters', |
|
108 | - ]) |
|
109 | - ->setConstructorArgs([$this->l10n, $this->database, $this->config, $this->logger]) |
|
110 | - ->getMock(); |
|
111 | - |
|
112 | - $validator->method('getForbiddenBasenames') |
|
113 | - ->willReturn($forbiddenBasenames); |
|
114 | - $validator->method('getForbiddenCharacters') |
|
115 | - ->willReturn($forbiddenCharacters); |
|
116 | - $validator->method('getForbiddenExtensions') |
|
117 | - ->willReturn($forbiddenExtensions); |
|
118 | - $validator->method('getForbiddenFilenames') |
|
119 | - ->willReturn($forbiddenNames); |
|
120 | - |
|
121 | - |
|
122 | - $this->assertEquals($exception === null, $validator->isFilenameValid($filename)); |
|
123 | - } |
|
124 | - |
|
125 | - public static function dataValidateFilename(): array { |
|
126 | - return [ |
|
127 | - 'valid name' => [ |
|
128 | - 'a: b.txt', ['.htaccess'], [], [], [], null |
|
129 | - ], |
|
130 | - 'forbidden name in the middle is ok' => [ |
|
131 | - 'a.htaccess.txt', ['.htaccess'], [], [], [], null |
|
132 | - ], |
|
133 | - 'valid name with some more parameters' => [ |
|
134 | - 'a: b.txt', ['.htaccess'], [], ['exe'], ['~'], null |
|
135 | - ], |
|
136 | - 'valid name checks only the full name' => [ |
|
137 | - '.htaccess.sample', ['.htaccess'], [], [], [], null |
|
138 | - ], |
|
139 | - 'forbidden name' => [ |
|
140 | - '.htaccess', ['.htaccess'], [], [], [], ReservedWordException::class |
|
141 | - ], |
|
142 | - 'forbidden name - name is case insensitive' => [ |
|
143 | - 'COM1', ['.htaccess', 'com1'], [], [], [], ReservedWordException::class |
|
144 | - ], |
|
145 | - 'forbidden basename' => [ |
|
146 | - // needed for Windows namespaces |
|
147 | - 'com1.suffix', ['.htaccess'], ['com1'], [], [], ReservedWordException::class |
|
148 | - ], |
|
149 | - 'forbidden basename case insensitive' => [ |
|
150 | - // needed for Windows namespaces |
|
151 | - 'COM1.suffix', ['.htaccess'], ['com1'], [], [], ReservedWordException::class |
|
152 | - ], |
|
153 | - 'forbidden basename for hidden files' => [ |
|
154 | - // needed for Windows namespaces |
|
155 | - '.thumbs.db', ['.htaccess'], ['.thumbs'], [], [], ReservedWordException::class |
|
156 | - ], |
|
157 | - 'invalid character' => [ |
|
158 | - 'a: b.txt', ['.htaccess'], [], [], [':'], InvalidCharacterInPathException::class |
|
159 | - ], |
|
160 | - 'invalid path' => [ |
|
161 | - '../../foo.bar', ['.htaccess'], [], [], ['/', '\\'], InvalidCharacterInPathException::class, |
|
162 | - ], |
|
163 | - 'invalid extension' => [ |
|
164 | - 'a: b.txt', ['.htaccess'], [], ['.txt'], [], InvalidPathException::class |
|
165 | - ], |
|
166 | - 'invalid extension case insensitive' => [ |
|
167 | - 'a: b.TXT', ['.htaccess'], [], ['.txt'], [], InvalidPathException::class |
|
168 | - ], |
|
169 | - 'empty filename' => [ |
|
170 | - '', [], [], [], [], EmptyFileNameException::class |
|
171 | - ], |
|
172 | - 'reserved unix name "."' => [ |
|
173 | - '.', [], [], [], [], InvalidDirectoryException::class |
|
174 | - ], |
|
175 | - 'reserved unix name ".."' => [ |
|
176 | - '..', [], [], [], [], InvalidDirectoryException::class |
|
177 | - ], |
|
178 | - 'weird but valid tripple dot name' => [ |
|
179 | - '...', [], [], [], [], null // is valid |
|
180 | - ], |
|
181 | - 'too long filename "."' => [ |
|
182 | - str_repeat('a', 251), [], [], [], [], FileNameTooLongException::class |
|
183 | - ], |
|
184 | - // make sure to not split the list entries as they migh contain Unicode sequences |
|
185 | - // in this example the "face in clouds" emoji contains the clouds emoji so only having clouds is ok |
|
186 | - [' |
@@ -36,856 +36,856 @@ |
||
36 | 36 | * @package Test\App |
37 | 37 | */ |
38 | 38 | class AppManagerTest extends TestCase { |
39 | - /** |
|
40 | - * @return AppConfig|MockObject |
|
41 | - */ |
|
42 | - protected function getAppConfig() { |
|
43 | - $appConfig = []; |
|
44 | - $config = $this->createMock(AppConfig::class); |
|
45 | - |
|
46 | - $config->expects($this->any()) |
|
47 | - ->method('getValue') |
|
48 | - ->willReturnCallback(function ($app, $key, $default) use (&$appConfig) { |
|
49 | - return (isset($appConfig[$app]) and isset($appConfig[$app][$key])) ? $appConfig[$app][$key] : $default; |
|
50 | - }); |
|
51 | - $config->expects($this->any()) |
|
52 | - ->method('setValue') |
|
53 | - ->willReturnCallback(function ($app, $key, $value) use (&$appConfig) { |
|
54 | - if (!isset($appConfig[$app])) { |
|
55 | - $appConfig[$app] = []; |
|
56 | - } |
|
57 | - $appConfig[$app][$key] = $value; |
|
58 | - }); |
|
59 | - $config->expects($this->any()) |
|
60 | - ->method('getValues') |
|
61 | - ->willReturnCallback(function ($app, $key) use (&$appConfig) { |
|
62 | - if ($app) { |
|
63 | - return $appConfig[$app]; |
|
64 | - } else { |
|
65 | - $values = []; |
|
66 | - foreach ($appConfig as $appid => $appData) { |
|
67 | - if (isset($appData[$key])) { |
|
68 | - $values[$appid] = $appData[$key]; |
|
69 | - } |
|
70 | - } |
|
71 | - return $values; |
|
72 | - } |
|
73 | - }); |
|
74 | - |
|
75 | - return $config; |
|
76 | - } |
|
77 | - |
|
78 | - /** @var IUserSession|MockObject */ |
|
79 | - protected $userSession; |
|
80 | - |
|
81 | - /** @var IConfig|MockObject */ |
|
82 | - private $config; |
|
83 | - |
|
84 | - /** @var IGroupManager|MockObject */ |
|
85 | - protected $groupManager; |
|
86 | - |
|
87 | - /** @var AppConfig|MockObject */ |
|
88 | - protected $appConfig; |
|
89 | - |
|
90 | - /** @var ICache|MockObject */ |
|
91 | - protected $cache; |
|
92 | - |
|
93 | - /** @var ICacheFactory|MockObject */ |
|
94 | - protected $cacheFactory; |
|
95 | - |
|
96 | - /** @var IEventDispatcher|MockObject */ |
|
97 | - protected $eventDispatcher; |
|
98 | - |
|
99 | - /** @var LoggerInterface|MockObject */ |
|
100 | - protected $logger; |
|
101 | - |
|
102 | - protected IURLGenerator&MockObject $urlGenerator; |
|
103 | - |
|
104 | - protected ServerVersion&MockObject $serverVersion; |
|
105 | - |
|
106 | - /** @var IAppManager */ |
|
107 | - protected $manager; |
|
108 | - |
|
109 | - protected function setUp(): void { |
|
110 | - parent::setUp(); |
|
111 | - |
|
112 | - $this->userSession = $this->createMock(IUserSession::class); |
|
113 | - $this->groupManager = $this->createMock(IGroupManager::class); |
|
114 | - $this->config = $this->createMock(IConfig::class); |
|
115 | - $this->appConfig = $this->getAppConfig(); |
|
116 | - $this->cacheFactory = $this->createMock(ICacheFactory::class); |
|
117 | - $this->cache = $this->createMock(ICache::class); |
|
118 | - $this->eventDispatcher = $this->createMock(IEventDispatcher::class); |
|
119 | - $this->logger = $this->createMock(LoggerInterface::class); |
|
120 | - $this->urlGenerator = $this->createMock(IURLGenerator::class); |
|
121 | - $this->serverVersion = $this->createMock(ServerVersion::class); |
|
122 | - |
|
123 | - $this->overwriteService(AppConfig::class, $this->appConfig); |
|
124 | - $this->overwriteService(IURLGenerator::class, $this->urlGenerator); |
|
125 | - |
|
126 | - $this->cacheFactory->expects($this->any()) |
|
127 | - ->method('createDistributed') |
|
128 | - ->with('settings') |
|
129 | - ->willReturn($this->cache); |
|
130 | - |
|
131 | - $this->config |
|
132 | - ->method('getSystemValueBool') |
|
133 | - ->with('installed', false) |
|
134 | - ->willReturn(true); |
|
135 | - |
|
136 | - $this->manager = new AppManager( |
|
137 | - $this->userSession, |
|
138 | - $this->config, |
|
139 | - $this->groupManager, |
|
140 | - $this->cacheFactory, |
|
141 | - $this->eventDispatcher, |
|
142 | - $this->logger, |
|
143 | - $this->serverVersion, |
|
144 | - ); |
|
145 | - } |
|
146 | - |
|
147 | - /** |
|
148 | - * @dataProvider dataGetAppIcon |
|
149 | - */ |
|
150 | - public function testGetAppIcon($callback, ?bool $dark, ?string $expected): void { |
|
151 | - $this->urlGenerator->expects($this->atLeastOnce()) |
|
152 | - ->method('imagePath') |
|
153 | - ->willReturnCallback($callback); |
|
154 | - |
|
155 | - if ($dark !== null) { |
|
156 | - $this->assertEquals($expected, $this->manager->getAppIcon('test', $dark)); |
|
157 | - } else { |
|
158 | - $this->assertEquals($expected, $this->manager->getAppIcon('test')); |
|
159 | - } |
|
160 | - } |
|
161 | - |
|
162 | - public static function dataGetAppIcon(): array { |
|
163 | - $nothing = function ($appId) { |
|
164 | - self::assertEquals('test', $appId); |
|
165 | - throw new \RuntimeException(); |
|
166 | - }; |
|
167 | - |
|
168 | - $createCallback = function ($workingIcons) { |
|
169 | - return function ($appId, $icon) use ($workingIcons) { |
|
170 | - self::assertEquals('test', $appId); |
|
171 | - if (in_array($icon, $workingIcons)) { |
|
172 | - return '/path/' . $icon; |
|
173 | - } |
|
174 | - throw new \RuntimeException(); |
|
175 | - }; |
|
176 | - }; |
|
177 | - |
|
178 | - return [ |
|
179 | - 'does not find anything' => [ |
|
180 | - $nothing, |
|
181 | - false, |
|
182 | - null, |
|
183 | - ], |
|
184 | - 'nothing if request dark but only bright available' => [ |
|
185 | - $createCallback(['app.svg']), |
|
186 | - true, |
|
187 | - null, |
|
188 | - ], |
|
189 | - 'nothing if request bright but only dark available' => [ |
|
190 | - $createCallback(['app-dark.svg']), |
|
191 | - false, |
|
192 | - null, |
|
193 | - ], |
|
194 | - 'bright and only app.svg' => [ |
|
195 | - $createCallback(['app.svg']), |
|
196 | - false, |
|
197 | - '/path/app.svg', |
|
198 | - ], |
|
199 | - 'dark and only app-dark.svg' => [ |
|
200 | - $createCallback(['app-dark.svg']), |
|
201 | - true, |
|
202 | - '/path/app-dark.svg', |
|
203 | - ], |
|
204 | - 'dark only appname -dark.svg' => [ |
|
205 | - $createCallback(['test-dark.svg']), |
|
206 | - true, |
|
207 | - '/path/test-dark.svg', |
|
208 | - ], |
|
209 | - 'bright and only appname.svg' => [ |
|
210 | - $createCallback(['test.svg']), |
|
211 | - false, |
|
212 | - '/path/test.svg', |
|
213 | - ], |
|
214 | - 'priotize custom over default' => [ |
|
215 | - $createCallback(['app.svg', 'test.svg']), |
|
216 | - false, |
|
217 | - '/path/test.svg', |
|
218 | - ], |
|
219 | - 'defaults to bright' => [ |
|
220 | - $createCallback(['test-dark.svg', 'test.svg']), |
|
221 | - null, |
|
222 | - '/path/test.svg', |
|
223 | - ], |
|
224 | - 'no dark icon on default' => [ |
|
225 | - $createCallback(['test-dark.svg', 'test.svg', 'app-dark.svg', 'app.svg']), |
|
226 | - false, |
|
227 | - '/path/test.svg', |
|
228 | - ], |
|
229 | - 'no bright icon on dark' => [ |
|
230 | - $createCallback(['test-dark.svg', 'test.svg', 'app-dark.svg', 'app.svg']), |
|
231 | - true, |
|
232 | - '/path/test-dark.svg', |
|
233 | - ], |
|
234 | - ]; |
|
235 | - } |
|
236 | - |
|
237 | - public function testEnableApp(): void { |
|
238 | - // making sure "files_trashbin" is disabled |
|
239 | - if ($this->manager->isEnabledForUser('files_trashbin')) { |
|
240 | - $this->manager->disableApp('files_trashbin'); |
|
241 | - } |
|
242 | - $this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new AppEnableEvent('files_trashbin')); |
|
243 | - $this->manager->enableApp('files_trashbin'); |
|
244 | - $this->assertEquals('yes', $this->appConfig->getValue('files_trashbin', 'enabled', 'no')); |
|
245 | - } |
|
246 | - |
|
247 | - public function testDisableApp(): void { |
|
248 | - $this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new AppDisableEvent('files_trashbin')); |
|
249 | - $this->manager->disableApp('files_trashbin'); |
|
250 | - $this->assertEquals('no', $this->appConfig->getValue('files_trashbin', 'enabled', 'no')); |
|
251 | - } |
|
252 | - |
|
253 | - public function testNotEnableIfNotInstalled(): void { |
|
254 | - try { |
|
255 | - $this->manager->enableApp('some_random_name_which_i_hope_is_not_an_app'); |
|
256 | - $this->assertFalse(true, 'If this line is reached the expected exception is not thrown.'); |
|
257 | - } catch (AppPathNotFoundException $e) { |
|
258 | - // Exception is expected |
|
259 | - $this->assertEquals('Could not find path for some_random_name_which_i_hope_is_not_an_app', $e->getMessage()); |
|
260 | - } |
|
261 | - |
|
262 | - $this->assertEquals('no', $this->appConfig->getValue( |
|
263 | - 'some_random_name_which_i_hope_is_not_an_app', 'enabled', 'no' |
|
264 | - )); |
|
265 | - } |
|
266 | - |
|
267 | - public function testEnableAppForGroups(): void { |
|
268 | - $group1 = $this->createMock(IGroup::class); |
|
269 | - $group1->method('getGID') |
|
270 | - ->willReturn('group1'); |
|
271 | - $group2 = $this->createMock(IGroup::class); |
|
272 | - $group2->method('getGID') |
|
273 | - ->willReturn('group2'); |
|
274 | - |
|
275 | - $groups = [$group1, $group2]; |
|
276 | - |
|
277 | - /** @var AppManager|MockObject $manager */ |
|
278 | - $manager = $this->getMockBuilder(AppManager::class) |
|
279 | - ->setConstructorArgs([ |
|
280 | - $this->userSession, |
|
281 | - $this->config, |
|
282 | - $this->groupManager, |
|
283 | - $this->cacheFactory, |
|
284 | - $this->eventDispatcher, |
|
285 | - $this->logger, |
|
286 | - $this->serverVersion, |
|
287 | - ]) |
|
288 | - ->onlyMethods([ |
|
289 | - 'getAppPath', |
|
290 | - ]) |
|
291 | - ->getMock(); |
|
292 | - |
|
293 | - $manager->expects($this->exactly(2)) |
|
294 | - ->method('getAppPath') |
|
295 | - ->with('test') |
|
296 | - ->willReturn('apps/test'); |
|
297 | - |
|
298 | - $this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new AppEnableEvent('test', ['group1', 'group2'])); |
|
299 | - |
|
300 | - $manager->enableAppForGroups('test', $groups); |
|
301 | - $this->assertEquals('["group1","group2"]', $this->appConfig->getValue('test', 'enabled', 'no')); |
|
302 | - } |
|
303 | - |
|
304 | - public static function dataEnableAppForGroupsAllowedTypes(): array { |
|
305 | - return [ |
|
306 | - [[]], |
|
307 | - [[ |
|
308 | - 'types' => [], |
|
309 | - ]], |
|
310 | - [[ |
|
311 | - 'types' => ['nickvergessen'], |
|
312 | - ]], |
|
313 | - ]; |
|
314 | - } |
|
315 | - |
|
316 | - /** |
|
317 | - * @dataProvider dataEnableAppForGroupsAllowedTypes |
|
318 | - * |
|
319 | - * @param array $appInfo |
|
320 | - */ |
|
321 | - public function testEnableAppForGroupsAllowedTypes(array $appInfo): void { |
|
322 | - $group1 = $this->createMock(IGroup::class); |
|
323 | - $group1->method('getGID') |
|
324 | - ->willReturn('group1'); |
|
325 | - $group2 = $this->createMock(IGroup::class); |
|
326 | - $group2->method('getGID') |
|
327 | - ->willReturn('group2'); |
|
328 | - |
|
329 | - $groups = [$group1, $group2]; |
|
330 | - |
|
331 | - /** @var AppManager|MockObject $manager */ |
|
332 | - $manager = $this->getMockBuilder(AppManager::class) |
|
333 | - ->setConstructorArgs([ |
|
334 | - $this->userSession, |
|
335 | - $this->config, |
|
336 | - $this->groupManager, |
|
337 | - $this->cacheFactory, |
|
338 | - $this->eventDispatcher, |
|
339 | - $this->logger, |
|
340 | - $this->serverVersion, |
|
341 | - ]) |
|
342 | - ->onlyMethods([ |
|
343 | - 'getAppPath', |
|
344 | - 'getAppInfo', |
|
345 | - ]) |
|
346 | - ->getMock(); |
|
347 | - |
|
348 | - $manager->expects($this->once()) |
|
349 | - ->method('getAppPath') |
|
350 | - ->with('test') |
|
351 | - ->willReturn(''); |
|
352 | - |
|
353 | - $manager->expects($this->once()) |
|
354 | - ->method('getAppInfo') |
|
355 | - ->with('test') |
|
356 | - ->willReturn($appInfo); |
|
357 | - |
|
358 | - $this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new AppEnableEvent('test', ['group1', 'group2'])); |
|
359 | - |
|
360 | - $manager->enableAppForGroups('test', $groups); |
|
361 | - $this->assertEquals('["group1","group2"]', $this->appConfig->getValue('test', 'enabled', 'no')); |
|
362 | - } |
|
363 | - |
|
364 | - public static function dataEnableAppForGroupsForbiddenTypes(): array { |
|
365 | - return [ |
|
366 | - ['filesystem'], |
|
367 | - ['prelogin'], |
|
368 | - ['authentication'], |
|
369 | - ['logging'], |
|
370 | - ['prevent_group_restriction'], |
|
371 | - ]; |
|
372 | - } |
|
373 | - |
|
374 | - /** |
|
375 | - * @dataProvider dataEnableAppForGroupsForbiddenTypes |
|
376 | - * |
|
377 | - * @param string $type |
|
378 | - * |
|
379 | - */ |
|
380 | - public function testEnableAppForGroupsForbiddenTypes($type): void { |
|
381 | - $this->expectException(\Exception::class); |
|
382 | - $this->expectExceptionMessage('test can\'t be enabled for groups.'); |
|
383 | - |
|
384 | - $group1 = $this->createMock(IGroup::class); |
|
385 | - $group1->method('getGID') |
|
386 | - ->willReturn('group1'); |
|
387 | - $group2 = $this->createMock(IGroup::class); |
|
388 | - $group2->method('getGID') |
|
389 | - ->willReturn('group2'); |
|
390 | - |
|
391 | - $groups = [$group1, $group2]; |
|
392 | - |
|
393 | - /** @var AppManager|MockObject $manager */ |
|
394 | - $manager = $this->getMockBuilder(AppManager::class) |
|
395 | - ->setConstructorArgs([ |
|
396 | - $this->userSession, |
|
397 | - $this->config, |
|
398 | - $this->groupManager, |
|
399 | - $this->cacheFactory, |
|
400 | - $this->eventDispatcher, |
|
401 | - $this->logger, |
|
402 | - $this->serverVersion, |
|
403 | - ]) |
|
404 | - ->onlyMethods([ |
|
405 | - 'getAppPath', |
|
406 | - 'getAppInfo', |
|
407 | - ]) |
|
408 | - ->getMock(); |
|
409 | - |
|
410 | - $manager->expects($this->once()) |
|
411 | - ->method('getAppPath') |
|
412 | - ->with('test') |
|
413 | - ->willReturn(''); |
|
414 | - |
|
415 | - $manager->expects($this->once()) |
|
416 | - ->method('getAppInfo') |
|
417 | - ->with('test') |
|
418 | - ->willReturn([ |
|
419 | - 'types' => [$type], |
|
420 | - ]); |
|
421 | - |
|
422 | - $this->eventDispatcher->expects($this->never())->method('dispatchTyped')->with(new AppEnableEvent('test', ['group1', 'group2'])); |
|
423 | - |
|
424 | - $manager->enableAppForGroups('test', $groups); |
|
425 | - } |
|
426 | - |
|
427 | - public function testIsInstalledEnabled(): void { |
|
428 | - $this->appConfig->setValue('test', 'enabled', 'yes'); |
|
429 | - $this->assertTrue($this->manager->isEnabledForAnyone('test')); |
|
430 | - } |
|
431 | - |
|
432 | - public function testIsInstalledDisabled(): void { |
|
433 | - $this->appConfig->setValue('test', 'enabled', 'no'); |
|
434 | - $this->assertFalse($this->manager->isEnabledForAnyone('test')); |
|
435 | - } |
|
436 | - |
|
437 | - public function testIsInstalledEnabledForGroups(): void { |
|
438 | - $this->appConfig->setValue('test', 'enabled', '["foo"]'); |
|
439 | - $this->assertTrue($this->manager->isEnabledForAnyone('test')); |
|
440 | - } |
|
441 | - |
|
442 | - private function newUser($uid) { |
|
443 | - $user = $this->createMock(IUser::class); |
|
444 | - $user->method('getUID') |
|
445 | - ->willReturn($uid); |
|
446 | - |
|
447 | - return $user; |
|
448 | - } |
|
449 | - |
|
450 | - public function testIsEnabledForUserEnabled(): void { |
|
451 | - $this->appConfig->setValue('test', 'enabled', 'yes'); |
|
452 | - $user = $this->newUser('user1'); |
|
453 | - $this->assertTrue($this->manager->isEnabledForUser('test', $user)); |
|
454 | - } |
|
455 | - |
|
456 | - public function testIsEnabledForUserDisabled(): void { |
|
457 | - $this->appConfig->setValue('test', 'enabled', 'no'); |
|
458 | - $user = $this->newUser('user1'); |
|
459 | - $this->assertFalse($this->manager->isEnabledForUser('test', $user)); |
|
460 | - } |
|
461 | - |
|
462 | - public function testGetAppPath(): void { |
|
463 | - $this->assertEquals(\OC::$SERVERROOT . '/apps/files', $this->manager->getAppPath('files')); |
|
464 | - } |
|
465 | - |
|
466 | - public function testGetAppPathSymlink(): void { |
|
467 | - $fakeAppDirname = sha1(uniqid('test', true)); |
|
468 | - $fakeAppPath = sys_get_temp_dir() . '/' . $fakeAppDirname; |
|
469 | - $fakeAppLink = \OC::$SERVERROOT . '/' . $fakeAppDirname; |
|
470 | - |
|
471 | - mkdir($fakeAppPath); |
|
472 | - if (symlink($fakeAppPath, $fakeAppLink) === false) { |
|
473 | - $this->markTestSkipped('Failed to create symlink'); |
|
474 | - } |
|
475 | - |
|
476 | - // Use the symlink as the app path |
|
477 | - \OC::$APPSROOTS[] = [ |
|
478 | - 'path' => $fakeAppLink, |
|
479 | - 'url' => \OC::$WEBROOT . '/' . $fakeAppDirname, |
|
480 | - 'writable' => false, |
|
481 | - ]; |
|
482 | - |
|
483 | - $fakeTestAppPath = $fakeAppPath . '/' . 'test-test-app'; |
|
484 | - mkdir($fakeTestAppPath); |
|
485 | - |
|
486 | - $generatedAppPath = $this->manager->getAppPath('test-test-app'); |
|
487 | - |
|
488 | - rmdir($fakeTestAppPath); |
|
489 | - unlink($fakeAppLink); |
|
490 | - rmdir($fakeAppPath); |
|
491 | - |
|
492 | - $this->assertEquals($fakeAppLink . '/test-test-app', $generatedAppPath); |
|
493 | - } |
|
494 | - |
|
495 | - public function testGetAppPathFail(): void { |
|
496 | - $this->expectException(AppPathNotFoundException::class); |
|
497 | - $this->manager->getAppPath('testnotexisting'); |
|
498 | - } |
|
499 | - |
|
500 | - public function testIsEnabledForUserEnabledForGroup(): void { |
|
501 | - $user = $this->newUser('user1'); |
|
502 | - $this->groupManager->expects($this->once()) |
|
503 | - ->method('getUserGroupIds') |
|
504 | - ->with($user) |
|
505 | - ->willReturn(['foo', 'bar']); |
|
506 | - |
|
507 | - $this->appConfig->setValue('test', 'enabled', '["foo"]'); |
|
508 | - $this->assertTrue($this->manager->isEnabledForUser('test', $user)); |
|
509 | - } |
|
510 | - |
|
511 | - public function testIsEnabledForUserDisabledForGroup(): void { |
|
512 | - $user = $this->newUser('user1'); |
|
513 | - $this->groupManager->expects($this->once()) |
|
514 | - ->method('getUserGroupIds') |
|
515 | - ->with($user) |
|
516 | - ->willReturn(['bar']); |
|
517 | - |
|
518 | - $this->appConfig->setValue('test', 'enabled', '["foo"]'); |
|
519 | - $this->assertFalse($this->manager->isEnabledForUser('test', $user)); |
|
520 | - } |
|
521 | - |
|
522 | - public function testIsEnabledForUserLoggedOut(): void { |
|
523 | - $this->appConfig->setValue('test', 'enabled', '["foo"]'); |
|
524 | - $this->assertFalse($this->manager->isEnabledForUser('test')); |
|
525 | - } |
|
526 | - |
|
527 | - public function testIsEnabledForUserLoggedIn(): void { |
|
528 | - $user = $this->newUser('user1'); |
|
529 | - |
|
530 | - $this->userSession->expects($this->once()) |
|
531 | - ->method('getUser') |
|
532 | - ->willReturn($user); |
|
533 | - $this->groupManager->expects($this->once()) |
|
534 | - ->method('getUserGroupIds') |
|
535 | - ->with($user) |
|
536 | - ->willReturn(['foo', 'bar']); |
|
537 | - |
|
538 | - $this->appConfig->setValue('test', 'enabled', '["foo"]'); |
|
539 | - $this->assertTrue($this->manager->isEnabledForUser('test')); |
|
540 | - } |
|
541 | - |
|
542 | - public function testGetEnabledApps(): void { |
|
543 | - $this->appConfig->setValue('test1', 'enabled', 'yes'); |
|
544 | - $this->appConfig->setValue('test2', 'enabled', 'no'); |
|
545 | - $this->appConfig->setValue('test3', 'enabled', '["foo"]'); |
|
546 | - $apps = [ |
|
547 | - 'cloud_federation_api', |
|
548 | - 'dav', |
|
549 | - 'federatedfilesharing', |
|
550 | - 'files', |
|
551 | - 'lookup_server_connector', |
|
552 | - 'oauth2', |
|
553 | - 'profile', |
|
554 | - 'provisioning_api', |
|
555 | - 'settings', |
|
556 | - 'test1', |
|
557 | - 'test3', |
|
558 | - 'theming', |
|
559 | - 'twofactor_backupcodes', |
|
560 | - 'viewer', |
|
561 | - 'workflowengine', |
|
562 | - ]; |
|
563 | - $this->assertEquals($apps, $this->manager->getEnabledApps()); |
|
564 | - } |
|
565 | - |
|
566 | - public function testGetAppsForUser(): void { |
|
567 | - $user = $this->newUser('user1'); |
|
568 | - $this->groupManager->expects($this->any()) |
|
569 | - ->method('getUserGroupIds') |
|
570 | - ->with($user) |
|
571 | - ->willReturn(['foo', 'bar']); |
|
572 | - |
|
573 | - $this->appConfig->setValue('test1', 'enabled', 'yes'); |
|
574 | - $this->appConfig->setValue('test2', 'enabled', 'no'); |
|
575 | - $this->appConfig->setValue('test3', 'enabled', '["foo"]'); |
|
576 | - $this->appConfig->setValue('test4', 'enabled', '["asd"]'); |
|
577 | - $enabled = [ |
|
578 | - 'cloud_federation_api', |
|
579 | - 'dav', |
|
580 | - 'federatedfilesharing', |
|
581 | - 'files', |
|
582 | - 'lookup_server_connector', |
|
583 | - 'oauth2', |
|
584 | - 'profile', |
|
585 | - 'provisioning_api', |
|
586 | - 'settings', |
|
587 | - 'test1', |
|
588 | - 'test3', |
|
589 | - 'theming', |
|
590 | - 'twofactor_backupcodes', |
|
591 | - 'viewer', |
|
592 | - 'workflowengine', |
|
593 | - ]; |
|
594 | - $this->assertEquals($enabled, $this->manager->getEnabledAppsForUser($user)); |
|
595 | - } |
|
596 | - |
|
597 | - public function testGetAppsNeedingUpgrade(): void { |
|
598 | - /** @var AppManager|MockObject $manager */ |
|
599 | - $manager = $this->getMockBuilder(AppManager::class) |
|
600 | - ->setConstructorArgs([ |
|
601 | - $this->userSession, |
|
602 | - $this->config, |
|
603 | - $this->groupManager, |
|
604 | - $this->cacheFactory, |
|
605 | - $this->eventDispatcher, |
|
606 | - $this->logger, |
|
607 | - $this->serverVersion, |
|
608 | - ]) |
|
609 | - ->onlyMethods(['getAppInfo']) |
|
610 | - ->getMock(); |
|
611 | - |
|
612 | - $appInfos = [ |
|
613 | - 'cloud_federation_api' => ['id' => 'cloud_federation_api'], |
|
614 | - 'dav' => ['id' => 'dav'], |
|
615 | - 'files' => ['id' => 'files'], |
|
616 | - 'federatedfilesharing' => ['id' => 'federatedfilesharing'], |
|
617 | - 'profile' => ['id' => 'profile'], |
|
618 | - 'provisioning_api' => ['id' => 'provisioning_api'], |
|
619 | - 'lookup_server_connector' => ['id' => 'lookup_server_connector'], |
|
620 | - 'test1' => ['id' => 'test1', 'version' => '1.0.1', 'requiremax' => '9.0.0'], |
|
621 | - 'test2' => ['id' => 'test2', 'version' => '1.0.0', 'requiremin' => '8.2.0'], |
|
622 | - 'test3' => ['id' => 'test3', 'version' => '1.2.4', 'requiremin' => '9.0.0'], |
|
623 | - 'test4' => ['id' => 'test4', 'version' => '3.0.0', 'requiremin' => '8.1.0'], |
|
624 | - 'testnoversion' => ['id' => 'testnoversion', 'requiremin' => '8.2.0'], |
|
625 | - 'settings' => ['id' => 'settings'], |
|
626 | - 'theming' => ['id' => 'theming'], |
|
627 | - 'twofactor_backupcodes' => ['id' => 'twofactor_backupcodes'], |
|
628 | - 'viewer' => ['id' => 'viewer'], |
|
629 | - 'workflowengine' => ['id' => 'workflowengine'], |
|
630 | - 'oauth2' => ['id' => 'oauth2'], |
|
631 | - ]; |
|
632 | - |
|
633 | - $manager->expects($this->any()) |
|
634 | - ->method('getAppInfo') |
|
635 | - ->willReturnCallback( |
|
636 | - function ($appId) use ($appInfos) { |
|
637 | - return $appInfos[$appId]; |
|
638 | - } |
|
639 | - ); |
|
640 | - |
|
641 | - $this->appConfig->setValue('test1', 'enabled', 'yes'); |
|
642 | - $this->appConfig->setValue('test1', 'installed_version', '1.0.0'); |
|
643 | - $this->appConfig->setValue('test2', 'enabled', 'yes'); |
|
644 | - $this->appConfig->setValue('test2', 'installed_version', '1.0.0'); |
|
645 | - $this->appConfig->setValue('test3', 'enabled', 'yes'); |
|
646 | - $this->appConfig->setValue('test3', 'installed_version', '1.0.0'); |
|
647 | - $this->appConfig->setValue('test4', 'enabled', 'yes'); |
|
648 | - $this->appConfig->setValue('test4', 'installed_version', '2.4.0'); |
|
649 | - |
|
650 | - $apps = $manager->getAppsNeedingUpgrade('8.2.0'); |
|
651 | - |
|
652 | - $this->assertCount(2, $apps); |
|
653 | - $this->assertEquals('test1', $apps[0]['id']); |
|
654 | - $this->assertEquals('test4', $apps[1]['id']); |
|
655 | - } |
|
656 | - |
|
657 | - public function testGetIncompatibleApps(): void { |
|
658 | - /** @var AppManager|MockObject $manager */ |
|
659 | - $manager = $this->getMockBuilder(AppManager::class) |
|
660 | - ->setConstructorArgs([ |
|
661 | - $this->userSession, |
|
662 | - $this->config, |
|
663 | - $this->groupManager, |
|
664 | - $this->cacheFactory, |
|
665 | - $this->eventDispatcher, |
|
666 | - $this->logger, |
|
667 | - $this->serverVersion, |
|
668 | - ]) |
|
669 | - ->onlyMethods(['getAppInfo']) |
|
670 | - ->getMock(); |
|
671 | - |
|
672 | - $appInfos = [ |
|
673 | - 'cloud_federation_api' => ['id' => 'cloud_federation_api'], |
|
674 | - 'dav' => ['id' => 'dav'], |
|
675 | - 'files' => ['id' => 'files'], |
|
676 | - 'federatedfilesharing' => ['id' => 'federatedfilesharing'], |
|
677 | - 'profile' => ['id' => 'profile'], |
|
678 | - 'provisioning_api' => ['id' => 'provisioning_api'], |
|
679 | - 'lookup_server_connector' => ['id' => 'lookup_server_connector'], |
|
680 | - 'test1' => ['id' => 'test1', 'version' => '1.0.1', 'requiremax' => '8.0.0'], |
|
681 | - 'test2' => ['id' => 'test2', 'version' => '1.0.0', 'requiremin' => '8.2.0'], |
|
682 | - 'test3' => ['id' => 'test3', 'version' => '1.2.4', 'requiremin' => '9.0.0'], |
|
683 | - 'settings' => ['id' => 'settings'], |
|
684 | - 'testnoversion' => ['id' => 'testnoversion', 'requiremin' => '8.2.0'], |
|
685 | - 'theming' => ['id' => 'theming'], |
|
686 | - 'twofactor_backupcodes' => ['id' => 'twofactor_backupcodes'], |
|
687 | - 'workflowengine' => ['id' => 'workflowengine'], |
|
688 | - 'oauth2' => ['id' => 'oauth2'], |
|
689 | - 'viewer' => ['id' => 'viewer'], |
|
690 | - ]; |
|
691 | - |
|
692 | - $manager->expects($this->any()) |
|
693 | - ->method('getAppInfo') |
|
694 | - ->willReturnCallback( |
|
695 | - function ($appId) use ($appInfos) { |
|
696 | - return $appInfos[$appId]; |
|
697 | - } |
|
698 | - ); |
|
699 | - |
|
700 | - $this->appConfig->setValue('test1', 'enabled', 'yes'); |
|
701 | - $this->appConfig->setValue('test2', 'enabled', 'yes'); |
|
702 | - $this->appConfig->setValue('test3', 'enabled', 'yes'); |
|
703 | - |
|
704 | - $apps = $manager->getIncompatibleApps('8.2.0'); |
|
705 | - |
|
706 | - $this->assertCount(2, $apps); |
|
707 | - $this->assertEquals('test1', $apps[0]['id']); |
|
708 | - $this->assertEquals('test3', $apps[1]['id']); |
|
709 | - } |
|
710 | - |
|
711 | - public function testGetEnabledAppsForGroup(): void { |
|
712 | - $group = $this->createMock(IGroup::class); |
|
713 | - $group->expects($this->any()) |
|
714 | - ->method('getGID') |
|
715 | - ->willReturn('foo'); |
|
716 | - |
|
717 | - $this->appConfig->setValue('test1', 'enabled', 'yes'); |
|
718 | - $this->appConfig->setValue('test2', 'enabled', 'no'); |
|
719 | - $this->appConfig->setValue('test3', 'enabled', '["foo"]'); |
|
720 | - $this->appConfig->setValue('test4', 'enabled', '["asd"]'); |
|
721 | - $enabled = [ |
|
722 | - 'cloud_federation_api', |
|
723 | - 'dav', |
|
724 | - 'federatedfilesharing', |
|
725 | - 'files', |
|
726 | - 'lookup_server_connector', |
|
727 | - 'oauth2', |
|
728 | - 'profile', |
|
729 | - 'provisioning_api', |
|
730 | - 'settings', |
|
731 | - 'test1', |
|
732 | - 'test3', |
|
733 | - 'theming', |
|
734 | - 'twofactor_backupcodes', |
|
735 | - 'viewer', |
|
736 | - 'workflowengine', |
|
737 | - ]; |
|
738 | - $this->assertEquals($enabled, $this->manager->getEnabledAppsForGroup($group)); |
|
739 | - } |
|
740 | - |
|
741 | - public function testGetAppRestriction(): void { |
|
742 | - $this->appConfig->setValue('test1', 'enabled', 'yes'); |
|
743 | - $this->appConfig->setValue('test2', 'enabled', 'no'); |
|
744 | - $this->appConfig->setValue('test3', 'enabled', '["foo"]'); |
|
745 | - |
|
746 | - $this->assertEquals([], $this->manager->getAppRestriction('test1')); |
|
747 | - $this->assertEquals([], $this->manager->getAppRestriction('test2')); |
|
748 | - $this->assertEquals(['foo'], $this->manager->getAppRestriction('test3')); |
|
749 | - } |
|
750 | - |
|
751 | - public static function isBackendRequiredDataProvider(): array { |
|
752 | - return [ |
|
753 | - // backend available |
|
754 | - [ |
|
755 | - 'caldav', |
|
756 | - ['app1' => ['caldav']], |
|
757 | - true, |
|
758 | - ], |
|
759 | - [ |
|
760 | - 'caldav', |
|
761 | - ['app1' => [], 'app2' => ['foo'], 'app3' => ['caldav']], |
|
762 | - true, |
|
763 | - ], |
|
764 | - // backend not available |
|
765 | - [ |
|
766 | - 'caldav', |
|
767 | - ['app3' => [], 'app1' => ['foo'], 'app2' => ['bar', 'baz']], |
|
768 | - false, |
|
769 | - ], |
|
770 | - // no app available |
|
771 | - [ |
|
772 | - 'caldav', |
|
773 | - [], |
|
774 | - false, |
|
775 | - ], |
|
776 | - ]; |
|
777 | - } |
|
778 | - |
|
779 | - /** |
|
780 | - * @dataProvider isBackendRequiredDataProvider |
|
781 | - */ |
|
782 | - public function testIsBackendRequired( |
|
783 | - string $backend, |
|
784 | - array $appBackends, |
|
785 | - bool $expected, |
|
786 | - ): void { |
|
787 | - $appInfoData = array_map( |
|
788 | - static fn (array $backends) => ['dependencies' => ['backend' => $backends]], |
|
789 | - $appBackends, |
|
790 | - ); |
|
791 | - |
|
792 | - $reflection = new \ReflectionClass($this->manager); |
|
793 | - $property = $reflection->getProperty('appInfos'); |
|
794 | - $property->setValue($this->manager, $appInfoData); |
|
795 | - |
|
796 | - $this->assertEquals($expected, $this->manager->isBackendRequired($backend)); |
|
797 | - } |
|
798 | - |
|
799 | - public function testGetAppVersion() { |
|
800 | - $manager = $this->getMockBuilder(AppManager::class) |
|
801 | - ->setConstructorArgs([ |
|
802 | - $this->userSession, |
|
803 | - $this->config, |
|
804 | - $this->groupManager, |
|
805 | - $this->cacheFactory, |
|
806 | - $this->eventDispatcher, |
|
807 | - $this->logger, |
|
808 | - $this->serverVersion, |
|
809 | - ]) |
|
810 | - ->onlyMethods([ |
|
811 | - 'getAppInfo', |
|
812 | - ]) |
|
813 | - ->getMock(); |
|
814 | - |
|
815 | - $manager->expects(self::once()) |
|
816 | - ->method('getAppInfo') |
|
817 | - ->with('myapp') |
|
818 | - ->willReturn(['version' => '99.99.99-rc.99']); |
|
819 | - |
|
820 | - $this->serverVersion |
|
821 | - ->expects(self::never()) |
|
822 | - ->method('getVersionString'); |
|
823 | - |
|
824 | - $this->assertEquals( |
|
825 | - '99.99.99-rc.99', |
|
826 | - $manager->getAppVersion('myapp'), |
|
827 | - ); |
|
828 | - } |
|
829 | - |
|
830 | - public function testGetAppVersionCore() { |
|
831 | - $manager = $this->getMockBuilder(AppManager::class) |
|
832 | - ->setConstructorArgs([ |
|
833 | - $this->userSession, |
|
834 | - $this->config, |
|
835 | - $this->groupManager, |
|
836 | - $this->cacheFactory, |
|
837 | - $this->eventDispatcher, |
|
838 | - $this->logger, |
|
839 | - $this->serverVersion, |
|
840 | - ]) |
|
841 | - ->onlyMethods([ |
|
842 | - 'getAppInfo', |
|
843 | - ]) |
|
844 | - ->getMock(); |
|
845 | - |
|
846 | - $manager->expects(self::never()) |
|
847 | - ->method('getAppInfo'); |
|
848 | - |
|
849 | - $this->serverVersion |
|
850 | - ->expects(self::once()) |
|
851 | - ->method('getVersionString') |
|
852 | - ->willReturn('1.2.3-beta.4'); |
|
853 | - |
|
854 | - $this->assertEquals( |
|
855 | - '1.2.3-beta.4', |
|
856 | - $manager->getAppVersion('core'), |
|
857 | - ); |
|
858 | - } |
|
859 | - |
|
860 | - public function testGetAppVersionUnknown() { |
|
861 | - $manager = $this->getMockBuilder(AppManager::class) |
|
862 | - ->setConstructorArgs([ |
|
863 | - $this->userSession, |
|
864 | - $this->config, |
|
865 | - $this->groupManager, |
|
866 | - $this->cacheFactory, |
|
867 | - $this->eventDispatcher, |
|
868 | - $this->logger, |
|
869 | - $this->serverVersion, |
|
870 | - ]) |
|
871 | - ->onlyMethods([ |
|
872 | - 'getAppInfo', |
|
873 | - ]) |
|
874 | - ->getMock(); |
|
875 | - |
|
876 | - $manager->expects(self::once()) |
|
877 | - ->method('getAppInfo') |
|
878 | - ->with('unknown') |
|
879 | - ->willReturn(null); |
|
880 | - |
|
881 | - $this->serverVersion |
|
882 | - ->expects(self::never()) |
|
883 | - ->method('getVersionString'); |
|
884 | - |
|
885 | - $this->assertEquals( |
|
886 | - '0', |
|
887 | - $manager->getAppVersion('unknown'), |
|
888 | - ); |
|
889 | - } |
|
39 | + /** |
|
40 | + * @return AppConfig|MockObject |
|
41 | + */ |
|
42 | + protected function getAppConfig() { |
|
43 | + $appConfig = []; |
|
44 | + $config = $this->createMock(AppConfig::class); |
|
45 | + |
|
46 | + $config->expects($this->any()) |
|
47 | + ->method('getValue') |
|
48 | + ->willReturnCallback(function ($app, $key, $default) use (&$appConfig) { |
|
49 | + return (isset($appConfig[$app]) and isset($appConfig[$app][$key])) ? $appConfig[$app][$key] : $default; |
|
50 | + }); |
|
51 | + $config->expects($this->any()) |
|
52 | + ->method('setValue') |
|
53 | + ->willReturnCallback(function ($app, $key, $value) use (&$appConfig) { |
|
54 | + if (!isset($appConfig[$app])) { |
|
55 | + $appConfig[$app] = []; |
|
56 | + } |
|
57 | + $appConfig[$app][$key] = $value; |
|
58 | + }); |
|
59 | + $config->expects($this->any()) |
|
60 | + ->method('getValues') |
|
61 | + ->willReturnCallback(function ($app, $key) use (&$appConfig) { |
|
62 | + if ($app) { |
|
63 | + return $appConfig[$app]; |
|
64 | + } else { |
|
65 | + $values = []; |
|
66 | + foreach ($appConfig as $appid => $appData) { |
|
67 | + if (isset($appData[$key])) { |
|
68 | + $values[$appid] = $appData[$key]; |
|
69 | + } |
|
70 | + } |
|
71 | + return $values; |
|
72 | + } |
|
73 | + }); |
|
74 | + |
|
75 | + return $config; |
|
76 | + } |
|
77 | + |
|
78 | + /** @var IUserSession|MockObject */ |
|
79 | + protected $userSession; |
|
80 | + |
|
81 | + /** @var IConfig|MockObject */ |
|
82 | + private $config; |
|
83 | + |
|
84 | + /** @var IGroupManager|MockObject */ |
|
85 | + protected $groupManager; |
|
86 | + |
|
87 | + /** @var AppConfig|MockObject */ |
|
88 | + protected $appConfig; |
|
89 | + |
|
90 | + /** @var ICache|MockObject */ |
|
91 | + protected $cache; |
|
92 | + |
|
93 | + /** @var ICacheFactory|MockObject */ |
|
94 | + protected $cacheFactory; |
|
95 | + |
|
96 | + /** @var IEventDispatcher|MockObject */ |
|
97 | + protected $eventDispatcher; |
|
98 | + |
|
99 | + /** @var LoggerInterface|MockObject */ |
|
100 | + protected $logger; |
|
101 | + |
|
102 | + protected IURLGenerator&MockObject $urlGenerator; |
|
103 | + |
|
104 | + protected ServerVersion&MockObject $serverVersion; |
|
105 | + |
|
106 | + /** @var IAppManager */ |
|
107 | + protected $manager; |
|
108 | + |
|
109 | + protected function setUp(): void { |
|
110 | + parent::setUp(); |
|
111 | + |
|
112 | + $this->userSession = $this->createMock(IUserSession::class); |
|
113 | + $this->groupManager = $this->createMock(IGroupManager::class); |
|
114 | + $this->config = $this->createMock(IConfig::class); |
|
115 | + $this->appConfig = $this->getAppConfig(); |
|
116 | + $this->cacheFactory = $this->createMock(ICacheFactory::class); |
|
117 | + $this->cache = $this->createMock(ICache::class); |
|
118 | + $this->eventDispatcher = $this->createMock(IEventDispatcher::class); |
|
119 | + $this->logger = $this->createMock(LoggerInterface::class); |
|
120 | + $this->urlGenerator = $this->createMock(IURLGenerator::class); |
|
121 | + $this->serverVersion = $this->createMock(ServerVersion::class); |
|
122 | + |
|
123 | + $this->overwriteService(AppConfig::class, $this->appConfig); |
|
124 | + $this->overwriteService(IURLGenerator::class, $this->urlGenerator); |
|
125 | + |
|
126 | + $this->cacheFactory->expects($this->any()) |
|
127 | + ->method('createDistributed') |
|
128 | + ->with('settings') |
|
129 | + ->willReturn($this->cache); |
|
130 | + |
|
131 | + $this->config |
|
132 | + ->method('getSystemValueBool') |
|
133 | + ->with('installed', false) |
|
134 | + ->willReturn(true); |
|
135 | + |
|
136 | + $this->manager = new AppManager( |
|
137 | + $this->userSession, |
|
138 | + $this->config, |
|
139 | + $this->groupManager, |
|
140 | + $this->cacheFactory, |
|
141 | + $this->eventDispatcher, |
|
142 | + $this->logger, |
|
143 | + $this->serverVersion, |
|
144 | + ); |
|
145 | + } |
|
146 | + |
|
147 | + /** |
|
148 | + * @dataProvider dataGetAppIcon |
|
149 | + */ |
|
150 | + public function testGetAppIcon($callback, ?bool $dark, ?string $expected): void { |
|
151 | + $this->urlGenerator->expects($this->atLeastOnce()) |
|
152 | + ->method('imagePath') |
|
153 | + ->willReturnCallback($callback); |
|
154 | + |
|
155 | + if ($dark !== null) { |
|
156 | + $this->assertEquals($expected, $this->manager->getAppIcon('test', $dark)); |
|
157 | + } else { |
|
158 | + $this->assertEquals($expected, $this->manager->getAppIcon('test')); |
|
159 | + } |
|
160 | + } |
|
161 | + |
|
162 | + public static function dataGetAppIcon(): array { |
|
163 | + $nothing = function ($appId) { |
|
164 | + self::assertEquals('test', $appId); |
|
165 | + throw new \RuntimeException(); |
|
166 | + }; |
|
167 | + |
|
168 | + $createCallback = function ($workingIcons) { |
|
169 | + return function ($appId, $icon) use ($workingIcons) { |
|
170 | + self::assertEquals('test', $appId); |
|
171 | + if (in_array($icon, $workingIcons)) { |
|
172 | + return '/path/' . $icon; |
|
173 | + } |
|
174 | + throw new \RuntimeException(); |
|
175 | + }; |
|
176 | + }; |
|
177 | + |
|
178 | + return [ |
|
179 | + 'does not find anything' => [ |
|
180 | + $nothing, |
|
181 | + false, |
|
182 | + null, |
|
183 | + ], |
|
184 | + 'nothing if request dark but only bright available' => [ |
|
185 | + $createCallback(['app.svg']), |
|
186 | + true, |
|
187 | + null, |
|
188 | + ], |
|
189 | + 'nothing if request bright but only dark available' => [ |
|
190 | + $createCallback(['app-dark.svg']), |
|
191 | + false, |
|
192 | + null, |
|
193 | + ], |
|
194 | + 'bright and only app.svg' => [ |
|
195 | + $createCallback(['app.svg']), |
|
196 | + false, |
|
197 | + '/path/app.svg', |
|
198 | + ], |
|
199 | + 'dark and only app-dark.svg' => [ |
|
200 | + $createCallback(['app-dark.svg']), |
|
201 | + true, |
|
202 | + '/path/app-dark.svg', |
|
203 | + ], |
|
204 | + 'dark only appname -dark.svg' => [ |
|
205 | + $createCallback(['test-dark.svg']), |
|
206 | + true, |
|
207 | + '/path/test-dark.svg', |
|
208 | + ], |
|
209 | + 'bright and only appname.svg' => [ |
|
210 | + $createCallback(['test.svg']), |
|
211 | + false, |
|
212 | + '/path/test.svg', |
|
213 | + ], |
|
214 | + 'priotize custom over default' => [ |
|
215 | + $createCallback(['app.svg', 'test.svg']), |
|
216 | + false, |
|
217 | + '/path/test.svg', |
|
218 | + ], |
|
219 | + 'defaults to bright' => [ |
|
220 | + $createCallback(['test-dark.svg', 'test.svg']), |
|
221 | + null, |
|
222 | + '/path/test.svg', |
|
223 | + ], |
|
224 | + 'no dark icon on default' => [ |
|
225 | + $createCallback(['test-dark.svg', 'test.svg', 'app-dark.svg', 'app.svg']), |
|
226 | + false, |
|
227 | + '/path/test.svg', |
|
228 | + ], |
|
229 | + 'no bright icon on dark' => [ |
|
230 | + $createCallback(['test-dark.svg', 'test.svg', 'app-dark.svg', 'app.svg']), |
|
231 | + true, |
|
232 | + '/path/test-dark.svg', |
|
233 | + ], |
|
234 | + ]; |
|
235 | + } |
|
236 | + |
|
237 | + public function testEnableApp(): void { |
|
238 | + // making sure "files_trashbin" is disabled |
|
239 | + if ($this->manager->isEnabledForUser('files_trashbin')) { |
|
240 | + $this->manager->disableApp('files_trashbin'); |
|
241 | + } |
|
242 | + $this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new AppEnableEvent('files_trashbin')); |
|
243 | + $this->manager->enableApp('files_trashbin'); |
|
244 | + $this->assertEquals('yes', $this->appConfig->getValue('files_trashbin', 'enabled', 'no')); |
|
245 | + } |
|
246 | + |
|
247 | + public function testDisableApp(): void { |
|
248 | + $this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new AppDisableEvent('files_trashbin')); |
|
249 | + $this->manager->disableApp('files_trashbin'); |
|
250 | + $this->assertEquals('no', $this->appConfig->getValue('files_trashbin', 'enabled', 'no')); |
|
251 | + } |
|
252 | + |
|
253 | + public function testNotEnableIfNotInstalled(): void { |
|
254 | + try { |
|
255 | + $this->manager->enableApp('some_random_name_which_i_hope_is_not_an_app'); |
|
256 | + $this->assertFalse(true, 'If this line is reached the expected exception is not thrown.'); |
|
257 | + } catch (AppPathNotFoundException $e) { |
|
258 | + // Exception is expected |
|
259 | + $this->assertEquals('Could not find path for some_random_name_which_i_hope_is_not_an_app', $e->getMessage()); |
|
260 | + } |
|
261 | + |
|
262 | + $this->assertEquals('no', $this->appConfig->getValue( |
|
263 | + 'some_random_name_which_i_hope_is_not_an_app', 'enabled', 'no' |
|
264 | + )); |
|
265 | + } |
|
266 | + |
|
267 | + public function testEnableAppForGroups(): void { |
|
268 | + $group1 = $this->createMock(IGroup::class); |
|
269 | + $group1->method('getGID') |
|
270 | + ->willReturn('group1'); |
|
271 | + $group2 = $this->createMock(IGroup::class); |
|
272 | + $group2->method('getGID') |
|
273 | + ->willReturn('group2'); |
|
274 | + |
|
275 | + $groups = [$group1, $group2]; |
|
276 | + |
|
277 | + /** @var AppManager|MockObject $manager */ |
|
278 | + $manager = $this->getMockBuilder(AppManager::class) |
|
279 | + ->setConstructorArgs([ |
|
280 | + $this->userSession, |
|
281 | + $this->config, |
|
282 | + $this->groupManager, |
|
283 | + $this->cacheFactory, |
|
284 | + $this->eventDispatcher, |
|
285 | + $this->logger, |
|
286 | + $this->serverVersion, |
|
287 | + ]) |
|
288 | + ->onlyMethods([ |
|
289 | + 'getAppPath', |
|
290 | + ]) |
|
291 | + ->getMock(); |
|
292 | + |
|
293 | + $manager->expects($this->exactly(2)) |
|
294 | + ->method('getAppPath') |
|
295 | + ->with('test') |
|
296 | + ->willReturn('apps/test'); |
|
297 | + |
|
298 | + $this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new AppEnableEvent('test', ['group1', 'group2'])); |
|
299 | + |
|
300 | + $manager->enableAppForGroups('test', $groups); |
|
301 | + $this->assertEquals('["group1","group2"]', $this->appConfig->getValue('test', 'enabled', 'no')); |
|
302 | + } |
|
303 | + |
|
304 | + public static function dataEnableAppForGroupsAllowedTypes(): array { |
|
305 | + return [ |
|
306 | + [[]], |
|
307 | + [[ |
|
308 | + 'types' => [], |
|
309 | + ]], |
|
310 | + [[ |
|
311 | + 'types' => ['nickvergessen'], |
|
312 | + ]], |
|
313 | + ]; |
|
314 | + } |
|
315 | + |
|
316 | + /** |
|
317 | + * @dataProvider dataEnableAppForGroupsAllowedTypes |
|
318 | + * |
|
319 | + * @param array $appInfo |
|
320 | + */ |
|
321 | + public function testEnableAppForGroupsAllowedTypes(array $appInfo): void { |
|
322 | + $group1 = $this->createMock(IGroup::class); |
|
323 | + $group1->method('getGID') |
|
324 | + ->willReturn('group1'); |
|
325 | + $group2 = $this->createMock(IGroup::class); |
|
326 | + $group2->method('getGID') |
|
327 | + ->willReturn('group2'); |
|
328 | + |
|
329 | + $groups = [$group1, $group2]; |
|
330 | + |
|
331 | + /** @var AppManager|MockObject $manager */ |
|
332 | + $manager = $this->getMockBuilder(AppManager::class) |
|
333 | + ->setConstructorArgs([ |
|
334 | + $this->userSession, |
|
335 | + $this->config, |
|
336 | + $this->groupManager, |
|
337 | + $this->cacheFactory, |
|
338 | + $this->eventDispatcher, |
|
339 | + $this->logger, |
|
340 | + $this->serverVersion, |
|
341 | + ]) |
|
342 | + ->onlyMethods([ |
|
343 | + 'getAppPath', |
|
344 | + 'getAppInfo', |
|
345 | + ]) |
|
346 | + ->getMock(); |
|
347 | + |
|
348 | + $manager->expects($this->once()) |
|
349 | + ->method('getAppPath') |
|
350 | + ->with('test') |
|
351 | + ->willReturn(''); |
|
352 | + |
|
353 | + $manager->expects($this->once()) |
|
354 | + ->method('getAppInfo') |
|
355 | + ->with('test') |
|
356 | + ->willReturn($appInfo); |
|
357 | + |
|
358 | + $this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new AppEnableEvent('test', ['group1', 'group2'])); |
|
359 | + |
|
360 | + $manager->enableAppForGroups('test', $groups); |
|
361 | + $this->assertEquals('["group1","group2"]', $this->appConfig->getValue('test', 'enabled', 'no')); |
|
362 | + } |
|
363 | + |
|
364 | + public static function dataEnableAppForGroupsForbiddenTypes(): array { |
|
365 | + return [ |
|
366 | + ['filesystem'], |
|
367 | + ['prelogin'], |
|
368 | + ['authentication'], |
|
369 | + ['logging'], |
|
370 | + ['prevent_group_restriction'], |
|
371 | + ]; |
|
372 | + } |
|
373 | + |
|
374 | + /** |
|
375 | + * @dataProvider dataEnableAppForGroupsForbiddenTypes |
|
376 | + * |
|
377 | + * @param string $type |
|
378 | + * |
|
379 | + */ |
|
380 | + public function testEnableAppForGroupsForbiddenTypes($type): void { |
|
381 | + $this->expectException(\Exception::class); |
|
382 | + $this->expectExceptionMessage('test can\'t be enabled for groups.'); |
|
383 | + |
|
384 | + $group1 = $this->createMock(IGroup::class); |
|
385 | + $group1->method('getGID') |
|
386 | + ->willReturn('group1'); |
|
387 | + $group2 = $this->createMock(IGroup::class); |
|
388 | + $group2->method('getGID') |
|
389 | + ->willReturn('group2'); |
|
390 | + |
|
391 | + $groups = [$group1, $group2]; |
|
392 | + |
|
393 | + /** @var AppManager|MockObject $manager */ |
|
394 | + $manager = $this->getMockBuilder(AppManager::class) |
|
395 | + ->setConstructorArgs([ |
|
396 | + $this->userSession, |
|
397 | + $this->config, |
|
398 | + $this->groupManager, |
|
399 | + $this->cacheFactory, |
|
400 | + $this->eventDispatcher, |
|
401 | + $this->logger, |
|
402 | + $this->serverVersion, |
|
403 | + ]) |
|
404 | + ->onlyMethods([ |
|
405 | + 'getAppPath', |
|
406 | + 'getAppInfo', |
|
407 | + ]) |
|
408 | + ->getMock(); |
|
409 | + |
|
410 | + $manager->expects($this->once()) |
|
411 | + ->method('getAppPath') |
|
412 | + ->with('test') |
|
413 | + ->willReturn(''); |
|
414 | + |
|
415 | + $manager->expects($this->once()) |
|
416 | + ->method('getAppInfo') |
|
417 | + ->with('test') |
|
418 | + ->willReturn([ |
|
419 | + 'types' => [$type], |
|
420 | + ]); |
|
421 | + |
|
422 | + $this->eventDispatcher->expects($this->never())->method('dispatchTyped')->with(new AppEnableEvent('test', ['group1', 'group2'])); |
|
423 | + |
|
424 | + $manager->enableAppForGroups('test', $groups); |
|
425 | + } |
|
426 | + |
|
427 | + public function testIsInstalledEnabled(): void { |
|
428 | + $this->appConfig->setValue('test', 'enabled', 'yes'); |
|
429 | + $this->assertTrue($this->manager->isEnabledForAnyone('test')); |
|
430 | + } |
|
431 | + |
|
432 | + public function testIsInstalledDisabled(): void { |
|
433 | + $this->appConfig->setValue('test', 'enabled', 'no'); |
|
434 | + $this->assertFalse($this->manager->isEnabledForAnyone('test')); |
|
435 | + } |
|
436 | + |
|
437 | + public function testIsInstalledEnabledForGroups(): void { |
|
438 | + $this->appConfig->setValue('test', 'enabled', '["foo"]'); |
|
439 | + $this->assertTrue($this->manager->isEnabledForAnyone('test')); |
|
440 | + } |
|
441 | + |
|
442 | + private function newUser($uid) { |
|
443 | + $user = $this->createMock(IUser::class); |
|
444 | + $user->method('getUID') |
|
445 | + ->willReturn($uid); |
|
446 | + |
|
447 | + return $user; |
|
448 | + } |
|
449 | + |
|
450 | + public function testIsEnabledForUserEnabled(): void { |
|
451 | + $this->appConfig->setValue('test', 'enabled', 'yes'); |
|
452 | + $user = $this->newUser('user1'); |
|
453 | + $this->assertTrue($this->manager->isEnabledForUser('test', $user)); |
|
454 | + } |
|
455 | + |
|
456 | + public function testIsEnabledForUserDisabled(): void { |
|
457 | + $this->appConfig->setValue('test', 'enabled', 'no'); |
|
458 | + $user = $this->newUser('user1'); |
|
459 | + $this->assertFalse($this->manager->isEnabledForUser('test', $user)); |
|
460 | + } |
|
461 | + |
|
462 | + public function testGetAppPath(): void { |
|
463 | + $this->assertEquals(\OC::$SERVERROOT . '/apps/files', $this->manager->getAppPath('files')); |
|
464 | + } |
|
465 | + |
|
466 | + public function testGetAppPathSymlink(): void { |
|
467 | + $fakeAppDirname = sha1(uniqid('test', true)); |
|
468 | + $fakeAppPath = sys_get_temp_dir() . '/' . $fakeAppDirname; |
|
469 | + $fakeAppLink = \OC::$SERVERROOT . '/' . $fakeAppDirname; |
|
470 | + |
|
471 | + mkdir($fakeAppPath); |
|
472 | + if (symlink($fakeAppPath, $fakeAppLink) === false) { |
|
473 | + $this->markTestSkipped('Failed to create symlink'); |
|
474 | + } |
|
475 | + |
|
476 | + // Use the symlink as the app path |
|
477 | + \OC::$APPSROOTS[] = [ |
|
478 | + 'path' => $fakeAppLink, |
|
479 | + 'url' => \OC::$WEBROOT . '/' . $fakeAppDirname, |
|
480 | + 'writable' => false, |
|
481 | + ]; |
|
482 | + |
|
483 | + $fakeTestAppPath = $fakeAppPath . '/' . 'test-test-app'; |
|
484 | + mkdir($fakeTestAppPath); |
|
485 | + |
|
486 | + $generatedAppPath = $this->manager->getAppPath('test-test-app'); |
|
487 | + |
|
488 | + rmdir($fakeTestAppPath); |
|
489 | + unlink($fakeAppLink); |
|
490 | + rmdir($fakeAppPath); |
|
491 | + |
|
492 | + $this->assertEquals($fakeAppLink . '/test-test-app', $generatedAppPath); |
|
493 | + } |
|
494 | + |
|
495 | + public function testGetAppPathFail(): void { |
|
496 | + $this->expectException(AppPathNotFoundException::class); |
|
497 | + $this->manager->getAppPath('testnotexisting'); |
|
498 | + } |
|
499 | + |
|
500 | + public function testIsEnabledForUserEnabledForGroup(): void { |
|
501 | + $user = $this->newUser('user1'); |
|
502 | + $this->groupManager->expects($this->once()) |
|
503 | + ->method('getUserGroupIds') |
|
504 | + ->with($user) |
|
505 | + ->willReturn(['foo', 'bar']); |
|
506 | + |
|
507 | + $this->appConfig->setValue('test', 'enabled', '["foo"]'); |
|
508 | + $this->assertTrue($this->manager->isEnabledForUser('test', $user)); |
|
509 | + } |
|
510 | + |
|
511 | + public function testIsEnabledForUserDisabledForGroup(): void { |
|
512 | + $user = $this->newUser('user1'); |
|
513 | + $this->groupManager->expects($this->once()) |
|
514 | + ->method('getUserGroupIds') |
|
515 | + ->with($user) |
|
516 | + ->willReturn(['bar']); |
|
517 | + |
|
518 | + $this->appConfig->setValue('test', 'enabled', '["foo"]'); |
|
519 | + $this->assertFalse($this->manager->isEnabledForUser('test', $user)); |
|
520 | + } |
|
521 | + |
|
522 | + public function testIsEnabledForUserLoggedOut(): void { |
|
523 | + $this->appConfig->setValue('test', 'enabled', '["foo"]'); |
|
524 | + $this->assertFalse($this->manager->isEnabledForUser('test')); |
|
525 | + } |
|
526 | + |
|
527 | + public function testIsEnabledForUserLoggedIn(): void { |
|
528 | + $user = $this->newUser('user1'); |
|
529 | + |
|
530 | + $this->userSession->expects($this->once()) |
|
531 | + ->method('getUser') |
|
532 | + ->willReturn($user); |
|
533 | + $this->groupManager->expects($this->once()) |
|
534 | + ->method('getUserGroupIds') |
|
535 | + ->with($user) |
|
536 | + ->willReturn(['foo', 'bar']); |
|
537 | + |
|
538 | + $this->appConfig->setValue('test', 'enabled', '["foo"]'); |
|
539 | + $this->assertTrue($this->manager->isEnabledForUser('test')); |
|
540 | + } |
|
541 | + |
|
542 | + public function testGetEnabledApps(): void { |
|
543 | + $this->appConfig->setValue('test1', 'enabled', 'yes'); |
|
544 | + $this->appConfig->setValue('test2', 'enabled', 'no'); |
|
545 | + $this->appConfig->setValue('test3', 'enabled', '["foo"]'); |
|
546 | + $apps = [ |
|
547 | + 'cloud_federation_api', |
|
548 | + 'dav', |
|
549 | + 'federatedfilesharing', |
|
550 | + 'files', |
|
551 | + 'lookup_server_connector', |
|
552 | + 'oauth2', |
|
553 | + 'profile', |
|
554 | + 'provisioning_api', |
|
555 | + 'settings', |
|
556 | + 'test1', |
|
557 | + 'test3', |
|
558 | + 'theming', |
|
559 | + 'twofactor_backupcodes', |
|
560 | + 'viewer', |
|
561 | + 'workflowengine', |
|
562 | + ]; |
|
563 | + $this->assertEquals($apps, $this->manager->getEnabledApps()); |
|
564 | + } |
|
565 | + |
|
566 | + public function testGetAppsForUser(): void { |
|
567 | + $user = $this->newUser('user1'); |
|
568 | + $this->groupManager->expects($this->any()) |
|
569 | + ->method('getUserGroupIds') |
|
570 | + ->with($user) |
|
571 | + ->willReturn(['foo', 'bar']); |
|
572 | + |
|
573 | + $this->appConfig->setValue('test1', 'enabled', 'yes'); |
|
574 | + $this->appConfig->setValue('test2', 'enabled', 'no'); |
|
575 | + $this->appConfig->setValue('test3', 'enabled', '["foo"]'); |
|
576 | + $this->appConfig->setValue('test4', 'enabled', '["asd"]'); |
|
577 | + $enabled = [ |
|
578 | + 'cloud_federation_api', |
|
579 | + 'dav', |
|
580 | + 'federatedfilesharing', |
|
581 | + 'files', |
|
582 | + 'lookup_server_connector', |
|
583 | + 'oauth2', |
|
584 | + 'profile', |
|
585 | + 'provisioning_api', |
|
586 | + 'settings', |
|
587 | + 'test1', |
|
588 | + 'test3', |
|
589 | + 'theming', |
|
590 | + 'twofactor_backupcodes', |
|
591 | + 'viewer', |
|
592 | + 'workflowengine', |
|
593 | + ]; |
|
594 | + $this->assertEquals($enabled, $this->manager->getEnabledAppsForUser($user)); |
|
595 | + } |
|
596 | + |
|
597 | + public function testGetAppsNeedingUpgrade(): void { |
|
598 | + /** @var AppManager|MockObject $manager */ |
|
599 | + $manager = $this->getMockBuilder(AppManager::class) |
|
600 | + ->setConstructorArgs([ |
|
601 | + $this->userSession, |
|
602 | + $this->config, |
|
603 | + $this->groupManager, |
|
604 | + $this->cacheFactory, |
|
605 | + $this->eventDispatcher, |
|
606 | + $this->logger, |
|
607 | + $this->serverVersion, |
|
608 | + ]) |
|
609 | + ->onlyMethods(['getAppInfo']) |
|
610 | + ->getMock(); |
|
611 | + |
|
612 | + $appInfos = [ |
|
613 | + 'cloud_federation_api' => ['id' => 'cloud_federation_api'], |
|
614 | + 'dav' => ['id' => 'dav'], |
|
615 | + 'files' => ['id' => 'files'], |
|
616 | + 'federatedfilesharing' => ['id' => 'federatedfilesharing'], |
|
617 | + 'profile' => ['id' => 'profile'], |
|
618 | + 'provisioning_api' => ['id' => 'provisioning_api'], |
|
619 | + 'lookup_server_connector' => ['id' => 'lookup_server_connector'], |
|
620 | + 'test1' => ['id' => 'test1', 'version' => '1.0.1', 'requiremax' => '9.0.0'], |
|
621 | + 'test2' => ['id' => 'test2', 'version' => '1.0.0', 'requiremin' => '8.2.0'], |
|
622 | + 'test3' => ['id' => 'test3', 'version' => '1.2.4', 'requiremin' => '9.0.0'], |
|
623 | + 'test4' => ['id' => 'test4', 'version' => '3.0.0', 'requiremin' => '8.1.0'], |
|
624 | + 'testnoversion' => ['id' => 'testnoversion', 'requiremin' => '8.2.0'], |
|
625 | + 'settings' => ['id' => 'settings'], |
|
626 | + 'theming' => ['id' => 'theming'], |
|
627 | + 'twofactor_backupcodes' => ['id' => 'twofactor_backupcodes'], |
|
628 | + 'viewer' => ['id' => 'viewer'], |
|
629 | + 'workflowengine' => ['id' => 'workflowengine'], |
|
630 | + 'oauth2' => ['id' => 'oauth2'], |
|
631 | + ]; |
|
632 | + |
|
633 | + $manager->expects($this->any()) |
|
634 | + ->method('getAppInfo') |
|
635 | + ->willReturnCallback( |
|
636 | + function ($appId) use ($appInfos) { |
|
637 | + return $appInfos[$appId]; |
|
638 | + } |
|
639 | + ); |
|
640 | + |
|
641 | + $this->appConfig->setValue('test1', 'enabled', 'yes'); |
|
642 | + $this->appConfig->setValue('test1', 'installed_version', '1.0.0'); |
|
643 | + $this->appConfig->setValue('test2', 'enabled', 'yes'); |
|
644 | + $this->appConfig->setValue('test2', 'installed_version', '1.0.0'); |
|
645 | + $this->appConfig->setValue('test3', 'enabled', 'yes'); |
|
646 | + $this->appConfig->setValue('test3', 'installed_version', '1.0.0'); |
|
647 | + $this->appConfig->setValue('test4', 'enabled', 'yes'); |
|
648 | + $this->appConfig->setValue('test4', 'installed_version', '2.4.0'); |
|
649 | + |
|
650 | + $apps = $manager->getAppsNeedingUpgrade('8.2.0'); |
|
651 | + |
|
652 | + $this->assertCount(2, $apps); |
|
653 | + $this->assertEquals('test1', $apps[0]['id']); |
|
654 | + $this->assertEquals('test4', $apps[1]['id']); |
|
655 | + } |
|
656 | + |
|
657 | + public function testGetIncompatibleApps(): void { |
|
658 | + /** @var AppManager|MockObject $manager */ |
|
659 | + $manager = $this->getMockBuilder(AppManager::class) |
|
660 | + ->setConstructorArgs([ |
|
661 | + $this->userSession, |
|
662 | + $this->config, |
|
663 | + $this->groupManager, |
|
664 | + $this->cacheFactory, |
|
665 | + $this->eventDispatcher, |
|
666 | + $this->logger, |
|
667 | + $this->serverVersion, |
|
668 | + ]) |
|
669 | + ->onlyMethods(['getAppInfo']) |
|
670 | + ->getMock(); |
|
671 | + |
|
672 | + $appInfos = [ |
|
673 | + 'cloud_federation_api' => ['id' => 'cloud_federation_api'], |
|
674 | + 'dav' => ['id' => 'dav'], |
|
675 | + 'files' => ['id' => 'files'], |
|
676 | + 'federatedfilesharing' => ['id' => 'federatedfilesharing'], |
|
677 | + 'profile' => ['id' => 'profile'], |
|
678 | + 'provisioning_api' => ['id' => 'provisioning_api'], |
|
679 | + 'lookup_server_connector' => ['id' => 'lookup_server_connector'], |
|
680 | + 'test1' => ['id' => 'test1', 'version' => '1.0.1', 'requiremax' => '8.0.0'], |
|
681 | + 'test2' => ['id' => 'test2', 'version' => '1.0.0', 'requiremin' => '8.2.0'], |
|
682 | + 'test3' => ['id' => 'test3', 'version' => '1.2.4', 'requiremin' => '9.0.0'], |
|
683 | + 'settings' => ['id' => 'settings'], |
|
684 | + 'testnoversion' => ['id' => 'testnoversion', 'requiremin' => '8.2.0'], |
|
685 | + 'theming' => ['id' => 'theming'], |
|
686 | + 'twofactor_backupcodes' => ['id' => 'twofactor_backupcodes'], |
|
687 | + 'workflowengine' => ['id' => 'workflowengine'], |
|
688 | + 'oauth2' => ['id' => 'oauth2'], |
|
689 | + 'viewer' => ['id' => 'viewer'], |
|
690 | + ]; |
|
691 | + |
|
692 | + $manager->expects($this->any()) |
|
693 | + ->method('getAppInfo') |
|
694 | + ->willReturnCallback( |
|
695 | + function ($appId) use ($appInfos) { |
|
696 | + return $appInfos[$appId]; |
|
697 | + } |
|
698 | + ); |
|
699 | + |
|
700 | + $this->appConfig->setValue('test1', 'enabled', 'yes'); |
|
701 | + $this->appConfig->setValue('test2', 'enabled', 'yes'); |
|
702 | + $this->appConfig->setValue('test3', 'enabled', 'yes'); |
|
703 | + |
|
704 | + $apps = $manager->getIncompatibleApps('8.2.0'); |
|
705 | + |
|
706 | + $this->assertCount(2, $apps); |
|
707 | + $this->assertEquals('test1', $apps[0]['id']); |
|
708 | + $this->assertEquals('test3', $apps[1]['id']); |
|
709 | + } |
|
710 | + |
|
711 | + public function testGetEnabledAppsForGroup(): void { |
|
712 | + $group = $this->createMock(IGroup::class); |
|
713 | + $group->expects($this->any()) |
|
714 | + ->method('getGID') |
|
715 | + ->willReturn('foo'); |
|
716 | + |
|
717 | + $this->appConfig->setValue('test1', 'enabled', 'yes'); |
|
718 | + $this->appConfig->setValue('test2', 'enabled', 'no'); |
|
719 | + $this->appConfig->setValue('test3', 'enabled', '["foo"]'); |
|
720 | + $this->appConfig->setValue('test4', 'enabled', '["asd"]'); |
|
721 | + $enabled = [ |
|
722 | + 'cloud_federation_api', |
|
723 | + 'dav', |
|
724 | + 'federatedfilesharing', |
|
725 | + 'files', |
|
726 | + 'lookup_server_connector', |
|
727 | + 'oauth2', |
|
728 | + 'profile', |
|
729 | + 'provisioning_api', |
|
730 | + 'settings', |
|
731 | + 'test1', |
|
732 | + 'test3', |
|
733 | + 'theming', |
|
734 | + 'twofactor_backupcodes', |
|
735 | + 'viewer', |
|
736 | + 'workflowengine', |
|
737 | + ]; |
|
738 | + $this->assertEquals($enabled, $this->manager->getEnabledAppsForGroup($group)); |
|
739 | + } |
|
740 | + |
|
741 | + public function testGetAppRestriction(): void { |
|
742 | + $this->appConfig->setValue('test1', 'enabled', 'yes'); |
|
743 | + $this->appConfig->setValue('test2', 'enabled', 'no'); |
|
744 | + $this->appConfig->setValue('test3', 'enabled', '["foo"]'); |
|
745 | + |
|
746 | + $this->assertEquals([], $this->manager->getAppRestriction('test1')); |
|
747 | + $this->assertEquals([], $this->manager->getAppRestriction('test2')); |
|
748 | + $this->assertEquals(['foo'], $this->manager->getAppRestriction('test3')); |
|
749 | + } |
|
750 | + |
|
751 | + public static function isBackendRequiredDataProvider(): array { |
|
752 | + return [ |
|
753 | + // backend available |
|
754 | + [ |
|
755 | + 'caldav', |
|
756 | + ['app1' => ['caldav']], |
|
757 | + true, |
|
758 | + ], |
|
759 | + [ |
|
760 | + 'caldav', |
|
761 | + ['app1' => [], 'app2' => ['foo'], 'app3' => ['caldav']], |
|
762 | + true, |
|
763 | + ], |
|
764 | + // backend not available |
|
765 | + [ |
|
766 | + 'caldav', |
|
767 | + ['app3' => [], 'app1' => ['foo'], 'app2' => ['bar', 'baz']], |
|
768 | + false, |
|
769 | + ], |
|
770 | + // no app available |
|
771 | + [ |
|
772 | + 'caldav', |
|
773 | + [], |
|
774 | + false, |
|
775 | + ], |
|
776 | + ]; |
|
777 | + } |
|
778 | + |
|
779 | + /** |
|
780 | + * @dataProvider isBackendRequiredDataProvider |
|
781 | + */ |
|
782 | + public function testIsBackendRequired( |
|
783 | + string $backend, |
|
784 | + array $appBackends, |
|
785 | + bool $expected, |
|
786 | + ): void { |
|
787 | + $appInfoData = array_map( |
|
788 | + static fn (array $backends) => ['dependencies' => ['backend' => $backends]], |
|
789 | + $appBackends, |
|
790 | + ); |
|
791 | + |
|
792 | + $reflection = new \ReflectionClass($this->manager); |
|
793 | + $property = $reflection->getProperty('appInfos'); |
|
794 | + $property->setValue($this->manager, $appInfoData); |
|
795 | + |
|
796 | + $this->assertEquals($expected, $this->manager->isBackendRequired($backend)); |
|
797 | + } |
|
798 | + |
|
799 | + public function testGetAppVersion() { |
|
800 | + $manager = $this->getMockBuilder(AppManager::class) |
|
801 | + ->setConstructorArgs([ |
|
802 | + $this->userSession, |
|
803 | + $this->config, |
|
804 | + $this->groupManager, |
|
805 | + $this->cacheFactory, |
|
806 | + $this->eventDispatcher, |
|
807 | + $this->logger, |
|
808 | + $this->serverVersion, |
|
809 | + ]) |
|
810 | + ->onlyMethods([ |
|
811 | + 'getAppInfo', |
|
812 | + ]) |
|
813 | + ->getMock(); |
|
814 | + |
|
815 | + $manager->expects(self::once()) |
|
816 | + ->method('getAppInfo') |
|
817 | + ->with('myapp') |
|
818 | + ->willReturn(['version' => '99.99.99-rc.99']); |
|
819 | + |
|
820 | + $this->serverVersion |
|
821 | + ->expects(self::never()) |
|
822 | + ->method('getVersionString'); |
|
823 | + |
|
824 | + $this->assertEquals( |
|
825 | + '99.99.99-rc.99', |
|
826 | + $manager->getAppVersion('myapp'), |
|
827 | + ); |
|
828 | + } |
|
829 | + |
|
830 | + public function testGetAppVersionCore() { |
|
831 | + $manager = $this->getMockBuilder(AppManager::class) |
|
832 | + ->setConstructorArgs([ |
|
833 | + $this->userSession, |
|
834 | + $this->config, |
|
835 | + $this->groupManager, |
|
836 | + $this->cacheFactory, |
|
837 | + $this->eventDispatcher, |
|
838 | + $this->logger, |
|
839 | + $this->serverVersion, |
|
840 | + ]) |
|
841 | + ->onlyMethods([ |
|
842 | + 'getAppInfo', |
|
843 | + ]) |
|
844 | + ->getMock(); |
|
845 | + |
|
846 | + $manager->expects(self::never()) |
|
847 | + ->method('getAppInfo'); |
|
848 | + |
|
849 | + $this->serverVersion |
|
850 | + ->expects(self::once()) |
|
851 | + ->method('getVersionString') |
|
852 | + ->willReturn('1.2.3-beta.4'); |
|
853 | + |
|
854 | + $this->assertEquals( |
|
855 | + '1.2.3-beta.4', |
|
856 | + $manager->getAppVersion('core'), |
|
857 | + ); |
|
858 | + } |
|
859 | + |
|
860 | + public function testGetAppVersionUnknown() { |
|
861 | + $manager = $this->getMockBuilder(AppManager::class) |
|
862 | + ->setConstructorArgs([ |
|
863 | + $this->userSession, |
|
864 | + $this->config, |
|
865 | + $this->groupManager, |
|
866 | + $this->cacheFactory, |
|
867 | + $this->eventDispatcher, |
|
868 | + $this->logger, |
|
869 | + $this->serverVersion, |
|
870 | + ]) |
|
871 | + ->onlyMethods([ |
|
872 | + 'getAppInfo', |
|
873 | + ]) |
|
874 | + ->getMock(); |
|
875 | + |
|
876 | + $manager->expects(self::once()) |
|
877 | + ->method('getAppInfo') |
|
878 | + ->with('unknown') |
|
879 | + ->willReturn(null); |
|
880 | + |
|
881 | + $this->serverVersion |
|
882 | + ->expects(self::never()) |
|
883 | + ->method('getVersionString'); |
|
884 | + |
|
885 | + $this->assertEquals( |
|
886 | + '0', |
|
887 | + $manager->getAppVersion('unknown'), |
|
888 | + ); |
|
889 | + } |
|
890 | 890 | |
891 | 891 | } |