9 Commits

Author SHA1 Message Date
Claudecio Martins
6071550f20 feat(router): atualizar versão do AxiumPHP e melhorar gerenciamento de rotas 2025-10-26 21:07:28 +01:00
Claudecio Martins
9cfa79db4b feat(funcionario): adicionar tabelas de estado civil, nível de instrução e raça/cor, além de ajustes na tabela de status 2025-10-23 19:51:27 +02:00
Claudecio Martins
263d513198 feat(esocial): adicionar tabelas de tipos de arquivos e tipos de logradouros com inserções iniciais 2025-10-23 19:51:13 +02:00
Claudecio Martins
2981ab64f1 feat(funcionario): criar tabelas de status e funcionário com inserções iniciais 2025-10-23 00:54:12 +02:00
Claudecio Martins
d17e6fa0d8 refactor(funcionario): adicionar comentário para clareza ao carregar arquivo de rotas 2025-10-23 00:54:05 +02:00
Claudecio Martins
037900720b feat(funcionario): adicionar módulo de gerenciamento de funcionários com rotas e controle de API 2025-10-22 16:03:18 +02:00
311cadc1d1 Merge pull request 'feature/login-jwt' (#1) from feature/login-jwt into main
Reviewed-on: #1
2025-10-22 11:16:28 +00:00
Claudecio Martins
ec216528b5 feat(auth): implementar rotas e serviços de autenticação
- Adicionadas rotas de login, logout e seleção de contexto de trabalho em AuthRoutes.php.
- AuthService aprimorado com login detalhado, validação de token, listagem de contexto de trabalho e métodos de seleção.
- JWTService introduzido para lidar com a geração e validação de JWT.
- Migração de banco de dados atualizada para incluir dados de amostra da empresa.
- Arquivo de migração RBAC criado para futura implementação de controle de acesso baseado em função.
2025-10-22 13:15:43 +02:00
Claudecio Martins
75047e8b34 corrige caminho da pasta de logs no .gitignore 2025-10-21 16:55:03 +02:00
37 changed files with 2449 additions and 258 deletions

2
.gitignore vendored
View File

@@ -1,4 +1,4 @@
# Arquivo de variáveis de ambiente
.env
# Pasta de Logs
app/Storage/logs
storage/logs/

View File

@@ -1,12 +1,25 @@
<?php
namespace Workbloom\Component\Auth\v0\Controllers;
use Workbloom\Helpers\DataSanitizer;
use Workbloom\Services\JWTService;
use AxiumPHP\Helpers\RequestHelper;
use Workbloom\Helpers\DataSanitizer;
use Workbloom\Component\Auth\v0\Services\AuthService;
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
$form = RequestHelper::getFilteredInput(form_type: INPUT_POST);
@@ -40,12 +53,117 @@
// Resposta JSON
RequestHelper::sendJsonResponse(
response_code: 200,
status: 'success',
message: 'Login successful',
output: [
'data' => $form
]
response_code: $loginService['response_code'] ?? 500,
status: $loginService['status'] ?? 'error',
message: $loginService['message'] ?? 'Internal server error',
output: $loginService['output'] ?? []
);
}
/**
* 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'] ?? []
);
}
}

View 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()
];
}
}
}

View File

@@ -8,8 +8,10 @@
use Workbloom\Component\Auth\v0\DTO\UsuarioTokenDTO;
class UsuarioModel {
protected string $empresaTable = 'empresa';
protected string $usuarioTable = 'usuario';
protected string $usuarioTokenTable = 'usuario_token';
protected string $usuarioEmpresaTable = 'usuario_empresa';
/**
* 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.
* @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 {
$sql =
"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'
];
}
}
}

View File

@@ -1,5 +1,6 @@
<?php
use AxiumPHP\Core\Router;
use Workbloom\Component\Auth\v0\Middlewares\AuthMiddleware;
use Workbloom\Component\Auth\v0\Controllers\AuthController;
// Rota de login
@@ -7,3 +8,30 @@
uri: '/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']
]
);

View File

@@ -1,8 +1,413 @@
<?php
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 {
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'
];
}
}
}

View 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;
}
}

View File

@@ -0,0 +1,75 @@
<?php
namespace Workbloom\Module\Funcionario;
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 = MODULE_PATH . "/{$manifest['dirName']}/{$api['version']}/Routes/Routes.php";
// Carrega arquivo de rotas
if (file_exists(filename: $routeFile)) {
Router::group(
prefix: "/{$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": "Funcionários",
"dirName": "Funcionario",
"slug": "funcionario",
"description": "Gerencia dados e operações relacionadas aos funcionários.",
"uuid": "019a0bfa-fc2f-7955-94d3-5f5273f07b3b",
"version": "1.0",
"dependencies": [],
"apis": [
{
"version": "v0",
"status": "active",
"start_date": "2025-10-22"
}
]
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Workbloom\Module\Funcionario\v0\Controllers;
use AxiumPHP\Helpers\RequestHelper;
class FuncionarioController {
public function listFuncionarios() {
// Resposta JSON
RequestHelper::sendJsonResponse(
response_code: 200,
status: 'success',
message: 'Lista de funcionários obtida com sucesso',
output: []
);
}
}

View File

@@ -0,0 +1,153 @@
-- ===============================================================================================================
-- Status Funcionário
-- ===============================================================================================================
CREATE TABLE IF NOT EXISTS public.funcionario_status (
id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
descricao VARCHAR(255) NOT NULL,
observacao TEXT DEFAULT NULL
);
INSERT INTO public.funcionario_status (id, descricao, observacao) VALUES
(1, 'Ativo', 'Funcionário ativo'),
(2, 'Inativo', 'Funcionário inativo recebendo benefício do INSS'),
(3, 'Inativo', 'Funcionário aposentado'),
(4, 'Inativo', 'Funcionário desligado da empresa');
SELECT setval(pg_get_serial_sequence('public.funcionario_status','id'), (SELECT MAX(id) FROM public.funcionario_status));
-- ===============================================================================================================
-- Estado Civil Funcionário
-- ===============================================================================================================
CREATE TABLE IF NOT EXISTS public.funcionario_estado_civil (
id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
descricao VARCHAR(255) NOT NULL
);
INSERT INTO public.funcionario_estado_civil (id, descricao) VALUES
(1, 'Solteiro(a)'),
(2, 'Casado(a)'),
(3, 'Divorciado(a)'),
(4, 'Separado(a)'),
(5, 'Viúvo(a)');
SELECT setval(pg_get_serial_sequence('public.funcionario_estado_civil','id'), (SELECT MAX(id) FROM public.funcionario_estado_civil));
-- ===============================================================================================================
-- Nível de Instrução Funcionário
-- ===============================================================================================================
CREATE TABLE IF NOT EXISTS public.funcionario_nivel_instrucao (
id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
codigo_xml VARCHAR(50) NOT NULL,
descricao VARCHAR(255) NOT NULL
);
INSERT INTO public.funcionario_nivel_instrucao (id, codigo_xml, descricao) VALUES
(1, '01', 'Analfabeto, inclusive o que, embora tenha recebido instrução, não se alfabetizou'),
(2, '02', 'Até o 5º ano incompleto do ensino fundamental (antiga 4ª série) ou que se tenha alfabetizado sem ter frequentado escola regular'),
(3, '03', '5º ano completo do ensino fundamental'),
(4, '04', 'Do 6º ao 9º ano do ensino fundamental incompleto (antiga 5ª a 8ª série)'),
(5, '05', 'Ensino fundamental completo'),
(6, '06', 'Ensino médio incompleto'),
(7, '07', 'Ensino médio completo'),
(8, '08', 'Educação superior incompleta'),
(9, '09', 'Educação superior completa'),
(10, '10', 'Pós-graduação completa'),
(11, '11', 'Mestrado completo'),
(12, '12', 'Doutorado completo');
SELECT setval(pg_get_serial_sequence('public.funcionario_nivel_instrucao','id'), (SELECT MAX(id) FROM public.funcionario_nivel_instrucao));
-- ===============================================================================================================
-- Raça/Cor Funcionário
-- ===============================================================================================================
CREATE TABLE IF NOT EXISTS public.funcionario_raca_cor (
id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
codigo_xml VARCHAR(50) NOT NULL,
descricao VARCHAR(255) NOT NULL
);
INSERT INTO public.funcionario_raca_cor (id, codigo_xml, descricao) VALUES
(1, '1', 'Branca'),
(2, '2', 'Preta'),
(3, '3', 'Parda'),
(4, '4', 'Amarela'),
(5, '5', 'Indígena'),
(6, '6', 'Não informado');
SELECT setval(pg_get_serial_sequence('public.funcionario_raca_cor','id'), (SELECT MAX(id) FROM public.funcionario_raca_cor));
-- ===============================================================================================================
-- Funcionário
-- ===============================================================================================================
CREATE TABLE IF NOT EXISTS public.funcionario (
-- Identificadores
id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
uuid UUID NOT NULL UNIQUE,
empresa_id BIGINT NOT NULL REFERENCES public.empresa(id) ON UPDATE CASCADE ON DELETE RESTRICT,
-- Dados Funcionário
status_id BIGINT NOT NULL REFERENCES public.funcionario_status(id) ON UPDATE CASCADE ON DELETE RESTRICT,
nome VARCHAR(255) NOT NULL,
have_nome_social SMALLINT NOT NULL DEFAULT 0,
nome_social VARCHAR(255) DEFAULT NULL,
-- Documentos
document_cpf VARCHAR(11) NOT NULL,
document_pis VARCHAR(11) DEFAULT NULL,
-- Nível de Instrução
nivel_instrucao_id BIGINT DEFAULT NULL REFERENCES public.funcionario_nivel_instrucao(id) ON UPDATE CASCADE ON DELETE RESTRICT,
-- Estado Civil
estado_civil_id BIGINT NOT NULL DEFAULT 1 REFERENCES public.funcionario_estado_civil(id) ON UPDATE CASCADE ON DELETE RESTRICT,
-- Raça/Cor
raca_cor_id BIGINT DEFAULT NULL REFERENCES public.funcionario_raca_cor(id) ON UPDATE CASCADE ON DELETE RESTRICT,
-- Data de Nascimento e Óbito
data_nascimento DATE NOT NULL,
data_obito DATE DEFAULT NULL,
-- Sexo
sexo CHAR(1) DEFAULT NULL,
-- Filiação
filiacao_1 VARCHAR(255) DEFAULT NULL,
filiacao_2 VARCHAR(255) DEFAULT NULL,
-- Naturalidade
naturalidade_pais BIGINT DEFAULT 115 REFERENCES esocial.tab_06(id) ON UPDATE CASCADE ON DELETE RESTRICT,
naturalidade_uf CHAR(2) DEFAULT NULL REFERENCES esocial.tab_07(id) ON UPDATE CASCADE ON DELETE RESTRICT,
naturalidade_municipio VARCHAR(255) DEFAULT NULL,
naturalidade_municipio_codigo_ibge VARCHAR(7) DEFAULT NULL,
-- Residência
endereco_tipo_logradouro BIGINT DEFAULT NULL REFERENCES esocial.tab_20(id) ON UPDATE CASCADE ON DELETE RESTRICT,
endereco_descricao_logradouro VARCHAR(100) DEFAULT NULL,
endereco_numero_logradouro VARCHAR(10) DEFAULT NULL,
endereco_complemento_logradouro VARCHAR(30) DEFAULT NULL,
endereco_bairro VARCHAR(90) DEFAULT NULL,
endereco_cep VARCHAR(8) DEFAULT NULL,
endereco_codigo_municipio_ibge VARCHAR(7) DEFAULT NULL,
endereco_uf CHAR(2) DEFAULT NULL,
-- Endereço no Exterior
endereco_exterior_pais_id BIGINT DEFAULT NULL REFERENCES esocial.tab_06(id) ON UPDATE CASCADE ON DELETE RESTRICT,
endereco_exterior_descricao_logradouro VARCHAR(100) DEFAULT NULL,
endereco_exterior_numero_logradouro VARCHAR(10) DEFAULT NULL,
endereco_exterior_complemento_logradouro VARCHAR(30) DEFAULT NULL,
endereco_exterior_bairro VARCHAR(90) DEFAULT NULL,
endereco_exterior_nome_cidade VARCHAR(50) DEFAULT NULL,
endereco_exterior_cep VARCHAR(12) DEFAULT NULL,
-- Contato
email VARCHAR(255) DEFAULT NULL,
telefone VARCHAR(20) DEFAULT NULL,
celular VARCHAR(20) DEFAULT NULL,
-- Controle de Registros
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT NULL,
deleted_at TIMESTAMP DEFAULT NULL
);

View File

@@ -0,0 +1,33 @@
<?php
use AxiumPHP\Core\Router;
use Workbloom\Module\Funcionario\v0\Controllers\FuncionarioController;
// Listagem de funcionários
Router::GET(
uri: '/',
handler: [FuncionarioController::class, 'listFuncionarios']
);
// Registro de novo funcionário
Router::POST(
uri: '/',
handler: [FuncionarioController::class, 'createFuncionario']
);
// Detalhes de um funcionário
Router::GET(
uri: '/{uuid}',
handler: [FuncionarioController::class, 'getFuncionario']
);
// Atualização de um funcionário
Router::PATCH(
uri: '/{uuid}',
handler: [FuncionarioController::class, 'updateFuncionario']
);
// Remoção de um funcionário
Router::DELETE(
uri: '/{uuid}',
handler: [FuncionarioController::class, 'deleteFuncionario']
);

View File

@@ -0,0 +1,2 @@
<?php
require_once 'FuncionarioRoutes.php';

View File

@@ -7,7 +7,7 @@
"firebase/php-jwt": "v6.11.1",
"vlucas/phpdotenv": "v5.6.2",
"symfony/var-dumper": "^v6.4.26",
"claudecio/axiumphp": "dev-dev-update-initializing",
"claudecio/axiumphp": "dev-feature-updated-router",
"ext-json": "*"
},
"repositories": [
@@ -19,8 +19,8 @@
"autoload": {
"psr-4": {
"Workbloom\\": "app/Common",
"WorkbloomComponent\\": "app/Common/Component",
"WorkbloomModule\\": "app/Module"
"Workbloom\\Component\\": "app/Common/Component",
"Workbloom\\Module\\": "app/Module"
}
},
"require-dev": {

26
composer.lock generated
View File

@@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "3e440c7d7c70dfe80c1e1f3c59e6adc5",
"content-hash": "f3706a4f041aac68b4feb4e9d952a8a2",
"packages": [
{
"name": "claudecio/axiumphp",
"version": "dev-dev-update-initializing",
"version": "dev-feature-updated-router",
"source": {
"type": "git",
"url": "https://github.com/claudecio/AxiumPHP.git",
"reference": "ccc3c7de5462371150ea8d82549701519503f9f7"
"reference": "c7353947a667ea857b461f2b6251441784a4b8ef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/claudecio/AxiumPHP/zipball/ccc3c7de5462371150ea8d82549701519503f9f7",
"reference": "ccc3c7de5462371150ea8d82549701519503f9f7",
"url": "https://api.github.com/repos/claudecio/AxiumPHP/zipball/c7353947a667ea857b461f2b6251441784a4b8ef",
"reference": "c7353947a667ea857b461f2b6251441784a4b8ef",
"shasum": ""
},
"require": {
@@ -35,10 +35,10 @@
],
"description": "Meu framework PHP para sistemas MVC modulares.",
"support": {
"source": "https://github.com/claudecio/AxiumPHP/tree/dev-update-initializing",
"source": "https://github.com/claudecio/AxiumPHP/tree/feature-updated-router",
"issues": "https://github.com/claudecio/AxiumPHP/issues"
},
"time": "2025-10-18T18:31:17+00:00"
"time": "2025-10-26T20:05:19+00:00"
},
{
"name": "firebase/php-jwt",
@@ -795,16 +795,16 @@
},
{
"name": "nikic/php-parser",
"version": "v5.6.1",
"version": "v5.6.2",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2"
"reference": "3a454ca033b9e06b63282ce19562e892747449bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
"reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3a454ca033b9e06b63282ce19562e892747449bb",
"reference": "3a454ca033b9e06b63282ce19562e892747449bb",
"shasum": ""
},
"require": {
@@ -847,9 +847,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1"
"source": "https://github.com/nikic/PHP-Parser/tree/v5.6.2"
},
"time": "2025-08-13T20:13:15+00:00"
"time": "2025-10-21T19:32:17+00:00"
},
{
"name": "phar-io/manifest",

View File

@@ -79,14 +79,227 @@ SELECT setval(pg_get_serial_sequence('esocial.tab_02','id'), (SELECT MAX(id) FRO
-- Tabela 03 - Natureza das Rubricas da Folha de Pagamento
-- ===============================================================================================================
CREATE TABLE IF NOT EXISTS esocial.tab_03 (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
id BIGINT,
nome VARCHAR(255) NOT NULL,
descricao TEXT DEFAULT NULL,
data_inicio DATE NOT NULL,
data_fim DATE DEFAULT NULL,
incide_cp SMALLINT DEFAULT 0
);
INSERT INTO esocial.tab_03 (id, nome, data_inicio, data_fim, incide_cp) VALUES
(1000, 'Salário, vencimento, soldo', '2014-01-01', NULL, '0'),
(1001, 'Subsídio', '2014-01-01', NULL, '0'),
(1002, 'Descanso semanal remunerado - DSR', '2014-01-01', '2024-04-30', '0'),
(1003, 'Horas extraordinárias', '2014-01-01', NULL, '0'),
(1004, 'Horas extraordinárias - Banco de horas', '2014-01-01', NULL, '0'),
(1005, 'Direito de arena', '2014-01-01', NULL, '0'),
(1006, 'Intervalos intra e inter jornadas não concedidos', '2014-01-01', NULL, '0'),
(1007, 'Luvas e premiações', '2014-01-01', NULL, '0'),
(1009, 'Salário-família - Complemento', '2014-01-01', NULL, '0'),
(1010, 'Salário in natura - Pagos em bens ou serviços', '2014-01-01', NULL, '0'),
(1011, 'Sobreaviso e prontidão', '2014-01-01', NULL, '0'),
(1012, 'Descanso semanal remunerado - DSR e feriado', '2014-01-01', NULL, '0'),
(1015, 'Adiantamento de férias', '2014-01-01', NULL, '0'),
(1016, 'Férias', '2014-01-01', '2025-12-31', '0'),
(1016, 'Férias', '2026-01-01', NULL, '0'),
(1017, 'Terço constitucional de férias', '2014-01-01', '2025-12-31', '1'),
(1017, 'Terço constitucional de férias', '2026-01-01', NULL, '1'),
(1018, 'Férias - Abono ou gratificação de férias superior a 20 dias', '2014-01-01', NULL, '1'),
(1019, 'Terço constitucional de férias - Abono ou gratificação de férias superior a 20 dias', '2014-01-01', NULL, '1'),
(1020, 'Férias', '2014-01-01', '2023-04-30', '0'),
(1021, 'Férias - Abono ou gratificação de férias superior a 20 dias', '2014-01-01', '2023-04-30', '1'),
(1022, 'Férias - Abono ou gratificação de férias não excedente a 20 dias', '2014-01-01', NULL, '1'),
(1023, 'Férias - Abono pecuniário', '2014-01-01', NULL, '0'),
(1024, 'Férias - Dobro na vigência do contrato', '2014-01-01', NULL, '0'),
(1040, 'Licença-prêmio', '2014-01-01', NULL, '0'),
(1041, 'Licença-prêmio indenizada', '2014-01-01', NULL, '0'),
(1050, 'Remuneração de dias de afastamento', '2014-01-01', NULL, '0'),
(1080, 'Stock option', '2014-01-01', NULL, '0'),
(1099, 'Outras verbas salariais', '2014-01-01', NULL, '0'),
(1201, 'Adicional de função / cargo confiança', '2014-01-01', NULL, '0'),
(1202, 'Adicional de insalubridade', '2014-01-01', NULL, '0'),
(1203, 'Adicional de periculosidade', '2014-01-01', NULL, '0'),
(1204, 'Adicional de transferência', '2014-01-01', NULL, '0'),
(1205, 'Adicional noturno', '2014-01-01', NULL, '0'),
(1206, 'Adicional por tempo de serviço', '2014-01-01', NULL, '0'),
(1207, 'Comissões, porcentagens, produção', '2014-01-01', NULL, '0'),
(1208, 'Gueltas ou gorjetas - Repassadas por fornecedores ou clientes', '2014-01-01', NULL, '0'),
(1209, 'Gueltas ou gorjetas - Repassadas pelo empregador', '2014-01-01', NULL, '0'),
(1210, 'Gratificação por acordo ou convenção coletiva', '2014-01-01', NULL, '0'),
(1211, 'Gratificações', '2014-01-01', NULL, '0'),
(1212, 'Gratificações ou outras verbas de natureza permanente', '2014-01-01', NULL, '0'),
(1213, 'Gratificações ou outras verbas de natureza transitória', '2014-01-01', NULL, '0'),
(1214, 'Adicional de penosidade', '2014-01-01', NULL, '0'),
(1215, 'Adicional de unidocência', '2014-01-01', NULL, '0'),
(1216, 'Adicional de localidade', '2014-01-01', NULL, '0'),
(1217, 'Gratificação de curso/concurso', '2014-01-01', NULL, '0'),
(1225, 'Quebra de caixa', '2014-01-01', NULL, '0'),
(1230, 'Remuneração do dirigente sindical', '2014-01-01', NULL, '0'),
(1299, 'Outros adicionais', '2014-01-01', NULL, '0'),
(1300, 'PLR - Participação em Lucros ou Resultados', '2014-01-01', NULL, '0'),
(1350, 'Bolsa de estudo - Estagiário', '2014-01-01', NULL, '0'),
(1351, 'Bolsa de estudo - Médico residente', '2014-01-01', NULL, '0'),
(1352, 'Bolsa de estudo ou pesquisa', '2014-01-01', NULL, '0'),
(1401, 'Abono', '2014-01-01', NULL, '0'),
(1402, 'Abono PIS/PASEP', '2014-01-01', NULL, '0'),
(1403, 'Abono legal', '2014-01-01', NULL, '0'),
(1404, 'Auxílio babá', '2014-01-01', NULL, '0'),
(1405, 'Assistência médica', '2014-01-01', NULL, '0'),
(1406, 'Auxílio-creche', '2014-01-01', NULL, '0'),
(1407, 'Auxílio-educação', '2014-01-01', NULL, '0'),
(1409, 'Salário-família', '2014-01-01', NULL, '0'),
(1410, 'Auxílio - Locais de difícil acesso', '2014-01-01', NULL, '0'),
(1411, 'Auxílio-natalidade', '2014-01-01', NULL, '1'),
(1412, 'Abono permanência', '2014-01-01', NULL, '0'),
(1601, 'Ajuda de custo - Aeronauta', '2014-01-01', NULL, '0'),
(1602, 'Ajuda de custo de transferência', '2014-01-01', NULL, '0'),
(1603, 'Ajuda de custo', '2018-05-01', NULL, '0'),
(1604, 'Ajuda de custo - Acima de 50% da remuneração mensal', '2018-05-01', '2019-03-31', '0'),
(1619, 'Ajuda compensatória - Programa Emergencial de Manutenção do Emprego e da Renda', '2020-04-01', NULL, '0'),
(1620, 'Ressarcimento de despesas pelo uso de veículo próprio', '2014-01-01', NULL, '0'),
(1621, 'Ressarcimento de despesas de viagem, exceto despesas com veículos', '2014-01-01', NULL, '0'),
(1623, 'Ressarcimento de provisão', '2014-01-01', NULL, '0'),
(1629, 'Ressarcimento de outras despesas', '2014-01-01', NULL, '0'),
(1650, 'Diárias de viagem', '2018-05-01', NULL, '0'),
(1651, 'Diárias de viagem - Até 50% do salário', '2014-01-01', '2018-04-30', '0'),
(1652, 'Diárias de viagem - Acima de 50% do salário', '2014-01-01', '2018-04-30', '0'),
(1799, 'Alimentação concedida em pecúnia com caráter indenizatório', '2014-01-01', NULL, '1'),
(1800, 'Alimentação concedida em pecúnia', '2014-01-01', '2025-12-31', '1'),
(1800, 'Alimentação concedida em pecúnia com caráter salarial', '2026-01-01', NULL, '1'),
(1801, 'Alimentação', '2014-01-01', '2021-06-30', '1'),
(1802, 'Etapas (marítimos)', '2014-01-01', NULL, '1'),
(1805, 'Moradia', '2014-01-01', NULL, '1'),
(1806, 'Alimentação em ticket ou cartão, vinculada ao PAT', '2014-01-01', NULL, '1'),
(1807, 'Alimentação em ticket ou cartão, não vinculada ao PAT', '2014-01-01', NULL, '1'),
(1808, 'Cesta básica ou refeição, vinculada ao PAT', '2014-01-01', NULL, '1'),
(1809, 'Cesta básica ou refeição, não vinculada ao PAT', '2014-01-01', NULL, '1'),
(1810, 'Transporte', '2014-01-01', '2025-12-31', '1'),
(1810, 'Vale-transporte ou auxílio-transporte com caráter indenizatório', '2026-01-01', NULL, '1'),
(1811, 'Auxílio-transporte ou auxílio-combustível com caráter salarial', '2014-01-01', NULL, '1'),
(1899, 'Outros auxílios', '2014-01-01', NULL, '0'),
(1901, 'Juros e/ou atualização monetária', '2014-01-01', NULL, '0'),
(2501, 'Prêmios', '2014-01-01', NULL, '0'),
(2502, 'Liberalidades concedidas em mais de duas parcelas anuais', '2018-05-01', '2019-03-31', '0'),
(2510, 'Direitos autorais e intelectuais', '2014-01-01', NULL, '0'),
(2801, 'Quarentena remunerada', '2014-01-01', NULL, '0'),
(2901, 'Empréstimos', '2014-01-01', NULL, '0'),
(2902, 'Vestuário e equipamentos', '2014-01-01', '2021-07-31', '0'),
(2903, 'Vestuário e equipamentos', '2014-01-01', NULL, '0'),
(2920, 'Reembolsos diversos', '2014-01-01', '2021-07-31', '0'),
(2930, 'Insuficiência de saldo', '2014-01-01', NULL, '0'),
(2999, 'Arredondamentos', '2014-01-01', NULL, '0'),
(3501, 'Remuneração por prestação de serviços', '2014-01-01', NULL, '0'),
(3505, 'Retiradas (pró-labore) de diretores empregados', '2014-01-01', NULL, '0'),
(3506, 'Retiradas (pró-labore) de diretores não empregados', '2014-01-01', NULL, '0'),
(3508, 'Retiradas (pró-labore) de proprietários ou sócios', '2014-01-01', NULL, '0'),
(3509, 'Honorários a conselheiros', '2014-01-01', NULL, '0'),
(3510, 'Gratificação (jeton)', '2014-01-01', NULL, '0'),
(3511, 'Gratificação eleitoral', '2014-01-01', NULL, '0'),
(3520, 'Remuneração de cooperado', '2014-01-01', NULL, '0'),
(3525, 'Côngruas, prebendas e afins', '2018-05-01', NULL, '0'),
(4010, 'Complementação salarial de auxílio-doença', '2014-01-01', NULL, '0'),
(4011, 'Complemento de salário-mínimo - RPPS', '2014-01-01', NULL, '0'),
(4050, 'Salário-maternidade', '2014-01-01', NULL, '1'),
(4051, 'Salário-maternidade - 13° salário', '2014-01-01', NULL, '1'),
(5001, '13º salário', '2014-01-01', NULL, '0'),
(5005, '13° salário complementar', '2014-01-01', NULL, '0'),
(5501, 'Adiantamento de salário', '2014-01-01', NULL, '0'),
(5504, '13º salário - Adiantamento', '2014-01-01', NULL, '0'),
(5510, 'Adiantamento de benefícios previdenciários', '2014-01-01', NULL, '0'),
(6000, 'Saldo de salários na rescisão contratual', '2014-01-01', NULL, '0'),
(6001, '13º salário relativo ao aviso prévio indenizado', '2014-01-01', NULL, '0'),
(6002, '13° salário proporcional na rescisão', '2014-01-01', NULL, '0'),
(6003, 'Indenização compensatória do aviso prévio', '2014-01-01', NULL, '0'),
(6004, 'Férias - Dobro na rescisão', '2014-01-01', NULL, '0'),
(6006, 'Férias proporcionais', '2014-01-01', NULL, '0'),
(6007, 'Férias vencidas na rescisão', '2014-01-01', NULL, '0'),
(6101, 'Indenização compensatória - Multa rescisória 20 ou 40% (CF/88)', '2014-01-01', NULL, '0'),
(6102, 'Indenização do art. 9º da Lei 7.238/1984', '2014-01-01', NULL, '0'),
(6103, 'Indenização do art. 14 da Lei 5.889/1973', '2014-01-01', NULL, '0'),
(6104, 'Indenização do art. 479 da CLT', '2014-01-01', NULL, '0'),
(6105, 'Indenização recebida a título de incentivo a demissão', '2014-01-01', NULL, '0'),
(6106, 'Multa do art. 477 da CLT', '2014-01-01', NULL, '0'),
(6107, 'Indenização por quebra de estabilidade', '2014-01-01', NULL, '0'),
(6108, 'Tempo de espera do motorista profissional', '2014-01-01', NULL, '0'),
(6119, 'Indenização rescisória - Programa Emergencial de Manutenção do Emprego e da Renda', '2020-04-01', NULL, '0'),
(6129, 'Outras verbas não remuneratórias (indenizatórias ou multas)', '2014-01-01', NULL, '0'),
(6901, 'Desconto do aviso prévio', '2014-01-01', NULL, '0'),
(6904, 'Multa prevista no art. 480 da CLT', '2014-01-01', NULL, '0'),
(7001, 'Proventos', '2014-01-01', NULL, '0'),
(7002, 'Proventos - Pensão por morte Civil', '2014-01-01', NULL, '0'),
(7003, 'Proventos - Reserva', '2014-01-01', NULL, '0'),
(7004, 'Proventos - Reforma', '2014-01-01', NULL, '0'),
(7005, 'Pensão Militar', '2014-01-01', NULL, '0'),
(7006, 'Auxílio-reclusão', '2014-01-01', NULL, '0'),
(7007, 'Pensões especiais', '2014-01-01', NULL, '0'),
(7008, 'Complementação de aposentadoria/ pensão', '2014-01-01', NULL, '0'),
(9200, 'Desconto de adiantamentos', '2014-01-01', NULL, '0'),
(9201, 'Contribuição previdenciária', '2014-01-01', NULL, '0'),
(9202, 'Contribuição militar', '2014-01-01', NULL, '0'),
(9203, 'Imposto de Renda Retido na Fonte', '2014-01-01', NULL, '0'),
(9205, 'Provisão de contribuição previdenciária', '2014-01-01', NULL, '0'),
(9207, 'Faltas', '2014-01-01', NULL, '0'),
(9208, 'Atrasos', '2014-01-01', NULL, '0'),
(9209, 'Faltas ou atrasos', '2014-01-01', NULL, '0'),
(9210, 'DSR s/faltas e atrasos', '2014-01-01', NULL, '0'),
(9211, 'DSR sobre faltas', '2014-01-01', NULL, '0'),
(9212, 'DSR sobre atrasos', '2014-01-01', NULL, '0'),
(9213, 'Pensão alimentícia', '2014-01-01', NULL, '0'),
(9214, '13° salário - Desconto de adiantamento', '2014-01-01', NULL, '0'),
(9216, 'Desconto de vale-transporte', '2014-01-01', NULL, '0'),
(9217, 'Contribuição a Outras Entidades e Fundos', '2014-01-01', NULL, '0'),
(9218, 'Retenções judiciais', '2014-01-01', NULL, '0'),
(9219, 'Desconto de assistência médica ou odontológica - Plano coletivo empresarial', '2014-01-01', NULL, '0'),
(9220, 'Alimentação - Desconto', '2014-01-01', '2021-06-30', '0'),
(9221, 'Desconto de férias', '2014-01-01', NULL, '0'),
(9222, 'Desconto de outros impostos e contribuições', '2014-01-01', NULL, '0'),
(9223, 'Previdência complementar - Parte do empregado', '2014-01-01', NULL, '0'),
(9224, 'FAPI - Parte do empregado', '2014-01-01', NULL, '0'),
(9225, 'Previdência complementar - Parte do servidor', '2014-01-01', NULL, '0'),
(9226, 'Desconto de férias - Abono', '2014-01-01', NULL, '0'),
(9230, 'Contribuição sindical laboral', '2014-01-01', NULL, '0'),
(9231, 'Mensalidade sindical ou associativa', '2014-01-01', NULL, '0'),
(9232, 'Contribuição sindical - Assistencial', '2014-01-01', NULL, '0'),
(9233, 'Contribuição sindical - Confederativa', '2014-01-01', NULL, '0'),
(9240, 'Alimentação concedida em pecúnia - Desconto', '2014-01-01', NULL, '0'),
(9241, 'Alimentação em ticket ou cartão, vinculada ao PAT - Desconto', '2014-01-01', NULL, '0'),
(9242, 'Alimentação em ticket ou cartão, não vinculada ao PAT - Desconto', '2014-01-01', NULL, '0'),
(9243, 'Cesta básica ou refeição, vinculada ao PAT - Desconto', '2014-01-01', NULL, '0'),
(9244, 'Cesta básica ou refeição, não vinculada ao PAT - Desconto', '2014-01-01', NULL, '0'),
(9250, 'Seguro de vida - Desconto', '2014-01-01', NULL, '0'),
(9253, 'Empréstimos eConsignado - Desconto', '2024-07-01', NULL, '0'),
(9254, 'Empréstimos consignados - Desconto', '2014-01-01', NULL, '0'),
(9255, 'Empréstimos do empregador - Desconto', '2014-01-01', NULL, '0'),
(9258, 'Convênios', '2014-01-01', NULL, '0'),
(9260, 'FIES - Desconto', '2018-05-01', NULL, '0'),
(9270, 'Danos e prejuízos causados pelo trabalhador', '2014-01-01', NULL, '0'),
(9290, 'Desconto de pagamento indevido em meses anteriores', '2014-01-01', '2021-07-31', '0'),
(9291, 'Abate-teto', '2014-01-01', NULL, '0'),
(9292, 'Ressarcimento ao erário', '2014-01-01', NULL, '0'),
(9293, 'Honorários advocatícios', '2014-01-01', NULL, '0'),
(9294, 'Redutor EC 41/03', '2014-01-01', NULL, '0'),
(9299, 'Outros descontos', '2014-01-01', NULL, '0'),
(9901, 'Base de cálculo da contribuição previdenciária', '2014-01-01', NULL, '0'),
(9902, 'Total da base de cálculo do FGTS', '2014-01-01', NULL, '0'),
(9903, 'Total da base de cálculo do IRRF', '2014-01-01', NULL, '0'),
(9904, 'Total da base de cálculo do FGTS rescisório', '2014-01-01', NULL, '0'),
(9905, 'Serviço militar', '2014-01-01', NULL, '0'),
(9906, 'Remuneração no exterior', '2014-01-01', NULL, '0'),
(9907, 'Total da contribuição da previdenciária patronal - RPPS', '2014-01-01', NULL, '0'),
(9908, 'FGTS - Depósito', '2014-01-01', NULL, '0'),
(9910, 'Seguros', '2014-01-01', NULL, '0'),
(9911, 'Assistência Médica', '2014-01-01', NULL, '0'),
(9912, 'Desconto de assistência médica ou odontológica - Plano diferente de coletivo empresarial', '2014-01-01', NULL, '0'),
(9930, 'Salário-maternidade pago pela Previdência Social', '2014-01-01', NULL, '1'),
(9931, 'Salário-maternidade pago pela Previdência Social - 13° salário', '2014-01-01', NULL, '1'),
(9932, 'Auxílio-doença acidentário', '2014-01-01', NULL, '0'),
(9933, 'Auxílio-doença', '2014-01-01', NULL, '0'),
(9938, 'Isenção IRRF - 65 anos', '2014-01-01', NULL, '0'),
(9939, 'Outros valores tributáveis', '2014-01-01', NULL, '0'),
(9950, 'Horas extraordinárias - Banco de horas', '2014-01-01', '2019-10-31', '0'),
(9951, 'Horas compensadas - Banco de horas', '2014-01-01', '2019-10-31', '0'),
(9989, 'Outros valores informativos', '2014-01-01', NULL, '0');
-- ===============================================================================================================
-- Tabela 04 - Códigos e Alíquotas de FPAS / Terceiros
-- ===============================================================================================================
@@ -178,3 +391,561 @@ INSERT INTO esocial.tab_05 (id, descricao) VALUES
-- Atualizando a sequência depois do insert
SELECT setval(pg_get_serial_sequence('esocial.tab_05','id'), (SELECT MAX(id) FROM esocial.tab_05));
-- ===============================================================================================================
-- Tabela 06 - Países
-- ===============================================================================================================
CREATE TABLE IF NOT EXISTS esocial.tab_06 (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
descricao VARCHAR(255) NOT NULL,
data_criacao DATE DEFAULT NULL,
data_extincao DATE DEFAULT NULL
);
INSERT INTO esocial.tab_06 (id, descricao, data_criacao, data_extincao) VALUES
(008, 'Abu Dhabi', NULL, '1996-12-13'),
(009, 'Dirce', NULL, '1996-12-13'),
(013, 'Afeganistão', NULL, NULL),
(015, 'Aland, Ilhas', '2015-12-07', '2023-01-15'),
(017, 'Albânia, República da', NULL, NULL),
(020, 'Alboran-Perejil, Ilhas', NULL, '1996-12-13'),
(023, 'Alemanha', NULL, NULL),
(025, 'Alemanha, República Democrática', NULL, '1996-12-13'),
(031, 'Burkina Faso', NULL, NULL),
(037, 'Andorra', NULL, NULL),
(040, 'Angola', NULL, NULL),
(041, 'Anguilla', NULL, NULL),
(042, 'Antártica', NULL, '2023-01-15'),
(043, 'Antígua e Barbuda', NULL, NULL),
(047, 'Antilhas Holandesas', NULL, '2018-04-30'),
(053, 'Arábia Saudita', NULL, NULL),
(059, 'Argélia', NULL, NULL),
(063, 'Argentina', NULL, NULL),
(064, 'Armênia, República da', NULL, NULL),
(065, 'Aruba', NULL, NULL),
(069, 'Austrália', NULL, NULL),
(072, 'Áustria', NULL, NULL),
(073, 'Azerbaijão, República do', NULL, NULL),
(077, 'Bahamas, Ilhas', NULL, NULL),
(080, 'Bahrein, Ilhas', NULL, NULL),
(081, 'Bangladesh', NULL, NULL),
(083, 'Barbados', NULL, NULL),
(085, 'Belarus, República da', NULL, NULL),
(087, 'Bélgica', NULL, NULL),
(088, 'Belize', NULL, NULL),
(090, 'Bermudas', NULL, NULL),
(093, 'Mianmar (Birmânia)', NULL, NULL),
(097, 'Bolívia, Estado Plurinacional da', NULL, NULL),
(098, 'Bósnia-Herzegovina, República da', NULL, NULL),
(099, 'Bonaire, Saint Eustatius e Saba', '2015-12-07', NULL),
(100, 'Int. Z. F. Manaus', '1991-12-01', '1996-12-13'),
(101, 'Botsuana', NULL, NULL),
(102, 'Bouvet, Ilha', '2015-12-07', NULL),
(105, 'Brasil', NULL, NULL),
(106, 'Fretado p/ Brasil', '1991-12-01', '1996-11-14'),
(108, 'Brunei', NULL, NULL),
(111, 'Bulgária, República da', NULL, NULL),
(115, 'Burundi', NULL, NULL),
(119, 'Butão', NULL, NULL),
(127, 'Cabo Verde, República de', NULL, NULL),
(131, 'Cachemira', NULL, '1996-12-13'),
(137, 'Cayman, Ilhas', NULL, NULL),
(141, 'Camboja', NULL, NULL),
(145, 'Camarões', NULL, NULL),
(149, 'Canadá', NULL, NULL),
(150, 'Ilhas do Canal (Jersey e Guernsey)', NULL, '2018-04-30'),
(151, 'Canárias, Ilhas', NULL, '2018-04-30'),
(152, 'Canal, Ilhas', NULL, '1996-12-13'),
(153, 'Cazaquistão, República do', NULL, NULL),
(154, 'Catar', NULL, NULL),
(158, 'Chile', NULL, NULL),
(160, 'China, República Popular da', NULL, NULL),
(161, 'Formosa (Taiwan)', NULL, NULL),
(163, 'Chipre', NULL, NULL),
(165, 'Cocos (Keeling), Ilhas', NULL, NULL),
(169, 'Colômbia', NULL, NULL),
(173, 'Comores, Ilhas', NULL, NULL),
(177, 'Congo', NULL, NULL),
(183, 'Cook, Ilhas', NULL, NULL),
(187, 'Coreia (do Norte), República Popular Democrática da', NULL, NULL),
(190, 'Coreia (do Sul), República da', NULL, NULL),
(193, 'Costa do Marfim', NULL, NULL),
(195, 'Croácia, República da', NULL, NULL),
(196, 'Costa Rica', NULL, NULL),
(198, 'Kuwait', NULL, NULL),
(199, 'Cuba', NULL, NULL),
(200, 'Curaçao', '2015-12-07', NULL),
(229, 'Benim', NULL, NULL),
(232, 'Dinamarca', NULL, NULL),
(235, 'Dominica, Ilha', NULL, NULL),
(237, 'Dubai', NULL, '1996-12-13'),
(239, 'Equador', NULL, NULL),
(240, 'Egito', NULL, NULL),
(243, 'Eritreia', '2006-07-17', NULL),
(244, 'Emirados Árabes Unidos', NULL, NULL),
(245, 'Espanha', NULL, NULL),
(246, 'Eslovênia, República da', NULL, NULL),
(247, 'Eslovaca, República', NULL, NULL),
(249, 'Estados Unidos', NULL, NULL),
(251, 'Estônia, República da', NULL, NULL),
(253, 'Etiópia', NULL, NULL),
(255, 'Falkland (Ilhas Malvinas)', NULL, NULL),
(259, 'Feroe, Ilhas', NULL, NULL),
(263, 'Fezzan', NULL, '1996-12-13'),
(267, 'Filipinas', NULL, NULL),
(271, 'Finlândia', NULL, NULL),
(275, 'França', NULL, NULL),
(281, 'Gabão', NULL, NULL),
(285, 'Gâmbia', NULL, NULL),
(289, 'Gana', NULL, NULL),
(291, 'Geórgia, República da', NULL, NULL),
(292, 'Geórgia do Sul e Sandwich do Sul, Ilhas', NULL, '2023-01-15'),
(293, 'Gibraltar', NULL, NULL),
(297, 'Granada', NULL, NULL),
(301, 'Grécia', NULL, NULL),
(305, 'Groenlândia', NULL, NULL),
(309, 'Guadalupe', NULL, NULL),
(313, 'Guam', NULL, NULL),
(317, 'Guatemala', NULL, NULL),
(321, 'Guernsey, Ilha do Canal', NULL, NULL),
(325, 'Guiana Francesa', NULL, NULL),
(329, 'Guiné', NULL, NULL),
(331, 'Guiné Equatorial', NULL, NULL),
(334, 'Guiné-Bissau', NULL, NULL),
(337, 'Guiana', NULL, NULL),
(341, 'Haiti', NULL, NULL),
(343, 'Heard e Ilhas McDonald, Ilha', NULL, '2023-01-15'),
(345, 'Honduras', NULL, NULL),
(351, 'Hong Kong', NULL, NULL),
(355, 'Hungria, República da', NULL, NULL),
(357, 'Iêmen', NULL, NULL),
(358, 'Iêmen do Sul', NULL, '1996-12-13'),
(359, 'Man, Ilha de', NULL, NULL),
(361, 'Índia', NULL, NULL),
(365, 'Indonésia', NULL, NULL),
(367, 'Inglaterra', NULL, '1997-03-18'),
(369, 'Iraque', NULL, NULL),
(372, 'Irã, República Islâmica do', NULL, NULL),
(375, 'Irlanda', NULL, NULL),
(379, 'Islândia', NULL, NULL),
(383, 'Israel', NULL, NULL),
(386, 'Itália', NULL, NULL),
(388, 'Sérvia e Montenegro', NULL, '2013-11-21'),
(391, 'Jamaica', NULL, NULL),
(393, 'Jersey, Ilha do Canal', NULL, NULL),
(395, 'Jammu', NULL, '1996-12-13'),
(396, 'Johnston, Ilhas', NULL, '2018-04-30'),
(399, 'Japão', NULL, NULL),
(403, 'Jordânia', NULL, NULL),
(411, 'Kiribati', NULL, NULL),
(420, 'Laos, República Popular Democrática do', NULL, NULL),
(423, 'Lebuan, Ilhas', NULL, '2018-04-30'),
(426, 'Lesoto', NULL, NULL),
(427, 'Letônia, República da', NULL, NULL),
(431, 'Líbano', NULL, NULL),
(434, 'Libéria', NULL, NULL),
(438, 'Líbia', NULL, NULL),
(440, 'Liechtenstein', NULL, NULL),
(442, 'Lituânia, República da', NULL, NULL),
(445, 'Luxemburgo', NULL, NULL),
(447, 'Macau', NULL, NULL),
(449, 'Macedônia do Norte', NULL, NULL),
(450, 'Madagascar', NULL, NULL),
(452, 'Ilha da Madeira', NULL, '2018-04-30'),
(455, 'Malásia', NULL, NULL),
(458, 'Malavi', NULL, NULL),
(461, 'Maldivas', NULL, NULL),
(464, 'Mali', NULL, NULL),
(467, 'Malta', NULL, NULL),
(472, 'Marianas do Norte', NULL, NULL),
(474, 'Marrocos', NULL, NULL),
(476, 'Marshall, Ilhas', NULL, NULL),
(477, 'Martinica', NULL, NULL),
(485, 'Maurício', NULL, NULL),
(488, 'Mauritânia', NULL, NULL),
(489, 'Mayotte', NULL, '2023-01-15'),
(490, 'Midway, Ilhas', NULL, '2018-04-30'),
(493, 'México', NULL, NULL),
(494, 'Moldávia, República da', NULL, NULL),
(495, 'Mônaco', NULL, NULL),
(497, 'Mongólia', NULL, NULL),
(498, 'Montenegro', '2006-06-03', NULL),
(499, 'Micronésia', NULL, NULL),
(501, 'Montserrat, Ilhas', NULL, NULL),
(505, 'Moçambique', NULL, NULL),
(507, 'Namíbia', NULL, NULL),
(508, 'Nauru', NULL, NULL),
(511, 'Christmas, Ilha (Navidad)', NULL, NULL),
(517, 'Nepal', NULL, NULL),
(521, 'Nicarágua', NULL, NULL),
(525, 'Níger', NULL, NULL),
(528, 'Nigéria', NULL, NULL),
(531, 'Niue, Ilha', NULL, NULL),
(535, 'Norfolk, Ilha', NULL, NULL),
(538, 'Noruega', NULL, NULL),
(542, 'Nova Caledônia', NULL, NULL),
(545, 'Papua Nova Guiné', NULL, NULL),
(548, 'Nova Zelândia', NULL, NULL),
(551, 'Vanuatu', NULL, NULL),
(556, 'Omã', NULL, NULL),
(563, 'Pacífico, Ilhas do (Administração dos EUA)', NULL, '1996-12-13'),
(566, 'Pacífico, Ilhas do (Possessão dos EUA)', NULL, NULL),
(569, 'Pacífico, Ilhas do (Território em Fideicomisso dos)', NULL, '1996-12-13'),
(573, 'Países Baixos (Holanda)', NULL, NULL),
(575, 'Palau', NULL, NULL),
(576, 'Paquistão', NULL, NULL),
(578, 'Palestina', '2011-01-25', NULL),
(580, 'Panamá', NULL, NULL),
(583, 'Papua Nova Guiné', '1991-12-01', '1996-12-13'),
(586, 'Paraguai', NULL, NULL),
(589, 'Peru', NULL, NULL),
(593, 'Pitcairn, Ilha', NULL, NULL),
(599, 'Polinésia Francesa', NULL, NULL),
(603, 'Polônia, República da', NULL, NULL),
(607, 'Portugal', NULL, NULL),
(611, 'Porto Rico', NULL, NULL),
(623, 'Quênia', NULL, NULL),
(625, 'Quirguiz, República', NULL, NULL),
(628, 'Reino Unido', NULL, NULL),
(640, 'República Centro-Africana', NULL, NULL),
(647, 'República Dominicana', NULL, NULL),
(660, 'Reunião, Ilha', NULL, NULL),
(665, 'Zimbábue', NULL, NULL),
(670, 'Romênia', NULL, NULL),
(675, 'Ruanda', NULL, NULL),
(676, 'Rússia, Federação da', NULL, NULL),
(677, 'Salomão, Ilhas', NULL, NULL),
(678, 'Saint Kitts e Nevis', NULL, '2016-06-27'),
(685, 'Saara Ocidental', NULL, NULL),
(687, 'El Salvador', NULL, NULL),
(690, 'Samoa', NULL, NULL),
(691, 'Samoa Americana', NULL, NULL),
(693, 'São Bartolomeu', '2015-12-07', '2023-01-15'),
(695, 'São Cristóvão e Neves, Ilhas', NULL, NULL),
(697, 'San Marino', NULL, NULL),
(698, 'São Martinho, Ilha de (Parte Francesa)', NULL, NULL),
(699, 'São Martinho, Ilha de (Parte Holandesa)', '2015-12-07', NULL),
(700, 'São Pedro e Miquelon', NULL, NULL),
(705, 'São Vicente e Granadinas', NULL, NULL),
(710, 'Santa Helena', NULL, NULL),
(715, 'Santa Lúcia', NULL, NULL),
(720, 'São Tomé e Príncipe, Ilhas', NULL, NULL),
(728, 'Senegal', NULL, NULL),
(731, 'Seychelles', NULL, NULL),
(735, 'Serra Leoa', NULL, NULL),
(737, 'Sérvia', '2006-06-03', NULL),
(738, 'Sikkim', NULL, '1996-12-13'),
(741, 'Singapura', NULL, NULL),
(744, 'Síria, República Árabe da', NULL, NULL),
(748, 'Somália', NULL, NULL),
(750, 'Sri Lanka', NULL, NULL),
(754, 'eSwatini (Essuatíni, Suazilândia)', NULL, NULL),
(755, 'Svalbard e Jan Mayen', NULL, NULL),
(756, 'África do Sul', NULL, NULL),
(759, 'Sudão', NULL, NULL),
(760, 'Sudão do Sul', '2013-05-27', NULL),
(764, 'Suécia', NULL, NULL),
(767, 'Suíça', NULL, NULL),
(770, 'Suriname', NULL, NULL),
(772, 'Tadjiquistão, República do', NULL, NULL),
(776, 'Tailândia', NULL, NULL),
(780, 'Tanzânia, República Unida da', NULL, NULL),
(781, 'Terras Austrais Francesas', NULL, '2023-01-15'),
(782, 'Território Britânico Oceano Índico', NULL, NULL),
(783, 'Djibuti', NULL, NULL),
(785, 'Território da Alta Comissão do Pacífico Ocidental', NULL, '1996-12-13'),
(788, 'Chade', NULL, NULL),
(790, 'Tchecoslováquia', NULL, '1996-12-13'),
(791, 'Tcheca, República', NULL, NULL),
(795, 'Timor Leste', NULL, NULL),
(800, 'Togo', NULL, NULL),
(805, 'Toquelau, Ilhas', NULL, NULL),
(810, 'Tonga', NULL, NULL),
(815, 'Trinidad e Tobago', NULL, NULL),
(820, 'Tunísia', NULL, NULL),
(823, 'Turcas e Caicos, Ilhas', NULL, NULL),
(824, 'Turcomenistão, República do', NULL, NULL),
(827, 'Turquia', NULL, NULL),
(828, 'Tuvalu', NULL, NULL),
(831, 'Ucrânia', NULL, NULL),
(833, 'Uganda', NULL, NULL),
(840, 'Uniao das Repúblicas Socialistas Soviéticas', NULL, '1996-12-13'),
(845, 'Uruguai', NULL, NULL),
(847, 'Uzbequistão, República do', NULL, NULL),
(848, 'Vaticano, Estado da Cidade do', NULL, NULL),
(850, 'Venezuela', NULL, NULL),
(855, 'Vietname Norte', NULL, '1996-12-13'),
(858, 'Vietnã', NULL, NULL),
(863, 'Virgens, Ilhas (Britânicas)', NULL, NULL),
(866, 'Virgens, Ilhas (EUA)', NULL, NULL),
(870, 'Fiji', NULL, NULL),
(873, 'Wake, Ilha', NULL, '2018-04-30'),
(875, 'Wallis e Futuna, Ilhas', NULL, NULL),
(888, 'Congo, República Democrática do', NULL, NULL),
(890, 'Zâmbia', NULL, NULL),
(895, 'Zona do Canal do Panamá', NULL, '2016-06-27'),
(995, 'Bancos Centrais', NULL, NULL),
(997, 'Organizações Internacionais', NULL, NULL);
SELECT setval(pg_get_serial_sequence('esocial.tab_06','id'), (SELECT MAX(id) FROM esocial.tab_06));
-- ===============================================================================================================
-- Tabela 09 - Tipos de arquivos do eSocial
-- ===============================================================================================================
CREATE TABLE IF NOT EXISTS esocial.tab_09 (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
codigo_xml VARCHAR(50) NOT NULL,
descricao VARCHAR(255) NOT NULL,
data_inicio DATE DEFAULT NULL,
data_fim DATE DEFAULT NULL
);
INSERT INTO esocial.tab_09 (id, codigo_xml, descricao, data_inicio, data_fim) VALUES
(1, 'S-1000', 'Informações do Empregador/Contribuinte/Órgão Público', '2014-01-01', NULL),
(2, 'S-1005', 'Tabela de Estabelecimentos, Obras ou Unidades de Órgãos Públicos', '2014-01-01', NULL),
(3, 'S-1010', 'Tabela de Rubricas', '2014-01-01', NULL),
(4, 'S-1020', 'Tabela de Lotações Tributárias', '2014-01-01', NULL),
(5, 'S-1070', 'Tabela de Processos Administrativos/Judiciais', '2014-01-01', NULL),
(6, 'S-1200', 'Remuneração de Trabalhador vinculado ao Regime Geral de Previd. Social', '2014-01-01', NULL),
(7, 'S-1202', 'Remuneração de Servidor vinculado ao Regime Próprio de Previd. Social', '2022-08-22', NULL),
(8, 'S-1207', 'Benefícios - Entes Públicos', '2022-08-22', NULL),
(9, 'S-1210', 'Pagamentos de Rendimentos do Trabalho', '2014-01-01', NULL),
(10, 'S-1260', 'Comercialização da Produção Rural Pessoa Física', '2014-01-01', NULL),
(11, 'S-1270', 'Contratação de Trabalhadores Avulsos Não Portuários', '2014-01-01', NULL),
(12, 'S-1280', 'Informações Complementares aos Eventos Periódicos', '2014-01-01', NULL),
(13, 'S-1298', 'Reabertura dos Eventos Periódicos', '2014-01-01', NULL),
(14, 'S-1299', 'Fechamento dos Eventos Periódicos', '2014-01-01', NULL),
(15, 'S-2190', 'Registro Preliminar de Trabalhador', '2014-01-01', NULL),
(16, 'S-2200', 'Cadastramento Inicial do Vínculo e Admissão/Ingresso de Trabalhador', '2014-01-01', NULL),
(17, 'S-2205', 'Alteração de Dados Cadastrais do Trabalhador', '2014-01-01', NULL),
(18, 'S-2206', 'Alteração de Contrato de Trabalho/Relação Estatutária', '2014-01-01', NULL),
(19, 'S-2210', 'Comunicação de Acidente de Trabalho', '2021-10-13', NULL),
(20, 'S-2220', 'Monitoramento da Saúde do Trabalhador', '2021-10-13', NULL),
(21, 'S-2221', 'Exame Toxicológico do Motorista Profissional Empregado', '2024-08-01', NULL),
(22, 'S-2230', 'Afastamento Temporário', '2014-01-01', NULL),
(23, 'S-2231', 'Cessão/Exercício em Outro Órgão', '2021-07-19', NULL),
(24, 'S-2240', 'Condições Ambientais do Trabalho - Agentes Nocivos', '2021-10-13', NULL),
(25, 'S-2298', 'Reintegração/Outros Provimentos', '2014-01-01', NULL),
(26, 'S-2299', 'Desligamento', '2014-01-01', NULL),
(27, 'S-2300', 'Trabalhador Sem Vínculo de Emprego/Estatutário - Início', '2014-01-01', NULL),
(28, 'S-2306', 'Trabalhador Sem Vínculo de Emprego/Estatutário - Alteração Contratual', '2014-01-01', NULL),
(29, 'S-2399', 'Trabalhador Sem Vínculo de Emprego/Estatutário - Término', '2014-01-01', NULL),
(30, 'S-2400', 'Cadastro de Beneficiário - Entes Públicos - Início', '2021-11-22', NULL),
(31, 'S-2405', 'Cadastro de Beneficiário - Entes Públicos - Alteração', '2021-11-22', NULL),
(32, 'S-2410', 'Cadastro de Benefício - Entes Públicos - Início', '2021-11-22', NULL),
(33, 'S-2416', 'Cadastro de Benefício - Entes Públicos - Alteração', '2021-11-22', NULL),
(34, 'S-2418', 'Reativação de Benefício - Entes Públicos', '2021-11-22', NULL),
(35, 'S-2420', 'Cadastro de Benefício - Entes Públicos - Término', '2021-11-22', NULL),
(36, 'S-2500', 'Processo Trabalhista', '2023-10-01', NULL),
(37, 'S-2501', 'Informações de Tributos Decorrentes de Processo Trabalhista', '2023-10-01', NULL),
(38, 'S-2555', 'Solicitação de Consolidação das Informações de Tributos Decorrentes de Processo Trabalhista', '2024-12-01', NULL),
(39, 'S-3000', 'Exclusão de Eventos', '2014-01-01', NULL),
(40, 'S-3500', 'Exclusão de Eventos - Processo Trabalhista', '2023-10-01', NULL),
(41, 'S-5001', 'Informações das Contribuições Sociais por Trabalhador', '2014-01-01', NULL),
(42, 'S-5002', 'Imposto de Renda Retido na Fonte por Trabalhador', '2014-01-01', NULL),
(43, 'S-5003', 'Informações do FGTS por Trabalhador', '2018-05-01', NULL),
(44, 'S-5011', 'Informações das Contribuições Sociais Consolidadas por Contribuinte', '2014-01-01', NULL),
(45, 'S-5012', 'Imposto de Renda Retido na Fonte Consolidado por Contribuinte', '2023-01-16', NULL),
(46, 'S-5013', 'Informações do FGTS Consolidadas por Contribuinte', '2018-05-01', NULL),
(47, 'S-5501', 'Informações Consolidadas de Tributos Decorrentes de Processo Trabalhista', '2023-10-01', NULL),
(48, 'S-5503', 'Informações do FGTS por Trabalhador em Processo Trabalhista', '2023-11-20', NULL),
(49, 'S-8200', 'Anotação Judicial do Vínculo', '2014-01-01', NULL),
(50, 'S-8299', 'Baixa Judicial do Vínculo', '2019-09-24', NULL);
SELECT setval(pg_get_serial_sequence('esocial.tab_09','id'), (SELECT MAX(id) FROM esocial.tab_09));
-- ===============================================================================================================
-- Tabela 20 - Tipos de Logradouros
-- ===============================================================================================================
CREATE TABLE IF NOT EXISTS esocial.tab_20 (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
codigo_xml VARCHAR(50) NOT NULL,
descricao VARCHAR(255) NOT NULL
);
INSERT INTO esocial.tab_20 (id, codigo_xml, descricao) VALUES
(1, 'A', 'Área'),
(2, 'AC', 'Acesso'),
(3, 'ACA', 'Acampamento'),
(4, 'ACL', 'Acesso Local'),
(5, 'AD', 'Adro'),
(6, 'AE', 'Área Especial'),
(7, 'AER', 'Aeroporto'),
(8, 'AL', 'Alameda'),
(9, 'ALD', 'Aldeia'),
(10, 'AMD', 'Avenida Marginal Direita'),
(11, 'AME', 'Avenida Marginal Esquerda'),
(12, 'AN', 'Anel Viário'),
(13, 'ANT', 'Antiga Estrada'),
(14, 'ART', 'Artéria'),
(15, 'AT', 'Alto'),
(16, 'ATL', 'Atalho'),
(17, 'A V', 'Área Verde'),
(18, 'AV', 'Avenida'),
(19, 'AVC', 'Avenida Contorno'),
(20, 'AVM', 'Avenida Marginal'),
(21, 'AVV', 'Avenida Velha'),
(22, 'BAL', 'Balneário'),
(23, 'BC', 'Beco'),
(24, 'BCO', 'Buraco'),
(25, 'BEL', 'Belvedere'),
(26, 'BL', 'Bloco'),
(27, 'BLO', 'Balão'),
(28, 'BLS', 'Blocos'),
(29, 'BLV', 'Bulevar'),
(30, 'BSQ', 'Bosque'),
(31, 'BVD', 'Boulevard'),
(32, 'BX', 'Baixa'),
(33, 'C', 'Cais'),
(34, 'CAL', 'Calçada'),
(35, 'CAM', 'Caminho'),
(36, 'CAN', 'Canal'),
(37, 'CH', 'Chácara'),
(38, 'CHA', 'Chapadão'),
(39, 'CIC', 'Ciclovia'),
(40, 'CIR', 'Circular'),
(41, 'CJ', 'Conjunto'),
(42, 'CJM', 'Conjunto Mutirão'),
(43, 'CMP', 'Complexo Viário'),
(44, 'COL', 'Colônia'),
(45, 'COM', 'Comunidade'),
(46, 'CON', 'Condomínio'),
(47, 'COND', 'Condomínio'),
(48, 'COR', 'Corredor'),
(49, 'CPO', 'Campo'),
(50, 'CRG', 'Córrego'),
(51, 'CTN', 'Contorno'),
(52, 'DSC', 'Descida'),
(53, 'DSV', 'Desvio'),
(54, 'DT', 'Distrito'),
(55, 'EB', 'Entre Bloco'),
(56, 'EIM', 'Estrada Intermunicipal'),
(57, 'ENS', 'Enseada'),
(58, 'ENT', 'Entrada Particular'),
(59, 'EQ', 'Entre Quadra'),
(60, 'ESC', 'Escada'),
(61, 'ESD', 'Escadaria'),
(62, 'ESE', 'Estrada Estadual'),
(63, 'ESI', 'Estrada Vicinal'),
(64, 'ESL', 'Estrada de Ligação'),
(65, 'ESM', 'Estrada Municipal'),
(66, 'ESP', 'Esplanada'),
(67, 'ESS', 'Estrada de Servidão'),
(68, 'EST', 'Estrada'),
(69, 'ESV', 'Estrada Velha'),
(70, 'ETA', 'Estrada Antiga'),
(71, 'ETC', 'Estação'),
(72, 'ETD', 'Estádio'),
(73, 'ETN', 'Estância'),
(74, 'ETP', 'Estrada Particular'),
(75, 'ETT', 'Estacionamento'),
(76, 'EVA', 'Evangélica'),
(77, 'EVD', 'Elevada'),
(78, 'EX', 'Eixo Industrial'),
(79, 'FAV', 'Favela'),
(80, 'FAZ', 'Fazenda'),
(81, 'FER', 'Ferrovia'),
(82, 'FNT', 'Fonte'),
(83, 'FRA', 'Feira'),
(84, 'FTE', 'Forte'),
(85, 'GAL', 'Galeria'),
(86, 'GJA', 'Granja'),
(87, 'HAB', 'Núcleo Habitacional'),
(88, 'IA', 'Ilha'),
(89, 'IGP', 'Igarapé'),
(90, 'IND', 'Indeterminado'),
(91, 'IOA', 'Ilhota'),
(92, 'JD', 'Jardim'),
(93, 'JDE', 'Jardinete'),
(94, 'LD', 'Ladeira'),
(95, 'LGA', 'Lagoa'),
(96, 'LGO', 'Lago'),
(97, 'LOT', 'Loteamento'),
(98, 'LRG', 'Largo'),
(99, 'LT', 'Lote'),
(100, 'MER', 'Mercado'),
(101, 'MNA', 'Marina'),
(102, 'MOD', 'Modulo'),
(103, 'MRG', 'Projeção'),
(104, 'MRO', 'Morro'),
(105, 'MTE', 'Monte'),
(106, 'NUC', 'Núcleo'),
(107, 'NUR', 'Núcleo Rural'),
(108, 'O', 'Outros'),
(109, 'OUT', 'Outeiro'),
(110, 'PAR', 'Paralela'),
(111, 'PAS', 'Passeio'),
(112, 'PAT', 'Pátio'),
(113, 'PC', 'Praça'),
(114, 'PCE', 'Praça de Esportes'),
(115, 'PDA', 'Parada'),
(116, 'PDO', 'Paradouro'),
(117, 'PNT', 'Ponta'),
(118, 'PR', 'Praia'),
(119, 'PRL', 'Prolongamento'),
(120, 'PRM', 'Parque Municipal'),
(121, 'PRQ', 'Parque'),
(122, 'PRR', 'Parque Residencial'),
(123, 'PSA', 'Passarela'),
(124, 'PSG', 'Passagem'),
(125, 'PSP', 'Passagem de Pedestre'),
(126, 'PSS', 'Passagem Subterrânea'),
(127, 'PTE', 'Ponte'),
(128, 'PTO', 'Porto'),
(129, 'Q', 'Quadra'),
(130, 'QTA', 'Quinta'),
(131, 'QTS', 'Quintas'),
(132, 'R', 'Rua'),
(133, 'R I', 'Rua Integração'),
(134, 'R L', 'Rua de Ligação'),
(135, 'R P', 'Rua Particular'),
(136, 'R V', 'Rua Velha'),
(137, 'RAM', 'Ramal'),
(138, 'RCR', 'Recreio'),
(139, 'REC', 'Recanto'),
(140, 'RER', 'Retiro'),
(141, 'RES', 'Residencial'),
(142, 'RET', 'Reta'),
(143, 'RLA', 'Ruela'),
(144, 'RMP', 'Rampa'),
(145, 'ROA', 'Rodo Anel'),
(146, 'ROD', 'Rodovia'),
(147, 'ROT', 'Rotula'),
(148, 'RPE', 'Rua de Pedestre'),
(149, 'RPR', 'Margem'),
(150, 'RTN', 'Retorno'),
(151, 'RTT', 'Rotatória'),
(152, 'SEG', 'Segunda Avenida'),
(153, 'SIT', 'Sitio'),
(154, 'SRV', 'Servidão'),
(155, 'ST', 'Setor'),
(156, 'SUB', 'Subida'),
(157, 'TCH', 'Trincheira'),
(158, 'TER', 'Terminal'),
(159, 'TR', 'Trecho'),
(160, 'TRV', 'Trevo'),
(161, 'TUN', 'Túnel'),
(162, 'TV', 'Travessa'),
(163, 'TVP', 'Travessa Particular'),
(164, 'TVV', 'Travessa Velha'),
(165, 'UNI', 'Unidade'),
(166, 'V', 'Via'),
(167, 'V C', 'Via Coletora'),
(168, 'V L', 'Via Local'),
(169, 'VAC', 'Via de Acesso'),
(170, 'VAL', 'Vala'),
(171, 'VCO', 'Via Costeira'),
(172, 'VD', 'Viaduto'),
(173, 'V-E', 'Via Expressa'),
(174, 'VER', 'Vereda'),
(175, 'VEV', 'Via Elevado'),
(176, 'VL', 'Vila'),
(177, 'VLA', 'Viela'),
(178, 'VLE', 'Vale'),
(179, 'VLT', 'Via Litorânea'),
(180, 'VPE', 'Via de Pedestre'),
(181, 'VRT', 'Variante'),
(182, 'ZIG', 'Zigue-Zague');
SELECT setval(pg_get_serial_sequence('esocial.tab_20','id'), (SELECT MAX(id) FROM esocial.tab_20));

View File

@@ -70,6 +70,10 @@ CREATE TABLE IF NOT EXISTS public.empresa (
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
-- ===============================================================================================================

View File

View File

@@ -3,7 +3,9 @@
require_once realpath(path: __DIR__ . '/../vendor/autoload.php');
use AxiumPHP\AxiumPHP;
use AxiumPHP\Core\Router;
use Workbloom\Config\Config;
use Workbloom\Component\Auth\v0\Middlewares\AuthMiddleware;
// ============================
// Configurações globais
@@ -48,6 +50,19 @@
// ============================
require COMPONENT_PATH . "/Auth/bootstrap.php";
// ============================================
// Carrega módulos do sistema versão 0
// ============================================
Router::group(
prefix: '/v0/module',
callback: function() {
require MODULE_PATH . "/Funcionario/bootstrap.php";
},
middlewares: [
[AuthMiddleware::class, 'handle']
]
);
// ============================
// Dispara o roteador
// ============================

View File

@@ -2,27 +2,19 @@
namespace AxiumPHP\Core;
use Exception;
use AxiumPHP\Helpers\RequestHelper;
class Router {
private static $routes = [];
private static $params = [];
private static $ROUTER_MODE = null;
private static $APP_SYS_MODE = null;
private static $ROUTER_ALLOWED_ORIGINS = ['*'];
private static string $basePath = '';
private static $currentGroupPrefix = '';
private static $currentGroupMiddlewares = [];
private static array $requiredConstants = [
'ROUTER_MODE',
'APP_SYS_MODE'
];
private static array $allowedHttpRequests = [
'GET',
'POST',
'PUT',
'PATCH',
'DELETE',
'OPTIONS'
];
private static $ROUTER_ALLOWED_ORIGINS = ['*'];
private static array $requiredConstants = ['ROUTER_MODE', 'APP_SYS_MODE'];
private static array $allowedHttpRequests = ['GET','POST','PUT','PATCH','DELETE','OPTIONS'];
/**
* Construtor que vai garantir que as constantes necessárias estejam definidas antes de
@@ -32,6 +24,11 @@
// Verificar as constantes no momento da criação da instância
self::checkRequiredConstant();
// Verifica se tem diretório base
if(defined(constant_name: 'ROUTER_BASE_PATH')) {
self::$basePath = ROUTER_BASE_PATH;
}
// Define constante
self::$ROUTER_MODE = strtoupper(string: ROUTER_MODE);
self::$APP_SYS_MODE = strtoupper(string: APP_SYS_MODE);
@@ -74,99 +71,26 @@
}
}
/**
* Adiciona uma rota com método GET à lista de rotas da aplicação.
*
* Este método é um atalho para adicionar rotas com o método HTTP GET. Ele
* chama o método `addRoute` internamente, passando os parâmetros
* fornecidos e o método 'GET'.
*
* @param string $uri O caminho da rota (ex: '/usuarios', '/produtos').
* @param array $handler Um array contendo o nome do controlador e o nome da ação
* que devem ser executados quando a rota for
* corresponder (ex: ['UsuarioController', 'index']).
* @param array $middlewares Um array opcional contendo os nomes dos middlewares que
* devem ser executados antes do handler da rota.
*
* @return void
*/
// =======================
// Métodos HTTP
// =======================
public static function GET(string $uri, array $handler, array $middlewares = []): void {
self::addRoute(method: "GET", uri: $uri, handler: $handler, middlewares: $middlewares);
}
/**
* Adiciona uma rota com método POST à lista de rotas da aplicação.
*
* Este método é um atalho para adicionar rotas com o método HTTP POST. Ele
* chama o método `addRoute` internamente, passando os parâmetros
* fornecidos e o método 'POST'.
*
* @param string $uri O caminho da rota (ex: '/usuarios', '/produtos').
* @param array $handler Um array contendo o nome do controlador e o nome da ação
* que devem ser executados quando a rota for
* corresponder (ex: ['UsuarioController', 'salvar']).
* @param array $middlewares Um array opcional contendo os nomes dos middlewares que
* devem ser executados antes do handler da rota.
*
* @return void
*/
public static function POST(string $uri, array $handler, array $middlewares = []): void {
self::addRoute(method: "POST", uri: $uri, handler: $handler, middlewares: $middlewares);
}
/**
* Adiciona uma rota com método PUT à lista de rotas da aplicação.
*
* Este método é um atalho para adicionar rotas com o método HTTP PUT. Ele
* chama o método `addRoute` internamente, passando os parâmetros
* fornecidos e o método 'PUT'.
*
* @param string $uri O caminho da rota (ex: '/usuarios', '/produtos').
* @param array $handler Um array contendo o nome do controlador e o nome da ação
* que devem ser executados quando a rota for
* corresponder (ex: ['UsuarioController', 'salvar']).
* @param array $middlewares Um array opcional contendo os nomes dos middlewares que
* devem ser executados antes do handler da rota.
*
* @return void
*/
public static function PUT(string $uri, array $handler, array $middlewares = []): void {
self::addRoute(method: "PUT", uri: $uri, handler: $handler, middlewares: $middlewares);
}
/**
* Adiciona uma nova rota que responde a requisições PATCH.
*
* Este é um método estático de conveniência que simplifica o registro de rotas
* para o método HTTP PATCH. Ele delega a tarefa principal para o método
* privado `addRoute`, passando o método HTTP, a URI, a função de manipulação
* (`handler`) e quaisquer middlewares associados.
*
* @param string $uri A URI da rota (ex: '/api/resource/{id}').
* @param array $handler Um array de dois elementos que define o manipulador da rota: o nome da classe do controlador e o nome do método a ser executado.
* @param array $middlewares Um array opcional de middlewares a serem executados antes do manipulador da rota.
* @return void
*/
public static function PATCH(string $uri, array $handler, array $middlewares = []): void {
self::addRoute(method: "PATCH", uri: $uri, handler: $handler, middlewares: $middlewares);
}
/**
* Adiciona uma rota com método DELETE à lista de rotas da aplicação.
*
* Este método é um atalho para adicionar rotas com o método HTTP DELETE. Ele
* chama o método `addRoute` internamente, passando os parâmetros
* fornecidos e o método 'DELETE'.
*
* @param string $uri O caminho da rota (ex: '/usuarios', '/produtos').
* @param array $handler Um array contendo o nome do controlador e o nome da ação
* que devem ser executados quando a rota for
* corresponder (ex: ['UsuarioController', 'salvar']).
* @param array $middlewares Um array opcional contendo os nomes dos middlewares que
* devem ser executados antes do handler da rota.
*
* @return void
*/
public static function DELETE(string $uri, array $handler, array $middlewares = []): void {
self::addRoute(method: "DELETE", uri: $uri, handler: $handler, middlewares: $middlewares);
}
@@ -189,7 +113,7 @@
* @return void
*/
private static function addRoute(string $method, string $uri, array $handler, array $middlewares = []): void {
self::$routes[] = [
self::$routes[$method][] = [
'method' => strtoupper(string: $method),
'path' => '/' . trim(string: self::$currentGroupPrefix . '/' . trim(string: $uri, characters: '/'), characters: '/'),
'controller' => $handler[0],
@@ -198,6 +122,46 @@
];
}
/**
* Redireciona para um caminho específico.
*
* Este método estático constrói uma URL de redirecionamento com base no
* caminho fornecido e no `basePath` configurado. Ele garante que o
* `basePath` e o `path` comecem com uma barra (`/`), monta a URL
* completa, limpa quaisquer duplicações de barras e executa o
* redirecionamento HTTP.
*
* @param string|null $path O caminho para o qual redirecionar. Se nulo ou vazio,
* redireciona para o `basePath`.
*
* @return void
*/
public static function redirect(?string $path): void {
// Garante que o basePath começa com "/"
$basePath = self::$basePath ? '/' . trim(string: self::$basePath, characters: '/') : '/';
// Se não tiver caminho, redireciona pro basePath direto
if (empty($path)) {
header(header: "Location: {$basePath}/");
exit;
}
// Garante que o path começa com "/"
if (!str_starts_with(haystack: $path, needle: '/')) {
$path = "/{$path}";
}
// Monta o destino completo
$redirectPath = "{$basePath}{$path}";
// Limpa duplicações tipo "//"
$redirectPath = preg_replace(pattern: '#/+#', replacement: '/', subject: $redirectPath);
// Executa o redirecionamento
header(header: "Location: {$redirectPath}");
exit;
}
/**
* Verifica se um caminho de rota corresponde a um caminho de requisição.
*
@@ -497,6 +461,50 @@
return $preparedParams;
}
/**
* Exibe a página de erro 404 (Página não encontrada).
*
* Este método estático define o código de resposta HTTP como 404 e renderiza
* a view "/Errors/404" para exibir a página de erro. Após a renderização,
* o script é encerrado.
*
* @return void
*/
private static function pageNotFound(): void {
switch (self::$ROUTER_MODE) {
case 'VIEW':
// Notifica erro em caso constante não definida
if(!defined(constant_name: 'ERROR_404_VIEW_PATH')) {
RequestHelper::sendJsonResponse(
response_code: 500,
status: 'error',
message: "Constante 'ERROR_404_VIEW_PATH' não foi definida."
);
}
// Caso o arquivo da constante não exista, notifica erro
if(!file_exists(filename: ERROR_404_VIEW_PATH)) {
RequestHelper::sendJsonResponse(
response_code: 500,
status: 'error',
message: "Arquivo da constante 'ERROR_404_VIEW_PATH' não foi encontrado."
);
}
http_response_code(response_code: 404);
require_once ERROR_404_VIEW_PATH;
break;
case 'JSON':
RequestHelper::sendJsonResponse(
response_code: 404,
status: 'error',
message: "Página não encontrada."
);
break;
}
}
/**
* Despacha a requisição para o controlador e ação correspondentes.
*
@@ -513,10 +521,21 @@
// Verificar as constantes necessárias antes de processar a requisição
self::checkRequiredConstant();
// Inicializa dados da requisição
$requestData = null;
$method = $_SERVER['REQUEST_METHOD'];
$uri = parse_url(url: $_SERVER['REQUEST_URI'], component: PHP_URL_PATH);
$uri = trim(string: rtrim(string: $uri, characters: '/'), characters: '/');
// Remove o basePath do início da URI (se tiver)
$basePath = rtrim(string: self::$basePath ?? '', characters: '/');
if (!empty($basePath) && str_starts_with(haystack: $uri, needle: $basePath)) {
$uri = substr(string: $uri, offset: strlen(string: $basePath));
}
// Limpa possíveis barras extras
$uri = trim(string: $uri, characters: '/');
// Suporte ao _method em POST para PUT/DELETE/PATCH
if ($method === 'POST' && isset($_POST['_method'])) {
$method = strtoupper(string: $_POST['_method']);
@@ -524,13 +543,11 @@
// Verifica se o método HTTP é permitido
if(!in_array(needle: $method, haystack: self::$allowedHttpRequests)) {
http_response_code(response_code: 405);
header(header: 'Content-Type: application/json; charset=utf-8');
echo json_encode(value: [
"status" => 'error',
"message" => "Método HTTP '{$method}' não permitido."
]);
exit;
RequestHelper::sendJsonResponse(
response_code: 405,
status: 'error',
message: "Método HTTP '{$method}' não permitido."
);
}
// =============================
@@ -572,16 +589,18 @@
// =============================
// EXTRAI DADOS DE PUT, DELETE, PATCH
// =============================
$requestData = match($method) {
'GET' => null,
'POST' => null,
default => self::extractRequestData(method: $method)
};
if(in_array(needle: $method, haystack: ['PUT', 'DELETE', 'PATCH'])) {
$requestData = self::extractRequestData(method: $method);
}
// Seleciona apenas as rotas do método atual
$routes = self::$routes[$method] ?? [];
// =============================
// LOOP PARA PROCESSAR ROTAS
// =============================
foreach (self::$routes as $route) {
if(!empty($routes)) {
foreach ($routes as $route) {
if (self::matchRoute(method: $method, uri: $uri, route: $route)) {
// Executa middlewares
if (!empty($route['middlewares']) && !self::runMiddlewares(middlewares: $route['middlewares'])) {
@@ -609,6 +628,15 @@
exit;
}
break;
default:
RequestHelper::sendJsonResponse(
response_code: 500,
status: 'error',
message: "Modo de roteamento inválido."
);
break;
}
}
}
}
@@ -619,54 +647,4 @@
self::pageNotFound();
exit;
}
/**
* Exibe a página de erro 404 (Página não encontrada).
*
* Este método estático define o código de resposta HTTP como 404 e renderiza
* a view "/Errors/404" para exibir a página de erro. Após a renderização,
* o script é encerrado.
*
* @return void
*/
private static function pageNotFound(): void {
switch (self::$ROUTER_MODE) {
case 'VIEW':
// Notifica erro em caso constante não definida
if(!defined(constant_name: 'ERROR_404_VIEW_PATH')) {
http_response_code(response_code: 500);
header(header: 'Content-Type: application/json; charset=utf-8');
echo json_encode( value: [
"status" => 'error',
"message" => "Constante 'ERROR_404_VIEW_PATH' não foi definida.",
]);
exit;
}
// Caso o arquivo da constante não exista, notifica erro
if(!file_exists(filename: ERROR_404_VIEW_PATH)) {
http_response_code(response_code: 500);
header(header: 'Content-Type: application/json; charset=utf-8');
echo json_encode( value: [
"status" => 'error',
"message" => "Arquivo da constante 'ERROR_404_VIEW_PATH' não foi encontrado.",
]);
exit;
}
http_response_code(response_code: 404);
require_once ERROR_404_VIEW_PATH;
break;
case 'JSON':
http_response_code(response_code: 404);
header(header: 'Content-Type: application/json; charset=utf-8');
echo json_encode( value: [
"status" => 'error',
"message" => "Página não encontrada.",
]);
break;
}
}
}

View File

@@ -6,9 +6,9 @@ $vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Workbloom\\Module\\' => array($baseDir . '/app/Module'),
'Workbloom\\Component\\' => array($baseDir . '/app/Common/Component'),
'Workbloom\\' => array($baseDir . '/app/Common'),
'WorkbloomModule\\' => array($baseDir . '/app/Module'),
'WorkbloomComponent\\' => array($baseDir . '/app/Common/Component'),
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),

View File

@@ -19,9 +19,9 @@ class ComposerStaticInit8166d455774ce82597f7c8b1884b0ce8
public static $prefixLengthsPsr4 = array (
'W' =>
array (
'Workbloom\\Module\\' => 17,
'Workbloom\\Component\\' => 20,
'Workbloom\\' => 10,
'WorkbloomModule\\' => 16,
'WorkbloomComponent\\' => 19,
),
'S' =>
array (
@@ -55,18 +55,18 @@ class ComposerStaticInit8166d455774ce82597f7c8b1884b0ce8
);
public static $prefixDirsPsr4 = array (
'Workbloom\\' =>
array (
0 => __DIR__ . '/../..' . '/app/Common',
),
'WorkbloomModule\\' =>
'Workbloom\\Module\\' =>
array (
0 => __DIR__ . '/../..' . '/app/Module',
),
'WorkbloomComponent\\' =>
'Workbloom\\Component\\' =>
array (
0 => __DIR__ . '/../..' . '/app/Common/Component',
),
'Workbloom\\' =>
array (
0 => __DIR__ . '/../..' . '/app/Common',
),
'Symfony\\Polyfill\\Php80\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',

View File

@@ -2,24 +2,24 @@
"packages": [
{
"name": "claudecio/axiumphp",
"version": "dev-dev-update-initializing",
"version_normalized": "dev-dev-update-initializing",
"version": "dev-feature-updated-router",
"version_normalized": "dev-feature-updated-router",
"source": {
"type": "git",
"url": "https://github.com/claudecio/AxiumPHP.git",
"reference": "ccc3c7de5462371150ea8d82549701519503f9f7"
"reference": "c7353947a667ea857b461f2b6251441784a4b8ef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/claudecio/AxiumPHP/zipball/ccc3c7de5462371150ea8d82549701519503f9f7",
"reference": "ccc3c7de5462371150ea8d82549701519503f9f7",
"url": "https://api.github.com/repos/claudecio/AxiumPHP/zipball/c7353947a667ea857b461f2b6251441784a4b8ef",
"reference": "c7353947a667ea857b461f2b6251441784a4b8ef",
"shasum": ""
},
"require": {
"php": ">=8.1",
"vlucas/phpdotenv": "v5.6.2"
},
"time": "2025-10-18T18:31:17+00:00",
"time": "2025-10-26T20:05:19+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -32,7 +32,7 @@
],
"description": "Meu framework PHP para sistemas MVC modulares.",
"support": {
"source": "https://github.com/claudecio/AxiumPHP/tree/dev-update-initializing",
"source": "https://github.com/claudecio/AxiumPHP/tree/feature-updated-router",
"issues": "https://github.com/claudecio/AxiumPHP/issues"
},
"install-path": "../claudecio/axiumphp"
@@ -233,17 +233,17 @@
},
{
"name": "nikic/php-parser",
"version": "v5.6.1",
"version_normalized": "5.6.1.0",
"version": "v5.6.2",
"version_normalized": "5.6.2.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2"
"reference": "3a454ca033b9e06b63282ce19562e892747449bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
"reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3a454ca033b9e06b63282ce19562e892747449bb",
"reference": "3a454ca033b9e06b63282ce19562e892747449bb",
"shasum": ""
},
"require": {
@@ -256,7 +256,7 @@
"ircmaxell/php-yacc": "^0.0.7",
"phpunit/phpunit": "^9.0"
},
"time": "2025-08-13T20:13:15+00:00",
"time": "2025-10-21T19:32:17+00:00",
"bin": [
"bin/php-parse"
],
@@ -288,7 +288,7 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1"
"source": "https://github.com/nikic/PHP-Parser/tree/v5.6.2"
},
"install-path": "../nikic/php-parser"
},

View File

@@ -1,9 +1,9 @@
<?php return array(
'root' => array(
'name' => 'cybercore/workbloom',
'pretty_version' => '1.0.0+no-version-set',
'version' => '1.0.0.0',
'reference' => null,
'pretty_version' => 'dev-main',
'version' => 'dev-main',
'reference' => '9cfa79db4b2f3aca5feab04bb1212cf87d9a8565',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -11,18 +11,18 @@
),
'versions' => array(
'claudecio/axiumphp' => array(
'pretty_version' => 'dev-dev-update-initializing',
'version' => 'dev-dev-update-initializing',
'reference' => 'ccc3c7de5462371150ea8d82549701519503f9f7',
'pretty_version' => 'dev-feature-updated-router',
'version' => 'dev-feature-updated-router',
'reference' => 'c7353947a667ea857b461f2b6251441784a4b8ef',
'type' => 'library',
'install_path' => __DIR__ . '/../claudecio/axiumphp',
'aliases' => array(),
'dev_requirement' => false,
),
'cybercore/workbloom' => array(
'pretty_version' => '1.0.0+no-version-set',
'version' => '1.0.0.0',
'reference' => null,
'pretty_version' => 'dev-main',
'version' => 'dev-main',
'reference' => '9cfa79db4b2f3aca5feab04bb1212cf87d9a8565',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -56,9 +56,9 @@
'dev_requirement' => true,
),
'nikic/php-parser' => array(
'pretty_version' => 'v5.6.1',
'version' => '5.6.1.0',
'reference' => 'f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2',
'pretty_version' => 'v5.6.2',
'version' => '5.6.2.0',
'reference' => '3a454ca033b9e06b63282ce19562e892747449bb',
'type' => 'library',
'install_path' => __DIR__ . '/../nikic/php-parser',
'aliases' => array(),

View File

@@ -5,7 +5,11 @@ namespace PhpParser\Node\Expr;
require __DIR__ . '/../ArrayItem.php';
if (false) {
// For classmap-authoritative support.
/**
* For classmap-authoritative support.
*
* @deprecated use \PhpParser\Node\ArrayItem instead.
*/
class ArrayItem extends \PhpParser\Node\ArrayItem {
}
}

View File

@@ -5,7 +5,11 @@ namespace PhpParser\Node\Expr;
require __DIR__ . '/../ClosureUse.php';
if (false) {
// For classmap-authoritative support.
/**
* For classmap-authoritative support.
*
* @deprecated use \PhpParser\Node\ClosureUse instead.
*/
class ClosureUse extends \PhpParser\Node\ClosureUse {
}
}

View File

@@ -71,6 +71,10 @@ class Param extends NodeAbstract {
return $this->flags !== 0 || $this->hooks !== [];
}
public function isFinal(): bool {
return (bool) ($this->flags & Modifiers::FINAL);
}
public function isPublic(): bool {
$public = (bool) ($this->flags & Modifiers::PUBLIC);
if ($public) {

View File

@@ -5,7 +5,11 @@ namespace PhpParser\Node\Scalar;
require __DIR__ . '/Float_.php';
if (false) {
// For classmap-authoritative support.
/**
* For classmap-authoritative support.
*
* @deprecated use \PhpParser\Node\Scalar\Float_ instead.
*/
class DNumber extends Float_ {
}
}

View File

@@ -5,7 +5,11 @@ namespace PhpParser\Node\Scalar;
require __DIR__ . '/InterpolatedString.php';
if (false) {
// For classmap-authoritative support.
/**
* For classmap-authoritative support.
*
* @deprecated use \PhpParser\Node\Scalar\InterpolatedString instead.
*/
class Encapsed extends InterpolatedString {
}
}

View File

@@ -7,7 +7,11 @@ use PhpParser\Node\InterpolatedStringPart;
require __DIR__ . '/../InterpolatedStringPart.php';
if (false) {
// For classmap-authoritative support.
/**
* For classmap-authoritative support.
*
* @deprecated use \PhpParser\Node\InterpolatedStringPart instead.
*/
class EncapsedStringPart extends InterpolatedStringPart {
}
}

View File

@@ -5,7 +5,11 @@ namespace PhpParser\Node\Scalar;
require __DIR__ . '/Int_.php';
if (false) {
// For classmap-authoritative support.
/**
* For classmap-authoritative support.
*
* @deprecated use \PhpParser\Node\Scalar\Int_ instead.
*/
class LNumber extends Int_ {
}
}

View File

@@ -124,7 +124,7 @@ class String_ extends Scalar {
// If it overflowed to float, treat as INT_MAX, it will throw an error anyway.
return self::codePointToUtf8(\is_int($dec) ? $dec : \PHP_INT_MAX);
} else {
return chr(octdec($str));
return chr(octdec($str) & 255);
}
},
$str

View File

@@ -7,7 +7,11 @@ use PhpParser\Node\DeclareItem;
require __DIR__ . '/../DeclareItem.php';
if (false) {
// For classmap-authoritative support.
/**
* For classmap-authoritative support.
*
* @deprecated use \PhpParser\Node\DeclareItem instead.
*/
class DeclareDeclare extends DeclareItem {
}
}

View File

@@ -7,7 +7,11 @@ use PhpParser\Node\PropertyItem;
require __DIR__ . '/../PropertyItem.php';
if (false) {
// For classmap-authoritative support.
/**
* For classmap-authoritative support.
*
* @deprecated use \PhpParser\Node\PropertyItem instead.
*/
class PropertyProperty extends PropertyItem {
}
}

View File

@@ -5,7 +5,11 @@ namespace PhpParser\Node\Stmt;
require __DIR__ . '/../StaticVar.php';
if (false) {
// For classmap-authoritative support.
/**
* For classmap-authoritative support.
*
* @deprecated use \PhpParser\Node\StaticVar instead.
*/
class StaticVar extends \PhpParser\Node\StaticVar {
}
}

View File

@@ -7,7 +7,11 @@ use PhpParser\Node\UseItem;
require __DIR__ . '/../UseItem.php';
if (false) {
// For classmap-authoritative support.
/**
* For classmap-authoritative support.
*
* @deprecated use \PhpParser\Node\UseItem instead.
*/
class UseUse extends UseItem {
}
}

View File

@@ -678,8 +678,10 @@ abstract class PrettyPrinterAbstract implements PrettyPrinter {
}
[$printFn, $findToken] = $this->modifierChangeMap[$key];
$skipWSPos = $this->origTokens->skipRightWhitespace($pos);
$result .= $this->origTokens->getTokenCode($pos, $skipWSPos, $indentAdjustment);
$result .= $this->$printFn($subNode);
$pos = $this->origTokens->findRight($pos, $findToken);
$pos = $this->origTokens->findRight($skipWSPos, $findToken);
continue;
}