Files
lucent-laravel/src/Account/AuthServiceLucent.php
T

225 lines
6.1 KiB
PHP
Raw Normal View History

2026-04-20 21:07:35 +03:00
<?php
namespace Lucent\Account;
use Carbon\Carbon;
use Illuminate\Contracts\Session\Session;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
use Lucent\Channel\ChannelService;
use Lucent\LucentException;
use Lucent\Mail\LoginMail;
use Filament\Facades\Filament;
readonly class AuthServiceLucent implements AuthService
{
public function __construct(
private ChannelService $channelService,
private UserRepo $userRepo,
public Session $session,
) {}
public function currentUserId(): ?string
{
if (app()->runningInConsole()) {
return config("lucent.systemUserId");
} elseif (request()->segment(1) !== "lucent") {
return config("lucent.systemUserId");
}
return $this->session->get("user.id");
}
public function currentUserRoles(): array
{
return $this->session->get("user.roles") ?? [];
}
public function getCurrentUser(): User
{
return new User(
id: $this->session->get("user.id"),
name: new Name($this->session->get("user.name")),
email: new Email($this->session->get("user.email")),
roles: $this->session->get("user.roles"),
createdAt: $this->session->get("user.createdAt"),
updatedAt: $this->session->get("user.updatedAt"),
loggedInAt: null,
mailToken: null,
);
}
public function isLoggedIn(): bool
{
return !empty($this->currentUserId());
}
/**
* @throws LucentException
*/
public function login(string $email, string $token): void
{
$user = $this->userRepo->findByEmail(new Email($email));
if ($user->isEmpty()) {
throw new LucentException("Your account was not found");
}
if ($user->get()->isRemoved()) {
throw new LucentException("Your account is not active");
}
if ($user->get()->mailToken !== $token) {
throw new LucentException("Token has expired or is invalid");
}
if (
Carbon::parse($user->get()->loggedInAt)->lte(
Carbon::now()->subHours(1),
)
) {
throw new LucentException("Token has expired.");
}
$newUser = $user->get();
$newUser->updatedAt = Carbon::now()->toJson();
$newUser->mailToken = null;
$this->userRepo->update($newUser);
$this->session->put(["user" => $user->get()->safe()]);
}
public function refreshSession()
{
$user = $this->userRepo->findById($this->currentUserId());
if ($user->isEmpty()) {
throw new LucentException("Your account was not found");
}
if ($user->get()->isRemoved()) {
throw new LucentException("Your account is not active");
}
$newUser = $user->get();
$this->session->put(["user" => $user->get()->safe()]);
}
public function create(string $name, string $email, array $roles): User
{
$user = new User(
id: (string) Str::uuid(),
name: new Name($name),
email: new Email($email),
roles: $this->validateRoles($roles),
createdAt: Carbon::now()->toJson(),
updatedAt: Carbon::now()->toJson(),
loggedInAt: Carbon::now()->toJson(),
mailToken: Token::new(32),
);
$this->userRepo->insert($user);
return $user;
}
public function sendLoginEmail(string $email): void
{
$emailAddress = new Email($email);
$user = $this->userRepo->findByEmail($emailAddress);
if ($user->isEmpty()) {
return;
}
if ($user->get()->isRemoved()) {
return;
}
$newToken = $this->userRepo->updateLoginToken($user->get()->id);
Mail::to($email)->send(
new LoginMail(
$email,
$newToken,
$this->channelService->channel->lucentUrl,
),
);
}
/**
* @throws LucentException
*/
public function changeRoles(string $userId, array $roles): void
{
$user = $this->userRepo->findById($userId);
if ($user->isEmpty()) {
throw new LucentException("User not found");
}
$newUser = $user->get();
$newUser->roles = $this->validateRoles($roles);
$newUser->updatedAt = Carbon::now()->toJson();
$this->userRepo->update($newUser);
}
/**
* @throws LucentException
*/
public function updateName(string $name): void
{
$name = new Name($name);
$this->userRepo->updateName($this->currentUserId(), $name);
$user = $this->userRepo->findById($this->currentUserId());
$this->session->put(["user" => $user->get()->safe()]);
}
/**
* @throws LucentException
*/
public function updateEmail(string $email): void
{
$email = new Email($email);
$user = $this->userRepo->findByEmail($email);
if ($user->isDefined()) {
throw new LucentException("Email already assigned to user");
}
$this->userRepo->updateEmail($this->currentUserId(), $email);
$user = $this->userRepo->findById($this->currentUserId());
$this->session->put(["user" => $user->get()->safe()]);
}
/**
* @throws LucentException
*/
public function invite(string $name, string $email, array $roles): User
{
$user = $this->create($name, $email, $roles);
$this->sendLoginEmail($user->email);
return $user;
}
/**
* @throws LucentException
*/
public function registerAdmin(string $name, string $email): User
{
$user = $this->invite($name, $email, ["admin"]);
$this->sendLoginEmail($user->email);
return $user;
}
public function validateRoles(array $roles): array
{
return collect($roles)
->filter(
fn(string $role) => in_array(
$role,
$this->channelService->channel->roles,
),
)
->unique()
->values()
->toArray();
}
}