Skip to content
This repository has been archived by the owner on Feb 17, 2022. It is now read-only.

Add custom validation rule with translation. #30

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,44 @@ public function confirmTwoFactor(Request $request)

If the User doesn't issue the correct Code, the method will return `false`. You can tell the User to double-check its device's timezone, or create another Shared Secret with `createTwoFactorAuth()`.

You may validate that Code passed to a controller is a valid Code by using the TotpCode rule.

```php
use DarkGhostHunter\Laraguard\Rules\TotpCode;

public function confirmTwoFactor(Request $request)
{
$this->validate($request, [
'2fa_code' => ['required', new TotpCode()],
DarkGhostHunter marked this conversation as resolved.
Show resolved Hide resolved
]);

$request->user()->enableTwoFactorAuth();
}
```

You can also use the 'pipe' syntax for rule.

```php
public function setSafeDevice(Request $request)
{
$this->validate($request, [
'2fa_code' => 'required|totp_code',
]);

$request->user()->addSafeDevice($request);

session()->flash('message', "This device has been added as safe and the app won't ask for codes");
}
```

You can also define an error message by adding an entry in the validation language file or you can publish the language files to your resources/lang folder.

```php
'totp_code' => 'The code you have entered is invalid.',

// The rest of the validation error messages...
```

### Recovery Codes

Recovery Codes are automatically generated each time the Two Factor Authentication is enabled. By default, a Collection of ten one-use 8-characters codes are created.
Expand Down Expand Up @@ -249,7 +287,7 @@ To further configure the package, publish the configuration files and assets:

php artisan vendor:publish --provider="DarkGhostHunter\Laraguard\LaraguardServiceProvider"

You will receive the authentication view in `resources/views/vendor/laraguard/auth.blade.php`, and the `config/laraguard.php` config file with the following contents:
You will receive the authentication view in `resources/views/vendor/laraguard/auth.blade.php`, the language files `resources/lang/vendor/laraguard` folder and the `config/laraguard.php` config file with the following contents:

```php
return [
Expand Down
5 changes: 5 additions & 0 deletions resources/lang/en/messages.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

return [
'totp_code' => 'The Code is invalid or has expired.',
];
5 changes: 5 additions & 0 deletions resources/lang/tr/messages.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

return [
'totp_code' => 'Kod geçersiz veya süresi dolmuş.',
];
19 changes: 19 additions & 0 deletions src/LaraguardServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace DarkGhostHunter\Laraguard;

use DarkGhostHunter\Laraguard\Rules\TotpCode;
use Illuminate\Routing\Router;
use Illuminate\Auth\Events\Validated;
use Illuminate\Auth\Events\Attempting;
Expand All @@ -19,6 +20,7 @@ class LaraguardServiceProvider extends ServiceProvider
public function register()
{
$this->mergeConfigFrom(__DIR__ . '/../config/laraguard.php', 'laraguard');
$this->loadTranslationsFrom(__DIR__ . '/../resources/lang/', 'laraguard');
}

/**
Expand All @@ -33,6 +35,7 @@ public function boot(Repository $config, Router $router, Dispatcher $dispatcher)
{
$this->registerListener($config, $dispatcher);
$this->registerMiddleware($router);
$this->registerValidators();

$this->loadViewsFrom(__DIR__ . '/../resources/views', 'laraguard');
$this->loadFactoriesFrom(__DIR__ . '/../database/factories');
Expand Down Expand Up @@ -72,6 +75,18 @@ protected function registerListener(Repository $config, Dispatcher $dispatcher)
$dispatcher->listen(Validated::class, Contracts\TwoFactorListener::class . '@checkTwoFactor');
}

/**
* Register the custom validators
*
* @return void
*/
private function registerValidators()
{
$this->app['validator']->extend('totp_code', function ($attribute, $value) {
return (new TotpCode())->passes($attribute, $value);
}, __('laraguard::messages.totp_code'));
}

/**
* Publish config, view and migrations files.
*
Expand All @@ -87,6 +102,10 @@ protected function publishFiles()
__DIR__ . '/../resources/views' => resource_path('views/vendor/laraguard'),
], 'views');

$this->publishes([
__DIR__ . '/../resources/lang' => resource_path('lang/vendor/laraguard'),
], 'translations');

// We will allow the publishing for the Two Factor Authentication migration that
// holds the TOTP data, only if it wasn't published before, avoiding multiple
// copies for the same migration, which can throw errors when re-migrating.
Expand Down
70 changes: 70 additions & 0 deletions src/Rules/TotpCode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

namespace DarkGhostHunter\Laraguard\Rules;

use DarkGhostHunter\Laraguard\Contracts\TwoFactorAuthenticatable;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Facades\Auth;

class TotpCode implements Rule
{
/**
* The name of the rule.
*
* @var string
*/
protected $rule = 'totp_code';

/**
* The auth user.
*
* @var \Illuminate\Foundation\Auth\User
*/
protected $user;

/**
* Create a new "totp code" rule instance.
*
* @return void
*/
public function __construct()
{
$this->user = Auth::user();
DarkGhostHunter marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value) : bool
{
if ($this->user instanceof TwoFactorAuthenticatable) {
return is_string($value) && $this->user->twoFactorAuth->validateCode($value);
DarkGhostHunter marked this conversation as resolved.
Show resolved Hide resolved
}

return false;
}

/**
* Get the validation error message.
*
* @return string
*/
public function message() : string
{
return __('laraguard::messages.totp_code');
}

/**
* Convert the rule to a validation string.
*
* @return string
*/
public function __toString() : string
{
return "{$this->rule}";
}
}