Skip to content
Code-Schnipsel Gruppen Projekte
Commit 78dcd6f5 erstellt von Patrick Müller's avatar Patrick Müller
Dateien durchsuchen

feat: max tries for verification code input

Übergeordneter abaeca17
Keine zugehörigen Branchen gefunden
Keine zugehörigen Tags gefunden
2 Merge Requests!14feat: max tries for verification code input,!13Update 'next-4.x' with latest changes from 'main'
Pipeline-Nr. 13785 mit Warnungen bestanden
......@@ -14,6 +14,7 @@
<field type="DATETIME NULL DEFAULT NULL">validUntilDate</field>
<field type="VARCHAR(255) NOT NULL">verificationHandler</field>
<field type="TINYINT(1) NOT NULL DEFAULT 0">status</field>
<field type="TINYINT UNSIGNED NOT NULL DEFAULT 0">tries</field>
</table>
</global>
......
......@@ -51,6 +51,14 @@
<de><![CDATA[Bestimmt, nach wievielen <b>Tagen</b> Verifizierungs-Vorgänge, die bereits validiert wurden, aus der Datenbank gelöscht werden. Dies setzt voraus, dass der Cron <b>Verifikations-Modul: Verifizierte Daten löschen</b> eingerichtet ist.]]></de>
<en><![CDATA[Determines after how many <b>days</b> verification processes are deleted from database after they have been verified. Required that cron <b>Verification module: Delete verified data</b> is set up.]]></en>
</locale>
<locale name="settings.maxTries.title">
<de><![CDATA[Maximale Anzahl Verifizierungs-Versuche]]></de>
<en><![CDATA[Maximum number of verification attempts]]></en>
</locale>
<locale name="settings.maxTries.description">
<de><![CDATA[Maximale Anzahl an Versuchen für die Bestätigung eines Verifizierungs-Prozesses mittels Verifizierungs-Code. Wird diese Anzahl überschritten, wird der Verifizierungs-Prozess automatisch auf "abgelaufen" gesetzt.]]></de>
<en><![CDATA[Maximum number of attempts to confirm a verification process via verification code. If this number is exceeded, the verification process is automatically set to "expired".]]></en>
</locale>
<!-- Cron -->
<locale name="cron.deleteVerified.title">
......
......@@ -13,6 +13,10 @@
<type><![CDATA[integer]]></type>
<defaultvalue>3</defaultvalue>
</conf>
<conf name="maxTries">
<type><![CDATA[integer]]></type>
<defaultvalue>5</defaultvalue>
</conf>
</section>
</config>
......@@ -55,6 +59,15 @@
</description>
</input>
<input conf="settings.maxTries" type="number">
<text>
<locale group="quiqqer/verification" var="settings.maxTries.title"/>
</text>
<description>
<locale group="quiqqer/verification" var="settings.maxTries.description"/>
</description>
</input>
</settings>
</category>
......
......@@ -13,6 +13,7 @@ abstract class AbstractVerification
* @param string $verificationCode
* @param DateTimeImmutable $createDate
* @param DateTimeImmutable $updateDate
* @param int $tries
* @param VerificationStatus $status
* @param array<string|int,mixed> $customData
* @param DateTimeImmutable|null $validUntilDate
......@@ -23,6 +24,7 @@ public function __construct(
public readonly string $verificationCode,
public readonly DateTimeImmutable $createDate,
public readonly DateTimeImmutable $updateDate,
public int $tries,
public VerificationStatus $status = VerificationStatus::PENDING,
public array $customData = [],
public ?DateTimeImmutable $validUntilDate = null
......
......@@ -13,6 +13,7 @@ class LinkVerification extends AbstractVerification
* @param string $verificationCode
* @param DateTimeImmutable $createDate
* @param DateTimeImmutable $updateDate
* @param int $tries
* @param string $verificationUrl
* @param VerificationStatus $status
* @param array<string|int,mixed> $customData
......@@ -24,6 +25,7 @@ public function __construct(
string $verificationCode,
DateTimeImmutable $createDate,
DateTimeImmutable $updateDate,
int $tries,
string $verificationUrl,
VerificationStatus $status = VerificationStatus::PENDING,
array $customData = [],
......@@ -36,6 +38,7 @@ public function __construct(
$verificationCode,
$createDate,
$updateDate,
$tries,
$status,
$customData,
$validUntilDate
......@@ -55,6 +58,7 @@ public static function fromArray(array $data): static
$data['verificationCode'],
new DateTimeImmutable($data['createDate']),
new DateTimeImmutable($data['updateDate']),
(int)$data['tries'],
$data['customData']['verificationUrl'],
VerificationStatus::from($data['status']),
$data['customData'],
......
......@@ -15,6 +15,7 @@ class PhoneNumberVerification extends AbstractVerification
* @param string $verificationCode
* @param DateTimeImmutable $createDate
* @param DateTimeImmutable $updateDate
* @param int $tries
* @param PhoneNumber $phoneNumber
* @param PhoneNumberVerificationStrategy $strategy
* @param VerificationStatus $status
......@@ -27,6 +28,7 @@ public function __construct(
string $verificationCode,
DateTimeImmutable $createDate,
DateTimeImmutable $updateDate,
int $tries,
public readonly PhoneNumber $phoneNumber,
PhoneNumberVerificationStrategy $strategy,
VerificationStatus $status = VerificationStatus::PENDING,
......@@ -42,6 +44,7 @@ public function __construct(
$verificationCode,
$createDate,
$updateDate,
$tries,
$status,
$customData,
$validUntilDate
......@@ -63,6 +66,7 @@ public static function fromArray(array $data): static
$data['verificationCode'],
new DateTimeImmutable($data['createDate']),
new DateTimeImmutable($data['updateDate']),
(int)$data['tries'],
new PhoneNumber($data['phoneNumber']),
PhoneNumberVerificationStrategy::from($data['strategy']),
VerificationStatus::from($data['status']),
......
<?php
namespace QUI\Verification;
use QUI;
use function is_null;
class Settings
{
private static ?QUI\Config $config = null;
/**
* @param string $key
* @return string
* @throws QUI\Exception
*/
public static function get(string $key): string
{
return self::getConfig()->get('settings', $key);
}
/**
* @return QUI\Config
* @throws QUI\Exception
*/
private static function getConfig(): QUI\Config
{
if (is_null(self::$config)) {
self::$config = QUI::getPackage('quiqqer/verification')->getConfig();
if (is_null(self::$config)) {
throw new QUI\Exception("Cannot load config of package 'quiqqer/verification'");
}
}
return self::$config;
}
}
......@@ -13,12 +13,11 @@
use QUI\Verification\Enum\PhoneNumberVerificationStrategy;
use QUI\Verification\Enum\VerificationStatus;
use QUI\Verification\Interface\LinkVerificationHandlerInterface;
use QUI\Verification\Interface\PhoneNumberVerificationHandlerInterface;
use QUI\Verification\Interface\VerificationCodeFactoryInterface;
use QUI\Verification\Interface\VerificationFactoryInterface;
use QUI\Verification\Interface\VerificationHandlerInterface;
use QUI\Verification\Interface\VerificationRepositoryInterface;
use Throwable;
use QUI\Verification\Interface\PhoneNumberVerificationHandlerInterface;
use function is_null;
use function strtotime;
......@@ -92,6 +91,7 @@ public function createLinkVerification(
$hash,
new DateTimeImmutable(),
new DateTimeImmutable(),
0,
$url,
VerificationStatus::PENDING,
$customData
......@@ -158,6 +158,7 @@ public function createPhoneNumberVerification(
$verificationCode,
new DateTimeImmutable(),
new DateTimeImmutable(),
0,
$phoneNumber,
$strategy,
VerificationStatus::PENDING,
......
......@@ -139,7 +139,8 @@ public function update(AbstractVerification $verification): void
$this->tableVerificationProcesses(),
[
'status' => $verification->status->value,
'updateDate' => date('Y-m-d H:i:s')
'updateDate' => date('Y-m-d H:i:s'),
'tries' => $verification->tries
]
);
});
......
......@@ -34,6 +34,7 @@ public function __construct(protected ?VerificationRepositoryInterface $verifica
* @throws InvalidVerificationCodeException
* @throws VerificationAlreadyVerifiedException
* @throws VerificationExpiredException
* @throws QUI\Exception
*/
public function verifyVerificationCode(AbstractVerification $verification, string $verificationCode): void
{
......@@ -59,7 +60,23 @@ public function verifyVerificationCode(AbstractVerification $verification, strin
);
}
// Check max tries -> if exceeded, set status to expired
$maxTries = (int)Settings::get('maxTries');
if ($verification->tries >= $maxTries) {
$verification->status = VerificationStatus::EXPIRED;
$this->verificationRepository->update($verification);
throw new VerificationExpiredException(
"Verification {$verification->uuid} is expired."
);
}
if ($verification->verificationCode !== $verificationCode) {
// Increase tries
$verification->tries += 1;
$this->verificationRepository->update($verification);
throw new InvalidVerificationCodeException(
"Verification code {$verificationCode} is invalid for verification {$verification->uuid}."
);
......@@ -75,6 +92,7 @@ public function verifyVerificationCode(AbstractVerification $verification, strin
* @return void
*
* @throws \Doctrine\DBAL\Exception
* @throws \Exception
*/
public function verifyPhoneNumberVerification(PhoneNumberVerification $verification, string $verificationCode): void
{
......
......@@ -7,6 +7,7 @@
use QUI\Verification\Exception\VerificationExpiredException;
use QUI\Verification\VerificationRepository;
use QUI\Verification\Verifier;
use QUI\Verification\Entity\LinkVerification;
/** @var QUI\Projects\Project $Project */
/** @var QUI\Projects\Site $Site */
......@@ -35,6 +36,10 @@ function redirect(string $target): never
try {
$verification = $repository->findByUuid(Orthos::clear($_REQUEST['verificationId']));
if (!($verification instanceof LinkVerification)) {
$verification = null;
}
} catch (\Throwable $Exception) {
if ($Exception instanceof Exception) {
QUI\System\Log::writeDebugException($Exception);
......
0% Lade oder .
You are about to add 0 people to the discussion. Proceed with caution.
Bearbeitung dieser Nachricht zuerst beenden!
Bitte registrieren oder zum Kommentieren