Compare commits
3 Commits
044c6bd587
...
311cadc1d1
| Author | SHA1 | Date | |
|---|---|---|---|
| 311cadc1d1 | |||
|
|
ec216528b5 | ||
|
|
75047e8b34 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,4 @@
|
|||||||
# Arquivo de variáveis de ambiente
|
# Arquivo de variáveis de ambiente
|
||||||
.env
|
.env
|
||||||
# Pasta de Logs
|
# Pasta de Logs
|
||||||
app/Storage/logs
|
storage/logs/
|
||||||
@@ -1,12 +1,25 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Workbloom\Component\Auth\v0\Controllers;
|
namespace Workbloom\Component\Auth\v0\Controllers;
|
||||||
|
|
||||||
use Workbloom\Helpers\DataSanitizer;
|
use Workbloom\Services\JWTService;
|
||||||
use AxiumPHP\Helpers\RequestHelper;
|
use AxiumPHP\Helpers\RequestHelper;
|
||||||
|
use Workbloom\Helpers\DataSanitizer;
|
||||||
use Workbloom\Component\Auth\v0\Services\AuthService;
|
use Workbloom\Component\Auth\v0\Services\AuthService;
|
||||||
|
|
||||||
class AuthController {
|
class AuthController {
|
||||||
public function login() {
|
/**
|
||||||
|
* Lida com a requisição de login de um usuário via POST.
|
||||||
|
*
|
||||||
|
* Este método atua como um **controlador** de API, processando as credenciais de login, realizando a validação de presença de campo e delegando a lógica complexa de autenticação, revogação/registro de token para a camada de serviço.
|
||||||
|
*
|
||||||
|
* #### Fluxo de Operação:
|
||||||
|
* 1. **Coleta e Validação de Presença:** Obtém os dados do formulário. Verifica se os campos **'login'** e **'password'** estão presentes. Se algum estiver ausente, envia um erro **400 Bad Request** e encerra a execução.
|
||||||
|
* 2. **Sanitização e Delegação:** Os dados são sanitizados e encapsulados em um array de credenciais. O método delega a lógica de autenticação (busca de usuário, `password_verify`, revogação de token antigo e registro de novo token) para o **`AuthService::login()`**.
|
||||||
|
* 3. **Envio da Resposta JSON:** O resultado retornado pelo serviço é formatado e enviado de volta ao cliente, comunicando o código HTTP, status e mensagem da operação.
|
||||||
|
*
|
||||||
|
* @return void Este método não retorna um valor, pois seu objetivo é enviar uma resposta JSON e encerrar a execução do script.
|
||||||
|
*/
|
||||||
|
public function login(): void {
|
||||||
// Recebe formulário de login
|
// Recebe formulário de login
|
||||||
$form = RequestHelper::getFilteredInput(form_type: INPUT_POST);
|
$form = RequestHelper::getFilteredInput(form_type: INPUT_POST);
|
||||||
|
|
||||||
@@ -40,12 +53,117 @@
|
|||||||
|
|
||||||
// Resposta JSON
|
// Resposta JSON
|
||||||
RequestHelper::sendJsonResponse(
|
RequestHelper::sendJsonResponse(
|
||||||
response_code: 200,
|
response_code: $loginService['response_code'] ?? 500,
|
||||||
status: 'success',
|
status: $loginService['status'] ?? 'error',
|
||||||
message: 'Login successful',
|
message: $loginService['message'] ?? 'Internal server error',
|
||||||
output: [
|
output: $loginService['output'] ?? []
|
||||||
'data' => $form
|
);
|
||||||
]
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lida com a requisição para listar os contextos de trabalho (empresas) disponíveis para o usuário autenticado.
|
||||||
|
*
|
||||||
|
* Este método atua como um **controlador** de API, extraindo o UUID e o status de root do usuário a partir do token JWT e delegando a lógica de busca de contextos para o `AuthService`.
|
||||||
|
*
|
||||||
|
* #### Fluxo de Operação:
|
||||||
|
* 1. **Obtenção e Decodificação do Token:** O token Bearer é obtido e decodificado via `JWTService`. Os dados essenciais do usuário, como `uuid` e `is_root`, são extraídos do payload.
|
||||||
|
* 2. **Delegação ao Serviço:** O método `listWorkContexts` do **`AuthService`** é chamado, passando o UUID do usuário e seu status de root. O serviço é responsável por consultar os contextos de trabalho (todas as empresas para usuários root ou apenas as associadas para usuários normais).
|
||||||
|
* 3. **Envio da Resposta JSON:** O resultado retornado pelo serviço (`workContexts`) é formatado para uma resposta JSON padronizada usando **`RequestHelper::sendJsonResponse`**. O código HTTP, status, mensagem e os dados dos contextos são comunicados ao cliente.
|
||||||
|
*
|
||||||
|
* @return void Este método não retorna um valor, pois seu objetivo é enviar uma resposta JSON e encerrar a execução do script.
|
||||||
|
*/
|
||||||
|
public function listWorkContexts(): void {
|
||||||
|
// Receve o token Bearer da requisição
|
||||||
|
$bearerToken = JWTService::decode(token: JWTService::getBearerToken());
|
||||||
|
|
||||||
|
// Consulta os contextos de trabalho associados ao token
|
||||||
|
$workContexts = (new AuthService())->listWorkContexts(usuario_uuid: $bearerToken['user_data']['uuid'], is_root: $bearerToken['user_data']['is_root']);
|
||||||
|
|
||||||
|
// Resposta JSON
|
||||||
|
RequestHelper::sendJsonResponse(
|
||||||
|
response_code: $workContexts['response_code'] ?? 500,
|
||||||
|
status: $workContexts['status'] ?? 'error',
|
||||||
|
message: $workContexts['message'] ?? 'Internal server error',
|
||||||
|
output: $workContexts['output'] ?? []
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lida com a requisição de seleção do contexto de trabalho (empresa) de um usuário.
|
||||||
|
*
|
||||||
|
* Este método atua como um **controlador** de API, responsável por:
|
||||||
|
* 1. **Extrair a Identidade:** Obtém e decodifica o token Bearer para identificar o usuário.
|
||||||
|
* 2. **Validação de Presença:** Verifica se o campo obrigatório `contexto_uuid` foi fornecido. Se estiver ausente, envia um erro **400 Bad Request** e encerra a execução.
|
||||||
|
* 3. **Delegação ao Serviço:** Delega a validação de acesso ao contexto, a revogação do token antigo e a geração do novo token atualizado (que inclui o contexto de trabalho) para o **`AuthService::selectWorkContext()`**.
|
||||||
|
* 4. **Envio da Resposta JSON:** O resultado retornado pelo serviço é formatado e enviado de volta ao cliente, comunicando o código HTTP, status, mensagem e o novo token JWT.
|
||||||
|
*
|
||||||
|
* @return void Este método não retorna um valor, pois seu objetivo é enviar uma resposta JSON e encerrar a execução do script.
|
||||||
|
*/
|
||||||
|
public function selectWorkContext(): void {
|
||||||
|
// Receve o token Bearer da requisição
|
||||||
|
$bearerToken = JWTService::decode(token: JWTService::getBearerToken());
|
||||||
|
|
||||||
|
// Recebe formulário de seleção de contexto
|
||||||
|
$form = RequestHelper::getFilteredInput(form_type: INPUT_POST);
|
||||||
|
|
||||||
|
// Campos Obrigatórios
|
||||||
|
$required_fields = [
|
||||||
|
'contexto_uuid'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 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 seleção de contexto
|
||||||
|
$workContexts = (new AuthService())->selectWorkContext(
|
||||||
|
usuario_uuid: $bearerToken['user_data']['uuid'],
|
||||||
|
contexto_uuid: DataSanitizer::string(value: $form['contexto_uuid'] ?? '')
|
||||||
|
);
|
||||||
|
|
||||||
|
// Resposta JSON
|
||||||
|
RequestHelper::sendJsonResponse(
|
||||||
|
response_code: $workContexts['response_code'] ?? 500,
|
||||||
|
status: $workContexts['status'] ?? 'error',
|
||||||
|
message: $workContexts['message'] ?? 'Internal server error',
|
||||||
|
output: $workContexts['output'] ?? []
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lida com a requisição de logout, revogando o token de autenticação do usuário.
|
||||||
|
*
|
||||||
|
* Este método atua como um **controlador** de API, responsável por extrair o token JWT do cabeçalho da requisição, delegar a lógica de revogação para o serviço e formatar a resposta JSON final.
|
||||||
|
*
|
||||||
|
* #### Fluxo de Operação:
|
||||||
|
* 1. **Obtenção do Token:** O token Bearer é extraído do cabeçalho da requisição.
|
||||||
|
* 2. **Delegação ao Serviço:** O método `logout` do **`AuthService`** é chamado com o token. O serviço é responsável por revogar o token no banco de dados e gerenciar a transação.
|
||||||
|
* 3. **Envio da Resposta JSON:** O resultado retornado pelo serviço (`logoutService`) é formatado para uma resposta JSON padronizada usando **`RequestHelper::sendJsonResponse`**. O código HTTP, status, mensagem e quaisquer dados de saída são comunicados ao cliente.
|
||||||
|
*
|
||||||
|
* @return void Este método não retorna um valor, pois seu objetivo é enviar uma resposta JSON e encerrar a execução do script.
|
||||||
|
*/
|
||||||
|
public function logout(): void {
|
||||||
|
// Chama o serviço de logout
|
||||||
|
$logoutService = (new AuthService())->logout(
|
||||||
|
token: JWTService::getBearerToken()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Resposta JSON
|
||||||
|
RequestHelper::sendJsonResponse(
|
||||||
|
response_code: $logoutService['response_code'] ?? 500,
|
||||||
|
status: $logoutService['status'] ?? 'error',
|
||||||
|
message: $logoutService['message'] ?? 'Internal server error',
|
||||||
|
output: $logoutService['output'] ?? []
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
64
app/Common/Component/Auth/v0/Middlewares/AuthMiddleware.php
Normal file
64
app/Common/Component/Auth/v0/Middlewares/AuthMiddleware.php
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
namespace Workbloom\Component\Auth\v0\Middlewares;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Workbloom\Services\JWTService;
|
||||||
|
use Workbloom\Component\Auth\v0\Services\AuthService;
|
||||||
|
|
||||||
|
class AuthMiddleware {
|
||||||
|
/**
|
||||||
|
* Gerencia o processo de autenticação de uma requisição de API via token Bearer.
|
||||||
|
*
|
||||||
|
* Este método estático atua como um **middleware de autenticação**, verificando a presença e a validade de um token JWT em uma requisição HTTP, incluindo checagens de revogação e expiração no banco de dados.
|
||||||
|
*
|
||||||
|
* #### Fluxo de Operação:
|
||||||
|
* 1. **Obtenção e Decodificação do Token:** Tenta extrair o token Bearer do cabeçalho `Authorization` e decodificá-lo. Se o token estiver ausente ou a decodificação inicial falhar, retorna `401 Unauthorized`.
|
||||||
|
* 2. **Validação de Segurança e Status:** Chama o método `validateAuthToken` do **`AuthService`**. Este serviço realiza as verificações críticas no banco de dados (revogação, expiração por data) e no dispositivo (IP/User Agent).
|
||||||
|
* 3. **Gerenciamento da Resposta:**
|
||||||
|
* * Se a validação do serviço for **bem-sucedida** (`status === 'success'`), o método retorna `true`, permitindo que o processamento da rota continue.
|
||||||
|
* * Se a validação do serviço **falhar** (por token expirado, revogado ou dispositivo inválido), o método retorna o array de erro formatado pelo serviço, com o código HTTP e a mensagem correspondente.
|
||||||
|
*
|
||||||
|
* @return array|bool Retorna `true` se o token for válido e o acesso for autorizado; caso contrário, retorna um array de erro formatado contendo o código HTTP e a mensagem da falha.
|
||||||
|
*/
|
||||||
|
public static function handle(): array|bool {
|
||||||
|
// Recebe o token decodificado do cabeçalho Authorization
|
||||||
|
$bearerToken = JWTService::getBearerToken();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Verifica se o token está presente
|
||||||
|
if (!$bearerToken) {
|
||||||
|
throw new Exception(message: "Token not provided", code: 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
$decodedToken = JWTService::decode(token: $bearerToken);
|
||||||
|
if(empty($decodedToken)) {
|
||||||
|
return [
|
||||||
|
'response_code' => 401,
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'Unauthorized: Invalid or missing token.'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chama serviço de login e valida token e permissões
|
||||||
|
$authService = (new AuthService())->validateAuthToken(token: $bearerToken);
|
||||||
|
|
||||||
|
// Verifica se a validação foi bem-sucedida
|
||||||
|
if($authService['status'] !== 'success') {
|
||||||
|
return [
|
||||||
|
'response_code' => $authService['response_code'] ?? 500,
|
||||||
|
'status' => $authService['status'] ?? 'error',
|
||||||
|
'message' => $authService['message'] ?? 'Internal server error',
|
||||||
|
'output' => $authService['output'] ?? []
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch(Exception $e) {
|
||||||
|
return [
|
||||||
|
'response_code' => $e->getCode(),
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => $e->getMessage()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,8 +8,10 @@
|
|||||||
use Workbloom\Component\Auth\v0\DTO\UsuarioTokenDTO;
|
use Workbloom\Component\Auth\v0\DTO\UsuarioTokenDTO;
|
||||||
|
|
||||||
class UsuarioModel {
|
class UsuarioModel {
|
||||||
|
protected string $empresaTable = 'empresa';
|
||||||
protected string $usuarioTable = 'usuario';
|
protected string $usuarioTable = 'usuario';
|
||||||
protected string $usuarioTokenTable = 'usuario_token';
|
protected string $usuarioTokenTable = 'usuario_token';
|
||||||
|
protected string $usuarioEmpresaTable = 'usuario_empresa';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Armazena um novo usuário no banco de dados.
|
* Armazena um novo usuário no banco de dados.
|
||||||
@@ -475,7 +477,7 @@
|
|||||||
* @param string $usuario_uuid O UUID do usuário para o qual os tokens serão revogados.
|
* @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.
|
* @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 {
|
public function revokeOldUsuarioTokens(string $usuario_uuid): array {
|
||||||
try {
|
try {
|
||||||
$sql =
|
$sql =
|
||||||
"UPDATE {$this->usuarioTokenTable} AS ut SET
|
"UPDATE {$this->usuarioTokenTable} AS ut SET
|
||||||
@@ -507,4 +509,290 @@
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Busca um registro de token de usuário no banco de dados por um identificador específico.
|
||||||
|
*
|
||||||
|
* Este método recupera todos os detalhes de um token de autenticação (JWT) 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 seguro (`:value`) para o valor. A consulta utiliza `DB::fetchOne`, indicando que apenas um registro é esperado.
|
||||||
|
* 2. **Verificação de Resultados:**
|
||||||
|
* - Se o token **não for encontrado** (`empty($result)`), retorna um array com **`status` 'error'** e código **404 Not Found**.
|
||||||
|
* - Se o token for encontrado, retorna um array com **`status` 'success'**, código **200 OK** e os dados do registro na chave `output`.
|
||||||
|
*
|
||||||
|
* #### 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: 'token', 'usuario_id', 'ip_address').
|
||||||
|
* @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 findUsuarioTokenByIdentifier(string $identifier, mixed $value): array {
|
||||||
|
try {
|
||||||
|
$sql =
|
||||||
|
"SELECT
|
||||||
|
id,
|
||||||
|
usuario_id,
|
||||||
|
usuario_ip,
|
||||||
|
usuario_user_agent,
|
||||||
|
token,
|
||||||
|
is_revoked,
|
||||||
|
created_at,
|
||||||
|
expires_at,
|
||||||
|
revoked_at
|
||||||
|
FROM {$this->usuarioTokenTable}
|
||||||
|
WHERE {$identifier} = :value";
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
":value" => $value,
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = DB::fetchOne(sql: $sql, params: $params);
|
||||||
|
if(empty($result)) {
|
||||||
|
return [
|
||||||
|
'response_code' => 404,
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'Token de usuário não encontrado',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'response_code' => 200,
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'Token de 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 e retorna todos os contextos de trabalho (empresas) associados a um usuário, identificando o usuário pelo seu UUID.
|
||||||
|
*
|
||||||
|
* Este método consulta a tabela de associação usuário-empresa para listar todas as empresas ativas (`status_id = 1`) às quais um usuário específico tem acesso.
|
||||||
|
*
|
||||||
|
* #### Fluxo de Operação:
|
||||||
|
* 1. **Execução da Query:** Executa uma consulta `SELECT` que une as tabelas de usuário, empresa e a tabela de associação (`{$this->usuarioEmpresaTable}`) para filtrar pelo `usuario_uuid`. A busca retorna múltiplos registros (empresas).
|
||||||
|
* 2. **Verificação de Resultados:**
|
||||||
|
* - Se **nenhum contexto de trabalho for encontrado** (`empty($result)`), retorna um array com **`status` 'error'** e código **404 Not Found**.
|
||||||
|
* - Se contextos forem encontrados, retorna um array com **`status` 'success'**, código **200 OK** e os dados das empresas encontradas na chave `output`.
|
||||||
|
*
|
||||||
|
* #### 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 contextos de trabalho serão buscados.
|
||||||
|
* @return array Um array associativo contendo o status da operação, o código de resposta HTTP e os dados dos contextos de trabalho, se encontrados.
|
||||||
|
*/
|
||||||
|
public function findWorkContextsByUsuarioUUID(string $usuario_uuid): array {
|
||||||
|
try {
|
||||||
|
$sql =
|
||||||
|
"SELECT
|
||||||
|
'Empresa' AS contexto_tipo,
|
||||||
|
e.uuid AS contexto_uuid,
|
||||||
|
e.razao_social,
|
||||||
|
e.nome_fantasia,
|
||||||
|
e.document_inscricao
|
||||||
|
FROM {$this->usuarioEmpresaTable} ue
|
||||||
|
LEFT JOIN {$this->usuarioTable} u ON ue.usuario_id = u.id
|
||||||
|
LEFT JOIN {$this->empresaTable} e ON ue.empresa_id = e.id
|
||||||
|
WHERE u.uuid = :usuario_uuid
|
||||||
|
AND e.status_id = :status_id";
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
":usuario_uuid"=> $usuario_uuid,
|
||||||
|
":status_id" => 1
|
||||||
|
];
|
||||||
|
|
||||||
|
// Executa a query
|
||||||
|
$result = DB::fetchAll(sql: $sql, params: $params);
|
||||||
|
if(empty($result)) {
|
||||||
|
return [
|
||||||
|
'response_code' => 404,
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'Contextos de trabalho não encontrados para o usuário',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'response_code' => 200,
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'Contextos de trabalho encontrados com sucesso',
|
||||||
|
'output' => [
|
||||||
|
'data' => ['contextos' => $result]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
} catch(Exception $e) {
|
||||||
|
return [
|
||||||
|
'response_code' => $e->getCode() ?? 500,
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => $e->getMessage() ?? 'Internal Server Error'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Busca e retorna todos os contextos de trabalho (empresas) ativos no sistema.
|
||||||
|
*
|
||||||
|
* Este método consulta a tabela `{$this->empresaTable}` para listar todas as empresas que estão marcadas como ativas (`status_id = 1`). É útil para a administração do sistema que precisa listar todas as entidades disponíveis.
|
||||||
|
*
|
||||||
|
* #### Fluxo de Operação:
|
||||||
|
* 1. **Execução da Query:** Executa uma consulta `SELECT` para buscar as informações essenciais de todas as empresas com `status_id = 1`.
|
||||||
|
* 2. **Verificação de Resultados:**
|
||||||
|
* * Se **nenhum contexto de trabalho for encontrado** (`empty($result)`), retorna um array com **`status` 'error'** e código **404 Not Found**, com uma mensagem indicando a ausência de contextos.
|
||||||
|
* * Se contextos forem encontrados, retorna um array com **`status` 'success'**, código **200 OK** e os dados das empresas na chave `output`.
|
||||||
|
*
|
||||||
|
* #### 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.
|
||||||
|
*
|
||||||
|
* @return array Um array associativo contendo o status da operação, um código de resposta HTTP e os dados dos contextos de trabalho, se encontrados.
|
||||||
|
*/
|
||||||
|
public function findAllWorkContexts(int $is_root = 0): array {
|
||||||
|
try {
|
||||||
|
$sql =
|
||||||
|
"SELECT
|
||||||
|
'Empresa' AS contexto_tipo,
|
||||||
|
e.uuid AS contexto_uuid,
|
||||||
|
e.razao_social,
|
||||||
|
e.nome_fantasia,
|
||||||
|
e.document_inscricao
|
||||||
|
FROM {$this->empresaTable} e
|
||||||
|
WHERE e.status_id = :status_id";
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
":status_id" => 1
|
||||||
|
];
|
||||||
|
|
||||||
|
// Executa a query
|
||||||
|
$result = DB::fetchAll(sql: $sql, params: $params);
|
||||||
|
if(empty($result)) {
|
||||||
|
return [
|
||||||
|
'response_code' => 404,
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'Contextos de trabalho não encontrados para o usuário',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adiciona o contexto da plataforma se o usuário for Administrador
|
||||||
|
if($is_root === 1) {
|
||||||
|
$adminContext = [
|
||||||
|
'contexto_tipo' => 'Sistema',
|
||||||
|
'contexto_uuid' => '019a07ee-0c7c-7dd7-a447-802ede64dc98',
|
||||||
|
'nome' => 'Área do Administrador'
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = array_merge([$adminContext], $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'response_code' => 200,
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'Contextos de trabalho encontrados com sucesso',
|
||||||
|
'output' => [
|
||||||
|
'data' => ['contextos' => $result]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
} catch(Exception $e) {
|
||||||
|
return [
|
||||||
|
'response_code' => $e->getCode() ?? 500,
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => $e->getMessage() ?? 'Internal Server Error'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Busca um contexto de trabalho (empresa) específico e verifica se o usuário tem permissão para acessá-lo.
|
||||||
|
*
|
||||||
|
* Este método é crucial para a validação do contexto de trabalho de um usuário (por exemplo, ao iniciar uma sessão em uma empresa). Ele usa uma lógica de consulta SQL para determinar se o `usuario_uuid` está associado à `contexto_uuid` fornecida ou se o usuário é um administrador de sistema (root).
|
||||||
|
*
|
||||||
|
* #### Fluxo de Permissão Lógica:
|
||||||
|
* A cláusula `WHERE` verifica DUAS condições de permissão:
|
||||||
|
* 1. **Associação Direta/Normal (EXISTS):** O usuário está diretamente associado à empresa (`ue.usuario_id = u.id AND ue.empresa_id = e.id`).
|
||||||
|
* 2. **Permissão de Root (OR EXISTS):** O usuário possui a flag `is_root = 1`.
|
||||||
|
*
|
||||||
|
* #### Fluxo de Operação:
|
||||||
|
* 1. **Execução da Query:** Executa uma consulta `SELECT` complexa que filtra as empresas por `contexto_uuid` e `status_id = 1`, além de verificar a permissão do usuário via `EXISTS`.
|
||||||
|
* 2. **Verificação de Resultados:**
|
||||||
|
* * Se o contexto for encontrado e o usuário tiver permissão, retorna um array com **`status` 'success'** e código **200 OK**, com os dados do contexto.
|
||||||
|
* * Se o contexto **não for encontrado** ou o usuário **não tiver permissão** (o que resulta em `empty($result)` devido ao `WHERE`), retorna um array com **`status` 'error'** e código **404 Not Found**.
|
||||||
|
*
|
||||||
|
* #### 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 cuja permissão de acesso está sendo verificada.
|
||||||
|
* @param string $contexto_uuid O UUID da empresa/contexto de trabalho que o usuário está tentando acessar.
|
||||||
|
* @return array Um array associativo contendo o status da operação, um código de resposta HTTP e os dados do contexto, se encontrado.
|
||||||
|
*/
|
||||||
|
public function findWorkContextByUsuarioAndContextoUUID(string $usuario_uuid, string $contexto_uuid): array {
|
||||||
|
try {
|
||||||
|
$sql =
|
||||||
|
"SELECT
|
||||||
|
'Empresa' AS contexto_tipo,
|
||||||
|
e.uuid AS contexto_uuid,
|
||||||
|
e.razao_social,
|
||||||
|
e.nome_fantasia,
|
||||||
|
e.document_inscricao
|
||||||
|
FROM {$this->empresaTable} e
|
||||||
|
WHERE
|
||||||
|
(
|
||||||
|
EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM {$this->usuarioEmpresaTable} ue
|
||||||
|
INNER JOIN {$this->usuarioTable} u
|
||||||
|
ON ue.usuario_id = u.id
|
||||||
|
WHERE
|
||||||
|
ue.empresa_id = e.id
|
||||||
|
AND u.uuid = :usuario_uuid
|
||||||
|
)
|
||||||
|
OR EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM {$this->usuarioTable} u2
|
||||||
|
WHERE
|
||||||
|
u2.uuid = :usuario_uuid
|
||||||
|
AND u2.is_root = 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
AND e.uuid = :contexto_uuid
|
||||||
|
AND e.status_id = :status_id";
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
":usuario_uuid"=> $usuario_uuid,
|
||||||
|
":contexto_uuid"=> $contexto_uuid,
|
||||||
|
":status_id" => 1
|
||||||
|
];
|
||||||
|
|
||||||
|
// Executa a query
|
||||||
|
$result = DB::fetchOne(sql: $sql, params: $params);
|
||||||
|
if(empty($result)) {
|
||||||
|
return [
|
||||||
|
'response_code' => 404,
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'Contexto de trabalho não encontrado para o usuário',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'response_code' => 200,
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'Contexto de trabalho encontrado com sucesso',
|
||||||
|
'output' => [
|
||||||
|
'data' => $result
|
||||||
|
]
|
||||||
|
];
|
||||||
|
} catch(Exception $e) {
|
||||||
|
return [
|
||||||
|
'response_code' => $e->getCode() ?? 500,
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => $e->getMessage() ?? 'Internal Server Error'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
use AxiumPHP\Core\Router;
|
use AxiumPHP\Core\Router;
|
||||||
|
use Workbloom\Component\Auth\v0\Middlewares\AuthMiddleware;
|
||||||
use Workbloom\Component\Auth\v0\Controllers\AuthController;
|
use Workbloom\Component\Auth\v0\Controllers\AuthController;
|
||||||
|
|
||||||
// Rota de login
|
// Rota de login
|
||||||
@@ -7,3 +8,30 @@
|
|||||||
uri: '/login',
|
uri: '/login',
|
||||||
handler: [AuthController::class, 'login']
|
handler: [AuthController::class, 'login']
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Rotas Logadas
|
||||||
|
Router::group(
|
||||||
|
prefix: '',
|
||||||
|
callback: function() {
|
||||||
|
// Lista Contextos de Trabalho
|
||||||
|
Router::GET(
|
||||||
|
uri: '/work-contexts',
|
||||||
|
handler: [AuthController::class, 'listWorkContexts']
|
||||||
|
);
|
||||||
|
|
||||||
|
// Seleção do contexto de trabalho
|
||||||
|
Router::POST(
|
||||||
|
uri: '/select-work-context',
|
||||||
|
handler: [AuthController::class, 'selectWorkContext']
|
||||||
|
);
|
||||||
|
|
||||||
|
// Logout
|
||||||
|
Router::POST(
|
||||||
|
uri: '/logout',
|
||||||
|
handler: [AuthController::class, 'logout']
|
||||||
|
);
|
||||||
|
},
|
||||||
|
middlewares: [
|
||||||
|
[AuthMiddleware::class, 'handle']
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|||||||
@@ -1,8 +1,413 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Workbloom\Component\Auth\v0\Services;
|
namespace Workbloom\Component\Auth\v0\Services;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
use Exception;
|
||||||
|
use Ramsey\Uuid\Uuid;
|
||||||
|
use Workbloom\Services\DB;
|
||||||
|
use Workbloom\Services\JWTService;
|
||||||
|
use Workbloom\Component\Auth\v0\DTO\UsuarioTokenDTO;
|
||||||
|
use Workbloom\Component\Auth\v0\Models\UsuarioModel;
|
||||||
|
|
||||||
class AuthService {
|
class AuthService {
|
||||||
public function login(array $credentials) {
|
/**
|
||||||
return ['data' => $credentials];
|
* Realiza a autenticação de um usuário, verificando as credenciais, revogando sessões antigas e gerando um novo token JWT.
|
||||||
|
*
|
||||||
|
* Este método gerencia todo o fluxo de login e a criação da sessão de autenticação. Ele garante a atomicidade das operações de banco de dados (`revogação` e `registro do token`) utilizando transações.
|
||||||
|
*
|
||||||
|
* #### Fluxo de Operação:
|
||||||
|
* 1. **Início da Transação:** Inicia uma transação no banco de dados (`DB::beginTransaction()`).
|
||||||
|
* 2. **Verificação de Credenciais:** Busca o usuário pelo login (e-mail ou nome de usuário) e verifica a senha fornecida contra o hash armazenado. Se falhar, lança uma `Exception` (código 401).
|
||||||
|
* 3. **Verificação de Status:** Confere se o usuário está ativo (`status_id = 1`) e não excluído. Se não, lança uma `Exception` (código 403).
|
||||||
|
* 4. **Geração do JWT:** Monta o payload do token com os dados essenciais do usuário e gera o novo token JWT.
|
||||||
|
* 5. **Revogação de Tokens Antigos:** Revoga todos os tokens ativos anteriores do usuário no banco de dados. Se a revogação falhar, a transação é revertida, e uma `Exception` é lançada.
|
||||||
|
* 6. **Registro do Novo Token:** Armazena o novo token JWT e metadados de sessão (IP, User Agent, expiração) no banco de dados. Se o registro falhar, a transação é revertida, e uma `Exception` é lançada.
|
||||||
|
* 7. **Confirmação e Retorno:** Se todas as etapas forem bem-sucedidas, a transação é confirmada (`DB::commit()`), e o token gerado é retornado com `status` 'success' e código `200 OK`.
|
||||||
|
*
|
||||||
|
* #### Tratamento de Erros:
|
||||||
|
* - Qualquer `Exception` capturada reverte a transação e retorna um array de erro formatado.
|
||||||
|
*
|
||||||
|
* @param array $credentials Um array associativo contendo as credenciais do usuário, com as chaves 'login' e 'password'.
|
||||||
|
* @return array Um array associativo contendo o status da operação, o código de resposta HTTP e o token JWT em caso de sucesso.
|
||||||
|
*/
|
||||||
|
public function login(array $credentials): array {
|
||||||
|
try {
|
||||||
|
// Consulta o usuario com base no login
|
||||||
|
$usuarioLogin = (new UsuarioModel())->findUsuarioByLogin(login: $credentials['login']);
|
||||||
|
if($usuarioLogin['status'] !== 'success') {
|
||||||
|
throw new Exception(message: 'Usuário não encontrado', code: 404);
|
||||||
|
}
|
||||||
|
$usuarioData = $usuarioLogin['output']['data'];
|
||||||
|
|
||||||
|
// Verifica a senha
|
||||||
|
if(!password_verify(password: $credentials['password'], hash: $usuarioData['senha_hash'])) {
|
||||||
|
throw new Exception(message: 'Senha inválida', code: 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifica se o usuário está ativo
|
||||||
|
if(($usuarioData['status_id'] != 1) || ($usuarioData['deleted_at'] !== null)) {
|
||||||
|
throw new Exception(message: 'Usuário inativo ou excluído', code: 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monta o payload do token
|
||||||
|
$payload['user_data'] = [
|
||||||
|
'uuid' => $usuarioData['uuid'],
|
||||||
|
'nome_completo' => $usuarioData['nome_completo'],
|
||||||
|
'nome_usuario' => $usuarioData['nome_usuario'],
|
||||||
|
'is_root' => $usuarioData['is_root']
|
||||||
|
];
|
||||||
|
|
||||||
|
// Gera o token JWT
|
||||||
|
$generateJWT = JWTService::generateToken(payload: $payload);
|
||||||
|
|
||||||
|
// Inicia Transação no Banco de Dados
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
// Revoga tokens de sessões anteriores
|
||||||
|
$revokeOldTokens = (new UsuarioModel())->revokeOldUsuarioTokens(usuario_uuid: $usuarioData['uuid']);
|
||||||
|
if($revokeOldTokens['status'] !== 'success') {
|
||||||
|
DB::rollBack();
|
||||||
|
throw new Exception(message: 'Erro ao revogar tokens antigos', code: 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registra o token da sessão
|
||||||
|
$registerToken = (new UsuarioModel())->storeUsuarioToken(
|
||||||
|
usuarioTokenDTO: new UsuarioTokenDTO(data: [
|
||||||
|
'usuario_id' => $usuarioData['id'],
|
||||||
|
'usuario_ip' => $_SERVER['REMOTE_ADDR'] ?? null,
|
||||||
|
'usuario_user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? null,
|
||||||
|
'token' => $generateJWT['token'],
|
||||||
|
'is_revoked' => 0,
|
||||||
|
'expires_at' => $generateJWT['expires_at']
|
||||||
|
])
|
||||||
|
);
|
||||||
|
if($registerToken['status'] !== 'success') {
|
||||||
|
DB::rollBack();
|
||||||
|
throw new Exception(message: 'Erro ao registrar token de sessão', code: 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
return [
|
||||||
|
'response_code' => 200,
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'Login realizado com sucesso',
|
||||||
|
'output' => [
|
||||||
|
'data' => $generateJWT
|
||||||
|
]
|
||||||
|
];
|
||||||
|
} catch(Exception $e) {
|
||||||
|
return [
|
||||||
|
'response_code' => $e->getCode() ?? 500,
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => $e->getMessage() ?? 'Internal server error'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valida um token de autenticação JWT contra o registro do banco de dados e verifica a expiração/revogação.
|
||||||
|
*
|
||||||
|
* Este método realiza uma série de verificações de segurança para garantir que o token seja válido e não tenha sido comprometido ou expirado. Ele gerencia o processo de revogação do token no banco de dados se o token for encontrado, mas estiver expirado.
|
||||||
|
*
|
||||||
|
* #### Fluxo de Operação:
|
||||||
|
* 1. **Busca e Validação no DB:** Consulta o token no banco de dados. Se não for encontrado, lança `Exception` (código 404/401).
|
||||||
|
* 2. **Verificação de Expiração e Revogação:** Checa se o token está revogado (`is_revoked === 1`) ou se o prazo de validade (`expires_at`) foi ultrapassado.
|
||||||
|
* 3. **Revogação Automática (se Expirado):** Se o token estiver expirado, e ainda não estiver revogado, o método inicia uma transação (`DB::beginTransaction()`) para revogá-lo no DB. Em seguida, lança uma `Exception` com código `401 Unauthorized` (Token revogado).
|
||||||
|
* 4. **Verificação de Dispositivo:** Compara o IP (`usuario_ip`) e o User Agent (`usuario_user_agent`) armazenados no token com os da requisição atual. Se não houver correspondência, lança uma `Exception` (código 401), invalidando o token para o dispositivo.
|
||||||
|
* 5. **Retorno de Sucesso:** Se todas as verificações passarem, retorna `status` 'success' com o código `200 OK` e os dados do token.
|
||||||
|
*
|
||||||
|
* #### Tratamento de Erros:
|
||||||
|
* - Qualquer `Exception` lançada durante o processo é capturada, e o método retorna um array de erro formatado. O `DB::rollBack()` é tratado nos sub-métodos de revogação, mas o fluxo garante que o erro seja propagado.
|
||||||
|
*
|
||||||
|
* @param string $token O token JWT de autenticação a ser validado.
|
||||||
|
* @return array Um array associativo contendo o status da operação, um código de resposta HTTP e os dados do token, se válido.
|
||||||
|
*/
|
||||||
|
public function validateAuthToken(string $token) {
|
||||||
|
try {
|
||||||
|
// Consulta o token no banco de dados
|
||||||
|
$findToken = (new UsuarioModel())->findUsuarioTokenByIdentifier(identifier: 'token', value: $token);
|
||||||
|
if($findToken['status'] !== 'success') {
|
||||||
|
throw new Exception(message: 'Token não encontrado', code: 404);
|
||||||
|
}
|
||||||
|
$tokenData = $findToken['output']['data'];
|
||||||
|
|
||||||
|
// Verifica se o token está revogado ou expirado
|
||||||
|
if(($tokenData['is_revoked'] === 1) || (new DateTime() > new DateTime(datetime: $tokenData['expires_at']))) {
|
||||||
|
|
||||||
|
// Revoga o token se ainda não estiver revogado
|
||||||
|
if($tokenData['is_revoked'] === 0) {
|
||||||
|
// Incia Transação no Banco de Dados
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
// Atualiza o token para revogado
|
||||||
|
$revokeToken = (new UsuarioModel())->updateUsuarioToken(usuarioTokenDTO: new UsuarioTokenDTO(data: [
|
||||||
|
'is_revoked' => 1,
|
||||||
|
'revoked_at' => (new DateTime())->format(format: 'Y-m-d H:i:s'),
|
||||||
|
'token' => $tokenData['token']
|
||||||
|
]));
|
||||||
|
|
||||||
|
// Verifica se a revogação foi bem-sucedida
|
||||||
|
if($revokeToken['status'] !== 'success') {
|
||||||
|
DB::rollBack();
|
||||||
|
throw new Exception(message: 'Erro ao revogar token', code: 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finaliza Transação no Banco de Dados
|
||||||
|
DB::commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lança exceção indicando que o token foi revogado
|
||||||
|
throw new Exception(message: 'Token revogado', code: 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifica se o agente do usuário e o IP correspondem ao da requisição atual
|
||||||
|
if(isset($tokenData['usuario_ip']) && !in_array(needle: $tokenData['usuario_ip'], haystack: [$_SERVER['REMOTE_ADDR'], null], strict: true)) {
|
||||||
|
throw new Exception(message: "Token inválido para este dispositivo ou IP", code: 401);
|
||||||
|
}
|
||||||
|
if(isset($tokenData['usuario_user_agent']) && !in_array(needle: $tokenData['usuario_user_agent'], haystack: [$_SERVER['HTTP_USER_AGENT'], null], strict: true)) {
|
||||||
|
throw new Exception(message: "Token inválido para este dispositivo ou IP", code: 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'response_code' => 200,
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'Token válido',
|
||||||
|
'output' => [
|
||||||
|
'data' => $tokenData
|
||||||
|
]
|
||||||
|
];
|
||||||
|
} catch(Exception $e) {
|
||||||
|
return [
|
||||||
|
'response_code' => $e->getCode() ?? 500,
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => $e->getMessage() ?? 'Internal server error'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lista os contextos de trabalho (empresas) disponíveis para um usuário.
|
||||||
|
*
|
||||||
|
* Este método determina quais empresas o usuário autenticado pode acessar. Se o usuário for marcado como 'root' (`$is_root` = 1), ele lista todos os contextos ativos no sistema. Caso contrário, lista apenas os contextos associados diretamente ao seu UUID.
|
||||||
|
*
|
||||||
|
* #### Fluxo de Operação:
|
||||||
|
* 1. **Verificação de Permissão Root:**
|
||||||
|
* - Se `$is_root` for `1`, chama `UsuarioModel::findAllWorkContexts()` para listar todos os contextos ativos do sistema.
|
||||||
|
* - Se a consulta falhar, lança uma `Exception` (código 500).
|
||||||
|
* 2. **Busca por Usuário Específico:**
|
||||||
|
* - Se o usuário não for root, chama `UsuarioModel::findWorkContextsByUsuarioUUID()` para listar apenas os contextos diretamente associados ao `usuario_uuid`.
|
||||||
|
* - Se a consulta falhar, lança uma `Exception` (código 500).
|
||||||
|
* 3. **Retorno:** Retorna o array de resultados de contextos (sucesso ou falha, conforme retornado pelo modelo).
|
||||||
|
*
|
||||||
|
* #### Tratamento de Erros:
|
||||||
|
* - Qualquer `Exception` capturada durante o processo (incluindo falhas nos métodos do modelo) retorna um array de erro formatado com o código HTTP e a mensagem da exceção.
|
||||||
|
*
|
||||||
|
* @param string $usuario_uuid O UUID do usuário autenticado.
|
||||||
|
* @param int $is_root Indica se o usuário possui permissão de root (1) ou não (0).
|
||||||
|
* @return array Um array associativo contendo o status da operação, código HTTP e os dados dos contextos de trabalho (`output` com `data`), ou um erro.
|
||||||
|
*/
|
||||||
|
public function listWorkContexts(string $usuario_uuid, int $is_root = 0): array {
|
||||||
|
try {
|
||||||
|
// Se for root, lista todos os contextos de trabalho
|
||||||
|
if($is_root) {
|
||||||
|
// Consulta os contextos de trabalho do usuário
|
||||||
|
$contextos = (new UsuarioModel())->findAllWorkContexts(is_root: $is_root);
|
||||||
|
if($contextos['status'] !== 'success') {
|
||||||
|
throw new Exception(message: 'Erro ao recuperar contextos de trabalho', code: 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lógica para listar todos os contextos de trabalho
|
||||||
|
return $contextos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consulta os contextos de trabalho do usuário
|
||||||
|
$contextos = (new UsuarioModel())->findWorkContextsByUsuarioUUID(usuario_uuid: $usuario_uuid);
|
||||||
|
if($contextos['status'] !== 'success') {
|
||||||
|
throw new Exception(message: 'Erro ao recuperar contextos de trabalho', code: 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lógica para listar os contextos de trabalho do usuário
|
||||||
|
return $contextos;
|
||||||
|
} catch(Exception $e) {
|
||||||
|
return [
|
||||||
|
'response_code' => $e->getCode() ?? 500,
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => $e->getMessage() ?? 'Internal server error'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seleciona e ativa um contexto de trabalho (empresa) para o usuário autenticado.
|
||||||
|
*
|
||||||
|
* Este método é chamado após o login para reemitir um token JWT que inclui as informações do contexto de trabalho selecionado. A operação revoga o token antigo da sessão atual e registra um novo, garantindo a atomicidade das operações de banco de dados.
|
||||||
|
*
|
||||||
|
* #### Fluxo de Operação:
|
||||||
|
* 1. **Verificação de Permissão:** Se o usuário não for 'root' (`$is_root === 0`), verifica se o usuário tem permissão para acessar o `contexto_uuid` específico. Se a verificação falhar, lança uma `Exception` (código 404).
|
||||||
|
* 2. **Busca de Dados:** Busca os dados completos do usuário e os dados do contexto (se não for root).
|
||||||
|
* 3. **Montagem do Payload:** Monta o payload do novo token JWT, incluindo os dados básicos do usuário e o novo `context_data` (UUID e informações da empresa, se aplicável).
|
||||||
|
* 4. **Gerenciamento Transacional:**
|
||||||
|
* - Inicia uma transação no banco de dados (`DB::beginTransaction()`).
|
||||||
|
* - **Revoga Token Antigo:** Atualiza o token anterior para revogado. Se falhar, reverte a transação e lança `Exception` (código 500).
|
||||||
|
* - **Gera e Registra Novo Token:** Gera um novo token JWT com o payload atualizado e o registra no banco de dados. Se falhar, reverte a transação e lança `Exception` (código 500).
|
||||||
|
* 5. **Confirmação e Retorno:** A transação é confirmada (`DB::commit()`), e o novo token é retornado com `status` 'success' e código `200 OK`.
|
||||||
|
*
|
||||||
|
* #### Tratamento de Erros:
|
||||||
|
* - Qualquer `Exception` lançada é capturada, e o método retorna um array de erro formatado com o código HTTP e a mensagem da exceção.
|
||||||
|
*
|
||||||
|
* @param string $usuario_uuid O UUID do usuário autenticado.
|
||||||
|
* @param string $contexto_uuid O UUID do contexto de trabalho (empresa) selecionado.
|
||||||
|
* @param int $is_root Flag que indica se o usuário é root (0 ou 1).
|
||||||
|
* @return array Um array associativo contendo o status da operação, o código de resposta HTTP e o novo token JWT.
|
||||||
|
*/
|
||||||
|
public function selectWorkContext(string $usuario_uuid, string $contexto_uuid, int $is_root = 0): array {
|
||||||
|
try {
|
||||||
|
// Se não for root, verifica se o contexto de trabalho pertence ao usuário
|
||||||
|
if($is_root === 0) {
|
||||||
|
// Consulta se o contexto de trabalho pertence ao usuário
|
||||||
|
$workContext = (new UsuarioModel())->findWorkContextByUsuarioAndContextoUUID(
|
||||||
|
usuario_uuid: $usuario_uuid,
|
||||||
|
contexto_uuid: $contexto_uuid
|
||||||
|
);
|
||||||
|
if($workContext['status'] !== 'success') {
|
||||||
|
throw new Exception(message: 'Contexto de trabalho não encontrado para o usuário', code: 404);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consulta os dados do usuário
|
||||||
|
$usuarioLogin = (new UsuarioModel())->findUsuarioByIdentifier(identifier: 'uuid', value: $usuario_uuid);
|
||||||
|
if($usuarioLogin['status'] !== 'success') {
|
||||||
|
throw new Exception(message: 'Usuário não encontrado', code: 404);
|
||||||
|
}
|
||||||
|
$usuarioData = $usuarioLogin['output']['data'];
|
||||||
|
|
||||||
|
// Monta novo payload do token com o contexto selecionado
|
||||||
|
$payload['user_data'] = [
|
||||||
|
'uuid' => $usuarioData['uuid'],
|
||||||
|
'nome_completo' => $usuarioData['nome_completo'],
|
||||||
|
'nome_usuario' => $usuarioData['nome_usuario'],
|
||||||
|
'is_root' => $usuarioData['is_root']
|
||||||
|
];
|
||||||
|
|
||||||
|
// Monta novo payload do token com o contexto selecionado
|
||||||
|
if(isset($workContext)) {
|
||||||
|
$payload['context_data'] = [
|
||||||
|
'uuid' => $workContext['output']['data']['contexto_uuid']
|
||||||
|
];
|
||||||
|
|
||||||
|
if($workContext['output']['data']['razao_social'] !== null) {
|
||||||
|
$payload['context_data']['razao_social'] = $workContext['output']['data']['razao_social'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if($workContext['output']['data']['nome_fantasia'] !== null) {
|
||||||
|
$payload['context_data']['nome_fantasia'] = $workContext['output']['data']['nome_fantasia'];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$payload['context_data'] = [
|
||||||
|
'uuid' => $contexto_uuid
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inicia Transação no Banco de Dados
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
// Gera o token JWT
|
||||||
|
$generateJWT = JWTService::generateToken(payload: $payload);
|
||||||
|
|
||||||
|
// Revoga o token antigo
|
||||||
|
$revokeToken = (new UsuarioModel())->updateUsuarioToken(usuarioTokenDTO: new UsuarioTokenDTO(data: [
|
||||||
|
'is_revoked' => 1,
|
||||||
|
'revoked_at' => (new DateTime())->format(format: 'Y-m-d H:i:s'),
|
||||||
|
'token' => JWTService::getBearerToken()
|
||||||
|
]));
|
||||||
|
if($revokeToken['status'] !== 'success') {
|
||||||
|
DB::rollBack();
|
||||||
|
throw new Exception(message: 'Erro ao revogar token antigo', code: 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registra o novo token da sessão
|
||||||
|
$registerToken = (new UsuarioModel())->storeUsuarioToken(
|
||||||
|
usuarioTokenDTO: new UsuarioTokenDTO(data: [
|
||||||
|
'usuario_id' => $usuarioData['id'],
|
||||||
|
'usuario_ip' => $_SERVER['REMOTE_ADDR'] ?? null,
|
||||||
|
'usuario_user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? null,
|
||||||
|
'token' => $generateJWT['token'],
|
||||||
|
'is_revoked' => 0,
|
||||||
|
'expires_at' => $generateJWT['expires_at']
|
||||||
|
])
|
||||||
|
);
|
||||||
|
if($registerToken['status'] !== 'success') {
|
||||||
|
DB::rollBack();
|
||||||
|
throw new Exception(message: 'Erro ao registrar token de sessão', code: 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirma a transação no banco de dados
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'response_code' => 200,
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'Contexto de trabalho selecionado com sucesso',
|
||||||
|
'output' => ['data' => $generateJWT]
|
||||||
|
];
|
||||||
|
} catch(Exception $e) {
|
||||||
|
return [
|
||||||
|
'response_code' => $e->getCode() ?? 500,
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => $e->getMessage() ?? 'Internal server error'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finaliza a sessão do usuário revogando um token de autenticação JWT específico.
|
||||||
|
*
|
||||||
|
* Este método atua como um **serviço**, orquestrando a revogação do token no banco de dados e garantindo a atomicidade da operação.
|
||||||
|
*
|
||||||
|
* #### Fluxo de Operação:
|
||||||
|
* 1. **Início da Transação:** Inicia uma transação no banco de dados (`DB::beginTransaction()`).
|
||||||
|
* 2. **Preparação do DTO:** Cria um `UsuarioTokenDTO` para a revogação, definindo o `token`, o status `is_revoked = 1` e o `revoked_at` como o timestamp atual.
|
||||||
|
* 3. **Revogação no Modelo:** Chama `UsuarioModel::updateUsuarioToken()` para invalidar o token no banco de dados.
|
||||||
|
* 4. **Gerenciamento de Transação:**
|
||||||
|
* * Se a revogação falhar (status do modelo for `!== 'success'`), a transação é **revertida** (`DB::rollBack()`), e uma `Exception` é lançada.
|
||||||
|
* * Se a revogação for bem-sucedida, a transação é **confirmada** (`DB::commit()`).
|
||||||
|
* 5. **Retorno de Sucesso:** Retorna um array com **`status` 'success'** e código **200 OK**.
|
||||||
|
*
|
||||||
|
* #### Tratamento de Erros:
|
||||||
|
* - Qualquer `Exception` lançada durante o processo é capturada, a transação é revertida, e o método retorna um array de erro formatado com o código HTTP e a mensagem da exceção.
|
||||||
|
*
|
||||||
|
* @param string $token O token JWT a ser revogado.
|
||||||
|
* @return array Um array associativo contendo o status da operação, o código de resposta HTTP e uma mensagem.
|
||||||
|
*/
|
||||||
|
public function logout(string $token): array {
|
||||||
|
try {
|
||||||
|
// Inicia Transação no Banco de Dados
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
// Atualiza o token para revogado
|
||||||
|
$revokeToken = (new UsuarioModel())->updateUsuarioToken(usuarioTokenDTO: new UsuarioTokenDTO(data: [
|
||||||
|
'is_revoked' => 1,
|
||||||
|
'revoked_at' => (new DateTime())->format(format: 'Y-m-d H:i:s'),
|
||||||
|
'token' => $token
|
||||||
|
]));
|
||||||
|
if($revokeToken['status'] !== 'success') {
|
||||||
|
DB::rollBack();
|
||||||
|
throw new Exception(message: 'Erro ao revogar token', code: 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirma a transação no banco de dados
|
||||||
|
DB::commit();
|
||||||
|
return [
|
||||||
|
'response_code' => 200,
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'Logout realizado com sucesso'
|
||||||
|
];
|
||||||
|
} catch(Exception $e) {
|
||||||
|
return [
|
||||||
|
'response_code' => $e->getCode() ?? 500,
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => $e->getMessage() ?? 'Internal server error'
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
179
app/Common/Services/JWTService.php
Normal file
179
app/Common/Services/JWTService.php
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
<?php
|
||||||
|
namespace Workbloom\Services;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
use Firebase\JWT\JWT;
|
||||||
|
use Firebase\JWT\Key;
|
||||||
|
use Workbloom\Config\Config;
|
||||||
|
|
||||||
|
class JWTService {
|
||||||
|
private static string $issuer;
|
||||||
|
private static int $expiration;
|
||||||
|
private static string $algorithm;
|
||||||
|
private static string $secretKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inicializa as configurações para a geração de tokens JWT.
|
||||||
|
*
|
||||||
|
* Este método estático carrega as informações necessárias para a criação e validação de tokens
|
||||||
|
* JWT (JSON Web Tokens) a partir de uma classe de configuração (`Config`). Ele busca a chave secreta,
|
||||||
|
* o algoritmo de criptografia, o emissor e o tempo de expiração definidos para a aplicação
|
||||||
|
* e os armazena como propriedades estáticas da classe.
|
||||||
|
*
|
||||||
|
* Este método deve ser chamado antes de qualquer operação que envolva a geração ou
|
||||||
|
* verificação de tokens, garantindo que as configurações estejam prontas para uso.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function init(): void {
|
||||||
|
$Config = Config::getInstance();
|
||||||
|
self::$issuer = $Config->get(key: 'JWT_ISSUER');
|
||||||
|
self::$algorithm = $Config->get(key: 'JWT_ALGO');
|
||||||
|
self::$secretKey = $Config->get(key: 'JWT_SECRET');
|
||||||
|
self::$expiration = $Config->get(key: 'JWT_EXPIRATION');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gera um token JWT com base em um payload e nas configurações da aplicação.
|
||||||
|
*
|
||||||
|
* Este método cria um token JWT válido a partir de um array de dados fornecido (`$payload`),
|
||||||
|
* adicionando automaticamente metadados essenciais como a data de emissão, a data de expiração e o emissor.
|
||||||
|
*
|
||||||
|
* O processo detalhado inclui:
|
||||||
|
* 1. **Inicialização:** Chama o método `init()` para garantir que todas as configurações do JWT
|
||||||
|
* (chave secreta, algoritmo, etc.) estejam carregadas.
|
||||||
|
* 2. **Definição dos Timestamps:** Calcula o timestamp de emissão (`iat`) e o de expiração (`exp`)
|
||||||
|
* com base no tempo de expiração definido nas configurações.
|
||||||
|
* 3. **Montagem do Payload:** Adiciona as chaves `iat`, `exp` e `iss` (emissor) ao array `$payload`.
|
||||||
|
* 4. **Codificação do Token:** Utiliza a biblioteca `JWT::encode()` para codificar o payload
|
||||||
|
* com a chave secreta e o algoritmo definidos nas configurações.
|
||||||
|
*
|
||||||
|
* @param array $payload Um array associativo contendo os dados personalizados que serão incluídos no token.
|
||||||
|
* @return array O token JWT gerado como um array.
|
||||||
|
*/
|
||||||
|
public static function generateToken(array $payload): array {
|
||||||
|
// Carrega as informações do arquivo de configuração
|
||||||
|
self::init();
|
||||||
|
|
||||||
|
// Define data de emissão e calcula a data de expiração do token
|
||||||
|
$expiration = self::$expiration;
|
||||||
|
$createdAt = (new DateTime())->getTimestamp();
|
||||||
|
$expireAt = (new DateTime())->modify(modifier: "+{$expiration} seconds")->getTimestamp();
|
||||||
|
|
||||||
|
// Adiciona data de criação ao payload
|
||||||
|
$payload['iat'] = $createdAt;
|
||||||
|
// Adiciona a expiração ao payload
|
||||||
|
$payload['exp'] = $expireAt;
|
||||||
|
// Adiciona o emissor ao payload
|
||||||
|
$payload['iss'] = self::$issuer;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'token' => JWT::encode(payload: $payload, key: self::$secretKey, alg: self::$algorithm),
|
||||||
|
'expires_at' => (new DateTime())->setTimestamp(timestamp: $expireAt)->format(format: 'Y-m-d H:i:s')
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valida um token JWT e retorna o objeto de payload decodificado.
|
||||||
|
*
|
||||||
|
* Este método estático decodifica e valida um token JWT fornecido, utilizando
|
||||||
|
* a chave secreta e o algoritmo de criptografia configurados na classe.
|
||||||
|
*
|
||||||
|
* #### Como funciona:
|
||||||
|
* 1. Recebe o token (`$token`) que precisa ser validado.
|
||||||
|
* 2. Usa a biblioteca `JWT::decode()` para decodificar o token.
|
||||||
|
* 3. Para a decodificação, ele cria uma nova instância de `Key`, passando
|
||||||
|
* a chave secreta (`self::$secretKey`) e o algoritmo (`self::$algorithm`).
|
||||||
|
* Isso garante que o token só será decodificado se tiver sido assinado com a chave e algoritmo corretos.
|
||||||
|
* 4. Se o token for válido e a assinatura corresponder, a função retorna o payload do token
|
||||||
|
* como um objeto.
|
||||||
|
* 5. Se o token for inválido (por exemplo, assinatura incorreta, expirado ou formato incorreto),
|
||||||
|
* a biblioteca JWT lançará uma exceção, que a função que chama este método deve capturar.
|
||||||
|
*
|
||||||
|
* @param string $token O token JWT a ser validado e decodificado.
|
||||||
|
* @return object O objeto de payload decodificado do token.
|
||||||
|
*/
|
||||||
|
public static function validateToken(string $token): object {
|
||||||
|
// Inicializa as configurações se ainda não estiverem definidas
|
||||||
|
if (!isset(self::$secretKey)) {
|
||||||
|
self::init();
|
||||||
|
}
|
||||||
|
|
||||||
|
return JWT::decode(jwt: $token, keyOrKeyArray: new Key(keyMaterial: self::$secretKey, algorithm: self::$algorithm));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodifica um token JWT e retorna seu payload como um array associativo.
|
||||||
|
*
|
||||||
|
* Este método estático é responsável por decodificar e validar um token JWT. Antes de decodificar, ele garante que as configurações de chave secreta e algoritmo (`self::$secretKey` e `self::$algorithm`) já foram inicializadas chamando o método `init()` se necessário.
|
||||||
|
*
|
||||||
|
* #### Como Funciona:
|
||||||
|
* 1. **Inicialização:** Primeiro, verifica se a chave secreta (`self::$secretKey`) já foi carregada. Se não, ele chama `self::init()` para carregar as configurações de um arquivo externo.
|
||||||
|
* 2. **Decodificação:** Usa a biblioteca `Firebase\JWT\JWT::decode()` para decodificar o token fornecido. O método passa a chave secreta e o algoritmo para verificar a assinatura do token.
|
||||||
|
* 3. **Conversão:** O payload decodificado, que por padrão é um objeto, é convertido para uma string JSON e depois para um array associativo, o que facilita o acesso aos dados.
|
||||||
|
* 4. **Retorno:** Retorna o payload do token como um array associativo. Se o token for inválido (assinatura incorreta, expirado, etc.), a biblioteca JWT lançará uma exceção, que a função que chama este método deve capturar.
|
||||||
|
*
|
||||||
|
* @param string $token O token JWT a ser decodificado.
|
||||||
|
* @return array O payload do token decodificado como um array associativo.
|
||||||
|
*/
|
||||||
|
public static function decode(?string $token): array {
|
||||||
|
// Inicializa as configurações se ainda não estiverem definidas
|
||||||
|
if (!isset(self::$secretKey)) {
|
||||||
|
self::init();
|
||||||
|
}
|
||||||
|
|
||||||
|
if($token === null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$decoded = JWT::decode(jwt: $token, keyOrKeyArray: new Key(keyMaterial: self::$secretKey, algorithm: self::$algorithm));
|
||||||
|
return json_decode(json: json_encode(value: $decoded), associative: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extrai o token de autenticação do tipo 'Bearer' do cabeçalho da requisição HTTP.
|
||||||
|
*
|
||||||
|
* Este método estático é um utilitário projetado para buscar um token JWT (JSON Web Token)
|
||||||
|
* que é enviado no cabeçalho `Authorization`. Ele é robusto o suficiente para verificar
|
||||||
|
* o token em diferentes superglobais do PHP, dependendo da configuração do servidor web.
|
||||||
|
*
|
||||||
|
* #### Fluxo de Busca:
|
||||||
|
* 1. Primeiro, tenta obter o cabeçalho `Authorization` diretamente da superglobal `$_SERVER`.
|
||||||
|
* 2. Em seguida, tenta a chave `HTTP_AUTHORIZATION`, que é um nome de variável comum em alguns ambientes.
|
||||||
|
* 3. Por último, usa a função `apache_request_headers()` para tentar obter o cabeçalho, caso as
|
||||||
|
* superglobais não estejam preenchidas. Isso garante compatibilidade com servidores Apache onde o cabeçalho pode não ser exposto.
|
||||||
|
* 4. Se o cabeçalho for encontrado, o valor é sanitizado (removendo espaços em branco) e a busca continua.
|
||||||
|
* 5. Se nenhum cabeçalho de autenticação for encontrado, o método retorna `null`.
|
||||||
|
*
|
||||||
|
* #### Extração do Token:
|
||||||
|
* - Depois de encontrar o cabeçalho, o método usa uma expressão regular (`/Bearer\s(\S+)/`)
|
||||||
|
* para verificar se o valor do cabeçalho está no formato `Bearer <token>`.
|
||||||
|
* - Se o padrão corresponder, ele extrai e retorna a string do token.
|
||||||
|
* - Se o padrão não corresponder, o método retorna `null`.
|
||||||
|
*
|
||||||
|
* @return string|null O token de autenticação do tipo 'Bearer' como uma string, ou `null`
|
||||||
|
* se o cabeçalho não for encontrado ou não estiver no formato esperado.
|
||||||
|
*/
|
||||||
|
public static function getBearerToken(): ?string {
|
||||||
|
if (!isset(self::$secretKey)) {
|
||||||
|
self::init();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tenta pegar o header de todas as fontes possíveis
|
||||||
|
$headers = $_SERVER['Authorization'] ?? $_SERVER['HTTP_AUTHORIZATION'] ?? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ?? (function_exists(function: 'apache_request_headers') ? apache_request_headers() : []);
|
||||||
|
|
||||||
|
// Se veio do apache_request_headers, normaliza chaves
|
||||||
|
if (is_array(value: $headers)) {
|
||||||
|
$headers = array_change_key_case(array: $headers, case: CASE_LOWER);
|
||||||
|
$headers = $headers['authorization'] ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$headers = trim(string: $headers);
|
||||||
|
|
||||||
|
if ($headers && preg_match(pattern: '/Bearer\s(\S+)/', subject: $headers, matches: $matches)) {
|
||||||
|
return $matches[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -70,6 +70,10 @@ CREATE TABLE IF NOT EXISTS public.empresa (
|
|||||||
deleted_at TIMESTAMP DEFAULT NULL
|
deleted_at TIMESTAMP DEFAULT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
INSERT INTO public.empresa (uuid, razao_social, nome_fantasia, inscricao_tipo_id, document_inscricao, inscricao_raiz, endereco_codigo_ibge, endereco_cep, endereco_logradouro, endereco_numero, endereco_complemento, endereco_bairro, endereco_cidade, endereco_estado) VALUES
|
||||||
|
('019a07d3-9174-76b6-a9f0-9e0e189fdba8', 'Ativa Servicos em Refrigeracao e Servicos em Eletrica LTDA', 'Ativa Refrigeração e Elétrica', 1, '61365393000121', '61365393', '2304400', '60115191', 'Rua Monesenhor Bruno', '1153', 'Sala 1423', 'Aldeota', 'Fortaleza', 'CE'),
|
||||||
|
('019a07d3-9174-7879-93ae-4de7da3b5a93', 'A C C Andrade LTDA', 'A.c. Car', 1, '21899523000191', '21899523', '2307601', '62930000', 'Rua Leila Kristinna Lopes Maia', '58', NULL, 'Limoeirinho', 'Limoeiro do Norte', 'CE');
|
||||||
|
|
||||||
-- ===============================================================================================================
|
-- ===============================================================================================================
|
||||||
-- Empresa Certificado Digital
|
-- Empresa Certificado Digital
|
||||||
-- ===============================================================================================================
|
-- ===============================================================================================================
|
||||||
|
|||||||
0
database/v0/migrations/004_RBAC.sql
Normal file
0
database/v0/migrations/004_RBAC.sql
Normal file
Reference in New Issue
Block a user