GeoNetAgent, LDAPWeb, server-audit, server-connection
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

102 lines
2.8 KiB

<?php
namespace App\Services;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
use InvalidArgumentException;
use RuntimeException;
use Throwable;
class LdapPasswordResetService
{
private const TOKEN_TTL_MINUTES = 60;
public function __construct(
private readonly LdapAuthService $authService,
private readonly LdapUserService $userService,
private readonly MailDeliveryService $mailDelivery
) {
}
public function sendResetLink(string $username): bool
{
$username = trim($username);
if (! preg_match('/^[a-zA-Z0-9._-]+$/', $username)) {
return false;
}
$user = $this->authService->lookupUser($username);
if ($user === null || $user['email'] === '') {
return false;
}
$token = Str::random(64);
Cache::put($this->cacheKey($token), $username, now()->addMinutes(self::TOKEN_TTL_MINUTES));
$url = route('password.reset', ['token' => $token]);
$this->mailDelivery->sendTemplated($user['email'], 'password_reset', [
'username' => $username,
'display_name' => $user['display_name'],
'reset_url' => $url,
'expires_minutes' => self::TOKEN_TTL_MINUTES,
]);
return true;
}
public function validateToken(string $token): ?string
{
if (! preg_match('/^[a-zA-Z0-9]{64}$/', $token)) {
return null;
}
return Cache::get($this->cacheKey($token));
}
public function resetPassword(string $token, string $password): void
{
$username = $this->validateToken($token);
if ($username === null) {
throw new InvalidArgumentException('Reset link is invalid or has expired.');
}
try {
$this->userService->resetPassword($username, $password);
Cache::forget($this->cacheKey($token));
$this->notifyPasswordChanged($username, session('ldap_username'));
} catch (RuntimeException $e) {
throw new InvalidArgumentException($e->getMessage());
}
}
public function notifyPasswordChanged(string $username, ?string $changedBy = null): void
{
try {
$user = $this->authService->lookupUser($username);
if ($user === null || $user['email'] === '') {
return;
}
$this->mailDelivery->notifyPasswordChanged(
$user['email'],
$username,
$user['display_name'],
$changedBy
);
} catch (Throwable) {
// Notification must not block password change.
}
}
private function cacheKey(string $token): string
{
return 'ldap_password_reset:' . $token;
}
}