Passed
Push — master ( 088a14...696b0c )
by Torben
02:02
created

evaluatePwnedPasswordCheck()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
namespace Derhansen\FeChangePwd\Validation\Validator;
3
4
/*
5
 * This file is part of the Extension "fe_change_pwd" for TYPO3 CMS.
6
 *
7
 * For the full copyright and license information, please read the
8
 * LICENSE.txt file that was distributed with this source code.
9
 */
10
11
use Derhansen\FeChangePwd\Domain\Model\Dto\ChangePassword;
12
use Derhansen\FeChangePwd\Service\LocalizationService;
13
use Derhansen\FeChangePwd\Service\PwnedPasswordsService;
14
use Derhansen\FeChangePwd\Service\SettingsService;
15
16
/**
17
 * Class RegistrationValidator
18
 */
19
class ChangePasswordValidator extends \TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator
20
{
21
    /**
22
     * Available password checks
23
     *
24
     * @var array
25
     */
26
    protected $checks = [
27
        'capitalCharCheck',
28
        'lowerCaseCharCheck',
29
        'digitCheck',
30
        'specialCharCheck',
31
    ];
32
33
    /**
34
     * @var SettingsService
35
     */
36
    protected $settingsService = null;
37
38
    /**
39
     * @var LocalizationService
40
     */
41
    protected $localizationService = null;
42
43
    /**
44
     * @var PwnedPasswordsService
45
     */
46
    protected $pwnedPasswordsService = null;
47
48
    /**
49
     * @param SettingsService $settingsService
50
     */
51
    public function injectSettingsService(\Derhansen\FeChangePwd\Service\SettingsService $settingsService)
52
    {
53
        $this->settingsService = $settingsService;
54
    }
55
56
    /**
57
     * @param LocalizationService $localizationService
58
     */
59
    public function injectLocalizationService(
60
        \Derhansen\FeChangePwd\Service\LocalizationService $localizationService
61
    ) {
62
        $this->localizationService = $localizationService;
63
    }
64
65
    /**
66
     * @param PwnedPasswordsService $PwnedPasswordsService
67
     */
68
    public function injectPwnedPasswordsService(
69
        \Derhansen\FeChangePwd\Service\PwnedPasswordsService $PwnedPasswordsService
70
    ) {
71
        $this->pwnedPasswordsService = $PwnedPasswordsService;
72
    }
73
74
    /**
75
     * Validates the password of the given ChangePassword object against the configured password complexity
76
     *
77
     * @param ChangePassword $value
78
     *
79
     * @return bool
80
     */
81
    protected function isValid($value)
82
    {
83
        $result = true;
84
        $settings = $this->settingsService->getSettings();
85
86
        // Early return if no passwords are given
87
        if ($value->getPassword1() === '' || $value->getPassword2() === '') {
88
            $this->addError(
89
                $this->localizationService->translate('passwordFieldsEmptyOrNotBothFilledOut'),
90
                1537701950
91
            );
92
93
            return false;
94
        }
95
96
        if ($value->getPassword1() !== $value->getPassword2()) {
97
            $this->addError(
98
                $this->localizationService->translate('passwordsDoNotMatch'),
99
                1537701950
100
            );
101
            // Early return, no other checks need to be done if passwords do not match
102
            return false;
103
        }
104
105
        if (isset($settings['passwordComplexity']['minLength'])) {
106
            $this->evaluateMinLengthCheck($value, (int)$settings['passwordComplexity']['minLength']);
107
        }
108
109
        foreach ($this->checks as $check) {
110
            if (isset($settings['passwordComplexity'][$check]) &&
111
                (bool)$settings['passwordComplexity'][$check]
112
            ) {
113
                $this->evaluatePasswordCheck($value, $check);
114
            }
115
        }
116
117
        if (isset($settings['pwnedpasswordsCheck']['enabled']) && (bool)$settings['pwnedpasswordsCheck']['enabled']) {
118
            $this->evaluatePwnedPasswordCheck($value);
119
        }
120
121
        if ($this->result->hasErrors()) {
122
            $result = false;
123
        }
124
125
        return $result;
126
    }
127
128
    /**
129
     * Checks if the password complexity in regards to minimum password length in met
130
     *
131
     * @param ChangePassword $changePassword
132
     * @param int $minLength
133
     * @return void
134
     */
135
    protected function evaluateMinLengthCheck(ChangePassword $changePassword, int $minLength)
136
    {
137
        if (strlen($changePassword->getPassword1()) < $minLength) {
138
            $this->addError(
139
                $this->localizationService->translate('passwordComplexity.failure.minLength', [$minLength]),
140
                1537898028
141
            );
142
        };
143
    }
144
145
    /**
146
     * Evaluates the password complexity in regards to the given check
147
     *
148
     * @param ChangePassword $changePassword
149
     * @param string $check
150
     * @return void
151
     */
152
    protected function evaluatePasswordCheck(ChangePassword $changePassword, $check)
153
    {
154
        $patterns = [
155
            'capitalCharCheck' => '/[A-Z]/',
156
            'lowerCaseCharCheck' => '/[a-z]/',
157
            'digitCheck' => '/[0-9]/',
158
            'specialCharCheck' => '/[^0-9a-z]/i'
159
        ];
160
161
        if (isset($patterns[$check])) {
162
            if (!preg_match($patterns[$check], $changePassword->getPassword1()) > 0) {
163
                $this->addError(
164
                    $this->localizationService->translate('passwordComplexity.failure.' . $check),
165
                    1537898029
166
                );
167
            }
168
        }
169
    }
170
171
    protected function evaluatePwnedPasswordCheck(ChangePassword $changePassword)
172
    {
173
        $foundCount = $this->pwnedPasswordsService->checkPassword($changePassword->getPassword1());
174
        if ($foundCount > 0) {
175
            $this->addError(
176
                $this->localizationService->translate('pwnedPasswordFailure', [$foundCount]),
177
                1537898030
178
            );
179
        }
180
    }
181
}
182