<commit_before><?php
namespace Neos\Flow\Tests\Unit\Security\Authentication\Provider;

/*
 * This file is part of the Neos.Flow package.
 *
 * (c) Contributors of the Neos Project - www.neos.io
 *
 * This package is Open Source Software. For the full copyright and license
 * information, please view the LICENSE file which was distributed with this
 * source code.
 */

use Neos\Flow\Persistence\PersistenceManagerInterface;
use Neos\Flow\Security;
use Neos\Flow\Security\Authentication\Provider\PersistedUsernamePasswordProvider;
use Neos\Flow\Tests\UnitTestCase;

/**
 * Testcase for username/password authentication provider. The account are stored in the CR.
 */
class PersistedUsernamePasswordProviderTest extends UnitTestCase
{
    /**
     * @var Security\Cryptography\HashService
     */
    protected $mockHashService;

    /**
     * @var Security\Account
     */
    protected $mockAccount;

    /**
     * @var Security\AccountRepository
     */
    protected $mockAccountRepository;

    /**
     * @var PersistenceManagerInterface
     */
    protected $mockPersistenceManager;

    /**
     * @var Security\Authentication\Token\UsernamePassword
     */
    protected $mockToken;

    /**
     * @var Security\Context
     */
    protected $mockSecurityContext;

    /**
     * @var Security\Authentication\Provider\PersistedUsernamePasswordProvider
     */
    protected $persistedUsernamePasswordProvider;


    protected function setUp(): void
    {
        $this->mockHashService = $this->createMock(Security\Cryptography\HashService::class);
        $this->mockAccount = $this->getMockBuilder(Security\Account::class)->disableOriginalConstructor()->getMock();
        $this->mockAccountRepository = $this->getMockBuilder(Security\AccountRepository::class)->disableOriginalConstructor()->getMock();
        $this->mockPersistenceManager = $this->createMock(PersistenceManagerInterface::class);
        $this->mockToken = $this->getMockBuilder(Security\Authentication\Token\UsernamePassword::class)->disableOriginalConstructor()->getMock();

        $this->mockSecurityContext = $this->createMock(Security\Context::class);
        $this->mockSecurityContext->expects(self::any())->method('withoutAuthorizationChecks')->will(self::returnCallBack(function ($callback) {
            return $callback->__invoke();
        }));

        $this->persistedUsernamePasswordProvider = $this->getAccessibleMock(Security\Authentication\Provider\PersistedUsernamePasswordProvider::class, ['dummy'], [], '', false);
        $this->persistedUsernamePasswordProvider->_set('name', 'myProvider');
        $this->persistedUsernamePasswordProvider->_set('options', []);
        $this->persistedUsernamePasswordProvider->_set('hashService', $this->mockHashService);
        $this->persistedUsernamePasswordProvider->_set('accountRepository', $this->mockAccountRepository);
        $this->persistedUsernamePasswordProvider->_set('persistenceManager', $this->mockPersistenceManager);
        $this->persistedUsernamePasswordProvider->_set('securityContext', $this->mockSecurityContext);
    }

    /**
     * @test
     */
    public function authenticatingAnUsernamePasswordTokenChecksIfTheGivenClearTextPasswordMatchesThePersistedHashedPassword()
    {
        $this->mockHashService->expects(self::once())->method('validatePassword')->with('password', '<PASSWORD>,<PASSWORD>')->will(self::returnValue(true));

        $this->mockAccount->expects(self::once())->method('getCredentialsSource')->will(self::returnValue('<PASSWORD>,8<PASSWORD>'));

        $this->mockAccountRepository->expects(self::once())->method('findActiveByAccountIdentifierAndAuthenticationProviderName')->with('admin', 'myProvider')->will(self::returnValue($this->mockAccount));

        $this->mockToken->expects(self::atLeastOnce())->method('getUsername')->will(self::returnValue('admin'));
        $this->mockToken->expects(self::atLeastOnce())->method('getPassword')->will(self::returnValue('password'));

        $lastAuthenticationStatus = null;
        $this->mockToken->method('setAuthenticationStatus')->willReturnCallback(static function ($status) use (&$lastAuthenticationStatus) {
            $lastAuthenticationStatus = $status;
        });

        $this->mockToken->expects(self::once())->method('setAccount')->with($this->mockAccount);

        $this->persistedUsernamePasswordProvider->authenticate($this->mockToken);
        self::assertSame(\Neos\Flow\Security\Authentication\TokenInterface::AUTHENTICATION_SUCCESSFUL, $lastAuthenticationStatus);
    }

    /**
     * @test
     */
    public function authenticatingAnUsernamePasswordTokenRespectsTheConfiguredLookupProviderName()
    {
        $this->mockHashService->expects(self::once())->method('validatePassword')->with('password', '<PASSWORD>,<PASSWORD>')->will(self::returnValue(true));

        $this->mockAccount->expects(self::once())->method('getCredentialsSource')->will(self::returnValue('<PASSWORD>,<PASSWORD>'));

        $this->mockAccountRepository->expects(self::once())->method('findActiveByAccountIdentifierAndAuthenticationProviderName')->with('admin', 'customLookupName')->will(self::returnValue($this->mockAccount));

        $this->mockToken->expects(self::atLeastOnce())->method('getUsername')->will(self::returnValue('admin'));
        $this->mockToken->expects(self::atLeastOnce())->method('getPassword')->will(self::returnValue('password'));

        $this->mockToken->expects(self::once())->method('setAccount')->with($this->mockAccount);

        $persistedUsernamePasswordProvider = PersistedUsernamePasswordProvider::create('providerName', ['lookupProviderName' => 'customLookupName']);<commit_msg>Fix typo in test name<commit_after><?php
namespace Neos\Flow\Tests\Unit\Security\Authentication\Provider;

/*
 * This file is part of the Neos.Flow package.
 *
 * (c) Contributors of the Neos Project - www.neos.io
 *
 * This package is Open Source Software. For the full copyright and license
 * information, please view the LICENSE file which was distributed with this
 * source code.
 */

use Neos\Flow\Persistence\PersistenceManagerInterface;
use Neos\Flow\Security;
use Neos\Flow\Security\Authentication\Provider\PersistedUsernamePasswordProvider;
use Neos\Flow\Tests\UnitTestCase;

/**
 * Testcase for username/password authentication provider. The account are stored in the CR.
 */
class PersistedUsernamePasswordProviderTest extends UnitTestCase
{
    /**
     * @var Security\Cryptography\HashService
     */
    protected $mockHashService;

    /**
     * @var Security\Account
     */
    protected $mockAccount;

    /**
     * @var Security\AccountRepository
     */
    protected $mockAccountRepository;

    /**
     * @var PersistenceManagerInterface
     */
    protected $mockPersistenceManager;

    /**
     * @var Security\Authentication\Token\UsernamePassword
     */
    protected $mockToken;

    /**
     * @var Security\Context
     */
    protected $mockSecurityContext;

    /**
     * @var Security\Authentication\Provider\PersistedUsernamePasswordProvider
     */
    protected $persistedUsernamePasswordProvider;


    protected function setUp(): void
    {
        $this->mockHashService = $this->createMock(Security\Cryptography\HashService::class);
        $this->mockAccount = $this->getMockBuilder(Security\Account::class)->disableOriginalConstructor()->getMock();
        $this->mockAccountRepository = $this->getMockBuilder(Security\AccountRepository::class)->disableOriginalConstructor()->getMock();
        $this->mockPersistenceManager = $this->createMock(PersistenceManagerInterface::class);
        $this->mockToken = $this->getMockBuilder(Security\Authentication\Token\UsernamePassword::class)->disableOriginalConstructor()->getMock();

        $this->mockSecurityContext = $this->createMock(Security\Context::class);
        $this->mockSecurityContext->expects(self::any())->method('withoutAuthorizationChecks')->will(self::returnCallBack(function ($callback) {
            return $callback->__invoke();
        }));

        $this->persistedUsernamePasswordProvider = $this->getAccessibleMock(Security\Authentication\Provider\PersistedUsernamePasswordProvider::class, ['dummy'], [], '', false);
        $this->persistedUsernamePasswordProvider->_set('name', 'myProvider');
        $this->persistedUsernamePasswordProvider->_set('options', []);
        $this->persistedUsernamePasswordProvider->_set('hashService', $this->mockHashService);
        $this->persistedUsernamePasswordProvider->_set('accountRepository', $this->mockAccountRepository);
        $this->persistedUsernamePasswordProvider->_set('persistenceManager', $this->mockPersistenceManager);
        $this->persistedUsernamePasswordProvider->_set('securityContext', $this->mockSecurityContext);
    }

    /**
     * @test
     */
    public function authenticatingAnUsernamePasswordTokenChecksIfTheGivenClearTextPasswordMatchesThePersistedHashedPassword()
    {
        $this->mockHashService->expects(self::once())->method('validatePassword')->with('password', '<PASSWORD>,<PASSWORD>')->will(self::returnValue(true));

        $this->mockAccount->expects(self::once())->method('getCredentialsSource')->will(self::returnValue('<PASSWORD>,<PASSWORD>'));

        $this->mockAccountRepository->expects(self::once())->method('findActiveByAccountIdentifierAndAuthenticationProviderName')->with('admin', 'myProvider')->will(self::returnValue($this->mockAccount));

        $this->mockToken->expects(self::atLeastOnce())->method('getUsername')->will(self::returnValue('admin'));
        $this->mockToken->expects(self::atLeastOnce())->method('getPassword')->will(self::returnValue('password'));

        $lastAuthenticationStatus = null;
        $this->mockToken->method('setAuthenticationStatus')->willReturnCallback(static function ($status) use (&$lastAuthenticationStatus) {
            $lastAuthenticationStatus = $status;
        });

        $this->mockToken->expects(self::once())->method('setAccount')->with($this->mockAccount);

        $this->persistedUsernamePasswordProvider->authenticate($this->mockToken);
        self::assertSame(\Neos\Flow\Security\Authentication\TokenInterface::AUTHENTICATION_SUCCESSFUL, $lastAuthenticationStatus);
    }

    /**
     * @test
     */
    public function authenticatingAndUsernamePasswordTokenRespectsTheConfiguredLookupProviderName()
    {
        $this->mockHashService->expects(self::once())->method('validatePassword')->with('password', '<PASSWORD>,<PASSWORD>')->will(self::returnValue(true));

        $this->mockAccount->expects(self::once())->method('getCredentialsSource')->will(self::returnValue('<PASSWORD>,<PASSWORD>'));

        $this->mockAccountRepository->expects(self::once())->method('findActiveByAccountIdentifierAndAuthenticationProviderName')->with('admin', 'customLookupName')->will(self::returnValue($this->mockAccount));

        $this->mockToken->expects(self::atLeastOnce())->method('getUsername')->will(self::returnValue('admin'));
        $this->mockToken->expects(self::atLeastOnce())->method('getPassword')->will(self::returnValue('password'));

        $this->mockToken->expects(self::once())->method('setAccount')->with($this->mockAccount);

        $persistedUsernamePasswordProvider = PersistedUsernamePasswordProvider::create('providerName', ['lookupProviderName' => 'customLookupName']);
{'fraction_non_alphanumeric': 0.15280225590412408, 'fraction_numerical': 8.812125484666901e-05, 'mean_word_length': 5.124662709120345, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 227, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1698668', 'n_tokens_mistral': 2907, 'n_tokens_neox': 2864, 'n_words': 343}