feat: harden admin auth and ticket workflows
- add rotating admin refresh tokens and password gates\n- expand ticket galleries, exports, and client resources\n- improve IP allocation auditing and dashboard data\n- enforce encrypted client access tokens on public routes
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Api\Admin;
|
||||
|
||||
use App\Models\AdminRefreshToken;
|
||||
use Carbon\CarbonInterface;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Tymon\JWTAuth\Facades\JWTAuth;
|
||||
|
||||
class AdminRefreshTokenService
|
||||
{
|
||||
public function create(int $userId, CarbonInterface $expiresAt): string
|
||||
{
|
||||
$rawToken = Str::random(64);
|
||||
|
||||
AdminRefreshToken::create([
|
||||
'user_id' => $userId,
|
||||
'token' => hash('sha256', $rawToken),
|
||||
'expires_at' => $expiresAt,
|
||||
]);
|
||||
|
||||
return $rawToken;
|
||||
}
|
||||
|
||||
public function rotate(string $rawToken): array
|
||||
{
|
||||
return DB::transaction(function () use ($rawToken): array {
|
||||
$record = AdminRefreshToken::where('token', hash('sha256', $rawToken))
|
||||
->lockForUpdate()
|
||||
->first();
|
||||
|
||||
if (! $record || $record->expires_at->isPast()) {
|
||||
$record?->delete();
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'refresh_token' => ['Refresh token không hợp lệ hoặc đã hết hạn.'],
|
||||
]);
|
||||
}
|
||||
|
||||
$user = $record->user;
|
||||
if (! $user) {
|
||||
$record->delete();
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'refresh_token' => ['Tài khoản không hợp lệ.'],
|
||||
]);
|
||||
}
|
||||
|
||||
$expiresAt = $record->expires_at->copy();
|
||||
$record->delete();
|
||||
$newRefreshToken = $this->create($user->id, $expiresAt);
|
||||
|
||||
return [
|
||||
'user' => $user,
|
||||
'token' => JWTAuth::fromUser($user),
|
||||
'refresh_token' => $newRefreshToken,
|
||||
'refresh_expires_in' => (int) max(0, now()->diffInSeconds($expiresAt, false)),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function revoke(string $rawToken): void
|
||||
{
|
||||
AdminRefreshToken::where('token', hash('sha256', $rawToken))->delete();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user