19 declare(strict_types=1);
53 protected function setUp(): void
55 vfs\vfsStream::setup();
56 $this->
setTestDirectory(vfs\vfsStream::newDirectory(
'tests')->at(vfs\vfsStreamWrapper::getRoot()));
67 $this->expectException(ilUserException::class);
76 $this->expectException(ilUserException::class);
78 'password_encoder' =>
'md5',
88 $this->expectException(TypeError::class);
89 $this->expectExceptionMessageMatches(
'/' . preg_quote(LocalUserPasswordManager::class,
'/') .
'/');
92 'password_encoder' =>
'md5',
93 'encoder_factory' =>
'test',
105 $factory_mock = $this->getMockBuilder(LocalUserPasswordEncoderFactory::class)->disableOriginalConstructor()->getMock();
107 ->expects($this->exactly(2))
108 ->method(
'getSupportedEncoderNames')
109 ->willReturnCallback(
function () use (&$call_count) {
111 if ($call_count === 1) {
123 'password_encoder' =>
'md5',
124 'encoder_factory' => $factory_mock,
127 $this->assertInstanceOf(LocalUserPasswordManager::class, $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(LocalUserPasswordEncoderFactory::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)
162 $factory_mock->expects($this->once())->method(
'getEncoderByName')->willReturn($encoder);
165 'password_encoder' =>
'mockencoder',
166 'encoder_factory' => $factory_mock,
170 $password_manager->encodePassword($user_mock, self::PASSWORD);
179 $user_mock = $this->getMockBuilder(ilObjUser::class)->disableOriginalConstructor()->getMock();
180 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
181 $factory_mock = $this->getMockBuilder(LocalUserPasswordEncoderFactory::class)->disableOriginalConstructor()->getMock();
183 $user_mock->expects($this->once())->method(
'setPasswordSalt')->with($this->equalTo(
null));
184 $user_mock->expects($this->once())->method(
'getPasswordSalt')->willReturn(
null);
185 $user_mock->expects($this->once())->method(
'setPasswordEncodingType')->with($this->equalTo(
'mockencoder'));
186 $user_mock->expects($this->once())->method(
'setPasswd')->with(
187 $this->equalTo(self::ENCODED_PASSWORD),
191 $encoder->expects($this->once())->method(
'getName')->willReturn(
'mockencoder');
192 $encoder->expects($this->once())->method(
'requiresSalt')->willReturn(
false);
193 $encoder->expects($this->once())->method(
'encodePassword')->with(
194 $this->equalTo(self::PASSWORD),
196 )->willReturn(self::ENCODED_PASSWORD);
198 $factory_mock->expects($this->once())->method(
'getEncoderByName')->willReturn($encoder);
201 'password_encoder' =>
'mockencoder',
202 'encoder_factory' => $factory_mock,
206 $password_manager->encodePassword($user_mock, self::PASSWORD);
215 $user_mock = $this->getMockBuilder(ilObjUser::class)->disableOriginalConstructor()->getMock();
216 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
217 $factory_mock = $this->getMockBuilder(LocalUserPasswordEncoderFactory::class)->disableOriginalConstructor()->getMock();
219 $user_mock->expects($this->atLeast(1))->method(
'getPasswordSalt')->willReturn(
'asuperrandomsalt');
220 $user_mock->expects($this->atLeast(1))->method(
'getPasswordEncodingType')->willReturn(
'mockencoder');
221 $user_mock->expects($this->atLeast(1))->method(
'getPasswd')->willReturn(self::ENCODED_PASSWORD);
222 $user_mock->expects($this->never())->method(
'resetPassword');
224 $encoder->expects($this->once())->method(
'getName')->willReturn(
'mockencoder');
225 $encoder->expects($this->once())->method(
'isPasswordValid')->with(
226 $this->equalTo(self::ENCODED_PASSWORD),
227 $this->equalTo(self::PASSWORD),
228 $this->isType(
'string')
230 $encoder->expects($this->once())->method(
'requiresReencoding')
231 ->with($this->equalTo(self::ENCODED_PASSWORD))
235 $factory_mock->expects($this->once())->method(
'getEncoderByName')->willReturn($encoder);
238 'password_encoder' =>
'mockencoder',
239 'encoder_factory' => $factory_mock,
243 $this->assertTrue($password_manager->verifyPassword($user_mock, self::PASSWORD));
252 $user_mock = $this->getMockBuilder(ilObjUser::class)->disableOriginalConstructor()->getMock();
253 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
254 $factory_mock = $this->getMockBuilder(LocalUserPasswordEncoderFactory::class)->disableOriginalConstructor()->getMock();
256 $user_mock->expects($this->once())->method(
'getPasswordSalt')->willReturn(
'asuperrandomsalt');
257 $user_mock->expects($this->once())->method(
'getPasswordEncodingType')->willReturn(
'second_mockencoder');
258 $user_mock->expects($this->once())->method(
'getPasswd')->willReturn(self::ENCODED_PASSWORD);
259 $user_mock->expects($this->once())->method(
'resetPassword')->with(
260 $this->equalTo(self::PASSWORD),
261 $this->equalTo(self::PASSWORD)
264 $encoder->expects($this->once())->method(
'getName')->willReturn(
'second_mockencoder');
265 $encoder->expects($this->once())->method(
'isPasswordValid')->with(
266 $this->equalTo(self::ENCODED_PASSWORD),
267 $this->equalTo(self::PASSWORD),
268 $this->isType(
'string')
270 $encoder->expects($this->never())->method(
'requiresReencoding')
271 ->with($this->equalTo(self::ENCODED_PASSWORD))
275 $factory_mock->expects($this->once())->method(
'getEncoderByName')->willReturn($encoder);
278 'password_encoder' =>
'mockencoder',
279 'encoder_factory' => $factory_mock,
283 $this->assertTrue($password_manager->verifyPassword($user_mock, self::PASSWORD));
292 $user_mock = $this->getMockBuilder(ilObjUser::class)->disableOriginalConstructor()->getMock();
293 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
294 $factory_mock = $this->getMockBuilder(LocalUserPasswordEncoderFactory::class)->disableOriginalConstructor()->getMock();
296 $user_mock->expects($this->once())->method(
'getPasswordSalt')->willReturn(
'asuperrandomsalt');
297 $user_mock->expects($this->once())->method(
'getPasswordEncodingType')->willReturn(
'mockencoder');
298 $user_mock->expects($this->exactly(2))->method(
'getPasswd')->willReturn(self::ENCODED_PASSWORD);
299 $user_mock->expects($this->once())->method(
'resetPassword')->with(
300 $this->equalTo(self::PASSWORD),
301 $this->equalTo(self::PASSWORD)
304 $encoder->expects($this->once())->method(
'getName')->willReturn(
'mockencoder');
305 $encoder->expects($this->once())->method(
'isPasswordValid')->with(
306 $this->equalTo(self::ENCODED_PASSWORD),
307 $this->equalTo(self::PASSWORD),
308 $this->isType(
'string')
310 $encoder->expects($this->once())->method(
'requiresReencoding')
311 ->with($this->equalTo(self::ENCODED_PASSWORD))
315 $factory_mock->expects($this->once())->method(
'getEncoderByName')->willReturn($encoder);
318 'password_encoder' =>
'mockencoder',
319 'encoder_factory' => $factory_mock,
323 $this->assertTrue($password_manager->verifyPassword($user_mock, self::PASSWORD));
332 $user_mock = $this->getMockBuilder(ilObjUser::class)->disableOriginalConstructor()->getMock();
333 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
334 $factory_mock = $this->getMockBuilder(LocalUserPasswordEncoderFactory::class)->disableOriginalConstructor()->getMock();
336 $user_mock->expects($this->once())->method(
'getPasswordSalt')->willReturn(
'asuperrandomsalt');
337 $user_mock->expects($this->once())->method(
'getPasswordEncodingType')->willReturn(
'second_mockencoder');
338 $user_mock->expects($this->once())->method(
'getPasswd')->willReturn(self::ENCODED_PASSWORD);
339 $user_mock->expects($this->never())->method(
'resetPassword');
341 $encoder->expects($this->once())->method(
'getName')->willReturn(
'second_mockencoder');
342 $encoder->expects($this->never())->method(
'requiresReencoding');
343 $encoder->expects($this->once())->method(
'isPasswordValid')
345 $this->equalTo(self::ENCODED_PASSWORD),
346 $this->equalTo(self::PASSWORD),
347 $this->isType(
'string')
351 $factory_mock->expects($this->once())->method(
'getEncoderByName')->willReturn($encoder);
354 'password_encoder' =>
'mockencoder',
355 'encoder_factory' => $factory_mock,
359 $this->assertFalse($password_manager->verifyPassword($user_mock, self::PASSWORD));
370 $this->assertInstanceOf(LocalUserPasswordEncoderFactory::class, $factory);
381 'default_password_encoder' =>
'md5',
384 $this->assertEquals(
'md5', $factory->getDefaultEncoder());
386 $encoder = $this->createMock(ilPasswordEncoder::class);
387 $encoder->expects($this->atLeastOnce())->method(
'getName')->willReturn(
'mockencoder');
388 $encoder->expects($this->atLeastOnce())->method(
'isSupportedByRuntime')->willReturn(
true);
390 $second_mockencoder = $this->createMock(ilPasswordEncoder::class);
391 $second_mockencoder->expects($this->atLeastOnce())->method(
'getName')->willReturn(
'second_mockencoder');
392 $second_mockencoder->expects($this->atLeastOnce())->method(
'isSupportedByRuntime')->willReturn(
true);
394 $factory->setSupportedEncoders([$encoder, $second_mockencoder]);
395 $this->assertCount(2, $factory->getSupportedEncoders());
396 $this->assertCount(2, $factory->getSupportedEncoderNames());
399 array_diff([
'mockencoder',
'second_mockencoder'], $factory->getSupportedEncoderNames())
403 array_diff($factory->getSupportedEncoderNames(), [
'mockencoder',
'second_mockencoder'])
413 $this->expectException(ilUserException::class);
417 $factory->setSupportedEncoders([
'phpunit']);
426 $this->expectException(ilUserException::class);
430 $factory->getEncoderByName(
'phpunit');
439 $this->expectException(ilUserException::class);
441 'default_password_encoder' =>
'phpunit',
444 $factory->getEncoderByName(
'phpunit');
454 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
455 $encoder->expects($this->atLeastOnce())->method(
'getName')->willReturn(
'mockencoder');
456 $encoder->expects($this->atLeastOnce())->method(
'isSupportedByRuntime')->willReturn(
true);
459 'default_password_encoder' => $encoder->getName(),
463 $this->assertEquals($encoder, $factory->getEncoderByName(
'phpunit'));
473 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
474 $encoder->expects($this->atLeastOnce())->method(
'getName')->willReturn(
'mockencoder');
475 $encoder->expects($this->atLeastOnce())->method(
'isSupportedByRuntime')->willReturn(
true);
478 'default_password_encoder' => $encoder->getName(),
482 $this->assertEquals($encoder, $factory->getEncoderByName(
'mockencoder'));
testFactoryCanBeCreated()
testExceptionIsRaisedIfPasswordManagerIsCreatedWithoutFactory()
testPasswordManagerEncodesRawPasswordWithSalt()
testGettersOfFactoryShouldReturnWhatWasSetBySetters()
testPasswordManagerMigratesPasswordOnVerificationWithVariantEncoders()
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
vfs vfsStreamDirectory $testDirectory
testFactoryReturnsTheDefaultEncoderIfAnUnsupportedEncoderIsRequestedAndASupportedDefaultEncoderWasSpecifiedInFallbackMode()
testInstanceCanBeCreated()
setTestDirectory(vfs\vfsStreamDirectory $testDirectory)
testFactoryRaisesAnExceptionIfAnUnsupportedEncoderIsRequestedAndNoDefaultEncoderWasSpecifiedInFallbackMode()
testPasswordManagerVerifiesPassword()
setTestDirectoryUrl(string $testDirectoryUrl)
testExceptionIsRaisedIfPasswordManagerIsCreatedWithoutValidFactory()
testPasswordManagerNeverMigratesPasswordOnFailedVerificationWithVariantEncoders()
testExceptionIsRaisedIfPasswordManagerIsCreatedWithoutEncoderInformation()
testFactoryReturnsCorrectEncoderIfAMatchingEncoderWasFound()
testFactoryRaisesAnExceptionIfAnUnsupportedEncoderWasInjected()
testPasswordManagerEncodesRawPasswordWithoutSalt()
testPasswordManagerReencodesPasswordIfReencodingIsNecessary()
testFactoryRaisesAnExceptionIfAnUnsupportedEncoderIsRequestedAndTheDefaultEncoderDoesNotMatchOneOfTheSupportedEncodersInFallbackMode()
setSupportedEncoders(array $supported_encoders)