add auth sessions
This commit is contained in:
parent
a37c8da555
commit
34e26f81f5
9 changed files with 243 additions and 0 deletions
10
backend/app/Auth/Clock.php
Normal file
10
backend/app/Auth/Clock.php
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Auth;
|
||||||
|
|
||||||
|
use DateTimeImmutable;
|
||||||
|
|
||||||
|
interface Clock
|
||||||
|
{
|
||||||
|
public function now(): DateTimeImmutable;
|
||||||
|
}
|
||||||
16
backend/app/Auth/CreateSessionDto.php
Normal file
16
backend/app/Auth/CreateSessionDto.php
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Auth;
|
||||||
|
|
||||||
|
use App\User\User;
|
||||||
|
use DateTimeImmutable;
|
||||||
|
|
||||||
|
final readonly class CreateSessionDto
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public string $token,
|
||||||
|
public User $user,
|
||||||
|
public DateTimeImmutable $createdAt,
|
||||||
|
public DateTimeImmutable $expiresAt,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
63
backend/app/Auth/EloquentSessionRepository.php
Normal file
63
backend/app/Auth/EloquentSessionRepository.php
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Auth;
|
||||||
|
|
||||||
|
use App\User\UserRepository;
|
||||||
|
use Carbon\CarbonInterface;
|
||||||
|
use DateTimeImmutable;
|
||||||
|
use DateTimeZone;
|
||||||
|
|
||||||
|
class EloquentSessionRepository implements SessionRepository
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private UserRepository $userRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function create(CreateSessionDto $dto): Session
|
||||||
|
{
|
||||||
|
SessionModel::create([
|
||||||
|
'token' => $dto->token,
|
||||||
|
'user_id' => $dto->user->getId(),
|
||||||
|
'created_at' => $dto->createdAt,
|
||||||
|
'expires_at' => $dto->expiresAt,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return new Session(
|
||||||
|
token: $dto->token,
|
||||||
|
user: $dto->user,
|
||||||
|
createdAt: $dto->createdAt,
|
||||||
|
expiresAt: $dto->expiresAt,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findByToken(string $token): ?Session
|
||||||
|
{
|
||||||
|
$model = SessionModel::find($token);
|
||||||
|
if ($model === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $this->userRepository->find($model->user_id);
|
||||||
|
if ($user === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Session(
|
||||||
|
token: $model->token,
|
||||||
|
user: $user,
|
||||||
|
createdAt: $this->toUtc($model->created_at),
|
||||||
|
expiresAt: $this->toUtc($model->expires_at),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteByToken(string $token): void
|
||||||
|
{
|
||||||
|
SessionModel::where('token', $token)->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function toUtc(CarbonInterface $dateTime): DateTimeImmutable
|
||||||
|
{
|
||||||
|
return DateTimeImmutable::createFromInterface($dateTime)
|
||||||
|
->setTimezone(new DateTimeZone('UTC'));
|
||||||
|
}
|
||||||
|
}
|
||||||
41
backend/app/Auth/Session.php
Normal file
41
backend/app/Auth/Session.php
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Auth;
|
||||||
|
|
||||||
|
use App\User\User;
|
||||||
|
use DateTimeImmutable;
|
||||||
|
|
||||||
|
final readonly class Session
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private string $token,
|
||||||
|
private User $user,
|
||||||
|
private DateTimeImmutable $createdAt,
|
||||||
|
private DateTimeImmutable $expiresAt,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function getToken(): string
|
||||||
|
{
|
||||||
|
return $this->token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUser(): User
|
||||||
|
{
|
||||||
|
return $this->user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCreatedAt(): DateTimeImmutable
|
||||||
|
{
|
||||||
|
return $this->createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getExpiresAt(): DateTimeImmutable
|
||||||
|
{
|
||||||
|
return $this->expiresAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isExpired(DateTimeImmutable $now): bool
|
||||||
|
{
|
||||||
|
return $now >= $this->expiresAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
50
backend/app/Auth/SessionModel.php
Normal file
50
backend/app/Auth/SessionModel.php
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Auth;
|
||||||
|
|
||||||
|
use Carbon\CarbonInterface;
|
||||||
|
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property string $token
|
||||||
|
* @property int $user_id
|
||||||
|
* @property CarbonInterface $created_at
|
||||||
|
* @property CarbonInterface $expires_at
|
||||||
|
*
|
||||||
|
* @method static Builder<static>|SessionModel newModelQuery()
|
||||||
|
* @method static Builder<static>|SessionModel newQuery()
|
||||||
|
* @method static Builder<static>|SessionModel query()
|
||||||
|
*
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
#[Fillable([
|
||||||
|
'token',
|
||||||
|
'user_id',
|
||||||
|
'created_at',
|
||||||
|
'expires_at',
|
||||||
|
])]
|
||||||
|
class SessionModel extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'auth_sessions';
|
||||||
|
|
||||||
|
protected $primaryKey = 'token';
|
||||||
|
|
||||||
|
public $incrementing = false;
|
||||||
|
|
||||||
|
protected $keyType = 'string';
|
||||||
|
|
||||||
|
public $timestamps = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'created_at' => 'datetime',
|
||||||
|
'expires_at' => 'datetime',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
12
backend/app/Auth/SessionRepository.php
Normal file
12
backend/app/Auth/SessionRepository.php
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Auth;
|
||||||
|
|
||||||
|
interface SessionRepository
|
||||||
|
{
|
||||||
|
public function create(CreateSessionDto $dto): Session;
|
||||||
|
|
||||||
|
public function findByToken(string $token): ?Session;
|
||||||
|
|
||||||
|
public function deleteByToken(string $token): void;
|
||||||
|
}
|
||||||
17
backend/app/Auth/SystemClock.php
Normal file
17
backend/app/Auth/SystemClock.php
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Auth;
|
||||||
|
|
||||||
|
use DateTimeImmutable;
|
||||||
|
use DateTimeZone;
|
||||||
|
|
||||||
|
class SystemClock implements Clock
|
||||||
|
{
|
||||||
|
public function now(): DateTimeImmutable
|
||||||
|
{
|
||||||
|
return new DateTimeImmutable(
|
||||||
|
'now',
|
||||||
|
new DateTimeZone('UTC'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use App\Auth\Clock;
|
||||||
|
use App\Auth\EloquentSessionRepository;
|
||||||
|
use App\Auth\SessionRepository;
|
||||||
|
use App\Auth\SystemClock;
|
||||||
use App\User\EloquentUserRepository;
|
use App\User\EloquentUserRepository;
|
||||||
use App\User\UserRepository;
|
use App\User\UserRepository;
|
||||||
use Carbon\CarbonImmutable;
|
use Carbon\CarbonImmutable;
|
||||||
|
|
@ -21,6 +25,11 @@ class AppServiceProvider extends ServiceProvider
|
||||||
UserRepository::class,
|
UserRepository::class,
|
||||||
EloquentUserRepository::class,
|
EloquentUserRepository::class,
|
||||||
);
|
);
|
||||||
|
$this->app->bind(
|
||||||
|
SessionRepository::class,
|
||||||
|
EloquentSessionRepository::class,
|
||||||
|
);
|
||||||
|
$this->app->bind(Clock::class, SystemClock::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('auth_sessions', function (Blueprint $table): void {
|
||||||
|
$table->string('token', 64)->primary();
|
||||||
|
$table->foreignId('user_id')
|
||||||
|
->constrained('users')
|
||||||
|
->cascadeOnDelete();
|
||||||
|
$table->timestamp('created_at');
|
||||||
|
$table->timestamp('expires_at')->index();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('auth_sessions');
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue