first commit

This commit is contained in:
Claudecio Martins
2025-10-21 16:51:43 +02:00
commit 044c6bd587
4215 changed files with 422857 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
<?php
namespace Workbloom\Component\Auth;
use DateTime;
use Exception;
use AxiumPHP\Core\Router;
// Caminho do manifest.json
$manifestPath = realpath(path: __DIR__ . "/manifest.json");
if (!$manifestPath || !file_exists(filename: $manifestPath)) {
throw new Exception(message: "Arquivo 'manifest.json' não encontrado.");
}
// Lê e decodifica
$manifest = json_decode(json: file_get_contents(filename: $manifestPath), associative: true);
// Verifica estrutura
if (!isset($manifest['apis']) || !is_array(value: $manifest['apis'])) {
throw new Exception(message: "Estrutura de 'apis' inválida no manifest.");
}
$now = (new DateTime())->format(format: 'Y-m-d');
$newApis = [];
$updated = false;
// Checa se tem versão esperando que começa hoje
foreach ($manifest['apis'] as $api) {
if ($api['status'] === 'planned' && $api['start_date'] === $now) {
// Promote a nova
$api['status'] = 'active';
$newApis[] = $api;
$updated = true;
} elseif ($api['status'] === 'active' && $api['start_date'] !== $now) {
// Ignora versão antiga ativa
continue;
} else {
$newApis[] = $api;
}
}
// Atualiza manifest se tiver mudança
if ($updated) {
$manifest['apis'] = $newApis;
file_put_contents(filename: $manifestPath, data: json_encode(value: $manifest, flags: JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
}
// Carrega a versão ativa
$loaded = false;
foreach ($manifest['apis'] as $api) {
$startDate = new DateTime(datetime: $api['start_date']);
if ($api['status'] === 'active' && $startDate <= new DateTime()) {
$routeFile = COMPONENT_PATH . "/{$manifest['dirName']}/{$api['version']}/Routes/Routes.php";
if (file_exists(filename: $routeFile)) {
Router::group(
prefix: "{$api['version']}/{$manifest['slug']}",
callback: function() use ($routeFile) {
require_once realpath(path: $routeFile);
},
middlewares: []
);
$loaded = true;
break;
} else {
throw new Exception(message: "Arquivo de rotas não encontrado para a versão '{$api['version']}'.");
}
}
}
// Verifica se carregou
if (!$loaded) {
throw new Exception(message: "Nenhuma versão ativa da API foi carregada.");
}

View File

@@ -0,0 +1,16 @@
{
"name": "Autenticação",
"dirName": "Auth",
"slug": "auth",
"description": "Gerencia login, logout, sessão e permissões de acesso.",
"uuid": "0199abc8-026a-75b0-9b25-0f9456a44c70",
"version": "1.0",
"dependencies": [],
"apis": [
{
"version": "v0",
"status": "active",
"start_date": "2025-08-01"
}
]
}

View File

@@ -0,0 +1,51 @@
<?php
namespace Workbloom\Component\Auth\v0\Controllers;
use Workbloom\Helpers\DataSanitizer;
use AxiumPHP\Helpers\RequestHelper;
use Workbloom\Component\Auth\v0\Services\AuthService;
class AuthController {
public function login() {
// Recebe formulário de login
$form = RequestHelper::getFilteredInput(form_type: INPUT_POST);
// Define campos obrigatórios
$required_fields = [
'login',
'password'
];
// Validação dos campos obrigatórios
foreach ($required_fields as $field) {
if (empty($form[$field])) {
// Resposta JSON de erro
RequestHelper::sendJsonResponse(
response_code: 400,
status: 'error',
message: "O campo '{$field}' é obrigatório",
output: []
);
return;
}
}
// Chama o serviço de autenticação
$loginService = (new AuthService())->login(
credentials: [
'login' => DataSanitizer::string(value: $form['login']),
'password' => DataSanitizer::string(value: $form['password'])
]
);
// Resposta JSON
RequestHelper::sendJsonResponse(
response_code: 200,
status: 'success',
message: 'Login successful',
output: [
'data' => $form
]
);
}
}

View File

@@ -0,0 +1,177 @@
<?php
namespace Workbloom\Component\Auth\v0\DTO;
class UsuarioDTO {
private ?int $id = null;
private ?string $uuid = null;
private ?int $status_id = null;
private ?int $is_root = 0;
private ?string $nome_completo = null;
private ?string $nome_usuario = null;
private ?string $email = null;
private ?string $senha_hash = null;
private ?int $need_update_password = 1;
private ?int $days_to_expire_password = 60;
private ?string $last_password_update = null;
private ?string $created_at = null;
private ?string $updated_at = null;
private ?string $deleted_at = null;
/**
* Construtor do DTO.
*
* Permite inicializar os atributos do objeto a partir de um array associativo.
*
* @param array<string, mixed> $data Array associativo opcional para popular os atributos.
*/
public function __construct(array $data = []) {
if (!empty($data)) {
$this->fromArray(data: $data);
}
}
/**
* Popula o DTO a partir de um array.
*
* @param array<string, mixed> $data
* @return void
*/
public function fromArray(array $data): void {
$this->id = $data['id'] ?? $this->id;
$this->uuid = $data['uuid'] ?? $this->uuid;
$this->status_id = $data['status_id'] ?? $this->status_id;
$this->is_root = $data['is_root'] ?? $this->is_root;
$this->nome_completo = $data['nome_completo'] ?? $this->nome_completo;
$this->nome_usuario = $data['nome_usuario'] ?? $this->nome_usuario;
$this->email = $data['email'] ?? $this->email;
$this->senha_hash = $data['senha_hash'] ?? $this->senha_hash;
$this->need_update_password = $data['need_update_password'] ?? $this->need_update_password;
$this->days_to_expire_password = $data['days_to_expire_password'] ?? $this->days_to_expire_password;
$this->last_password_update = $data['last_password_update'] ?? $this->last_password_update;
$this->created_at = $data['created_at'] ?? $this->created_at;
$this->updated_at = $data['updated_at'] ?? $this->updated_at;
$this->deleted_at = $data['deleted_at'] ?? $this->deleted_at;
}
/**
* Converte o DTO para um array associativo.
*
* @return array<string, mixed>
*/
public function toArray(): array {
return [
'id' => $this->id,
'uuid' => $this->uuid,
'status_id' => $this->status_id,
'is_root' => $this->is_root,
'nome_completo' => $this->nome_completo,
'nome_usuario' => $this->nome_usuario,
'email' => $this->email,
'senha_hash' => $this->senha_hash,
'need_update_password' => $this->need_update_password,
'days_to_expire_password' => $this->days_to_expire_password,
'last_password_update' => $this->last_password_update,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'deleted_at' => $this->deleted_at,
];
}
public function getId(): ?int {
return $this->id;
}
public function setId(?int $id): void {
$this->id = $id;
}
public function getUuid(): ?string {
return $this->uuid;
}
public function setUuid(?string $uuid): void {
$this->uuid = $uuid;
}
public function getStatusId(): ?int {
return $this->status_id;
}
public function setStatusId(?int $status_id): void {
$this->status_id = $status_id;
}
public function getIsRoot(): ?int {
return $this->is_root;
}
public function setIsRoot(?int $is_root): void {
$this->is_root = $is_root;
}
public function getNomeCompleto(): ?string {
return $this->nome_completo;
}
public function setNomeCompleto(?string $nome_completo): void {
$this->nome_completo = $nome_completo;
}
public function getNomeUsuario(): ?string {
return $this->nome_usuario;
}
public function setNomeUsuario(?string $nome_usuario): void {
$this->nome_usuario = $nome_usuario;
}
public function getEmail(): ?string {
return $this->email;
}
public function setEmail(?string $email): void {
$this->email = $email;
}
public function getSenhaHash(): ?string {
return $this->senha_hash;
}
public function setSenhaHash(?string $senha_hash): void {
$this->senha_hash = $senha_hash;
}
public function getNeedUpdatePassword(): ?int {
return $this->need_update_password;
}
public function setNeedUpdatePassword(?int $need_update_password): void {
$this->need_update_password = $need_update_password;
}
public function getDaysToExpirePassword(): ?int {
return $this->days_to_expire_password;
}
public function setDaysToExpirePassword(?int $days_to_expire_password): void {
$this->days_to_expire_password = $days_to_expire_password;
}
public function getLastPasswordUpdate(): ?string {
return $this->last_password_update;
}
public function setLastPasswordUpdate(?string $last_password_update): void {
$this->last_password_update = $last_password_update;
}
public function getCreatedAt(): ?string {
return $this->created_at;
}
public function setCreatedAt(?string $created_at): void {
$this->created_at = $created_at;
}
public function getUpdatedAt(): ?string {
return $this->updated_at;
}
public function setUpdatedAt(?string $updated_at): void {
$this->updated_at = $updated_at;
}
public function getDeletedAt(): ?string {
return $this->deleted_at;
}
public function setDeletedAt(?string $deleted_at): void {
$this->deleted_at = $deleted_at;
}
}

View File

@@ -0,0 +1,127 @@
<?php
namespace Workbloom\Component\Auth\v0\DTO;
class UsuarioTokenDTO {
private ?int $id = null;
private ?int $usuario_id = null;
private ?string $usuario_ip = null;
private ?string $usuario_user_agent = null;
private ?string $token = null;
private ?int $is_revoked = 0;
private ?string $created_at = null;
private ?string $revoked_at = null;
private ?string $expires_at = null;
/**
* Construtor do DTO.
*
* Permite inicializar os atributos do objeto a partir de um array associativo.
*
* @param array<string, mixed> $data Array associativo opcional para popular os atributos.
*/
public function __construct(array $data = []) {
if (!empty($data)) {
$this->fromArray(data: $data);
}
}
/**
* Popula o DTO a partir de um array.
*
* @param array<string, mixed> $data
* @return void
*/
public function fromArray(array $data): void {
$this->id = $data['id'] ?? $this->id;
$this->usuario_id = $data['usuario_id'] ?? $this->usuario_id;
$this->usuario_ip = $data['usuario_ip'] ?? $this->usuario_ip;
$this->usuario_user_agent = $data['usuario_user_agent'] ?? $this->usuario_user_agent;
$this->token = $data['token'] ?? $this->token;
$this->is_revoked = $data['is_revoked'] ?? $this->is_revoked;
$this->created_at = $data['created_at'] ?? $this->created_at;
$this->revoked_at = $data['revoked_at'] ?? $this->revoked_at;
$this->expires_at = $data['expires_at'] ?? $this->expires_at;
}
/**
* Converte o DTO para um array associativo.
*
* @return array<string, mixed>
*/
public function toArray(): array {
return [
'id' => $this->id,
'usuario_id' => $this->usuario_id,
'usuario_ip' => $this->usuario_ip,
'usuario_user_agent' => $this->usuario_user_agent,
'token' => $this->token,
'is_revoked' => $this->is_revoked,
'created_at' => $this->created_at,
'revoked_at' => $this->revoked_at,
'expires_at' => $this->expires_at,
];
}
public function getId(): ?int {
return $this->id;
}
public function setId(?int $id): void {
$this->id = $id;
}
public function getUsuarioId(): ?int {
return $this->usuario_id;
}
public function setUsuarioId(?int $usuario_id): void {
$this->usuario_id = $usuario_id;
}
public function getUsuarioIp(): ?string {
return $this->usuario_ip;
}
public function setUsuarioIp(?string $usuario_ip): void {
$this->usuario_ip = $usuario_ip;
}
public function getUsuarioUserAgent(): ?string {
return $this->usuario_user_agent;
}
public function setUsuarioUserAgent(?string $usuario_user_agent): void {
$this->usuario_user_agent = $usuario_user_agent;
}
public function getToken(): ?string {
return $this->token;
}
public function setToken(?string $token): void {
$this->token = $token;
}
public function getIsRevoked(): ?int {
return $this->is_revoked;
}
public function setIsRevoked(?int $is_revoked): void {
$this->is_revoked = $is_revoked;
}
public function getCreatedAt(): ?string {
return $this->created_at;
}
public function setCreatedAt(?string $created_at): void {
$this->created_at = $created_at;
}
public function getRevokedAt(): ?string {
return $this->revoked_at;
}
public function setRevokedAt(?string $revoked_at): void {
$this->revoked_at = $revoked_at;
}
public function getExpiresAt(): ?string {
return $this->expires_at;
}
public function setExpiresAt(?string $expires_at): void {
$this->expires_at = $expires_at;
}
}

View File

@@ -0,0 +1,510 @@
<?php
namespace Workbloom\Component\Auth\v0\Models;
use DateTime;
use Exception;
use Workbloom\Services\DB;
use Workbloom\Component\Auth\v0\DTO\UsuarioDTO;
use Workbloom\Component\Auth\v0\DTO\UsuarioTokenDTO;
class UsuarioModel {
protected string $usuarioTable = 'usuario';
protected string $usuarioTokenTable = 'usuario_token';
/**
* Armazena um novo usuário no banco de dados.
*
* Este método insere os dados de um novo usuário na tabela `{$this->usuarioTable}`, incluindo informações de segurança como hash de senha, status e configurações de expiração de senha. A operação é protegida por um bloco `try-catch` para garantir o tratamento de erros.
*
* #### Fluxo de Operação:
* 1. **Execução da Query:** Prepara e executa a instrução `INSERT` com todos os campos preenchidos a partir do `UsuarioDTO`.
* 2. **Confirmação e Retorno de Sucesso:** Se a inserção for bem-sucedida, retorna um array com **`status` 'success'**, código **201 Created** e os dados do usuário criado (ID e UUID).
*
* #### Tratamento de Erros:
* - Qualquer `Exception` capturada durante o processo retorna um array com **`status` 'error'**, código **500 Internal Server Error** (ou o código da exceção) e a mensagem detalhada de erro.
*
* @param UsuarioDTO $usuarioDTO O objeto DTO contendo os dados do usuário a ser criado.
* @return array Um array associativo contendo o status da operação, um código de resposta HTTP e os dados do usuário criado.
*/
public function storeUsuario(UsuarioDTO $usuarioDTO): array {
try {
$sql =
"INSERT INTO {$this->usuarioTable} (
uuid,
status_id,
is_root,
nome_completo,
nome_usuario,
email,
senha_hash,
need_update_password,
days_to_expire_password,
last_password_update,
created_at,
updated_at,
deleted_at
) VALUES (
:uuid,
:status_id,
:is_root,
:nome_completo,
:nome_usuario,
:email,
:senha_hash,
:need_update_password,
:days_to_expire_password,
:last_password_update,
:created_at,
:updated_at,
:deleted_at
)";
$params = [
":uuid"=> $usuarioDTO->getUuid(),
":status_id"=> $usuarioDTO->getStatusId(),
":is_root"=> $usuarioDTO->getIsRoot(),
":nome_completo"=> $usuarioDTO->getNomeCompleto(),
":nome_usuario"=> $usuarioDTO->getNomeUsuario(),
":email"=> $usuarioDTO->getEmail(),
":senha_hash"=> $usuarioDTO->getSenhaHash(),
":need_update_password"=> $usuarioDTO->getNeedUpdatePassword(),
":days_to_expire_password"=> $usuarioDTO->getDaysToExpirePassword(),
":last_password_update"=> $usuarioDTO->getLastPasswordUpdate(),
":created_at"=> $usuarioDTO->getCreatedAt(),
":updated_at"=> $usuarioDTO->getUpdatedAt(),
":deleted_at"=> $usuarioDTO->getDeletedAt(),
];
// Executa a query
DB::execute(sql: $sql, params: $params);
return [
'response_code' => 201,
'status' => 'success',
'message' => 'Usuário criado com sucesso',
'output' => [
'data' => [
'id' => DB::lastInsertId(),
'uuid' => $usuarioDTO->getUuid()
]
]
];
} catch (Exception $e) {
return [
'response_code' => $e->getCode() ?? 500,
'status' => 'error',
'message' => $e->getMessage() ?? 'Internal Server Error'
];
}
}
/**
* Atualiza um usuário existente no banco de dados.
*
* Este método modifica os dados de um usuário na tabela `{$this->usuarioTable}` com base no **UUID** fornecido no objeto `UsuarioDTO`. Ele atualiza informações de segurança e perfil, como hash de senha, status, permissão de root, nome e configurações de expiração de senha. A operação utiliza um bloco `try-catch` para garantir o tratamento de erros.
*
* #### Fluxo de Operação:
* 1. **Execução da Query:** Prepara e executa a instrução `UPDATE` com todos os campos preenchidos a partir do `UsuarioDTO`, modificando o registro correspondente ao UUID.
* 2. **Confirmação e Retorno de Sucesso:** Se a atualização for bem-sucedida, retorna um array com **`status` 'success'**, código **200 OK** e uma mensagem de êxito.
*
* #### Tratamento de Erros:
* - Qualquer `Exception` capturada durante o processo retorna um array com **`status` 'error'**, o código de erro da exceção (ou `500` como fallback) e a mensagem detalhada de erro.
*
* @param UsuarioDTO $usuarioDTO O objeto DTO contendo os dados atualizados do usuário, incluindo o UUID para identificação.
* @return array Um array associativo contendo o status da operação, um código de resposta HTTP e uma mensagem.
*/
public function updateUsuario(UsuarioDTO $usuarioDTO): array {
try {
$sql =
"UPDATE {$this->usuarioTable} SET
status_id = :status_id,
is_root = :is_root,
nome_completo = :nome_completo,
nome_usuario = :nome_usuario,
email = :email,
senha_hash = :senha_hash,
need_update_password = :need_update_password,
days_to_expire_password = :days_to_expire_password,
last_password_update = :last_password_update,
updated_at = :updated_at
WHERE uuid = :uuid";
$params = [
":status_id" => $usuarioDTO->getStatusId(),
":is_root" => $usuarioDTO->getIsRoot(),
":nome_completo" => $usuarioDTO->getNomeCompleto(),
":nome_usuario" => $usuarioDTO->getNomeUsuario(),
":email" => $usuarioDTO->getEmail(),
":senha_hash" => $usuarioDTO->getSenhaHash(),
":need_update_password" => $usuarioDTO->getNeedUpdatePassword(),
":days_to_expire_password" => $usuarioDTO->getDaysToExpirePassword(),
":last_password_update" => $usuarioDTO->getLastPasswordUpdate(),
":updated_at" => $usuarioDTO->getUpdatedAt(),
":uuid" => $usuarioDTO->getUuid(),
];
// Executa a query
DB::execute(sql: $sql, params: $params);
return [
'response_code' => 200,
'status' => 'success',
'message' => 'Usuário atualizado com sucesso',
];
} catch(Exception $e) {
return [
'response_code' => $e->getCode() ?? 500,
'status' => 'error',
'message' => $e->getMessage() ?? 'Internal Server Error'
];
}
}
/**
* Realiza a exclusão lógica de um usuário no banco de dados.
*
* Este método atualiza a coluna `deleted_at` do registro do usuário na tabela `{$this->usuarioTable}` com o timestamp fornecido no objeto `UsuarioDTO`. Isso garante uma **exclusão lógica**, mantendo o registro para fins de auditoria, mas marcando-o como inativo.
*
* #### Fluxo de Operação:
* 1. **Execução da Query:** Prepara e executa a instrução `UPDATE` que define a data de exclusão para o registro correspondente ao UUID do usuário.
* 2. **Retorno de Sucesso:** Se a atualização for bem-sucedida, retorna um array com **`status` 'success'**, código **200 OK** e uma mensagem de êxito.
*
* #### Tratamento de Erros:
* - Qualquer `Exception` capturada durante o processo retorna um array com **`status` 'error'**, o código de erro da exceção (ou `500` como fallback) e a mensagem detalhada da exceção.
*
* @param UsuarioDTO $usuarioDTO O objeto DTO contendo o UUID do usuário a ser excluído e o timestamp a ser definido em `deleted_at`.
* @return array Um array associativo contendo o status da operação, um código de resposta HTTP e uma mensagem.
*/
public function deleteUsuario(UsuarioDTO $usuarioDTO): array {
try {
$sql =
"UPDATE {$this->usuarioTable} SET
deleted_at = :deleted_at
WHERE uuid = :uuid";
$params = [
":deleted_at" => $usuarioDTO->getDeletedAt(),
":uuid" => $usuarioDTO->getUuid(),
];
// Executa a query
DB::execute(sql: $sql, params: $params);
return [
'response_code' => 200,
'status' => 'success',
'message' => 'Usuário excluído com sucesso',
];
} catch(Exception $e) {
return [
'response_code' => $e->getCode() ?? 500,
'status' => 'error',
'message' => $e->getMessage() ?? 'Internal Server Error'
];
}
}
/**
* Busca um único usuário no banco de dados por um identificador específico.
*
* Este método recupera todos os detalhes de um usuário da tabela `{$this->usuarioTable}`. A busca é flexível e permite usar qualquer coluna como identificador (`$identifier`) e o valor correspondente.
*
* #### Fluxo de Operação:
* 1. **Construção da Query Dinâmica:** O método monta e executa uma consulta `SELECT` que usa o `$identifier` de forma dinâmica na cláusula `WHERE` e um parâmetro nomeado seguro (`:value`) para o valor.
* 2. **Execução da Consulta:** A consulta usa `DB::fetchOne`, indicando que apenas um registro é esperado.
* 3. **Verificação de Resultados:**
* * Se o usuário for encontrado, retorna um array com **`status` 'success'**, código **200 OK** e os dados do usuário na chave `output`.
* * Se o usuário **não for encontrado** (`empty($result)`), retorna um array com **`status` 'error'** e código **404 Not Found**, com uma mensagem indicando que o usuário não foi encontrado.
*
* #### Tratamento de Erros:
* - Qualquer `Exception` capturada durante o processo retorna um array com **`status` 'error'**, o código de erro da exceção (ou `500` como fallback) e uma mensagem detalhada de erro.
*
* @param string $identifier A coluna da tabela a ser usada como critério de busca (ex: 'uuid', 'email', 'nome_usuario').
* @param mixed $value O valor correspondente ao identificador que está sendo buscado.
* @return array Um array associativo contendo o status da operação, um código de resposta HTTP e os dados do usuário, se encontrado.
*/
public function findUsuarioByIdentifier(string $identifier, mixed $value): array {
try {
$sql =
"SELECT
id,
uuid,
status_id,
is_root,
nome_completo,
nome_usuario,
email,
senha_hash,
need_update_password,
days_to_expire_password,
last_password_update,
created_at,
updated_at,
deleted_at
FROM {$this->usuarioTable}
WHERE {$identifier} = :value";
$params = [
":value" => $value,
];
$result = DB::fetchOne(sql: $sql, params: $params);
if(empty($result)) {
return [
'response_code' => 404,
'status' => 'error',
'message' => 'Usuário não encontrado',
];
}
return [
'response_code' => 200,
'status' => 'success',
'message' => 'Usuário encontrado com sucesso',
'output' => [
'data' => $result
]
];
} catch(Exception $e) {
return [
'response_code' => $e->getCode() ?? 500,
'status' => 'error',
'message' => $e->getMessage() ?? 'Internal Server Error'
];
}
}
/**
* Busca um único usuário no banco de dados usando seu e-mail ou nome de usuário como critério de login.
*
* Este método é utilizado para o processo de autenticação, tentando encontrar um usuário na tabela `{$this->usuarioTable}` por meio de uma correspondência na coluna `nome_usuario` ou `email`.
*
* #### Fluxo de Operação:
* 1. **Execução da Query:** Monta e executa uma consulta `SELECT` que usa o valor `$login` para tentar encontrar um registro no campo `email` ou `nome_usuario`.
* 2. **Verificação de Resultados:**
* * Se o usuário for encontrado, retorna um array com **`status` 'success'**, código **200 OK** e os dados do usuário na chave `output`.
* * Se o usuário **não for encontrado** (`empty($result)`), retorna um array com **`status` 'error'** e código **404 Not Found**, com uma mensagem indicando que o usuário não foi encontrado.
*
* #### Tratamento de Erros:
* - Qualquer `Exception` capturada durante o processo retorna um array com **`status` 'error'**, o código de erro da exceção (ou `500` como fallback) e uma mensagem detalhada de erro.
*
* @param string $login O valor do e-mail ou nome de usuário a ser pesquisado.
* @return array Um array associativo contendo o status da operação, um código de resposta HTTP e os dados do usuário, se encontrado.
*/
public function findUsuarioByLogin(string $login): array {
try {
$sql =
"SELECT
id,
uuid,
status_id,
is_root,
nome_completo,
nome_usuario,
email,
senha_hash,
need_update_password,
days_to_expire_password,
last_password_update,
created_at,
updated_at,
deleted_at
FROM {$this->usuarioTable}
WHERE (nome_usuario = :value OR email = :value)";
$params = [
":value" => $login,
];
$result = DB::fetchOne(sql: $sql, params: $params);
if(empty($result)) {
return [
'response_code' => 404,
'status' => 'error',
'message' => 'Usuário não encontrado',
];
}
return [
'response_code' => 200,
'status' => 'success',
'message' => 'Usuário encontrado com sucesso',
'output' => [
'data' => $result
]
];
} catch(Exception $e) {
return [
'response_code' => $e->getCode() ?? 500,
'status' => 'error',
'message' => $e->getMessage() ?? 'Internal Server Error'
];
}
}
/**
* Armazena um novo token de autenticação de usuário no banco de dados.
*
* Este método é responsável por registrar o token na tabela `{$this->usuarioTokenTable}`, associando-o ao usuário, IP, User Agent e definindo seu status de revogação e tempo de expiração.
*
* #### Fluxo de Operação:
* 1. **Execução da Query:** Prepara e executa a instrução `INSERT` para inserir o registro do token com todos os detalhes fornecidos pelo `UsuarioTokenDTO`.
* 2. **Confirmação e Retorno de Sucesso:** Se a inserção for bem-sucedida, retorna um array com **`status` 'success'**, código **201 Created** e os dados do token (ID gerado e o token).
*
* #### Tratamento de Erros:
* - Qualquer `Exception` capturada durante o processo retorna um array com **`status` 'error'**, o código de erro da exceção (ou `500` como fallback) e a mensagem detalhada de erro.
*
* @param UsuarioTokenDTO $usuarioTokenDTO O objeto DTO contendo os dados do token a ser armazenado.
* @return array Um array associativo contendo o status da operação, um código de resposta HTTP e os dados do token.
*/
public function storeUsuarioToken(UsuarioTokenDTO $usuarioTokenDTO): array {
try {
$sql =
"INSERT INTO {$this->usuarioTokenTable} (
usuario_id,
usuario_ip,
usuario_user_agent,
token,
is_revoked,
created_at,
expires_at
) VALUES (
:usuario_id,
:usuario_ip,
:usuario_user_agent,
:token,
:is_revoked,
:created_at,
:expires_at
)";
$params = [
":usuario_id"=> $usuarioTokenDTO->getUsuarioId(),
":usuario_ip"=> $usuarioTokenDTO->getUsuarioIp(),
":usuario_user_agent"=> $usuarioTokenDTO->getUsuarioUserAgent(),
":token"=> $usuarioTokenDTO->getToken(),
":is_revoked"=> $usuarioTokenDTO->getIsRevoked(),
":created_at"=> $usuarioTokenDTO->getCreatedAt(),
":expires_at"=> $usuarioTokenDTO->getExpiresAt(),
];
// Executa a query
DB::execute(sql: $sql, params: $params);
return [
'response_code' => 201,
'status' => 'success',
'message' => 'Token de usuário criado com sucesso',
'output' => [
'data' => [
'id' => DB::lastInsertId(),
'token' => $usuarioTokenDTO->getToken()
]
]
];
} catch (Exception $e) {
return [
'response_code' => $e->getCode() ?? 500,
'status' => 'error',
'message' => $e->getMessage() ?? 'Internal Server Error'
];
}
}
/**
* Atualiza o status de revogação de um token de usuário no banco de dados.
*
* Este método modifica o registro de um token na tabela `{$this->usuarioTokenTable}`, alterando o status de revogação (`is_revoked`) e o timestamp de revogação (`revoked_at`), com base na string do token fornecida no DTO.
*
* #### Fluxo de Operação:
* 1. **Execução da Query:** Prepara e executa a instrução `UPDATE` para modificar o status de revogação do token.
* 2. **Retorno de Sucesso:** Se a atualização for bem-sucedida, retorna um array com **`status` 'success'**, código **200 OK** e uma mensagem de êxito.
*
* #### Tratamento de Erros:
* - Qualquer `Exception` capturada durante o processo retorna um array com **`status` 'error'**, o código de erro da exceção (ou `500` como fallback) e a mensagem detalhada de erro.
*
* @param UsuarioTokenDTO $usuarioTokenDTO O objeto DTO contendo o token a ser atualizado, o novo status de revogação (`is_revoked`) e a data de revogação (`revoked_at`).
* @return array Um array associativo contendo o status da operação, um código de resposta HTTP e uma mensagem.
*/
public function updateUsuarioToken(UsuarioTokenDTO $usuarioTokenDTO): array {
try {
$sql =
"UPDATE {$this->usuarioTokenTable} SET
is_revoked = :is_revoked,
revoked_at = :revoked_at
WHERE token = :token";
$params = [
":is_revoked"=> $usuarioTokenDTO->getIsRevoked(),
":revoked_at"=> $usuarioTokenDTO->getRevokedAt(),
":token"=> $usuarioTokenDTO->getToken(),
];
// Executa a query
DB::execute(sql: $sql, params: $params);
return [
'response_code' => 200,
'status' => 'success',
'message' => 'Token de usuário atualizado com sucesso',
];
} catch(Exception $e) {
return [
'response_code' => $e->getCode() ?? 500,
'status' => 'error',
'message' => $e->getMessage() ?? 'Internal Server Error'
];
}
}
/**
* Revoga (invalida) todos os tokens de autenticação ativos de um usuário no banco de dados, buscando o usuário pelo UUID.
*
* Este método executa uma exclusão lógica em todos os tokens não revogados (`is_revoked = 0`) associados ao ID interno de um usuário, que é determinado pelo `usuario_uuid` fornecido.
*
* #### Atenção à Sintaxe SQL (PostgreSQL/SQL Server):
* A sintaxe `UPDATE ... FROM` é comum em PostgreSQL ou SQL Server e está sendo usada para realizar um JOIN implícito na instrução UPDATE, o que não é sintaxe padrão do MySQL. Assumindo que o ambiente de banco de dados suporte essa sintaxe (ou que o código seja adaptado para o SGBD correto).
*
* #### Fluxo de Operação:
* 1. **Execução da Query:** Prepara e executa a instrução `UPDATE` para definir `is_revoked = 1` e `revoked_at` para o timestamp atual para todos os tokens ativos do usuário.
* 2. **Confirmação e Retorno de Sucesso:** Se a atualização for bem-sucedida, retorna um array com **`status` 'success'**, código **200 OK** e uma mensagem de êxito.
*
* #### Tratamento de Erros:
* - Qualquer `Exception` capturada durante o processo retorna um array com **`status` 'error'**, o código de erro da exceção (ou `500` como fallback) e uma mensagem detalhada de erro.
*
* @param string $usuario_uuid O UUID do usuário para o qual os tokens serão revogados.
* @return array Um array associativo contendo o status da operação ("success" ou "error"), um código de resposta HTTP e uma mensagem.
*/
public function revolkOldUsuarioTokens(string $usuario_uuid): array {
try {
$sql =
"UPDATE {$this->usuarioTokenTable} AS ut SET
is_revoked = 1,
revoked_at = :revoked_at
FROM {$this->usuarioTable} AS u
WHERE ut.usuario_id = u.id
AND u.uuid = :usuario_uuid
AND ut.is_revoked = 0";
$params = [
":revoked_at"=> (new DateTime())->format(format: 'Y-m-d H:i:s'),
":usuario_uuid"=> $usuario_uuid
];
// Executa a query
DB::execute(sql: $sql, params: $params);
return [
'response_code' => 200,
'status' => 'success',
'message' => 'Tokens antigos revogados com sucesso',
];
} catch(Exception $e) {
return [
'response_code' => $e->getCode() ?? 500,
'status' => 'error',
'message' => $e->getMessage() ?? 'Internal Server Error'
];
}
}
}

View File

@@ -0,0 +1,9 @@
<?php
use AxiumPHP\Core\Router;
use Workbloom\Component\Auth\v0\Controllers\AuthController;
// Rota de login
Router::POST(
uri: '/login',
handler: [AuthController::class, 'login']
);

View File

@@ -0,0 +1,3 @@
<?php
// Importa rotas de autenticação
require_once __DIR__ . '/AuthRoutes.php';

View File

@@ -0,0 +1,8 @@
<?php
namespace Workbloom\Component\Auth\v0\Services;
class AuthService {
public function login(array $credentials) {
return ['data' => $credentials];
}
}