Skip to content

Commit

Permalink
[Feature] Show user phone or email before sending OTP (#39)
Browse files Browse the repository at this point in the history
* wip

* Fix styling

* wip

* Fix styling

* Add missing period

* Only show ask for confirmation when necessary

* Fix styling

* Fix PHPStan

* User should define phone number field

* Fix styling

* Add missing return types

* Fix styling

* Fix missing deactivated notification

---------

Co-authored-by: Baspa <[email protected]>
  • Loading branch information
Baspa and Baspa authored Sep 20, 2024
1 parent 1d1f44f commit a8502b1
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 26 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ return [

'sms_service' => null, // For example 'vonage', 'twilio', 'nexmo', etc.
'send_otp_class' => null,
'phone_number_field' => 'phone', // The field name of the phone number in your user model
];
```

Expand Down
1 change: 1 addition & 0 deletions config/filament-two-factor-auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
*/
'sms_service' => null, // For example 'vonage', 'twilio', 'nexmo', etc.
'send_otp_class' => null,
'phone_number_field' => 'phone',

/*
|--------------------------------------------------------------------------
Expand Down
8 changes: 7 additions & 1 deletion resources/lang/en.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"Activate": "Activate",
"Activate Two-Factor Authentication": "Activate Two-Factor Authentication",
"Add additional security to your account using two factor authentication": "Add additional security to your account using two factor authentication",
"Authenticate with your code": "Authenticate with your code",
"Authenticator app": "Authenticator app",
Expand All @@ -15,6 +16,11 @@
"Login": "Login",
"Or scan the QR code with your authenticator app": "Or scan the QR code with your authenticator app",
"Password Confirmation": "Password Confirmation",
"Phone number": "Phone number",
"email": "email",
"phone": "phone",
"authenticator app": "authenticator app",
"Please confirm this is your :type before continuing.": "Please confirm this is your :type before continuing.",
"Recovery code": "Recovery code",
"Regenerate": "Regenerate",
"Resend": "Resend",
Expand All @@ -38,4 +44,4 @@
"Your account has been secured with two factor authentication": "Your account has been secured with two factor authentication",
"Your security code for :app": "Your security code for :app",
"Your security code is": "Your security code is"
}
}
8 changes: 7 additions & 1 deletion resources/lang/nl.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"Activate": "Activeer",
"Activate Two-Factor Authentication": "Activeer tweestapsverificatie",
"Add additional security to your account using two factor authentication": "Voeg extra beveiliging toe aan uw account met tweestapsverificatie",
"Authenticate with your code": "Verifieer met uw authenticatiecode",
"Authenticator app": "Authenticator app",
Expand All @@ -15,6 +16,11 @@
"Login": "Inloggen",
"Or scan the QR code with your authenticator app": "Of scan de QR-code met uw authenticator-app",
"Password Confirmation": "Wachtwoordbevestiging",
"Phone number": "Telefoonnummer",
"email": "e-mailadres",
"phone": "telefoonnummer",
"authenticator app": "authenticator app",
"Please confirm this is your :type before continuing.": "Bevestig dat dit uw :type is voordat u doorgaat.",
"Recovery code": "Herstelcode",
"Regenerate": "Opnieuw genereren",
"Resend": "Opnieuw Verzenden",
Expand All @@ -40,4 +46,4 @@
"Your administrator requires you to enable two-factor authentication.": "Uw beheerder vereist dat u tweestapsverificatie inschakelt.",
"Your security code for :app": "Uw beveiligingscode voor :app",
"Your security code is": "Uw beveiligingscode is"
}
}
130 changes: 106 additions & 24 deletions src/Pages/TwoFactor.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,36 +143,119 @@ protected function getForms(): array
];
}

public function translatedType(string $type): string
{
return match ($type) {
TwoFactorType::email->value => __('email'),
TwoFactorType::phone->value => __('phone'),
TwoFactorType::authenticator->value => __('authenticator app'),
default => $type,
};
}

public function enableAction(): Action
{
return Action::make('enable')
->label(__('Activate'))
$action = Action::make('enable')
->color('primary')
->action(function ($data) {
$formData = [];
->label(__('Activate'));

if (isset($this->twoFactorData['option']) && $this->twoFactorData['option'] !== TwoFactorType::authenticator->value) {
$action->requiresConfirmation()
->modalHeading(__('Activate Two-Factor Authentication'))
->modalDescription(__('Please confirm this is your :type before continuing.', [
'type' => $this->translatedType($this->twoFactorData['option']),
]))
->form(function (): array {
$fields = $this->getConfirmableFields();
$option = $this->twoFactorData['option'];

if (isset($fields[$option])) {
$field = $fields[$option];

return [
TextInput::make($field['name'])
->label($field['label'])
->default($field['default'])
->required()
->rules($field['rules'])
->inlineLabel(),
];
}

return [];
});
}

if (isset($data['email'])) {
$formData['email'] = $data['email'];
}
return $action->action(function (array $data): void {
$formData = [];

if ($this->twoFactorData['option']) {
$formData['two_factor_type'] = TwoFactorType::tryFrom($this->twoFactorData['option']);
}
if (isset($data['email'])) {
$formData['email'] = $data['email'];
}

/** @var array{two_factor_type: TwoFactorType|null, email?: mixed} $formData */
if (
isset($formData['two_factor_type']) &&
($formData['two_factor_type'] === TwoFactorType::email || $formData['two_factor_type'] === TwoFactorType::phone)
) {
$this->showQrCode = false;
} else {
$this->showQrCode = true;
}
if ($this->twoFactorData['option']) {
$formData['two_factor_type'] = TwoFactorType::tryFrom($this->twoFactorData['option']);
}

$this->user->update($formData);
/** @var array{two_factor_type: TwoFactorType|null, email?: mixed} $formData */
if (
isset($formData['two_factor_type']) &&
($formData['two_factor_type'] === TwoFactorType::email || $formData['two_factor_type'] === TwoFactorType::phone)
) {
$this->showQrCode = false;
} else {
$this->showQrCode = true;
}

$this->enableTwoFactorAuthentication(app(EnableTwoFactorAuthentication::class));
});
$this->user->update($formData);

$this->enableTwoFactorAuthentication(app(EnableTwoFactorAuthentication::class));
});
}

/** @return array<int|string, array{name: 'authenticator'|'email'|'phone', label: string, default: mixed, rules: array{0: 'required', 1?: 'email'}}> */
private function getConfirmableFields(): array
{
$confirmableOptions = config('filament-two-factor-auth.options', [
TwoFactorType::email,
TwoFactorType::phone,
]);

$fields = [];

foreach ($confirmableOptions as $option) {
switch ($option) {
case TwoFactorType::authenticator:
$fields[$option->value] = [
'name' => 'authenticator',
'label' => __('Authenticator'),
'default' => null, // Set default value if needed
'rules' => ['required'],
];

break;
case TwoFactorType::email:
$fields[$option->value] = [
'name' => 'email',
'label' => __('Email'),
'default' => $this->user->email,
'rules' => ['required', 'email'],
];

break;
case TwoFactorType::phone:
$fields[$option->value] = [
'name' => 'phone',
'label' => __('Phone number'),
'default' => $this->user->{config('filament-two-factor-auth.phone_number_field', 'phone')},
'rules' => ['required'],
];

break;
}
}

return $fields;
}

public function confirmAction(): Action
Expand Down Expand Up @@ -273,8 +356,6 @@ public function confirmTwoFactorAuthentication(ConfirmTwoFactorAuthentication $c

public function disableTwoFactorAuthentication(DisableTwoFactorAuthentication $disable): void
{
$disable($this->user);

if ($this->user->two_factor_confirmed_at) {
Notification::make()
->title(__('Two-Factor Authentication deactivated'))
Expand All @@ -283,6 +364,7 @@ public function disableTwoFactorAuthentication(DisableTwoFactorAuthentication $d
->duration(5000)
->send();
}
$disable($this->user);

$this->showingQrCode = false;
$this->showingConfirmation = false;
Expand Down

0 comments on commit a8502b1

Please sign in to comment.