2023-10-02 23:10:49 +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;
|
|
|
|
|
|
|
|
|
|
readonly class AuthService
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
public function __construct(
|
|
|
|
|
private ChannelService $channelService,
|
|
|
|
|
private UserRepo $userRepo,
|
|
|
|
|
public Session $session,
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-06 13:07:09 +03:00
|
|
|
|
2023-10-02 23:10:49 +03:00
|
|
|
public function currentUserId(): ?string
|
|
|
|
|
{
|
2024-01-15 16:32:24 +02:00
|
|
|
|
2023-10-17 22:57:25 +03:00
|
|
|
if (app()->runningInConsole()) {
|
2023-10-06 13:07:09 +03:00
|
|
|
return config("lucent.systemUserId");
|
2024-01-15 16:32:24 +02:00
|
|
|
} elseif(request()->segment(1) !== "lucent") {
|
|
|
|
|
return config("lucent.systemUserId");
|
2023-10-17 22:57:25 +03:00
|
|
|
} else {
|
2024-01-15 16:32:24 +02:00
|
|
|
return $this->session->get("user.id");
|
2023-10-06 13:07:09 +03:00
|
|
|
}
|
|
|
|
|
|
2023-10-02 23:10:49 +03:00
|
|
|
}
|
|
|
|
|
|
2024-01-15 16:32:24 +02:00
|
|
|
public
|
|
|
|
|
function currentUserRoles(): array
|
2023-10-17 22:57:25 +03:00
|
|
|
{
|
|
|
|
|
return $this->session->get("user.roles") ?? [];
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-15 16:32:24 +02:00
|
|
|
public
|
|
|
|
|
function isLoggedIn(): bool
|
2023-10-02 23:10:49 +03:00
|
|
|
{
|
|
|
|
|
return !empty($this->currentUserId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @throws LucentException
|
|
|
|
|
*/
|
2024-01-15 16:32:24 +02:00
|
|
|
public
|
|
|
|
|
function login(string $email, string $token): void
|
2023-10-02 23:10:49 +03:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
$user = $this->userRepo->findByEmail(new Email($email));
|
|
|
|
|
|
|
|
|
|
if ($user->isEmpty()) {
|
2023-10-18 01:54:24 +03:00
|
|
|
throw new LucentException("Your account was not found");
|
2023-10-02 23:10:49 +03:00
|
|
|
}
|
|
|
|
|
|
2023-10-17 22:57:25 +03:00
|
|
|
if ($user->get()->isRemoved()) {
|
2023-10-02 23:10:49 +03:00
|
|
|
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()]);
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-15 16:32:24 +02:00
|
|
|
public
|
|
|
|
|
function refreshSession()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
2023-10-18 01:54:24 +03:00
|
|
|
$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()]);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-02 23:10:49 +03:00
|
|
|
|
2024-01-15 16:32:24 +02:00
|
|
|
public
|
|
|
|
|
function create(string $name, string $email, array $roles): User
|
2023-10-02 23:10:49 +03:00
|
|
|
{
|
|
|
|
|
$user = new User(
|
|
|
|
|
id: (string)Str::uuid(),
|
|
|
|
|
name: new Name($name),
|
|
|
|
|
email: new Email($email),
|
2023-10-17 22:57:25 +03:00
|
|
|
roles: $this->validateRoles($roles),
|
2023-10-02 23:10:49 +03:00
|
|
|
createdAt: Carbon::now()->toJson(),
|
|
|
|
|
updatedAt: Carbon::now()->toJson(),
|
|
|
|
|
loggedInAt: Carbon::now()->toJson(),
|
|
|
|
|
mailToken: Token::new(32),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$this->userRepo->insert($user);
|
|
|
|
|
return $user;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2024-08-14 22:04:34 +03:00
|
|
|
|
|
|
|
|
public function sendLoginEmail(string $email): void
|
2023-10-02 23:10:49 +03:00
|
|
|
{
|
|
|
|
|
$emailAddress = (new Email($email));
|
|
|
|
|
$user = $this->userRepo->findByEmail($emailAddress);
|
|
|
|
|
|
|
|
|
|
if ($user->isEmpty()) {
|
2024-08-14 22:04:34 +03:00
|
|
|
return;
|
2023-10-02 23:10:49 +03:00
|
|
|
}
|
|
|
|
|
|
2023-10-17 22:57:25 +03:00
|
|
|
if ($user->get()->isRemoved()) {
|
2024-08-14 22:04:34 +03:00
|
|
|
return;
|
2023-10-02 23:10:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$newToken = $this->userRepo->updateLoginToken($user->get()->id);
|
|
|
|
|
|
|
|
|
|
Mail::to($email)->send(
|
|
|
|
|
new LoginMail(
|
|
|
|
|
$email,
|
|
|
|
|
$newToken,
|
|
|
|
|
$this->channelService->channel->lucentUrl
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @throws LucentException
|
|
|
|
|
*/
|
2024-01-15 16:32:24 +02:00
|
|
|
public
|
|
|
|
|
function changeRoles(string $userId, array $roles): void
|
2023-10-02 23:10:49 +03:00
|
|
|
{
|
|
|
|
|
$user = $this->userRepo->findById($userId);
|
|
|
|
|
|
|
|
|
|
if ($user->isEmpty()) {
|
|
|
|
|
throw new LucentException("User not found");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$newUser = $user->get();
|
2023-10-17 22:57:25 +03:00
|
|
|
$newUser->roles = $this->validateRoles($roles);
|
2023-10-02 23:10:49 +03:00
|
|
|
$newUser->updatedAt = Carbon::now()->toJson();
|
|
|
|
|
$this->userRepo->update($newUser);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @throws LucentException
|
|
|
|
|
*/
|
2024-01-15 16:32:24 +02:00
|
|
|
public
|
|
|
|
|
function updateName(string $name): void
|
2023-10-02 23:10:49 +03:00
|
|
|
{
|
|
|
|
|
$name = (new Name($name));
|
2023-10-04 23:48:12 +03:00
|
|
|
$this->userRepo->updateName($this->currentUserId(), $name);
|
2023-10-17 18:30:41 +03:00
|
|
|
$user = $this->userRepo->findById($this->currentUserId());
|
|
|
|
|
$this->session->put(["user" => $user->get()->safe()]);
|
|
|
|
|
}
|
2023-10-02 23:10:49 +03:00
|
|
|
|
2023-10-17 18:30:41 +03:00
|
|
|
/**
|
|
|
|
|
* @throws LucentException
|
|
|
|
|
*/
|
2024-01-15 16:32:24 +02:00
|
|
|
public
|
|
|
|
|
function updateEmail(string $email): void
|
2023-10-17 18:30:41 +03:00
|
|
|
{
|
|
|
|
|
$email = (new Email($email));
|
|
|
|
|
$user = $this->userRepo->findByEmail($email);
|
2023-10-17 22:57:25 +03:00
|
|
|
if ($user->isDefined()) {
|
2023-10-17 18:30:41 +03:00
|
|
|
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()]);
|
2023-10-02 23:10:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @throws LucentException
|
|
|
|
|
*/
|
2024-01-15 16:32:24 +02:00
|
|
|
public
|
|
|
|
|
function invite(
|
2023-10-02 23:10:49 +03:00
|
|
|
string $name,
|
|
|
|
|
string $email,
|
2023-10-17 22:57:25 +03:00
|
|
|
array $roles
|
2023-10-02 23:10:49 +03:00
|
|
|
): User
|
|
|
|
|
{
|
2023-10-17 22:57:25 +03:00
|
|
|
$user = $this->create($name, $email, $roles);
|
2023-10-02 23:10:49 +03:00
|
|
|
$this->sendLoginEmail($user->email);
|
|
|
|
|
return $user;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-04 13:32:30 +03:00
|
|
|
/**
|
|
|
|
|
* @throws LucentException
|
|
|
|
|
*/
|
2024-01-15 16:32:24 +02:00
|
|
|
public
|
|
|
|
|
function registerAdmin(
|
2023-10-04 13:32:30 +03:00
|
|
|
string $name,
|
|
|
|
|
string $email
|
|
|
|
|
): User
|
|
|
|
|
{
|
2023-10-17 22:57:25 +03:00
|
|
|
$user = $this->invite($name, $email, ["admin"]);
|
2023-10-04 13:32:30 +03:00
|
|
|
$this->sendLoginEmail($user->email);
|
|
|
|
|
return $user;
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-15 16:32:24 +02:00
|
|
|
public
|
|
|
|
|
function validateRoles(array $roles): array
|
2023-10-17 22:57:25 +03:00
|
|
|
{
|
|
|
|
|
return collect($roles)
|
|
|
|
|
->filter(fn(string $role) => in_array($role, $this->channelService->channel->roles))
|
|
|
|
|
->unique()
|
|
|
|
|
->values()
|
|
|
|
|
->toArray();
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-02 23:10:49 +03:00
|
|
|
|
|
|
|
|
}
|