From 34e26f81f535ae58293a74f90a1e75640c365e63 Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Fri, 31 Jul 2026 09:51:39 +0300 Subject: [PATCH] add auth sessions --- backend/app/Auth/Clock.php | 10 +++ backend/app/Auth/CreateSessionDto.php | 16 +++++ .../app/Auth/EloquentSessionRepository.php | 63 +++++++++++++++++++ backend/app/Auth/Session.php | 41 ++++++++++++ backend/app/Auth/SessionModel.php | 50 +++++++++++++++ backend/app/Auth/SessionRepository.php | 12 ++++ backend/app/Auth/SystemClock.php | 17 +++++ backend/app/Providers/AppServiceProvider.php | 9 +++ ...7_31_000000_create_auth_sessions_table.php | 25 ++++++++ 9 files changed, 243 insertions(+) create mode 100644 backend/app/Auth/Clock.php create mode 100644 backend/app/Auth/CreateSessionDto.php create mode 100644 backend/app/Auth/EloquentSessionRepository.php create mode 100644 backend/app/Auth/Session.php create mode 100644 backend/app/Auth/SessionModel.php create mode 100644 backend/app/Auth/SessionRepository.php create mode 100644 backend/app/Auth/SystemClock.php create mode 100644 backend/database/migrations/2026_07_31_000000_create_auth_sessions_table.php diff --git a/backend/app/Auth/Clock.php b/backend/app/Auth/Clock.php new file mode 100644 index 0000000..b96ad32 --- /dev/null +++ b/backend/app/Auth/Clock.php @@ -0,0 +1,10 @@ + $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')); + } +} diff --git a/backend/app/Auth/Session.php b/backend/app/Auth/Session.php new file mode 100644 index 0000000..5fd9cb1 --- /dev/null +++ b/backend/app/Auth/Session.php @@ -0,0 +1,41 @@ +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; + } +} diff --git a/backend/app/Auth/SessionModel.php b/backend/app/Auth/SessionModel.php new file mode 100644 index 0000000..75e87e3 --- /dev/null +++ b/backend/app/Auth/SessionModel.php @@ -0,0 +1,50 @@ +|SessionModel newModelQuery() + * @method static Builder|SessionModel newQuery() + * @method static Builder|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 + */ + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'expires_at' => 'datetime', + ]; + } +} diff --git a/backend/app/Auth/SessionRepository.php b/backend/app/Auth/SessionRepository.php new file mode 100644 index 0000000..cabae60 --- /dev/null +++ b/backend/app/Auth/SessionRepository.php @@ -0,0 +1,12 @@ +app->bind( + SessionRepository::class, + EloquentSessionRepository::class, + ); + $this->app->bind(Clock::class, SystemClock::class); } /** diff --git a/backend/database/migrations/2026_07_31_000000_create_auth_sessions_table.php b/backend/database/migrations/2026_07_31_000000_create_auth_sessions_table.php new file mode 100644 index 0000000..995c147 --- /dev/null +++ b/backend/database/migrations/2026_07_31_000000_create_auth_sessions_table.php @@ -0,0 +1,25 @@ +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'); + } +};