🔖 1.2.4

This commit is contained in:
MarceauKa 2019-09-27 17:35:01 +02:00
parent 5b2e6f9e56
commit 7637c2b506
11 changed files with 108 additions and 23 deletions

View File

@ -2,19 +2,28 @@
namespace App\Http\Controllers;
use App\Login;
use App\Notifications\SecureLoginCode;
use App\SecureLogin;
use App\User;
use Illuminate\Auth\Events\Failed;
use Illuminate\Auth\SessionGuard;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
use Lab404\AuthChecker\Services\AuthChecker;
class LoginController extends Controller
{
use ThrottlesLogins;
public $maxAttempts = 5;
public $decayMinutes = 1;
public function __construct()
{
$this->middleware('guest')->except('logout');
$this->middleware('throttle:5,1')->only('check');
}
public function form()
@ -29,21 +38,57 @@ class LoginController extends Controller
'password' => 'required|string',
]);
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
$this->sendLockoutResponse($request);
}
if (true === app('shaarli')->getSecureLogin()) {
return $this->checkWithSecureLogin($request, $validated);
}
return $this->checkWithoutSecureLogin($request, $validated);
}
protected function checkWithoutSecureLogin(Request $request, array $validated)
{
if (Auth::guard()->attempt($validated, $request->filled('remember'))) {
$request->session()->regenerate();
if (true === app('shaarli')->getSecureLogin()) {
$user = Auth::guard()->user();
$secure = SecureLogin::createForUser($user);
$user->notify(new SecureLoginCode($secure));
Auth::logout();
return redirect()->route('login.secure', $secure);
}
return redirect()->intended('/');
}
$this->incrementLoginAttempts($request);
throw ValidationException::withMessages([
'email' => [__("Invalid credentials")],
]);
}
protected function checkWithSecureLogin(Request $request, array $validated)
{
/** @var SessionGuard $guard */
$guard = Auth::guard();
if ($guard->validate($validated)) {
/** @var User $user */
$user = $guard->getLastAttempted();
/** @var AuthChecker $checker */
$checker = app('authchecker');
$device = $checker->findOrCreateUserDeviceByAgent($user);
$checker->createUserLoginForDevice($user, $device, Login::TYPE_2FA);
$secure = SecureLogin::createForUser($user);
$user->notify(new SecureLoginCode($secure));
return redirect()->route('login.secure', $secure);
}
event(new Failed('web', $guard->getLastAttempted(), $validated));
$this->incrementLoginAttempts($request);
throw ValidationException::withMessages([
'email' => [__("Invalid credentials")],
]);
@ -57,4 +102,9 @@ class LoginController extends Controller
return redirect('/');
}
public function username(): string
{
return 'email';
}
}

10
app/Login.php Normal file
View File

@ -0,0 +1,10 @@
<?php
namespace App;
use Lab404\AuthChecker\Models\Login as BaseLogin;
class Login extends BaseLogin
{
const TYPE_2FA = '2fa';
}

View File

@ -29,8 +29,8 @@ class SecureLoginCode extends Notification
{
return (new MailMessage)
->subject(__("Secure your login"))
->line(__("Please use the following code to access your account."))
->action($this->secure->code, sprintf('%s?code=%s', route('login.secure', $this->secure), $this->secure->code));
->line(__("Please use the following code :code to access your account.", ['code' => $this->secure->code]))
->action(__("Confirm login"), sprintf('%s?code=%s', route('login.secure', $this->secure), $this->secure->code));
}
public function toArray($notifiable)

View File

@ -2,6 +2,7 @@
namespace App;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@ -33,7 +34,11 @@ class SecureLogin extends Model
return 'token';
}
public static function createForUser(User $user): self
/**
* @param Authenticatable|User $user
* @return static
*/
public static function createForUser($user): self
{
$code_length = app('shaarli')->getSecureCodeLength();
$expire_minutes = app('shaarli')->getSecureCodeExpires();

View File

@ -15,7 +15,7 @@ use Spatie\Valuestore\Valuestore;
class Shaarli
{
/** @var string VERSION */
public const VERSION = '1.2.3';
public const VERSION = '1.2.4';
/** @var Application $app */
protected $app;
/** @var Valuestore $settings */

View File

@ -1,3 +1,17 @@
# 1.2.4
## Changed
- LoginController throttles request
- AuthChecker now handles 2FA
- Secure login email notification CTA and message
## Fixed
- Secure Login don't log failed attempts
- Use `request()->input('code')` instead of `request('code')` in secure login form
- Story form confirm message i18n
# 1.2.3
## Added

View File

@ -1,5 +1,7 @@
<?php
use App\Login;
return [
/*
@ -60,7 +62,7 @@ return [
# Ex: App\Models\Device (default: Lab404\AuthChecker\Models\Device)
'device' => null,
# Ex: App\Models\Login (default: Lab404\AuthChecker\Models\Login)
'login' => null,
'login' => Login::class,
]
];

View File

@ -128,10 +128,10 @@ export default {
data: this.form
}).then((response) => {
if (this.story) {
this.$toasted.success(this.__("Story updated !"));
this.$toasted.success(this.__("Story updated"));
this.loading = false;
} else {
this.$toasted.success(this.__("Story created !"));
this.$toasted.success(this.__("Story created"));
this.reset();
}
}).catch((error) => {

View File

@ -36,7 +36,8 @@
"Invalid secure code": "Code de sécurité invalide",
"A security code has been sent to you. This code will expire :expire.": "Un code de sécurité vous a été envoyé. Il expirera :expire.",
"Secure your login": "Sécurisez votre connexion",
"Please use the following code to access your account.": "Veuillez utiliser le code suivant pour sécuriser votre connexion.",
"Please use the following code :code to access your account.": "Veuillez utiliser le code suivant :code pour sécuriser votre connexion.",
"Confirm login": "Confirmer la connexion",
"Manage": "Gestion",
"Page": "Page",
@ -157,6 +158,7 @@
"Date": "Date",
"Status": "Statut",
"Succeeded": "Réussie",
"2FA": "2FA",
"Locked": "Bloquée",
"Failed": "Échouée",

View File

@ -19,7 +19,7 @@
<label for="code" class="col-md-4 col-form-label text-md-right">{{ __('Secure code') }}</label>
<div class="col-md-6">
<input id="code" type="text" class="form-control @error('code') is-invalid @enderror" name="code" value="{{ request('code') }}" required autofocus>
<input id="code" type="text" class="form-control @error('code') is-invalid @enderror" name="code" value="{{ request()->input('code') }}" required autofocus>
@error('code')
<span class="invalid-feedback" role="alert">

View File

@ -41,11 +41,13 @@
</td>
<td class="align-middle">{{ $login->created_at->diffForHumans() }}</td>
<td class="align-middle">
@if($login->type === \Lab404\AuthChecker\Models\Login::TYPE_LOGIN)
@if($login->type === App\Login::TYPE_LOGIN)
<span class="badge badge-success">{{ __('Succeeded') }}</span>
@elseif($login->type === \Lab404\AuthChecker\Models\Login::TYPE_LOCKOUT)
@elseif($login->type === App\Login::TYPE_2FA)
<span class="badge badge-warning">{{ __('2FA') }}</span>
@elseif($login->type === App\Login::TYPE_LOCKOUT)
<span class="badge badge-danger">{{ __('Locked') }}</span>
@else
@elseif($login->type === App\Login::TYPE_FAILED)
<span class="badge badge-danger">{{ __('Failed') }}</span>
@endif
</td>