CenixPackage 2.0.4

dotnet add package CenixPackage --version 2.0.4
                    
NuGet\Install-Package CenixPackage -Version 2.0.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CenixPackage" Version="2.0.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CenixPackage" Version="2.0.4" />
                    
Directory.Packages.props
<PackageReference Include="CenixPackage" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add CenixPackage --version 2.0.4
                    
#r "nuget: CenixPackage, 2.0.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package CenixPackage@2.0.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=CenixPackage&version=2.0.4
                    
Install as a Cake Addin
#tool nuget:?package=CenixPackage&version=2.0.4
                    
Install as a Cake Tool

CenixPackage

build

dotnet pack -C Release

Pacote NuGet desenvolvido pela Cenix para integração com os serviços internos da plataforma. Oferece autenticação JWT, gestão de usuários, empresas, departamentos, módulos, sistemas e permissões — tudo configurável em uma única chamada de injeção de dependência.

Versão atual: 2.0.1 · .NET 8.0

Superfície pública: apenas as interfaces ICenix*Service (injetadas via DI) e os DTOs. As interfaces de API e as classes de Infrastructure são internal (uso interno do pacote).


Sumário


Instalação

dotnet add package CenixPackage

Configuração

Configuração mínima

Auto‑configuração por ambiente (recomendado): se as variáveis padrão existirem no ambiente (o .env do projeto), não precisa passar nada — o pacote lê sozinho:

using CenixPackage.CrossCutting.IoC;

builder.Services.CenixServiceInjection(); // lê MODULE_ID, JWT_KEY, JWT_ISSUER, JWT_AUDIENCE, AIACOS_API, ZEUS_API

Variáveis reconhecidas automaticamente:

Variável Vai para Obrigatória
MODULE_ID ModuleId ✅
JWT_KEY / JWT_ISSUER / JWT_AUDIENCE Jwt.* ✅
AIACOS_API Urls.AiacosApi ✅
ZEUS_API Urls.ZeusApi necessária p/ users/permissões/etc.
AIACOS_APP Urls.AiacosApp opcional

Se faltar alguma obrigatória (nem no ambiente nem no options), a injeção lança um erro claro dizendo qual faltou. As variáveis precisam estar no ambiente do processo (ex.: .env carregado no startup / env do container).

Passando manualmente (o que você informar sobrescreve o ambiente):

builder.Services.CenixServiceInjection(options =>
{
    options.ModuleId = 1;

    options.Jwt = new CenixJwtSettignsDTO
    {
        Issuer   = "seu-issuer",
        Audience = "seu-audience",
        Key      = "sua-chave-secreta"
    };

    options.Urls = new CenixUrlSettingsDTO
    {
        AiacosApi  = "https://aiacos.suaempresa.com.br",  // autenticação (obrigatório)
        ZeusApi    = "https://zeus.suaempresa.com.br"     // usuários, empresas, etc.
    };
});

Dá pra misturar: passe só o que quiser customizar; o resto vem do ambiente.

Adicione também o middleware de autenticação no pipeline:

app.UseAuthentication();
app.UseAuthorization();

Todas as opções

builder.Services.CenixServiceInjection(options =>
{
    options.ModuleId = 1;

    // JWT — obrigatório
    options.Jwt = new CenixJwtSettignsDTO
    {
        Issuer   = builder.Configuration["Jwt:Issuer"]!,
        Audience = builder.Configuration["Jwt:Audience"]!,
        Key      = builder.Configuration["Jwt:Key"]!
    };

    // URLs das APIs — obrigatório
    options.Urls = new CenixUrlSettingsDTO
    {
        AiacosApi  = builder.Configuration["Urls:AiacosApi"]!,
        AiacosApp  = builder.Configuration["Urls:AiacosApp"],   // opcional
        ZeusApi    = builder.Configuration["Urls:ZeusApi"]!
    };
});

Exemplo de appsettings.json:

{
  "Jwt": {
    "Issuer": "seu-issuer",
    "Audience": "seu-audience",
    "Key": "sua-chave-secreta-muito-longa"
  },
  "Urls": {
    "AiacosApi": "https://aiacos.suaempresa.com.br",
    "ZeusApi": "https://zeus.suaempresa.com.br"
  }
}

Serviços disponíveis

Todos os serviços são registrados automaticamente e podem ser injetados via construtor:

public class MeuController : ControllerBase
{
    private readonly ICenixUserService _userService;
    private readonly ICenixAuthService _authService;

    public MeuController(
        ICenixUserService userService,
        ICenixAuthService authService)
    {
        _userService = userService;
        _authService = authService;
    }
}
Serviço Descrição Requisito
ICenixAuthService Autenticação, usuário logado, login de módulo, login de conta de serviço Urls.AiacosApi
ICenixUserService Busca e listagem de usuários Urls.ZeusApi
ICenixCompanyService Empresas Urls.ZeusApi
ICenixDepartmentService Departamentos Urls.ZeusApi
ICenixModuleService Módulos Urls.ZeusApi
ICenixSystemService Sistemas Urls.ZeusApi
ICenixPermissionSyncService Registra o catálogo de permissões do módulo no Zeus Urls.ZeusApi

Erros: qualquer falha nas chamadas às APIs internas lança CenixApiException (CenixPackage.Application.Exceptions) com StatusCode, ResponseBody e Endpoint. Use IsAuthError (401/403) para distinguir problema de autenticação de erro do servidor (5xx) ou não encontrado (404).


ICenixAuthService

Responsável por autenticação, obtenção do usuário logado e login de módulo.

Requer: Urls.AiacosApi

// Realiza login com e-mail/usuário e senha, retornando token, refresh token e dados do usuário
// Se storeToken = true, o token retornado é armazenado internamente e usado nas demais chamadas
// quando não houver HttpContext (cenários de background service)
Task<CenixAuthResponseDTO?> LoginAsync(string emailOrUsername, string password, bool storeToken = false)

// Seleciona um módulo para o usuário autenticado (usa o Bearer token do HttpContext)
// moduleId é obrigatório; companyId, code2FA e rememberDevice são opcionais
// Se storeToken = true, o novo token (com o módulo selecionado) é armazenado internamente
Task<CenixAuthResponseDTO?> SelectModuleAsync(
    int moduleId,
    int? companyId        = null,
    string? code2FA       = null,
    bool? rememberDevice  = null,
    bool storeToken       = false)

// Login de CONTA DE SERVIÇO (M2M) em uma única chamada: autentica pela credencial da
// conta de serviço e já emite o token no módulo indicado (moduleKey), sem precisar de
// login + seleção de módulo. Por padrão armazena o token internamente (storeToken = true)
// para uso em chamadas de background sem HttpContext. Só funciona para contas de serviço.
Task<CenixAuthResponseDTO?> ServiceLoginAsync(
    string emailOrUsername,
    string password,
    string moduleKey,
    int? companyId        = null,   // usado quando o módulo de destino não é global
    string? moduleKeyUsed = null,   // moduleKey do sistema chamador (rastreio nos logs)
    bool storeToken       = true)

// Define manualmente o token a ser usado nas chamadas quando não houver HttpContext
// (background services, schedulers, workers, etc.)
void SetAuthorizationToken(string token)

// Remove o token armazenado internamente
void ClearAuthorizationToken()

// Retorna os dados do usuário autenticado (lê o Bearer token do HttpContext automaticamente)
Task<CenixLoggedUserDTO> GetLoggedUserAsync()

// Retorna os módulos e perfis do usuário logado, opcionalmente filtrado por módulo
Task<List<CenixModulesAndProfilesOfUserDTO>> GetProfilesOfUserAsync(int? moduleId = null)

// Realiza login de módulo com clientId/clientSecret e armazena o token internamente
Task<CenixLoginResponseModuleDTO?> LoginModuleAsync(string clientId, string clientSecret)

// Retorna o módulo atualmente logado
Task<CenixModuleDTO> GetLoggedModuleAsync()

// Retorna as empresas acessíveis no módulo informado
Task<List<CenixCompanyDTO>> GetCompaniesByModuleAsync(int moduleId)

// ----- Senha / desbloqueio / SSO -----

// Dispara o e-mail de recuperação (envia um código ao usuário)
Task ForgotPasswordAsync(string emailOrUsername)

// Redefine a senha com o código recebido por e-mail
Task ResetPasswordAsync(string emailOrUsername, string code, string password, string confirmationPassword)

// Dispara o e-mail de desbloqueio de conta
Task RequestUnlockAsync(string emailOrUsername)

// Desbloqueia a conta com o token recebido por e-mail
Task UnlockAccountAsync(string token)

// Troca a senha do usuário logado (usa o token do HttpContext)
Task ChangePasswordAsync(string currentPassword, string password, string confirmationPassword)

// Troca um transfer-token (SSO) por um token de acesso normal; storeToken armazena o novo token
Task<CenixAuthResponseDTO?> ExchangeTransferTokenAsync(string transferToken, bool storeToken = false)

Exemplo — login de usuário:

var resposta = await _authService.LoginAsync("luiz.natividade", "minhasenha");

if (resposta != null)
{
    var token = resposta.Token;
    var usuario = resposta.User;
    Console.WriteLine($"Bem-vindo, {usuario.Name}");
}

Exemplo — seleção de módulo:

var resposta = await _authService.SelectModuleAsync(
    moduleId: 9,
    companyId: null,
    code2FA: "123456",      // opcional
    rememberDevice: true    // opcional
);

if (resposta != null)
{
    // Novo token contendo o módulo selecionado
    var tokenComModulo = resposta.Token;
}

Exemplo — login de conta de serviço (M2M / integração):

Para integrações e workers que usam uma conta de serviço, o ServiceLoginAsync faz tudo em uma chamada: autentica pela credencial e já emite o token no módulo (moduleKey). Por padrão o token fica armazenado internamente, então as demais chamadas do pacote funcionam sem HttpContext.

var resposta = await _authService.ServiceLoginAsync(
    emailOrUsername: "svc.integracao",
    password: "***",
    moduleKey: "ZEUS_GESTAO_DE_USUARIOS",   // módulo de DESTINO
    companyId: 4,                            // opcional (módulo não-global)
    moduleKeyUsed: "ARGUS_WMS"               // opcional (rastreio: quem está chamando)
);

// A partir daqui, qualquer chamada do pacote usa o token da conta de serviço.
var usuarios = await _userService.GetAllUsersAsync(name: null, departmentId: null, permissionId: null);

A conta precisa ser marcada como conta de serviço e ter acesso ao módulo. A trava de IP (allowlist da conta) continua valendo — a credencial só funciona a partir das origens autorizadas.

Exemplo — uso em background service (sem HttpContext):

Em workers, schedulers e outros serviços de background, não há HttpContext para extrair o token. Para esses casos, autentique-se via LoginAsync + SelectModuleAsync (ou ServiceLoginAsync para conta de serviço) e armazene o token internamente — assim as demais chamadas do pacote funcionam normalmente.

public class MeuWorker : BackgroundService
{
    private readonly IServiceProvider _serviceProvider;

    public MeuWorker(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            using var scope = _serviceProvider.CreateScope();
            var authService = scope.ServiceProvider.GetRequiredService<ICenixAuthService>();
            var userService = scope.ServiceProvider.GetRequiredService<ICenixUserService>();

            // Opção 1 — usando storeToken (mais conciso)
            await authService.LoginAsync("usuario.background", "senha");
            await authService.SelectModuleAsync(moduleId: 9, storeToken: true);

            // Opção 2 — controle explícito do token
            // var login   = await authService.LoginAsync("usuario.background", "senha");
            // var module  = await authService.SelectModuleAsync(moduleId: 9);
            // authService.SetAuthorizationToken(module!.Token);

            // A partir daqui, qualquer chamada do pacote funciona normalmente
            var usuarios = await userService.GetAllUsersAsync(name: null, departmentId: null, permissionId: null);

            // (opcional) ao final do ciclo
            authService.ClearAuthorizationToken();

            await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
        }
    }
}

Importante: o token armazenado por SetAuthorizationToken / storeToken: true é mantido em um Singleton interno (LocalStorage) e tem escopo global na aplicação. Isso é ideal para workers e schedulers (um único token por processo), mas não deve ser usado em requests web — nessas, o token continua sendo lido automaticamente do HttpContext, que é por-request. O pacote prioriza o HttpContext quando ele existe.

Exemplo — usuário logado:

var user = await _authService.GetLoggedUserAsync();
Console.WriteLine(user.Name);

// Verificar permissão por chave
bool podeCriar = user.PermissionsKeys?.Contains("USER_CREATE") ?? false;

// Verificar departamentos gerenciados
var deptsGerenciados = user.ManagedDepartments;

ICenixUserService

Busca e listagem de usuários. Por padrão, os métodos de listagem filtram pelo ModuleId configurado na injeção de dependência.

Requer: Urls.ZeusApi

// Busca um usuário pelo ID
Task<CenixUserDTO?> GetByIdAsync(int id)

// Busca múltiplos usuários por lista de IDs
Task<List<CenixUserDTO>> GetByListIdAsync(List<int> ids, bool? includeDeleted = false)

// Lista usuários com filtros simples
// filterByModule = true  → filtra pelo ModuleId configurado
// filterByModule = false → retorna usuários de todos os módulos
Task<List<CenixUserDTO>> GetAllUsersAsync(
    string? name,
    int? departmentId,
    int? permissionId,
    bool? filterByModule = true,
    bool? includeDeleted = false)

// Lista usuários paginados com filtros avançados e ordenação
Task<CenixPagedResponseDTO<CenixUserDTO>> GetAllUsersPagedAsync(
    string? name          = null,
    int? departmentId     = null,
    int? permissionId     = null,
    string? permissionKey = null,   // ex: "USER_CREATE"
    List<int>? ids        = null,
    bool? filterByModule  = true,
    bool? includeDeleted  = false,
    int pageNumber        = 0,
    int pageSize          = 10,     // máximo: 50
    string sortBy         = "Id",
    string direction      = "desc") // "asc" ou "desc"

Exemplo — busca paginada:

var resultado = await _userService.GetAllUsersPagedAsync(
    permissionKey: "USER_CREATE",
    pageNumber: 0,
    pageSize: 20,
    sortBy: "Name",
    direction: "asc"
);

Console.WriteLine($"Total: {resultado.TotalCount}, Páginas: {resultado.TotalPages}");
foreach (var u in resultado.Data)
    Console.WriteLine(u.Name);

ICenixCompanyService

Requer: Urls.ZeusApi

// Retorna todas as empresas
Task<List<CenixCompanyDTO>> GetAllAsync()

// Retorna uma empresa pelo ID
Task<CenixCompanyDTO?> GetByIdAsync(int id)

ICenixDepartmentService

Requer: Urls.ZeusApi

// Retorna todos os departamentos, opcionalmente filtrado por empresa
Task<List<CenixDepartmentDTO>> GetAllAsync(int? companyId = null)

// Retorna um departamento pelo ID
Task<CenixDepartmentDTO?> GetByIdAsync(int id)

ICenixModuleService

Requer: Urls.ZeusApi

// Retorna um módulo pelo ID
Task<CenixModuleDTO?> GetByIdAsync(int id)

// Lista módulos com filtros opcionais
Task<List<CenixModuleDTO>?> GetAllAsync(
    int? systemId     = null,
    string? name      = null,
    bool? isGlobal    = null,
    bool? required2FA = null,
    bool? deleted     = null)

// Lista módulos paginados com filtros e ordenação
Task<CenixPagedResponseDTO<CenixModuleDTO>> GetPagedAsync(
    string? name  = null,
    int? systemId = null,
    int pageNumber = 0,
    int pageSize   = 10,
    string sortBy    = "Id",
    string direction = "desc")

Exemplo — busca paginada de módulos:

var resultado = await _moduleService.GetPagedAsync(
    name: "Admin",
    systemId: 1,
    pageNumber: 0,
    pageSize: 20,
    sortBy: "Name",
    direction: "asc"
);

Console.WriteLine($"Total: {resultado.TotalCount}, Páginas: {resultado.TotalPages}");
foreach (var m in resultado.Data)
    Console.WriteLine(m.Name);

ICenixSystemService

Requer: Urls.ZeusApi

// Retorna um sistema pelo ID
Task<CenixSystemDTO?> GetByIdAsync(int id)

// Lista sistemas com filtros opcionais
Task<List<CenixSystemDTO>?> GetAllAsync(string? name = null, bool? deleted = null)

// Lista sistemas paginados com filtro e ordenação
Task<CenixPagedResponseDTO<CenixSystemDTO>> GetPagedAsync(
    string? name   = null,
    int pageNumber = 0,
    int pageSize   = 10,
    string sortBy    = "Id",
    string direction = "desc")

Exemplo — busca paginada de sistemas:

var resultado = await _systemService.GetPagedAsync(
    name: "ERP",
    pageNumber: 0,
    pageSize: 20,
    sortBy: "Name",
    direction: "asc"
);

Console.WriteLine($"Total: {resultado.TotalCount}, Páginas: {resultado.TotalPages}");
foreach (var s in resultado.Data)
    Console.WriteLine(s.Name);

ICenixPermissionSyncService

Registra/atualiza o catálogo de permissões deste módulo no Zeus. Cria as que faltam e vincula ao perfil Administrador do módulo. Idempotente — ideal para chamar no boot.

Você passa as KEYS completas (as mesmas que usa no can(...)). O Zeus valida o prefixo do módulo (SISTEMA_MODULO_) e o formato (MAIÚSCULAS/underscore) e rejeita as fora do padrão — listando as inválidas. Assim você mantém as keys no seu código (sem olhar no Zeus) e ninguém sobe uma key errada.

Requer: Urls.ZeusApi + token com PERMISSOES_CADASTRAR no Zeus (ex.: conta de serviço do módulo).

Task<CenixPermissionSyncResultDTO> SyncAsync(IEnumerable<string> permissionKeys)

Padrão recomendado — declare as keys uma vez (constantes) e reuse:

public static class WmsPermissions
{
    private const string P = "ARGUS_WMS_";                        // prefixo do módulo
    public const string AdminSistema = P + "ADMINISTRADOR_DE_SISTEMA";
    public const string AdminArmazem = P + "ADMINISTRADOR_DE_ARMAZEM";
    public const string Conferente   = P + "CONFERENTE";

    public static readonly string[] All = { AdminSistema, AdminArmazem, Conferente };
}
// no boot — registra o catálogo:
var r = await _permissionSync.SyncAsync(WmsPermissions.All);
// r.Created / r.Linked / r.Keys

// em qualquer lugar — usa a MESMA constante (sem olhar no Zeus):
if (user.PermissionsKeys.Contains(WmsPermissions.Conferente)) { ... }

Se alguma key não começar com o prefixo do módulo ou estiver mal formatada, o SyncAsync lança erro (via CenixApiException) com a lista das inválidas — você corrige e sobe de novo.

Em background (sem HttpContext), autentique antes com ServiceLoginAsync(..., storeToken: true) para o token ser usado na chamada.


DTOs de referência

CenixAuthResponseDTO — resposta de login/seleção de módulo

Retornado por LoginAsync() e SelectModuleAsync().

Campo Tipo Descrição
Token string JWT de acesso
RefreshToken string Token de renovação
User CenixLoggedUserDTO Dados completos do usuário autenticado

CenixLoggedUserDTO — usuário autenticado

Retornado por GetLoggedUserAsync(). Contém os dados completos do usuário no contexto de autenticação:

Campo Tipo Descrição
Id int ID do usuário
Name string Nome completo
Email string E-mail
Username string Login do usuário
CompanyId int? ID da empresa principal
DepartmentId int? ID do departamento principal
Company CenixCompanyDTO? Empresa principal (objeto)
Department CenixDepartmentDTO? Departamento principal (objeto)
Profile CenixProfileDTO? Perfil do usuário no módulo atual
Permissions List<int>? IDs das permissões
PermissionsKeys List<string>? Chaves textuais das permissões (ex: "USER_CREATE")
SecondaryDepartments List<CenixDepartmentDTO>? Departamentos secundários
ManagedDepartments List<CenixDepartmentDTO>? Departamentos gerenciados pelo usuário
ChangePasswordOnNextLogin bool Troca de senha obrigatória
TwoFactorActive bool 2FA ativo
ProtheusCode string? Código Protheus vinculado
ExpiresAt DateTime? Data de expiração do acesso
CreatedAt DateTime? Data de criação
DeletedAt DateTime? Data de exclusão (soft delete)

CenixUserDTO

Campo Tipo Descrição
Id int ID do usuário
Name string Nome completo
Email string E-mail
Username string Login do usuário
CompanyId int? ID da empresa principal
DepartmentId int? ID do departamento principal
Company CenixCompanyDTO? Empresa principal (objeto)
Department CenixDepartmentDTO? Departamento principal (objeto)
Permissions List<int>? IDs das permissões
PermissionsKeys List<string> Chaves textuais das permissões (ex: "USER_CREATE")
SecondaryDepartments List<CenixDepartmentDTO>? Departamentos secundários
ManagedDepartments List<CenixDepartmentDTO>? Departamentos gerenciados pelo usuário
ForcePasswordChange bool Exige troca de senha no próximo login
LastLogin DateTime? Último acesso
EmailVerifiedAt DateTime? Data de verificação do e-mail
AccessUntil DateTime? Data limite de acesso
CreatedAt DateTime Data de criação
DeletedAt DateTime? Data de exclusão (soft delete)

CenixCompanyDTO

Campo Tipo Descrição
Id int ID da empresa
Name string Nome da empresa
Code string? Código interno
ParentCompanyId int? ID da empresa pai
IsExternal bool Empresa externa
Type string? Tipo da empresa
StoreNumber string? Número da loja
CpfCnpj string? CPF/CNPJ
CreatedAt DateTime? Data de criação
DeletedAt DateTime? Data de exclusão

CenixDepartmentDTO

Campo Tipo Descrição
Id int ID do departamento
Name string Nome do departamento
Company CenixCompanyDTO? Empresa vinculada
Managers List<CenixUserDTO>? Gestores do departamento

CenixModuleDTO

Campo Tipo Descrição
Id int ID do módulo
Name string Nome do módulo
Link string URL do módulo
SystemId int ID do sistema vinculado
System CenixSystemDTO? Sistema vinculado (objeto)
IsGlobal bool Módulo global
Requires2FA bool Exige autenticação de dois fatores
CreatedAt DateTime Data de criação
DeletedAt DateTime? Data de exclusão

CenixSystemDTO

Campo Tipo Descrição
Id int ID do sistema
Name string Nome do sistema
CreatedAt DateTime Data de criação
DeletedAt DateTime? Data de exclusão

CenixPagedResponseDTO<T> — resposta paginada

Campo Tipo Descrição
Data List<T> Itens da página atual
CurrentPage int Página atual (base 0)
TotalPages int Total de páginas
PageSize int Itens por página
TotalCount int Total de registros

Arquitetura

O pacote segue o padrão DDD em camadas:

Application/    → DTOs e serviços de aplicação (implementações internal)
Domain/         → Interfaces (contratos)
Infrastructure/ → Implementações HTTP (Zeus / Aiacos) (internal)
CrossCutting/   → Injeção de dependência

Superfície pública: só as interfaces ICenix*Service (injetadas via DI) e os DTOs. As interfaces de API (ICenix*API) e as classes de Infrastructure são internal — não fazem parte do contrato do pacote.

Propagação do token JWT

Todas as chamadas às APIs internas repassam automaticamente o Bearer token. O pacote suporta dois contextos:

  • Login de usuário — token lido do HttpContext.Request.Headers["Authorization"]
  • Login de módulo / conta de serviço — token obtido via LoginModuleAsync() / ServiceLoginAsync() e armazenado internamente, usado em chamadas de background (sem HttpContext)

Notas de Atualização

Resumo rápido (desde 08/02/2026)

Versão O que mudou
2.0.1 ICenixPermissionSyncService finalizado: o módulo envia as keys (as mesmas do can(...), como constantes no código) e o Zeus valida o prefixo SISTEMA_MODULO_ + formato, rejeitando as fora do padrão. Sem precisar consultar o Zeus pra saber a key.
2.0.0 ⚠️ Breaking. Removidos ICenixLogService, ICenixCacheService (Redis), o pipeline RabbitMQ e o serviço de e-mail (ICenixEmailService). Superfície pública restrita às interfaces ICenix*Service + DTOs (API e Infrastructure agora internal). Dependências RabbitMQ.Client e StackExchangeRedis removidas. Novos: auto-configuração por variáveis de ambiente (configureOptions opcional); ServiceLoginAsync (conta de serviço M2M); fluxos de senha/desbloqueio/SSO no ICenixAuthService (forgot/reset/unlock/change-password/exchange-transfer-token); ICenixPermissionSyncService (registra o catálogo de permissões do módulo no Zeus); cache por-request do /auth/me; erros agora lançam CenixApiException (status HTTP + corpo reais, não mais 401 genérico); GetLoggedModuleAsync nullable
1.5.4 Novo método ServiceLoginAsync no ICenixAuthService — login de conta de serviço (M2M) em uma chamada (autentica + emite token no módulo por moduleKey)
1.5.3 Novos métodos LoginAsync e SelectModuleAsync no ICenixAuthService, suporte a autenticação em background services via SetAuthorizationToken / ClearAuthorizationToken
1.5.2 Novos campos PermissionsKeys e ManagedDepartments no CenixUserDTO
1.5.1 Serviço de cache Redis (ICenixCacheService), novos campos em CenixLoggedUserDTO e CenixCompanyDTO
1.5.0 Serviço de sistemas (ICenixSystemService), endpoints paginados para sistemas e módulos
1.4.9 Endpoint paginado de usuários (GetAllUsersPagedAsync), novos campos no CenixUserDTO
1.4.8 Propriedade PermissionsKeys no CenixLoggedUserDTO

v2.0.1 — 03/09/2026

Registro de permissões do módulo — por KEY, com validação

O ICenixPermissionSyncService foi finalizado no formato definitivo. O módulo envia as keys completas (as MESMAS usadas no can(...)), normalmente declaradas uma vez como constantes no próprio código:

public static class WmsPermissions
{
    private const string P = "ARGUS_WMS_";
    public const string Conferente   = P + "CONFERENTE";
    public const string AdminArmazem = P + "ADMINISTRADOR_DE_ARMAZEM";
    public static readonly string[] All = { Conferente, AdminArmazem };
}

// no boot:
await _permissionSync.SyncAsync(WmsPermissions.All);
// em qualquer lugar (sem olhar no Zeus):
if (user.PermissionsKeys.Contains(WmsPermissions.Conferente)) { ... }
  • O Zeus valida cada key contra o prefixo do módulo (SISTEMA_MODULO_) e o formato (MAIÚSCULAS/underscore) e rejeita as fora do padrão, retornando a lista das inválidas (o pacote entrega isso via CenixApiException).
  • Vantagem: a key vive no código do módulo (fonte única, reusada no SyncAsync e no can(...)) — você não precisa consultar o Zeus pra saber a key, e ninguém sobe uma key errada.
  • SyncAsync(IEnumerable<string> permissionKeys); resultado traz Created, Linked e Keys. Idempotente; cria as ausentes (Id pela sequence) e vincula ao Administrador do módulo.
  • Requer o endpoint POST /permissions/sync no Zeus (deploy).

v2.0.0 — 02/09/2026

✨ Novidades

  • Auto‑configuração por ambiente: configureOptions agora é opcional — o que não for passado é lido das variáveis padrão (MODULE_ID, JWT_KEY, JWT_ISSUER, JWT_AUDIENCE, AIACOS_API, ZEUS_API, + AIACOS_APP opcional). O que o dev passa manualmente sempre vence. Erro claro se faltar alguma obrigatória.
  • ICenixAuthService.ServiceLoginAsync(...) — login de conta de serviço (M2M) em uma chamada (POST /auth/service-login).
  • Fluxos de senha/desbloqueio/SSO no ICenixAuthService: ForgotPasswordAsync, ResetPasswordAsync, RequestUnlockAsync, UnlockAccountAsync, ChangePasswordAsync, ExchangeTransferTokenAsync.
  • ICenixPermissionSyncService.SyncAsync(permissionKeys) — o módulo registra o próprio catálogo passando as keys (as mesmas do can(...)); o Zeus valida o prefixo SISTEMA_MODULO_ + formato e rejeita as fora do padrão. Vincula ao Administrador do módulo. Idempotente; ideal no boot. Requer Urls.ZeusApi + token com PERMISSOES_CADASTRAR.
  • CenixApiException — toda falha de API interna agora lança essa exceção com StatusCode, ResponseBody e Endpoint reais (antes: UnauthorizedAccessException genérico pra qualquer erro). IsAuthError (401/403) ajuda a mapear a resposta ao cliente.
  • Cache por‑request do /auth/me — dentro de uma mesma requisição, o GetLoggedUserAsync é resolvido uma vez só (guardado no HttpContext.Items, chaveado pelo hash do token) e reusado; some no fim do request. Sem risco de role velha (cada nova ação busca de novo). Novo RefreshLoggedUser() limpa o cache no mesmo request se você alterar as permissões do próprio usuário e precisar reler. Sem HttpContext (background) não cacheia.
  • GetLoggedModuleAsync agora é Task<CenixModuleDTO?> (pode ser null quando não é login de módulo) — evita NullReferenceException.

⚠️ Mudanças que quebram compatibilidade (major)

  • Superfície pública restrita: só as interfaces ICenix*Service (injetadas via DI) e os DTOs continuam públicos. As interfaces de API (ICenix*API), as classes de Infrastructure (clientes HTTP, LocalStorage) e as implementações dos serviços passaram a internal. Quem só injeta os ICenix*Service (uso recomendado) não é afetado; quem referenciava tipos internos precisa parar de fazê-lo.
  • Removido ICenixLogService (logs de erro/auditoria/info) e o ZeusLogApi de Urls.
  • Removido ICenixCacheService (cache Redis) e a opção Redis; dependência Microsoft.Extensions.Caching.StackExchangeRedis removida.
  • Removido RabbitMQ (consumer + fila) e a opção RabbitMQ; dependência RabbitMQ.Client removida.
  • Removido o serviço de e-mail (ICenixEmailService), o CenixEmailMessageDTO, o options.Email e o envio via SMTP — não era usado.

Migração: remova options.Redis, options.RabbitMQ, options.Email e Urls.ZeusLogApi do setup; troque usos de ICenixLogService/ICenixCacheService/ICenixEmailService por implementação própria, se necessário.


v1.5.4 — 02/09/2026

Login de conta de serviço (M2M)

  • Novo método ServiceLoginAsync(emailOrUsername, password, moduleKey, companyId?, moduleKeyUsed?, storeToken = true) no ICenixAuthService — autentica a conta de serviço e já emite o token no módulo de destino (moduleKey) em uma única chamada (POST /auth/service-login no Aiacos), sem precisar de login + seleção de módulo. Por padrão armazena o token internamente (ideal para workers/integrações).
  • Novo DTO CenixServiceLoginDTO. Só funciona para contas marcadas como conta de serviço; a allowlist de IP da conta continua sendo aplicada pelo Aiacos.

v1.5.3 — 11/05/2026

Autenticação direta no ICenixAuthService

  • Novo método LoginAsync(emailOrUsername, password, storeToken) — autenticação via POST /auth/login no Aiacos, retorna CenixAuthResponseDTO (token + refreshToken + usuário)
  • Novo método SelectModuleAsync(moduleId, companyId?, code2FA?, rememberDevice?, storeToken) — seleção de módulo via POST /auth/select-module no Aiacos, retorna CenixAuthResponseDTO com novo token contendo o módulo no payload

Suporte a background services

  • Novos métodos SetAuthorizationToken(token) e ClearAuthorizationToken() para definir/limpar manualmente o token usado em chamadas sem HttpContext (workers, schedulers)
  • Parâmetro opcional storeToken em LoginAsync e SelectModuleAsync: quando true, o token retornado é armazenado automaticamente para uso nas chamadas subsequentes

Novos DTOs

  • CenixLoginDTO, CenixSelectModuleDTO (request)
  • CenixAuthResponseDTO (response compartilhado entre login e seleção de módulo)

v1.5.2 — 07/05/2026

DTOs atualizados

  • CenixUserDTO: adicionados PermissionsKeys (List<string>) e ManagedDepartments (List<CenixDepartmentDTO>?), espelhando os campos já existentes em CenixLoggedUserDTO

v1.5.1 — 16/04/2026

Cache Redis

  • Novo serviço ICenixCacheService com métodos SetAsync<T>, GetAsync<T>, RemoveAsync e ExistsAsync
  • Configuração opcional: basta informar Redis.StringConnection no setup. Se não informar, o cache não é registrado
  • Dependência StackExchangeRedis atualizada para 8.0.22

DTOs atualizados

  • CenixLoggedUserDTO: adicionados CompanyId, CreatedAt, SecondaryDepartments
  • CenixCompanyDTO: adicionados ParentCompanyId, CreatedAt, DeletedAt

v1.5.0 — 01/03/2026

Serviço de Sistemas

  • Novo ICenixSystemService com GetByIdAsync, GetAllAsync (filtros por nome e status) e GetPagedAsync (paginação com ordenação)
  • Injeção de dependência do CenixSystemService registrada automaticamente

Endpoints paginados para Módulos

  • ICenixModuleService.GetPagedAsync — paginação com filtros por nome, sistema, e ordenação

v1.4.9 — 27/02/2026

Endpoint paginado de Usuários

  • Novo GetAllUsersPagedAsync em ICenixUserService com paginação, filtros avançados (nome, departamento, permissão, permissionKey, lista de IDs) e ordenação
  • Novo DTO CenixPagedResponseDTO<T> para respostas paginadas padronizadas
  • CenixUserDTO atualizado com novos campos

v1.4.8 — 08/02/2026

Permissões por chave

  • Adicionada propriedade PermissionsKeys (List<string>) no CenixLoggedUserDTO para acesso às chaves textuais de permissão (ex: ZEUS_GESTAO_DE_USUARIOS_USUARIOS_VISUALIZAR)
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.4 74 9/28/2026
2.0.2 98 9/22/2026
2.0.1 124 9/3/2026
2.0.0 90 9/3/2026
Loading failed