396 lines
18 KiB
PHP
Executable File
396 lines
18 KiB
PHP
Executable File
<?php
|
|
namespace Zampet\Module\Auth\v0\Models;
|
|
|
|
use DateTime;
|
|
use Exception;
|
|
use Zampet\Services\DB;
|
|
use Zampet\Module\Auth\v0\DTO\UsuarioDTO;
|
|
|
|
class UsuarioModel {
|
|
protected string $usuarioTable = 'usuario';
|
|
protected string $usuarioTokenTable = 'usuario_token';
|
|
|
|
/**
|
|
* Cria e armazena um novo usuário no banco de dados.
|
|
*
|
|
* Este método é responsável por inserir os dados completos de um novo usuário, incluindo informações pessoais, documentos, credenciais e endereço, na tabela `{$this->usuarioTable}`. A operação é atômica e utiliza uma transação de banco de dados para garantir a consistência dos dados.
|
|
*
|
|
* #### Fluxo de Operação:
|
|
* 1. **Início da Transação:** Inicia uma transação no banco de dados (`DB::beginTransaction()`).
|
|
* 2. **Execução da Query:** Prepara e executa a instrução `INSERT` com todos os campos preenchidos a partir do `UsuarioDTO`.
|
|
* 3. **Confirmação:** Se a inserção for bem-sucedida, a transação é confirmada (`DB::commit()`).
|
|
* 4. **Retorno de Sucesso:** Retorna um array com `status` 'success', o código `201 Created`, uma mensagem de êxito e os dados do usuário criado (ID e UUID).
|
|
*
|
|
* #### Tratamento de Erros:
|
|
* - Qualquer `Exception` capturada durante o processo faz com que a transação seja revertida (`DB::rollBack()`).
|
|
* - Retorna um array com `status` 'error', código `500 Internal Server Error` e uma mensagem genérica de erro.
|
|
*
|
|
* @param UsuarioDTO $usuarioDTO O objeto DTO contendo os dados do usuário a ser criado.
|
|
* @return array Um array associativo com o status da operação, um código de resposta HTTP e uma mensagem.
|
|
*/
|
|
public function store(UsuarioDTO $usuarioDTO): array {
|
|
try {
|
|
$sql =
|
|
"INSERT INTO {$this->usuarioTable} (
|
|
uuid,
|
|
nome_completo,
|
|
status_id,
|
|
documentcpf,
|
|
documentcrmv,
|
|
email,
|
|
senha,
|
|
telefone,
|
|
data_nascimento,
|
|
endereco_rua,
|
|
endereco_numero,
|
|
endereco_complemento,
|
|
endereco_bairro,
|
|
endereco_cidade,
|
|
endereco_uf,
|
|
endereco_cep,
|
|
created_at,
|
|
updated_at,
|
|
deleted_at
|
|
) VALUES (
|
|
:uuid,
|
|
:nome_completo,
|
|
:status_id,
|
|
:documentcpf,
|
|
:documentcrmv,
|
|
:email,
|
|
:senha,
|
|
:telefone,
|
|
:data_nascimento,
|
|
:endereco_rua,
|
|
:endereco_numero,
|
|
:endereco_complemento,
|
|
:endereco_bairro,
|
|
:endereco_cidade,
|
|
:endereco_uf,
|
|
:endereco_cep,
|
|
:created_at,
|
|
:updated_at,
|
|
:deleted_at
|
|
)";
|
|
|
|
$params = [
|
|
":uuid" => $usuarioDTO->getUuid(),
|
|
":nome_completo" => $usuarioDTO->getNomeCompleto(),
|
|
":status_id" => $usuarioDTO->getStatusId(),
|
|
":documentcpf" => $usuarioDTO->getDocumentCpf(),
|
|
":documentcrmv" => $usuarioDTO->getDocumentCrmv(),
|
|
":email" => $usuarioDTO->getEmail(),
|
|
":senha" => $usuarioDTO->getSenha(),
|
|
":telefone" => $usuarioDTO->getTelefone(),
|
|
":data_nascimento" => $usuarioDTO->getDataNascimento(),
|
|
":endereco_rua" => $usuarioDTO->getEnderecoRua(),
|
|
":endereco_numero" => $usuarioDTO->getEnderecoNumero(),
|
|
":endereco_complemento" => $usuarioDTO->getEnderecoComplemento(),
|
|
":endereco_bairro" => $usuarioDTO->getEnderecoBairro(),
|
|
":endereco_cidade" => $usuarioDTO->getEnderecoCidade(),
|
|
":endereco_uf" => $usuarioDTO->getEnderecoUf(),
|
|
":endereco_cep" => $usuarioDTO->getEnderecoCep(),
|
|
":created_at" => $usuarioDTO->getCreatedAt(),
|
|
":updated_at" => $usuarioDTO->getUpdatedAt(),
|
|
":deleted_at" => $usuarioDTO->getDeletedAt()
|
|
];
|
|
|
|
// Executa a query de inserção
|
|
DB::execute(sql: $sql, params: $params);
|
|
|
|
return [
|
|
'response_code' => 201,
|
|
'status' => 'success',
|
|
'message' => 'Usuário registrado com sucesso.',
|
|
'output' => [
|
|
'data' => [
|
|
'user_id' => DB::lastInsertId(),
|
|
'uuid' => $usuarioDTO->getUuid()
|
|
]
|
|
]
|
|
];
|
|
} catch (Exception $e) {
|
|
return [
|
|
'response_code' => 500,
|
|
'status' => 'error',
|
|
'message' => 'Ocorreu um erro ao registrar o usuário. Tente novamente mais tarde.',
|
|
'output' => ['errors' => $e->getMessage()]
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Busca um único usuário ativo no banco de dados por um identificador específico.
|
|
*
|
|
* Este método recupera todos os detalhes de um usuário na tabela `{$this->usuarioTable}`. A busca é flexível e permite usar qualquer coluna como identificador (`$identifier`), mas é estritamente restrita a registros que não foram logicamente excluídos (`deleted_at IS NULL`).
|
|
*
|
|
* @param string $identifier A coluna da tabela a ser usada como critério de busca (ex: 'uuid', 'email', 'documentcpf').
|
|
* @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 getUsuarioByIdentifier(string $identifier, mixed $value): array {
|
|
try {
|
|
$sql =
|
|
"SELECT
|
|
id,
|
|
uuid,
|
|
nome_completo,
|
|
status_id,
|
|
documentcpf,
|
|
documentcrmv,
|
|
email,
|
|
senha,
|
|
telefone,
|
|
data_nascimento,
|
|
endereco_rua,
|
|
endereco_numero,
|
|
endereco_complemento,
|
|
endereco_bairro,
|
|
endereco_cidade,
|
|
endereco_uf,
|
|
endereco_cep,
|
|
created_at,
|
|
updated_at,
|
|
deleted_at
|
|
FROM {$this->usuarioTable}
|
|
WHERE {$identifier} = :value
|
|
AND deleted_at IS NULL";
|
|
|
|
$params = [
|
|
':value' => $value
|
|
];
|
|
|
|
$result = DB::fetchOne(sql: $sql, params: $params);
|
|
|
|
if (!$result) {
|
|
return [
|
|
'response_code' => 404,
|
|
'status' => 'fail',
|
|
'message' => 'Usuário não encontrado.',
|
|
'output' => [
|
|
'data' => []
|
|
]
|
|
];
|
|
}
|
|
|
|
return [
|
|
'response_code' => 200,
|
|
'status' => 'success',
|
|
'output' => ['data' => $result]
|
|
];
|
|
} catch(Exception $e) {
|
|
return [
|
|
'response_code' => 500,
|
|
'status' => 'error',
|
|
'message' => 'Ocorreu um erro ao buscar usuário. Tente novamente mais tarde.',
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Armazena um novo token de autenticação no banco de dados para um usuário específico.
|
|
*
|
|
* Este método é responsável por registrar um token na tabela `{$this->usuarioTokenTable}`. Ele associa o token a um ID de usuário, define o status inicial como não revogado (`revoked = 0`) e registra o timestamp de criação.
|
|
*
|
|
* #### Fluxo de Operação:
|
|
* 1. **Início da Transação:** O método inicia uma transação no banco de dados (`DB::beginTransaction()`).
|
|
* 2. **Execução da Query:** Prepara e executa a instrução `INSERT` com o ID do usuário, a string do token, o status inicial de revogação e o timestamp atual.
|
|
* 3. **Confirmação:** Se a inserção for bem-sucedida, a transação é confirmada (`DB::commit()`).
|
|
* 4. **Retorno de Sucesso:** Retorna um array com `status` 'success', o código `201 Created` e uma mensagem de êxito.
|
|
*
|
|
* #### Tratamento de Erros:
|
|
* - Qualquer `Exception` capturada durante o processo faz com que a transação seja revertida (`DB::rollback()`).
|
|
* - Retorna um array com `status` 'error', o código `500 Internal Server Error` e uma mensagem genérica de erro.
|
|
*
|
|
* @param int $user_id O ID do usuário ao qual o token pertence.
|
|
* @param string $token A string do token de autenticação (JWT ou similar).
|
|
* @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 storeToken(int $user_id, string $token): array {
|
|
try {
|
|
$sql =
|
|
"INSERT INTO {$this->usuarioTokenTable} (
|
|
usuario_id,
|
|
token,
|
|
revoked,
|
|
created_at
|
|
) VALUES (
|
|
:usuario_id,
|
|
:token,
|
|
:revoked,
|
|
:created_at
|
|
)";
|
|
|
|
$params = [
|
|
":usuario_id" => $user_id,
|
|
":token" => $token,
|
|
":revoked" => 0,
|
|
":created_at" => (new DateTime())->format(format: 'Y-m-d H:i:s')
|
|
];
|
|
|
|
DB::execute(sql: $sql, params: $params);
|
|
|
|
return [
|
|
'response_code' => 201,
|
|
'status' => 'success',
|
|
'message' => 'Token registrado com sucesso.'
|
|
];
|
|
} catch (Exception $e) {
|
|
return [
|
|
'response_code' => 500,
|
|
'status' => 'error',
|
|
'message' => 'Erro ao registrar token. Tente novamente mais tarde.'
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Revoga todos os tokens de autenticação ativos de um usuário específico.
|
|
*
|
|
* Este método atualiza a coluna `revoked` para `1` (revogado) para todos os tokens não revogados (`revoked = 0`) associados a um `user_id` específico na tabela `{$this->usuarioTokenTable}`. Isso invalida todas as sessões ativas do usuário, forçando-o a fazer login novamente.
|
|
*
|
|
* #### Fluxo de Operação:
|
|
* 1. **Execução da Query:** Prepara e executa a instrução `UPDATE` para revogar os tokens.
|
|
* 2. **Confirmação:** Se a atualização for bem-sucedida, retorna um array com `status` 'success' e código `200 OK`.
|
|
*
|
|
* #### Tratamento de Erros:
|
|
* - Qualquer `Exception` capturada durante o processo reverte qualquer transação de banco de dados e retorna um array com `status` 'error' e código `500 Internal Server Error`, com uma mensagem de erro genérica.
|
|
*
|
|
* @param int $user_id O ID 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 descritiva.
|
|
*/
|
|
public function revokeOldTokens(int $user_id): array {
|
|
try {
|
|
$sql =
|
|
"UPDATE {$this->usuarioTokenTable} SET
|
|
revoked = 1,
|
|
updated_at = CURRENT_TIMESTAMP
|
|
WHERE usuario_id = :usuario_id
|
|
AND revoked = 0";
|
|
|
|
$params = [
|
|
":usuario_id" => $user_id
|
|
];
|
|
|
|
DB::execute(sql: $sql, params: $params);
|
|
|
|
return [
|
|
'response_code' => 200,
|
|
'status' => 'success',
|
|
'message' => 'Old tokens revoked successfully.'
|
|
];
|
|
} catch (Exception $e) {
|
|
return [
|
|
'response_code' => 500,
|
|
'status' => 'error',
|
|
'message' => 'Error revoking old tokens. Please try again later.'
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Busca um token de usuário no banco de dados por um identificador específico.
|
|
*
|
|
* Este método recupera os dados de um único token de autenticação da tabela `{$this->usuarioTokenTable}` de forma flexível, permitindo a busca por qualquer coluna (`$identifier`) e o valor correspondente.
|
|
*
|
|
* #### Fluxo de Operação:
|
|
* 1. **Execução da Query**: Monta e executa uma consulta `SELECT` que usa o `$identifier` de forma dinâmica na cláusula `WHERE` e um parâmetro nomeado (`:value`) para o valor.
|
|
* 2. **Verificação de Resultados**:
|
|
* - Se o token for encontrado, retorna um array com **`status` 'success'**, código **200 OK** e os dados do token.
|
|
* - Se o token **não for encontrado**, retorna um array com **`status` 'fail'** e código **404 Not Found**.
|
|
*
|
|
* #### Tratamento de Erros:
|
|
* - Qualquer `Exception` capturada durante a consulta retorna um array com **`status` 'error'** e código **500 Internal Server Error**, com uma mensagem genérica de erro.
|
|
*
|
|
* @param string $identifier A coluna da tabela a ser usada como critério de busca (ex: 'id', 'token').
|
|
* @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 token, se encontrado.
|
|
*/
|
|
public function getTokenByidentifier(string $identifier, mixed $value): array {
|
|
try {
|
|
$sql =
|
|
"SELECT
|
|
id,
|
|
usuario_id,
|
|
token,
|
|
revoked,
|
|
created_at,
|
|
updated_at
|
|
FROM {$this->usuarioTokenTable}
|
|
WHERE {$identifier} = :value";
|
|
|
|
$params = [
|
|
':value' => $value
|
|
];
|
|
|
|
$result = DB::fetchOne(sql: $sql, params: $params);
|
|
|
|
if (!$result) {
|
|
return [
|
|
'response_code' => 404,
|
|
'status' => 'fail',
|
|
'message' => 'Token não encontrado.',
|
|
'output' => [
|
|
'data' => []
|
|
]
|
|
];
|
|
}
|
|
|
|
return [
|
|
'response_code' => 200,
|
|
'status' => 'success',
|
|
'output' => ['data' => $result]
|
|
];
|
|
} catch(Exception $e) {
|
|
return [
|
|
'response_code' => 500,
|
|
'status' => 'error',
|
|
'message' => 'Ocorreu um erro ao buscar token. Tente novamente mais tarde.',
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Revoga um token de autenticação de usuário no banco de dados.
|
|
*
|
|
* Este método marca um token específico como revogado, atualizando a coluna `revoked` para `1`. Ele garante que apenas tokens que ainda não foram revogados (`revoked = 0`) sejam atualizados.
|
|
*
|
|
* #### Fluxo de Operação:
|
|
* 1. **Execução da Query**: Prepara e executa a instrução `UPDATE` para definir `revoked = 1` para o token correspondente.
|
|
* 2. **Confirmação**: Se a atualização for bem-sucedida, retorna um array com **`status` 'success'** e código **200 OK**.
|
|
*
|
|
* #### Tratamento de Erros:
|
|
* - Qualquer `Exception` capturada durante o processo retorna um array com **`status` 'error'** e código **500 Internal Server Error**, com uma mensagem de erro genérica.
|
|
*
|
|
* @param string $token O token de autenticação a ser revogado.
|
|
* @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 revokeToken(string $token): array {
|
|
try {
|
|
$sql =
|
|
"UPDATE {$this->usuarioTokenTable} SET
|
|
revoked = 1,
|
|
updated_at = CURRENT_TIMESTAMP
|
|
WHERE token = :token
|
|
AND revoked = 0";
|
|
|
|
$params = [
|
|
":token" => $token
|
|
];
|
|
|
|
DB::execute(sql: $sql, params: $params);
|
|
|
|
return [
|
|
'response_code' => 200,
|
|
'status' => 'success',
|
|
'message' => 'Token revoked successfully.'
|
|
];
|
|
} catch (Exception $e) {
|
|
return [
|
|
'response_code' => 500,
|
|
'status' => 'error',
|
|
'message' => 'Error revoking token. Please try again later.'
|
|
];
|
|
}
|
|
}
|
|
} |