19declare(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)
263 $encoder->expects($this->once())->method(
'getName')->willReturn(
'second_mockencoder');
264 $encoder->expects($this->once())->method(
'isPasswordValid')->with(
265 $this->equalTo(self::ENCODED_PASSWORD),
266 $this->equalTo(self::PASSWORD),
267 $this->isType(
'string')
269 $encoder->expects($this->never())->method(
'requiresReencoding')
270 ->with($this->equalTo(self::ENCODED_PASSWORD))
274 $factory_mock->expects($this->once())->method(
'getEncoderByName')->willReturn($encoder);
277 'password_encoder' =>
'mockencoder',
278 'encoder_factory' => $factory_mock,
282 $this->assertTrue($password_manager->verifyPassword($user_mock, self::PASSWORD));
291 $user_mock = $this->getMockBuilder(ilObjUser::class)->disableOriginalConstructor()->getMock();
292 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
293 $factory_mock = $this->getMockBuilder(LocalUserPasswordEncoderFactory::class)->disableOriginalConstructor()->getMock();
295 $user_mock->expects($this->once())->method(
'getPasswordSalt')->willReturn(
'asuperrandomsalt');
296 $user_mock->expects($this->once())->method(
'getPasswordEncodingType')->willReturn(
'mockencoder');
297 $user_mock->expects($this->exactly(2))->method(
'getPasswd')->willReturn(self::ENCODED_PASSWORD);
298 $user_mock->expects($this->once())->method(
'resetPassword')->with(
299 $this->equalTo(self::PASSWORD)
302 $encoder->expects($this->once())->method(
'getName')->willReturn(
'mockencoder');
303 $encoder->expects($this->once())->method(
'isPasswordValid')->with(
304 $this->equalTo(self::ENCODED_PASSWORD),
305 $this->equalTo(self::PASSWORD),
306 $this->isType(
'string')
308 $encoder->expects($this->once())->method(
'requiresReencoding')
309 ->with($this->equalTo(self::ENCODED_PASSWORD))
313 $factory_mock->expects($this->once())->method(
'getEncoderByName')->willReturn($encoder);
316 'password_encoder' =>
'mockencoder',
317 'encoder_factory' => $factory_mock,
321 $this->assertTrue($password_manager->verifyPassword($user_mock, self::PASSWORD));
330 $user_mock = $this->getMockBuilder(ilObjUser::class)->disableOriginalConstructor()->getMock();
331 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
332 $factory_mock = $this->getMockBuilder(LocalUserPasswordEncoderFactory::class)->disableOriginalConstructor()->getMock();
334 $user_mock->expects($this->once())->method(
'getPasswordSalt')->willReturn(
'asuperrandomsalt');
335 $user_mock->expects($this->once())->method(
'getPasswordEncodingType')->willReturn(
'second_mockencoder');
336 $user_mock->expects($this->once())->method(
'getPasswd')->willReturn(self::ENCODED_PASSWORD);
337 $user_mock->expects($this->never())->method(
'resetPassword');
339 $encoder->expects($this->once())->method(
'getName')->willReturn(
'second_mockencoder');
340 $encoder->expects($this->never())->method(
'requiresReencoding');
341 $encoder->expects($this->once())->method(
'isPasswordValid')
343 $this->equalTo(self::ENCODED_PASSWORD),
344 $this->equalTo(self::PASSWORD),
345 $this->isType(
'string')
349 $factory_mock->expects($this->once())->method(
'getEncoderByName')->willReturn($encoder);
352 'password_encoder' =>
'mockencoder',
353 'encoder_factory' => $factory_mock,
357 $this->assertFalse($password_manager->verifyPassword($user_mock, self::PASSWORD));
368 $this->assertInstanceOf(LocalUserPasswordEncoderFactory::class, $factory);
379 'default_password_encoder' =>
'md5',
382 $this->assertEquals(
'md5', $factory->getDefaultEncoder());
384 $encoder = $this->createMock(ilPasswordEncoder::class);
385 $encoder->expects($this->atLeastOnce())->method(
'getName')->willReturn(
'mockencoder');
386 $encoder->expects($this->atLeastOnce())->method(
'isSupportedByRuntime')->willReturn(
true);
388 $second_mockencoder = $this->createMock(ilPasswordEncoder::class);
389 $second_mockencoder->expects($this->atLeastOnce())->method(
'getName')->willReturn(
'second_mockencoder');
390 $second_mockencoder->expects($this->atLeastOnce())->method(
'isSupportedByRuntime')->willReturn(
true);
392 $factory->setSupportedEncoders([$encoder, $second_mockencoder]);
393 $this->assertCount(2, $factory->getSupportedEncoders());
394 $this->assertCount(2, $factory->getSupportedEncoderNames());
397 array_diff([
'mockencoder',
'second_mockencoder'], $factory->getSupportedEncoderNames())
401 array_diff($factory->getSupportedEncoderNames(), [
'mockencoder',
'second_mockencoder'])
411 $this->expectException(ilUserException::class);
415 $factory->setSupportedEncoders([
'phpunit']);
424 $this->expectException(ilUserException::class);
428 $factory->getEncoderByName(
'phpunit');
437 $this->expectException(ilUserException::class);
439 'default_password_encoder' =>
'phpunit',
442 $factory->getEncoderByName(
'phpunit');
452 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
453 $encoder->expects($this->atLeastOnce())->method(
'getName')->willReturn(
'mockencoder');
454 $encoder->expects($this->atLeastOnce())->method(
'isSupportedByRuntime')->willReturn(
true);
457 'default_password_encoder' => $encoder->getName(),
458 'data_directory' => $this->getTestDirectoryUrl()
460 $factory->setSupportedEncoders([$encoder]);
461 $this->assertEquals($encoder, $factory->getEncoderByName(
'phpunit'));
471 $encoder = $this->getMockBuilder(ilBasePasswordEncoder::class)->disableOriginalConstructor()->getMock();
472 $encoder->expects($this->atLeastOnce())->method(
'getName')->willReturn(
'mockencoder');
473 $encoder->expects($this->atLeastOnce())->method(
'isSupportedByRuntime')->willReturn(
true);
476 'default_password_encoder' => $encoder->getName(),
477 'data_directory' => $this->getTestDirectoryUrl()
479 $factory->setSupportedEncoders([$encoder]);
480 $this->assertEquals($encoder, $factory->getEncoderByName(
'mockencoder'));
testPasswordManagerMigratesPasswordOnVerificationWithVariantEncoders()
setTestDirectoryUrl(string $testDirectoryUrl)
testGettersOfFactoryShouldReturnWhatWasSetBySetters()
testFactoryRaisesAnExceptionIfAnUnsupportedEncoderIsRequestedAndTheDefaultEncoderDoesNotMatchOneOfTheSupportedEncodersInFallbackMode()
testExceptionIsRaisedIfPasswordManagerIsCreatedWithoutValidFactory()
testFactoryCanBeCreated()
vfs vfsStreamDirectory $testDirectory
testPasswordManagerNeverMigratesPasswordOnFailedVerificationWithVariantEncoders()
testFactoryReturnsTheDefaultEncoderIfAnUnsupportedEncoderIsRequestedAndASupportedDefaultEncoderWasSpecifiedInFallbackMode()
testFactoryRaisesAnExceptionIfAnUnsupportedEncoderWasInjected()
testExceptionIsRaisedIfPasswordManagerIsCreatedWithoutFactory()
testPasswordManagerVerifiesPassword()
testExceptionIsRaisedIfPasswordManagerIsCreatedWithoutEncoderInformation()
setTestDirectory(vfs\vfsStreamDirectory $testDirectory)
testPasswordManagerEncodesRawPasswordWithoutSalt()
testPasswordManagerEncodesRawPasswordWithSalt()
testPasswordManagerReencodesPasswordIfReencodingIsNecessary()
testInstanceCanBeCreated()
testFactoryRaisesAnExceptionIfAnUnsupportedEncoderIsRequestedAndNoDefaultEncoderWasSpecifiedInFallbackMode()
testFactoryReturnsCorrectEncoderIfAMatchingEncoderWasFound()