protected const SETUP_SECRET_SESSION_KEY = 'mfa-setup-totp-secret';
+ public function __construct(
+ protected TotpService $totp
+ ) {
+ }
+
/**
* Show a view that generates and displays a TOTP QR code.
*/
- public function generate(TotpService $totp)
+ public function generate()
{
if (session()->has(static::SETUP_SECRET_SESSION_KEY)) {
$totpSecret = decrypt(session()->get(static::SETUP_SECRET_SESSION_KEY));
} else {
- $totpSecret = $totp->generateSecret();
+ $totpSecret = $this->totp->generateSecret();
session()->put(static::SETUP_SECRET_SESSION_KEY, encrypt($totpSecret));
}
- $qrCodeUrl = $totp->generateUrl($totpSecret, $this->currentOrLastAttemptedUser());
- $svg = $totp->generateQrCodeSvg($qrCodeUrl);
+ $qrCodeUrl = $this->totp->generateUrl($totpSecret, $this->currentOrLastAttemptedUser());
+ $svg = $this->totp->generateQrCodeSvg($qrCodeUrl);
$this->setPageTitle(trans('auth.mfa_gen_totp_title'));
'code' => [
'required',
'max:12', 'min:4',
- new TotpValidationRule($totpSecret),
+ new TotpValidationRule($totpSecret, $this->totp),
],
]);
'code' => [
'required',
'max:12', 'min:4',
- new TotpValidationRule($totpSecret),
+ new TotpValidationRule($totpSecret, $this->totp),
],
]);
namespace BookStack\Access\Mfa;
-use Illuminate\Contracts\Validation\Rule;
+use Closure;
+use Illuminate\Contracts\Validation\ValidationRule;
-class TotpValidationRule implements Rule
+class TotpValidationRule implements ValidationRule
{
- protected $secret;
- protected $totpService;
-
/**
* Create a new rule instance.
* Takes the TOTP secret that must be system provided, not user provided.
*/
- public function __construct(string $secret)
- {
- $this->secret = $secret;
- $this->totpService = app()->make(TotpService::class);
+ public function __construct(
+ protected string $secret,
+ protected TotpService $totpService,
+ ) {
}
- /**
- * Determine if the validation rule passes.
- */
- public function passes($attribute, $value)
- {
- return $this->totpService->verifyCode($value, $this->secret);
- }
-
- /**
- * Get the validation error message.
- */
- public function message()
+ public function validate(string $attribute, mixed $value, Closure $fail): void
{
- return trans('validation.totp');
+ $passes = $this->totpService->verifyCode($value, $this->secret);
+ if (!$passes) {
+ $fail(trans('validation.totp'));
+ }
}
}
public function down(): void
{
$sm = Schema::getConnection()->getDoctrineSchemaManager();
- $pages = $sm->listTableDetails('pages');
- $books = $sm->listTableDetails('books');
- $chapters = $sm->listTableDetails('chapters');
+ $pages = $sm->introspectTable('pages');
+ $books = $sm->introspectTable('books');
+ $chapters = $sm->introspectTable('chapters');
if ($pages->hasIndex('search')) {
Schema::table('pages', function (Blueprint $table) {
public function down(): void
{
$sm = Schema::getConnection()->getDoctrineSchemaManager();
- $pages = $sm->listTableDetails('pages');
- $books = $sm->listTableDetails('books');
- $chapters = $sm->listTableDetails('chapters');
+ $pages = $sm->introspectTable('pages');
+ $books = $sm->introspectTable('books');
+ $chapters = $sm->introspectTable('chapters');
if ($pages->hasIndex('name_search')) {
Schema::table('pages', function (Blueprint $table) {
});
$sm = Schema::getConnection()->getDoctrineSchemaManager();
- $pages = $sm->listTableDetails('pages');
- $books = $sm->listTableDetails('books');
- $chapters = $sm->listTableDetails('chapters');
+ $pages = $sm->introspectTable('pages');
+ $books = $sm->introspectTable('books');
+ $chapters = $sm->introspectTable('chapters');
if ($pages->hasIndex('search')) {
Schema::table('pages', function (Blueprint $table) {