feat: implement JWT-based authentication system with repository, service, and middleware layers
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
namespace WorkbloomERP\Module\Auth\Service;
|
||||
|
||||
use RuntimeException;
|
||||
use WorkbloomERP\Module\Auth\DTO\LoginDTO;
|
||||
use WorkbloomERP\Module\Auth\Repository\AuthRepository;
|
||||
use WorkbloomERP\Security\JwtService;
|
||||
|
||||
class AuthService {
|
||||
private AuthRepository $repository;
|
||||
private JwtService $jwtService;
|
||||
|
||||
public function __construct(
|
||||
?AuthRepository $repository = null,
|
||||
?JwtService $jwtService = null
|
||||
) {
|
||||
$this->repository = $repository ?? new AuthRepository();
|
||||
$this->jwtService = $jwtService ?? new JwtService();
|
||||
}
|
||||
|
||||
/**
|
||||
* Realiza a autenticação do usuário com validação de credenciais e status.
|
||||
*
|
||||
* @param LoginDTO $dto
|
||||
* @return array
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function login(LoginDTO $dto): array {
|
||||
$user = $this->repository->findByLogin($dto->login);
|
||||
|
||||
// Prevenção contra enumeração de usuários: mensagem genérica para usuário inexistente
|
||||
if ($user === null) {
|
||||
throw new RuntimeException('Credenciais inválidas.', 401);
|
||||
}
|
||||
|
||||
// Validação de conta ativa
|
||||
if (empty($user['ativo'])) {
|
||||
throw new RuntimeException('Usuário inativo no sistema.', 403);
|
||||
}
|
||||
|
||||
// Validação segura de senha com hash
|
||||
if (!password_verify($dto->senha, $user['senha_hash'])) {
|
||||
throw new RuntimeException('Credenciais inválidas.', 401);
|
||||
}
|
||||
|
||||
$userUuid = (string)$user['uuid'];
|
||||
$empresas = $this->repository->findEmpresasByUsuarioUuid($userUuid);
|
||||
|
||||
$tokenPayload = [
|
||||
'sub' => $userUuid,
|
||||
'email' => $user['email'],
|
||||
'nome_usuario' => $user['nome_usuario'],
|
||||
'nome_completo' => $user['nome_completo'],
|
||||
];
|
||||
|
||||
$tokenData = $this->jwtService->generateToken($tokenPayload);
|
||||
|
||||
return [
|
||||
'token' => $tokenData['token'],
|
||||
'token_type' => 'Bearer',
|
||||
'expires_in' => $tokenData['expires_in'],
|
||||
'expires_at' => $tokenData['expires_at'],
|
||||
'usuario' => [
|
||||
'uuid' => $user['uuid'],
|
||||
'nome_completo' => $user['nome_completo'],
|
||||
'cpf' => $user['cpf'],
|
||||
'email' => $user['email'],
|
||||
'nome_usuario' => $user['nome_usuario'],
|
||||
],
|
||||
'empresas' => $empresas,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retorna os dados do usuário autenticado a partir do UUID (sem expor credenciais nem ID inteiro).
|
||||
*
|
||||
* @param string $userUuid
|
||||
* @return array
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function getProfile(string $userUuid): array {
|
||||
$user = $this->repository->findByUuid($userUuid);
|
||||
|
||||
if ($user === null) {
|
||||
throw new RuntimeException('Usuário não encontrado.', 404);
|
||||
}
|
||||
|
||||
if (empty($user['ativo'])) {
|
||||
throw new RuntimeException('Usuário inativo no sistema.', 403);
|
||||
}
|
||||
|
||||
$empresas = $this->repository->findEmpresasByUsuarioUuid($userUuid);
|
||||
|
||||
return [
|
||||
'usuario' => [
|
||||
'uuid' => $user['uuid'],
|
||||
'nome_completo' => $user['nome_completo'],
|
||||
'cpf' => $user['cpf'],
|
||||
'email' => $user['email'],
|
||||
'nome_usuario' => $user['nome_usuario'],
|
||||
'ativo' => (bool)$user['ativo'],
|
||||
'created_at' => $user['created_at'],
|
||||
],
|
||||
'empresas' => $empresas,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user