19 declare(strict_types=1);
23 require_once
'libs/composer/vendor/autoload.php';
24 require_once
'Services/User/classes/class.ilUserPasswordManager.php';
25 require_once
'Services/User/classes/class.ilUserPasswordEncoderFactory.php';
26 require_once
'Services/Password/classes/class.ilBasePasswordEncoder.php';
27 require_once
'Services/Utilities/classes/class.ilUtil.php';
28 require_once
'Services/User/classes/class.ilObjUser.php';
29 require_once
'Services/User/exceptions/class.ilUserException.php';
30 require_once
'Services/User/test/ilUserBaseTest.php';
60 protected function setUp(): void
62 vfs\vfsStream::setup();
63 $this->
setTestDirectory(vfs\vfsStream::newDirectory(
'tests')->at(vfs\vfsStreamWrapper::getRoot()));
85 'password_encoder' =>
'md5',
95 $this->expectException(TypeError::class);
96 $this->expectExceptionMessageMatches(
'/' . ilUserPasswordEncoderFactory::class .
'/');
99 'password_encoder' =>
'md5',
100 'encoder_factory' =>
'test',
111 $factory_mock = $this->getMockBuilder(ilUserPasswordEncoderFactory::class)->disableOriginalConstructor()->getMock();
112 $factory_mock->expects($this->exactly(2))->method(
'getSupportedEncoderNames')->will($this->onConsecutiveCalls(
123 'password_encoder' =>
'md5',
124 'encoder_factory' => $factory_mock,
127 $this->assertInstanceOf(
'ilUserPasswordManager', $password_manager);
128 $this->assertEquals(
'md5', $password_manager->getEncoderName());
129 $this->assertEquals($factory_mock, $password_manager->getEncoderFactory());
131 $this->assertTrue($password_manager->isEncodingTypeSupported(
'second_mockencoder'));
132 $this->assertFalse($password_manager->isEncodingTypeSupported(
'second_mockencoder'));
141 $user_mock = $this->getMockBuilder(ilObjUser::class)->disableOriginalConstructor()->getMock();
142 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
143 $factory_mock = $this->getMockBuilder(ilUserPasswordEncoderFactory::class)->disableOriginalConstructor()->getMock();
145 $user_mock->expects($this->once())->method(
'setPasswordSalt')->with($this->isType(
'string'));
146 $user_mock->expects($this->once())->method(
'getPasswordSalt')->willReturn(
'asuperrandomsalt');
147 $user_mock->expects($this->once())->method(
'setPasswordEncodingType')->with($this->equalTo(
'mockencoder'));
148 $user_mock->expects($this->once())->method(
'setPasswd')->with(
149 $this->equalTo(self::ENCODED_PASSWORD),
153 $encoder->expects($this->once())->method(
'getName')->willReturn(
'mockencoder');
154 $encoder->expects($this->once())->method(
'requiresSalt')->willReturn(
true);
155 $encoder->expects($this->once())->method(
'encodePassword')
157 $this->equalTo(self::PASSWORD),
158 $this->isType(
'string')
159 )->willReturn(self::ENCODED_PASSWORD);
161 $factory_mock->expects($this->once())->method(
'getEncoderByName')->willReturn($encoder);
164 'password_encoder' =>
'mockencoder',
165 'encoder_factory' => $factory_mock,
169 $password_manager->encodePassword($user_mock, self::PASSWORD);
178 $user_mock = $this->getMockBuilder(ilObjUser::class)->disableOriginalConstructor()->getMock();
179 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
180 $factory_mock = $this->getMockBuilder(ilUserPasswordEncoderFactory::class)->disableOriginalConstructor()->getMock();
182 $user_mock->expects($this->once())->method(
'setPasswordSalt')->with($this->equalTo(null));
183 $user_mock->expects($this->once())->method(
'getPasswordSalt')->willReturn(null);
184 $user_mock->expects($this->once())->method(
'setPasswordEncodingType')->with($this->equalTo(
'mockencoder'));
185 $user_mock->expects($this->once())->method(
'setPasswd')->with(
186 $this->equalTo(self::ENCODED_PASSWORD),
190 $encoder->expects($this->once())->method(
'getName')->willReturn(
'mockencoder');
191 $encoder->expects($this->once())->method(
'requiresSalt')->willReturn(
false);
192 $encoder->expects($this->once())->method(
'encodePassword')->with(
193 $this->equalTo(self::PASSWORD),
195 )->willReturn(self::ENCODED_PASSWORD);
197 $factory_mock->expects($this->once())->method(
'getEncoderByName')->willReturn($encoder);
200 'password_encoder' =>
'mockencoder',
201 'encoder_factory' => $factory_mock,
205 $password_manager->encodePassword($user_mock, self::PASSWORD);
214 $user_mock = $this->getMockBuilder(ilObjUser::class)->disableOriginalConstructor()->getMock();
215 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
216 $factory_mock = $this->getMockBuilder(ilUserPasswordEncoderFactory::class)->disableOriginalConstructor()->getMock();
218 $user_mock->expects($this->atLeast(1))->method(
'getPasswordSalt')->willReturn(
'asuperrandomsalt');
219 $user_mock->expects($this->atLeast(1))->method(
'getPasswordEncodingType')->willReturn(
'mockencoder');
220 $user_mock->expects($this->atLeast(1))->method(
'getPasswd')->willReturn(self::ENCODED_PASSWORD);
221 $user_mock->expects($this->never())->method(
'resetPassword');
223 $encoder->expects($this->once())->method(
'getName')->willReturn(
'mockencoder');
224 $encoder->expects($this->once())->method(
'isPasswordValid')->with(
225 $this->equalTo(self::ENCODED_PASSWORD),
226 $this->equalTo(self::PASSWORD),
227 $this->isType(
'string')
229 $encoder->expects($this->once())->method(
'requiresReencoding')
230 ->with($this->equalTo(self::ENCODED_PASSWORD))
233 $factory_mock->expects($this->once())->method(
'getEncoderByName')->willReturn($encoder);
236 'password_encoder' =>
'mockencoder',
237 'encoder_factory' => $factory_mock,
241 $this->assertTrue($password_manager->verifyPassword($user_mock, self::PASSWORD));
250 $user_mock = $this->getMockBuilder(ilObjUser::class)->disableOriginalConstructor()->getMock();
251 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
252 $factory_mock = $this->getMockBuilder(ilUserPasswordEncoderFactory::class)->disableOriginalConstructor()->getMock();
254 $user_mock->expects($this->once())->method(
'getPasswordSalt')->willReturn(
'asuperrandomsalt');
255 $user_mock->expects($this->once())->method(
'getPasswordEncodingType')->willReturn(
'second_mockencoder');
256 $user_mock->expects($this->once())->method(
'getPasswd')->willReturn(self::ENCODED_PASSWORD);
257 $user_mock->expects($this->once())->method(
'resetPassword')->with(
258 $this->equalTo(self::PASSWORD),
259 $this->equalTo(self::PASSWORD)
262 $encoder->expects($this->once())->method(
'getName')->willReturn(
'second_mockencoder');
263 $encoder->expects($this->once())->method(
'isPasswordValid')->with(
264 $this->equalTo(self::ENCODED_PASSWORD),
265 $this->equalTo(self::PASSWORD),
266 $this->isType(
'string')
268 $encoder->expects($this->never())->method(
'requiresReencoding')
269 ->with($this->equalTo(self::ENCODED_PASSWORD))
272 $factory_mock->expects($this->once())->method(
'getEncoderByName')->willReturn($encoder);
275 'password_encoder' =>
'mockencoder',
276 'encoder_factory' => $factory_mock,
280 $this->assertTrue($password_manager->verifyPassword($user_mock, self::PASSWORD));
289 $user_mock = $this->getMockBuilder(ilObjUser::class)->disableOriginalConstructor()->getMock();
290 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
291 $factory_mock = $this->getMockBuilder(ilUserPasswordEncoderFactory::class)->disableOriginalConstructor()->getMock();
293 $user_mock->expects($this->once())->method(
'getPasswordSalt')->willReturn(
'asuperrandomsalt');
294 $user_mock->expects($this->once())->method(
'getPasswordEncodingType')->willReturn(
'mockencoder');
295 $user_mock->expects($this->exactly(2))->method(
'getPasswd')->willReturn(self::ENCODED_PASSWORD);
296 $user_mock->expects($this->once())->method(
'resetPassword')->with(
297 $this->equalTo(self::PASSWORD),
298 $this->equalTo(self::PASSWORD)
301 $encoder->expects($this->once())->method(
'getName')->willReturn(
'mockencoder');
302 $encoder->expects($this->once())->method(
'isPasswordValid')->with(
303 $this->equalTo(self::ENCODED_PASSWORD),
304 $this->equalTo(self::PASSWORD),
305 $this->isType(
'string')
307 $encoder->expects($this->once())->method(
'requiresReencoding')
308 ->with($this->equalTo(self::ENCODED_PASSWORD))
311 $factory_mock->expects($this->once())->method(
'getEncoderByName')->willReturn($encoder);
314 'password_encoder' =>
'mockencoder',
315 'encoder_factory' => $factory_mock,
319 $this->assertTrue($password_manager->verifyPassword($user_mock, self::PASSWORD));
328 $user_mock = $this->getMockBuilder(ilObjUser::class)->disableOriginalConstructor()->getMock();
329 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
330 $factory_mock = $this->getMockBuilder(ilUserPasswordEncoderFactory::class)->disableOriginalConstructor()->getMock();
332 $user_mock->expects($this->once())->method(
'getPasswordSalt')->willReturn(
'asuperrandomsalt');
333 $user_mock->expects($this->once())->method(
'getPasswordEncodingType')->willReturn(
'second_mockencoder');
334 $user_mock->expects($this->once())->method(
'getPasswd')->willReturn(self::ENCODED_PASSWORD);
335 $user_mock->expects($this->never())->method(
'resetPassword');
337 $encoder->expects($this->once())->method(
'getName')->willReturn(
'second_mockencoder');
338 $encoder->expects($this->never())->method(
'requiresReencoding');
339 $encoder->expects($this->once())->method(
'isPasswordValid')
341 $this->equalTo(self::ENCODED_PASSWORD),
342 $this->equalTo(self::PASSWORD),
343 $this->isType(
'string')
344 )->willReturn(
false);
346 $factory_mock->expects($this->once())->method(
'getEncoderByName')->willReturn($encoder);
349 'password_encoder' =>
'mockencoder',
350 'encoder_factory' => $factory_mock,
354 $this->assertFalse($password_manager->verifyPassword($user_mock, self::PASSWORD));
365 $this->assertInstanceOf(ilUserPasswordEncoderFactory::class, $factory);
376 'default_password_encoder' =>
'md5',
379 $this->assertEquals(
'md5', $factory->getDefaultEncoder());
381 $encoder = $this->createMock(ilPasswordEncoder::class);
382 $encoder->expects($this->atLeastOnce())->method(
'getName')->willReturn(
'mockencoder');
383 $encoder->expects($this->atLeastOnce())->method(
'isSupportedByRuntime')->willReturn(
true);
385 $second_mockencoder = $this->createMock(ilPasswordEncoder::class);
386 $second_mockencoder->expects($this->atLeastOnce())->method(
'getName')->willReturn(
'second_mockencoder');
387 $second_mockencoder->expects($this->atLeastOnce())->method(
'isSupportedByRuntime')->willReturn(
true);
389 $factory->setSupportedEncoders([$encoder, $second_mockencoder]);
390 $this->assertCount(2, $factory->getSupportedEncoders());
391 $this->assertCount(2, $factory->getSupportedEncoderNames());
394 array_diff([
'mockencoder',
'second_mockencoder'], $factory->getSupportedEncoderNames())
398 array_diff($factory->getSupportedEncoderNames(), [
'mockencoder',
'second_mockencoder'])
412 $factory->setSupportedEncoders([
'phpunit']);
425 $factory->getEncoderByName(
'phpunit');
436 'default_password_encoder' =>
'phpunit',
439 $factory->getEncoderByName(
'phpunit');
449 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
450 $encoder->expects($this->atLeastOnce())->method(
'getName')->willReturn(
'mockencoder');
451 $encoder->expects($this->atLeastOnce())->method(
'isSupportedByRuntime')->willReturn(
true);
454 'default_password_encoder' => $encoder->getName(),
458 $this->assertEquals($encoder, $factory->getEncoderByName(
'phpunit'));
468 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
469 $encoder->expects($this->atLeastOnce())->method(
'getName')->willReturn(
'mockencoder');
470 $encoder->expects($this->atLeastOnce())->method(
'isSupportedByRuntime')->willReturn(
true);
473 'default_password_encoder' => $encoder->getName(),
477 $this->assertEquals($encoder, $factory->getEncoderByName(
'mockencoder'));
testPasswordManagerEncodesRawPasswordWithoutSalt()
testPasswordManagerNeverMigratesPasswordOnFailedVerificationWithVariantEncoders()
testExceptionIsRaisedIfPasswordManagerIsCreatedWithoutValidFactory()
testFactoryReturnsTheDefaultEncoderIfAnUnsupportedEncoderIsRequestedAndASupportedDefaultEncoderWasSpecifiedInFallbackMode()
testFactoryRaisesAnExceptionIfAnUnsupportedEncoderWasInjected()
setSupportedEncoders(array $supported_encoders)
setTestDirectoryUrl(string $testDirectoryUrl)
testPasswordManagerVerifiesPassword()
testExceptionIsRaisedIfPasswordManagerIsCreatedWithoutEncoderInformation()
assertException(string $exception_class)
vfs vfsStreamDirectory $testDirectory
setTestDirectory(vfs\vfsStreamDirectory $testDirectory)
testInstanceCanBeCreated()
testPasswordManagerEncodesRawPasswordWithSalt()
testFactoryReturnsCorrectEncoderIfAMatchingEncoderWasFound()
testFactoryCanBeCreated()
testFactoryRaisesAnExceptionIfAnUnsupportedEncoderIsRequestedAndNoDefaultEncoderWasSpecifiedInFallbackMode()
testFactoryRaisesAnExceptionIfAnUnsupportedEncoderIsRequestedAndTheDefaultEncoderDoesNotMatchOneOfTheSupportedEncodersInFallbackMode()
testPasswordManagerMigratesPasswordOnVerificationWithVariantEncoders()
testExceptionIsRaisedIfPasswordManagerIsCreatedWithoutFactory()
testPasswordManagerReencodesPasswordIfReencodingIsNecessary()
testGettersOfFactoryShouldReturnWhatWasSetBySetters()