<commit_before><?php

namespace Spec\Minds\Core\Security;

use Minds\Core\Security\Exceptions\UserNotSetupException;
use Minds\Entities\User;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class LoginAttemptsSpec extends ObjectBehavior
{
    public function it_is_initializable()
    {
        $this->shouldHaveType('Minds\Core\Security\LoginAttempts');
    }

    public function it_logFailure_should_throw_if_user_isnt_set()
    {
        $this->shouldThrow(UserNotSetupException::class)->during('logFailure');
    }

    public function it_checkFailures_should_throw_if_user_isnt_set()
    {
        $this->shouldThrow(UserNotSetupException::class)->during('checkFailures');
    }

    public function it_resetFailuresCount_should_throw_if_user_isnt_set()
    {
        $this->shouldThrow(UserNotSetupException::class)->during('resetFailuresCount');
    }

    public function it_should_log_the_failure(User $user)
    {
        $user->guid = '123';

        $user->get('guid')
            ->shouldBeCalled()
            ->willReturn('123');

        $user->getPrivateSetting(Argument::exact('login_failures'))
            ->shouldBeCalled()
            ->willReturn(0);

        $user->setPrivateSetting(Argument::that(function ($param) {
            return $param === 'login_failures' || $param === 'login_failure_1';
        }), Argument::any())
            ->shouldBeCalled()
            ->willReturn(true);


        $this->setUser($user);

        $this->logFailure()->shouldReturn(true);
    }

    public function it_should_return_false_if_attempts_limit_was_reached(User $user)
    {
        $user->guid = '123';

        $user->get('guid')
            ->shouldBeCalled()
            ->willReturn('123');

        $user->getPrivateSetting(Argument::exact('login_failures'))
            ->shouldBeCalled()
            ->willReturn(5);

        $user->getPrivateSetting(Argument::containingString('login_failure_'))
            ->shouldBeCalled()
            ->willReturn(strtotime('-30 sec'));

        $this->setUser($user);

        $this->checkFailures()->shouldReturn(true);
    }

    public function it_should_return_true_if_attempts_limit_wasnt_reached(User $user)
    {
        $user->guid = '123';

        $user->get('guid')
            ->shouldBeCalled()
            ->willReturn('123');

        $user->getPrivateSetting(Argument::exact('login_failures'))
            ->shouldBeCalled()
            ->willReturn(3);

        $this->setUser($user);

        $this->checkFailures()->shouldReturn(false);
    }

    public function it_should_reset_failures_count(User $user)
    {
        $user->guid = '123';

        $user->get('guid')
            ->shouldBeCalled()<commit_msg>(fix): failing spec tests<commit_after><?php

namespace Spec\Minds\Core\Security;

use Minds\Core\Security\Exceptions\UserNotSetupException;
use Minds\Core\Security\RateLimits\KeyValueLimiter;
use Minds\Entities\User;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class LoginAttemptsSpec extends ObjectBehavior
{
    private $keyValueLimiter;

    public function let(KeyValueLimiter $keyValueLimiter)
    {
        $this->beConstructedWith($keyValueLimiter);
        $this->keyValueLimiter = $keyValueLimiter;
    }

    public function it_is_initializable()
    {
        $this->shouldHaveType('Minds\Core\Security\LoginAttempts');
    }

    public function it_logFailure_should_throw_if_user_isnt_set()
    {
        $this->shouldThrow(UserNotSetupException::class)->during('logFailure');
    }

    public function it_checkFailures_should_throw_if_user_isnt_set()
    {
        $this->shouldThrow(UserNotSetupException::class)->during('checkFailures');
    }

    public function it_resetFailuresCount_should_throw_if_user_isnt_set()
    {
        $this->shouldThrow(UserNotSetupException::class)->during('resetFailuresCount');
    }

    public function it_should_log_the_failure(User $user)
    {
        $user->guid = '123';

        $user->get('guid')
            ->shouldBeCalled()
            ->willReturn('123');

        $user->getPrivateSetting(Argument::exact('login_failures'))
            ->shouldBeCalled()
            ->willReturn(0);

        $user->setPrivateSetting(Argument::that(function ($param) {
            return $param === 'login_failures' || $param === 'login_failure_1';
        }), Argument::any())
            ->shouldBeCalled()
            ->willReturn(true);


        $this->setUser($user);

        $this->logFailure()->shouldReturn(true);
    }

    public function it_should_return_false_if_attempts_limit_was_reached(User $user)
    {
        $user->guid = '123';

        $user->get('guid')
            ->shouldBeCalled()
            ->willReturn('123');

        $user->getPrivateSetting(Argument::exact('login_failures'))
            ->shouldBeCalled()
            ->willReturn(5);

        $user->getPrivateSetting(Argument::containingString('login_failure_'))
            ->shouldBeCalled()
            ->willReturn(strtotime('-30 sec'));

        $this->keyValueLimiter
            ->setKey('login-attempts-ip')
            ->willReturn($this->keyValueLimiter);
        $this->keyValueLimiter->setValue(Argument::any())
            ->willReturn($this->keyValueLimiter);

        $this->keyValueLimiter->setSeconds(Argument::any())
            ->willReturn($this->keyValueLimiter);
        
        $this->keyValueLimiter->setMax(Argument::any())
            ->willReturn($this->keyValueLimiter);
        
        $this->keyValueLimiter->checkAndIncrement()
            ->shouldBeCalled();

        $this->setUser($user);

        $this->checkFailures()->shouldReturn(true);
    }

    public function it_should_return_true_if_attempts_limit_wasnt_reached(User $user)
    {
        $user->guid = '123';

        $user->get('guid')
            ->shouldBeCalled()
            ->willReturn('123');

        $user->getPrivateSetting(Argument::exact('login_failures'))
            ->shouldBeCalled()
            ->willReturn(3);

        $this->keyValueLimiter
            ->setKey('login-attempts-ip')
            ->willReturn($this->keyValueLimiter);

        $this->keyValueLimiter->setValue(Argument::any())
            ->willReturn($this->keyValueLimiter);

        $this->keyValueLimiter->setSeconds(Argument::any())
            ->willReturn($this->keyValueLimiter);
        
        $this->keyValueLimiter->setMax(Argument::any())
            ->willReturn($this->keyValueLimiter);
        
        $this->keyValueLimiter->checkAndIncrement()
            ->shouldBeCalled();

        $this->setUser($user);

        $this->checkFailures()->shouldReturn(false);
    }

    public function it_should_reset_failures_count(User $user)
    {
        $user->guid = '123';

        $user->get('guid')
            ->shouldBeCalled()
{'fraction_non_alphanumeric': 0.14273075788852846, 'fraction_numerical': 0.007962253022707167, 'mean_word_length': 2.7704280155642023, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 135, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '5615414', 'n_tokens_mistral': 2056, 'n_tokens_neox': 1970, 'n_words': 225}