mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-17 08:14:25 +00:00
feat: harden auth flows and server mobile navigation
Add normalized email identity rate limiting for registration and forgot-password requests, and refresh Sentinel status from restart broadcasts. Rework server sidebars and navbar for mobile menus and active status visibility.
This commit is contained in:
1 parent
94079c90f2
commit
b0f0f7d8d0
42 files changed
+1064
-128
No files matched your search
@@ -4,7 +4,9 @@ namespace App\Actions\Fortify;
|
||||
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\Rules\Password;
|
||||
@@ -12,6 +14,16 @@ use Laravel\Fortify\Contracts\CreatesNewUsers;
|
||||
|
||||
class CreateNewUser implements CreatesNewUsers
|
||||
{
|
||||
private const REGISTRATION_IP_MAX_ATTEMPTS = 3;
|
||||
|
||||
private const REGISTRATION_IP_DECAY_SECONDS = 600;
|
||||
|
||||
private const REGISTRATION_EMAIL_IDENTITY_MAX_ATTEMPTS = 3;
|
||||
|
||||
private const REGISTRATION_EMAIL_IDENTITY_DECAY_SECONDS = 3600;
|
||||
|
||||
public function __construct(private readonly Request $request) {}
|
||||
|
||||
/**
|
||||
* Validate and create a newly registered user.
|
||||
*
|
||||
@@ -23,6 +35,9 @@ class CreateNewUser implements CreatesNewUsers
|
||||
if (! $settings->is_registration_enabled) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$this->ensureRegistrationIsNotRateLimited($input);
|
||||
|
||||
Validator::make($input, [
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => [
|
||||
@@ -72,4 +87,42 @@ class CreateNewUser implements CreatesNewUsers
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $input
|
||||
*/
|
||||
private function ensureRegistrationIsNotRateLimited(array $input): void
|
||||
{
|
||||
$keys = [
|
||||
[
|
||||
'key' => 'registration:ip:'.sha1($this->realIp()),
|
||||
'max' => self::REGISTRATION_IP_MAX_ATTEMPTS,
|
||||
'decay' => self::REGISTRATION_IP_DECAY_SECONDS,
|
||||
],
|
||||
];
|
||||
|
||||
$emailIdentity = normalize_email_identity($input['email'] ?? null);
|
||||
if ($emailIdentity !== null) {
|
||||
$keys[] = [
|
||||
'key' => 'registration:email-identity:'.sha1($emailIdentity),
|
||||
'max' => self::REGISTRATION_EMAIL_IDENTITY_MAX_ATTEMPTS,
|
||||
'decay' => self::REGISTRATION_EMAIL_IDENTITY_DECAY_SECONDS,
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($keys as $limit) {
|
||||
if (RateLimiter::tooManyAttempts($limit['key'], $limit['max'])) {
|
||||
abort(429, 'Too many registration attempts. Please try again later.');
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($keys as $limit) {
|
||||
RateLimiter::hit($limit['key'], $limit['decay']);
|
||||
}
|
||||
}
|
||||
|
||||
private function realIp(): string
|
||||
{
|
||||
return $this->request->server('REMOTE_ADDR') ?? $this->request->ip();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user