### Install Mermaid Preview Extension for VS Code Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/diagrams/README.md Install the 'Markdown Preview Mermaid Support' extension in VS Code to render Mermaid diagrams within Markdown files. ```bash ext install bierner.markdown-mermaid ``` -------------------------------- ### Permission Matching Examples Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/architecture/permissions-system.md Illustrates practical scenarios of the permission matching algorithm, including global permissions, tenant-scoped permissions, and project-specific mismatches. ```pseudo Exemplo 1: Permissão Global vs. Contexto Específico Permissão: ```java tenantId = null companyId = null projectId = null ``` Contexto da Requisição: ```java tenantId = "ABC" companyId = "ABC-BR" projectId = "PROJ-1" ``` Resultado: ✓ **MATCH** (permissão global aceita qualquer contexto) ``` ```pseudo Exemplo 2: Permissão Tenant vs. Contexto Company Permissão: ```java tenantId = "ABC" companyId = null projectId = null ``` Contexto da Requisição: ```java tenantId = "ABC" companyId = "ABC-BR" projectId = "PROJ-1" ``` Resultado: ✓ **MATCH** (tenant coincide, company/project são wildcards) ``` ```pseudo Exemplo 3: Permissão Project vs. Contexto Diferente Permissão: ```java tenantId = "ABC" companyId = "ABC-BR" projectId = "PROJ-1" ``` Contexto da Requisição: ```java tenantId = "ABC" companyId = "ABC-BR" projectId = "PROJ-2" // Projeto diferente! ``` Resultado: ✗ **NO MATCH** (projeto não coincide) ``` ```pseudo Exemplo 4: Múltiplas Permissões Permissões do Usuário: 1. `tenantId="ABC", companyId="ABC-BR", projectId="PROJ-1"` 2. `tenantId="ABC", companyId="ABC-AR", projectId=null` Contexto da Requisição: ```java tenantId = "ABC" companyId = "ABC-AR" projectId = "PROJ-5" ``` Análise: - Permissão 1: ✗ NO MATCH (company diferente) - Permissão 2: ✓ **MATCH** (tenant e company coincidem, project é wildcard) Resultado Final: ✓ **ACESSO CONCEDIDO** (pelo menos uma permissão fez match) ``` -------------------------------- ### ResourceEntity Creation Examples Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/entities/permission-entities.md Demonstrates how to create and save ResourceEntity instances for both API endpoints and UI views using the builder pattern. ```java // Criar recurso de API ResourceEntity userApi = ResourceEntity.builder() .name("USER_API") .description("API de gerenciamento de usuários") .type(TipoRecurso.API) .active(true) .build(); resourceRepository.save(userApi); // Criar recurso de VIEW ResourceEntity dashboardView = ResourceEntity.builder() .name("DASHBOARD") .description("Dashboard principal do sistema") .type(TipoRecurso.VIEW) .active(true) .build(); resourceRepository.save(dashboardView); ``` -------------------------------- ### Example: Creating a Global Permission Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/entities/permission-entities.md Demonstrates how to build a PermissionEntity that grants access universally across all tenants, companies, and projects by setting context fields to null. ```java PermissionEntity permission = PermissionEntity.builder() .security(adminUser) .action(viewAction) .tenantId(null) // Wildcard - qualquer tenant .companyId(null) // Wildcard - qualquer empresa .projectId(null) // Wildcard - qualquer projeto .build(); ``` -------------------------------- ### Securely Store API Tokens Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/guides/code-examples.md Example of using environment variables for securely storing API tokens. This is a recommended practice to avoid hardcoding sensitive credentials. ```bash # Use variáveis de ambiente ou secrets manager export EXTERNAL_API_TOKEN="" ``` -------------------------------- ### Example JSON Authentication Response Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/architecture/authentication-system.md Illustrates the structure of a typical JSON response returned after a successful authentication, containing tokens and user information. ```json { "id": "550e8400-e29b-41d4-a716-446655440000", "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3VhcmlvQGV4ZW1wbG8uY29tIiwiaWF0IjoxNzA0MDYzNjAwLCJleHAiOjE3MDQwNjcyMDB9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", "expirationTime": 1704067200000, "tokenType": "BEARER", "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3VhcmlvQGV4ZW1wbG8uY29tIiwiaWF0IjoxNzA0MDYzNjAwLCJleHAiOjE3MDQ2Njg0MDB9.dQw4w9WgXcQ5qpJ4RhNZ9jqxwEhv8J3nwxTqGvZ4qPo", "user": { "id": "user-uuid-123", "name": "Usuário Exemplo", "email": "usuario@exemplo.com", "avatar": "https://exemplo.com/avatar.jpg", "isAdministrator": false, "enabled": true } } ``` -------------------------------- ### Complete Security Setup Service Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/guides/code-examples.md This service demonstrates the full flow of creating security entities: resources, actions, users, and permissions. It's useful for initializing security configurations or setting up administrative users. ```java package com.example.security.service; import br.com.archbase.security.persistence.*; import br.com.archbase.security.repository.*; import br.com.archbase.ddd.domain.annotations.DomainService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.UUID; /** * Service para criação e configuração de usuários com permissões. * * Este service encapsula toda a lógica de criação de entidades de segurança, * incluindo recursos, ações, usuários e permissões, seguindo o padrão * Domain-Driven Design. */ @Service @DomainService public class SecuritySetupService { @Autowired private UserJpaRepository userRepository; @Autowired private ResourceJpaRepository resourceRepository; @Autowired private ActionJpaRepository actionRepository; @Autowired private PermissionJpaRepository permissionRepository; @Autowired private PasswordEncoder passwordEncoder; /** * Cria um usuário completo com permissões de gerenciamento. * * Este método demonstra o fluxo completo: * 1. Criação de recurso (o que está sendo protegido) * 2. Criação de ações no recurso (o que pode ser feito) * 3. Criação do usuário * 4. Atribuição de permissões ao usuário * * @return ID do usuário criado */ @Transactional public String createUserWithPermissions() { // === PASSO 1: Criar Recurso === // Recursos representam entidades ou funcionalidades da aplicação ResourceEntity resource = ResourceEntity.builder() .id(UUID.randomUUID().toString()) .code("RES_USER_MANAGEMENT") .name("USER_MANAGEMENT") .description("Gerenciamento de Usuários do Sistema") .active(true) .type(TipoRecurso.API) .tenantId("TENANT_ABC") .createEntityDate(LocalDateTime.now()) .createdByUser("SYSTEM") .build(); resourceRepository.save(resource); // === PASSO 2: Criar Ações no Recurso === // Ações definem operações específicas que podem ser realizadas no recurso // Ação VIEW - Para consulta de dados ActionEntity viewAction = ActionEntity.builder() .id(UUID.randomUUID().toString()) .code("ACT_VIEW_USER") .name("VIEW") .description("Visualizar usuários do sistema") .resource(resource) .category("READ") .active(true) .tenantId("TENANT_ABC") .createEntityDate(LocalDateTime.now()) .createdByUser("SYSTEM") .build(); actionRepository.save(viewAction); // Ação CREATE - Para criação de novos registros ActionEntity createAction = ActionEntity.builder() .id(UUID.randomUUID().toString()) .code("ACT_CREATE_USER") .name("CREATE") .description("Criar novos usuários no sistema") .resource(resource) .category("WRITE") .active(true) .tenantId("TENANT_ABC") .createEntityDate(LocalDateTime.now()) .createdByUser("SYSTEM") .build(); actionRepository.save(createAction); // Ação UPDATE - Para modificação de registros existentes ActionEntity updateAction = ActionEntity.builder() .id(UUID.randomUUID().toString()) .code("ACT_UPDATE_USER") .name("UPDATE") .description("Atualizar dados de usuários existentes") .resource(resource) .category("WRITE") .active(true) .tenantId("TENANT_ABC") .createEntityDate(LocalDateTime.now()) .createdByUser("SYSTEM") .build(); actionRepository.save(updateAction); // Ação DELETE - Para remoção de registros ActionEntity deleteAction = ActionEntity.builder() .id(UUID.randomUUID().toString()) .code("ACT_DELETE_USER") .name("DELETE") .description("Excluir usuários do sistema") .resource(resource) .category("DELETE") .active(true) .tenantId("TENANT_ABC") .createEntityDate(LocalDateTime.now()) .createdByUser("SYSTEM") .build(); actionRepository.save(deleteAction); // === PASSO 3: Criar Usuário === // Usuários são as entidades de segurança que podem fazer login UserEntity user = UserEntity.builder() .id(UUID.randomUUID().toString()) .code("USR_JOHN_DOE") .name("John Doe") .description("Gerente de TI - Responsável pelo gerenciamento de usuários") ``` -------------------------------- ### HTTP Request with Authorization Header Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/architecture/authentication-system.md Example of an HTTP GET request to a protected API endpoint, demonstrating how to include the Bearer token in the Authorization header. ```http GET /api/v1/users/profile HTTP/1.1 Host: api.exemplo.com Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... Content-Type: application/json ``` -------------------------------- ### Enable Multi-Tenancy Configuration Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/architecture/multi-tenancy.md Configuration properties to enable and set the mode for multi-tenancy. This example shows how to enable multi-tenancy and set the mode to 'database'. Other modes like 'schema' or 'shared' might also be available. ```properties archbase.multitenancy.enabled=true archbase.multitenancy.mode=database # ou schema, ou shared ``` -------------------------------- ### Combining Security Annotations Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/readme-security.md Demonstrates combining multiple security annotations on a single method for complex access control requirements. This example requires both a specific profile and a permission. ```java import com.example.archbase.security.RequireProfile; import com.example.archbase.security.HasPermission; // Assume FinancialReport is defined elsewhere public class SecurityAnnotations { @RequireProfile("MANAGER") @HasPermission(resource = "FINANCIAL", action = "READ") public FinancialReport getFinancialReport() { // Usuário deve ter profile MANAGER E permissão FINANCIAL:READ return null; // Placeholder } } ``` -------------------------------- ### Parent Domain Model Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-validation/documentation/1-quick-start.md Example of a Parent domain model class with fields for name, age, cities, and children. ```java public class Parent { private String name; private Integer age; private List cities; private List children; public List getChildren() { return children; } public void setChildren(List children) { this.children = children; } public List getCities() { return this.cities; } public void setCities(List cities) { this.cities = cities; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public Integer getAge() { return this.age; } public void setAge(Integer age) { this.age = age; } } ``` -------------------------------- ### ComplexObject, City, and State Classes Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-validation/documentation/9-function-builder.md Example data classes used to demonstrate nested object access. ```java public class ComplexObject { private City city; public City getCity() { return this.city; } } public class City { private String name; private State state; public String getName() { return this.name; } public State getState() { return this.state; } } public class State { public String name; public String getName() { return this.name; } } ``` -------------------------------- ### Async Service with Automatic Tenant Context Propagation Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/architecture/multi-tenancy.md An example of an asynchronous service that benefits from the TenantAwareTaskDecorator. The tenant context is automatically propagated, allowing the service to operate within the correct tenant's scope without explicit context management within the method. ```java @Service public class NotificationService { @Async public void sendNotification(String userId, String message) { // O contexto de tenant foi propagado automaticamente // pelo TenantAwareTaskDecorator String currentTenant = ArchbaseTenantContext.getTenantId(); logger.info("Sending notification to user {} in tenant {}", userId, currentTenant); // Lógica de envio de notificação } } ``` -------------------------------- ### Initiate Authentication Request Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/keycloak/research/entities-guide.md Start the OpenID Connect authentication flow by requesting an authorization code. Ensure all parameters like client ID and redirect URI are correctly configured. ```http GET /realms/minha-aplicacao/protocol/openid-connect/auth?response_type=code&client_id=minha-aplicacao&redirect_uri=https://bi.exemplo.com.br/callback&scope=openid email profile&state=random_state_value ``` -------------------------------- ### Get User Information Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/keycloak/research/entities-guide.md Retrieve detailed information about the authenticated user by making a request to the userinfo endpoint, using a valid access token. ```bash curl --location 'https://keycloak.exemplo.com.br/realms/minha-aplicacao/protocol/openid-connect/userinfo' \ --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI...' ``` -------------------------------- ### Spring Validator Integration Example Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-validation/documentation/3-spring-support.md Demonstrates how to extend AbstractValidator in a Spring environment, utilizing dependency injection for child validators and defining validation rules for a Parent object. ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Collection; import java.util.Optional; import java.util.stream.Collectors; import static br.com.fluentvalidator.predicate.ComparablePredicate.greaterThanOrEqual; import static br.com.fluentvalidator.predicate.ComparablePredicate.lessThanOrEqual; import static br.com.fluentvalidator.predicate.ObjectPredicate.nullValue; import static br.com.fluentvalidator.predicate.StringPredicate.stringContains; import static br.com.fluentvalidator.predicate.StringPredicate.stringEmptyOrNull; import static br.com.fluentvalidator.predicate.CollectionPredicate.hasSize; import static br.com.fluentvalidator.predicate.CollectionPredicate.empty; import static br.com.fluentvalidator.builder.ValidationBuilder.from; @Component public class ValidatorSpringParent extends AbstractValidator { @Autowired ValidatorSpringChild validatorChild; @Autowired ValidatorSpringId validatorId; @Autowired ValidatorSpringGirl validatorGirl; @Autowired ValidatorSpringBoy validatorBoy; @Override protected void rules() { setPropertyOnContext("parent"); ruleForEach(Parent::getChildren) .must(not(nullValue())) .withMessage("parent's children cannot be null") .withCode("555") .withFieldName("children") .must(not(empty())) .when(not(nullValue())) .withMessage("parent must have at least one child") .withFieldName("children") .whenever(not(nullValue())) .withValidator(validatorChild) .critical(); ruleFor(Parent::getId) .whenever(isTrue()) .withValidator(validatorId) .critical(); ruleFor(Parent::getAge) .must(greaterThanOrEqual(5)) .when(not(nullValue())) .withMessage("age must be greater than or equal to 10") .withFieldName("age") .must(lessThanOrEqual(7)) .when(not(nullValue())) .withMessage("age must be less than or equal to 7") .withCode("666") .withFieldName("age"); ruleFor(Parent::getCities) .must(hasSize(10)) .when(not(nullValue())) .withMessage("cities size must be 10") .withFieldName("cities"); ruleFor(Parent::getName) .must(stringContains("John")) .when(not(stringEmptyOrNull())) .withMessage("name must contains key John") .withFieldName("name"); ruleForEach(parent -> extractGirls(parent.getChildren())) .whenever(not(nullValue())) .withValidator(validatorGirl); ruleForEach(parent -> extractBoys(parent.getChildren())) .whenever(not(nullValue())) .withValidator(validatorBoy) .critical(); } private Collection extractGirls(Collection children) { return Optional.ofNullable(children).orElseGet(ArrayList::new) .stream() .filter(Girl.class::isInstance) .map(Girl.class::cast) .collect(Collectors.toList()); } private Collection extractBoys(Collection children) { return Optional.ofNullable(children).orElseGet(ArrayList::new) .stream() .filter(Boy.class::isInstance) .map(Boy.class::cast) .collect(Collectors.toList()); } } ``` -------------------------------- ### Perform Security Tests with MockMvc Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/guides/code-examples.md Example of using Spring Boot's MockMvc to test security configurations, verifying access to public endpoints, protection of private endpoints, and authenticated access. ```java @SpringBootTest @AutoConfigureMockMvc class SecurityConfigTest { @Autowired private MockMvc mockMvc; @Test void shouldAllowPublicEndpoints() throws Exception { mockMvc.perform(get("/api/v1/auth/login")) .andExpect(status().isOk()); } @Test void shouldProtectPrivateEndpoints() throws Exception { mockMvc.perform(get("/api/v1/users")) .andExpect(status().isUnauthorized()); } @Test @WithMockUser void shouldAllowAuthenticatedAccess() throws Exception { mockMvc.perform(get("/api/v1/users")) .andExpect(status().isOk()); } } ``` -------------------------------- ### Permission Entity with Company-Specific Access Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/architecture/multi-tenancy.md Example of creating a permission entity that grants access to a specific company within a tenant. This demonstrates how to define granular permissions by specifying tenantId, companyId, and optionally projectId. ```java // Usuário com acesso a uma company específica PermissionEntity permission = PermissionEntity.builder() .security(user) .action(viewAction) .tenantId("GRUPO_XYZ") .companyId("XYZ_BRASIL") // Apenas esta company .projectId(null) // Todos os projetos .build(); ``` -------------------------------- ### Repository Method with Explicit Company Context Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/architecture/multi-tenancy.md Demonstrates how to enforce company-level data access using the @HasPermission annotation. This example explicitly defines the required action, resource, and companyId for the method, ensuring that only data belonging to 'XYZ_BRASIL' is retrieved. ```java @HasPermission( action = "VIEW", resource = "SALES_DATA", companyId = "XYZ_BRASIL" // Contexto explícito ) public List getSalesByCompany() { return saleRepository.findAll(); } ``` -------------------------------- ### API Token HTTP Request Header Example Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/architecture/authentication-system.md Illustrates the correct format for including an API Token in the Authorization header of an HTTP request. Note the 'ApiToken' prefix instead of 'Bearer'. ```http GET /api/v1/external/data HTTP/1.1 Host: api.exemplo.com Authorization: ApiToken dGhpc2lzYXRva2VuZXhhbXBsZQ... Content-Type: application/json ``` -------------------------------- ### Automatic Tenant Filtering in Queries Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/architecture/multi-tenancy.md Illustrates how Archbase automatically applies a tenant filter to all queries when multi-tenancy is enabled. The example shows a typical repository call and the resulting SQL query with a WHERE clause for TENANT_ID. ```java // Todas as queries automáticas incluem filtro de tenant List users = userRepository.findAll(); // SQL gerado: SELECT * FROM SEGURANCA WHERE TP_SEGURANCA='USUARIO' AND TENANT_ID=? ``` -------------------------------- ### Controller Method Security Annotations Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/readme-security.md Examples of applying security annotations to controller methods for granular access control. Annotations like @RequireProfile, @HasPermission, @RequirePersona, and @RequireRole are used to define access rules. ```java import org.springframework.web.bind.annotation.*; import java.util.List; // Assume Product, ProductDto, ProductService, ProductReport, ReportService are defined elsewhere @RestController @RequestMapping("/api/v1/products") public class ProductController { // Assume productService and reportService are injected private ProductService productService; private ReportService reportService; @GetMapping @RequireProfile("USER") // Qualquer usuário logado public List listProducts() { return productService.findAll(); } @PostMapping @HasPermission(resource = "PRODUCT", action = "CREATE") public Product createProduct(@RequestBody ProductDto dto) { return productService.create(dto); } @PutMapping("/{id}") @RequirePersona(value = "STORE_ADMIN", context = "STORE_APP") public Product updateProduct(@PathVariable String id, @RequestBody ProductDto dto) { return productService.update(id, dto); } @DeleteMapping("/{id}") @RequireRole(value = "STORE_OWNER", ownerOnly = true) public void deleteProduct(@PathVariable String id) { productService.delete(id); } @GetMapping("/reports") @RequireProfile(value = {"ADMIN", "FINANCE"}, requireAll = true) @HasPermission(resource = "REPORTS", action = "GENERATE") public ProductReport generateReport() { return reportService.generateProductReport(); } } ``` -------------------------------- ### Kotlin Boy Validation Example Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-validation/README.md Defines validation rules for a 'Boy' object in Kotlin. Similar to the Java example, it validates gender and name, using Kotlin's syntax for lambda expressions and property access. The `.`when` syntax is used for conditional validation. ```kotlin import predicate.br.com.archbase.validation.fluentvalidator.ComparablePredicate.equalTo; import predicate.br.com.archbase.validation.fluentvalidator.LogicalPredicate.not; import predicate.br.com.archbase.validation.fluentvalidator.ObjectPredicate.nullValue; import predicate.br.com.archbase.validation.fluentvalidator.StringPredicate.stringContains; import predicate.br.com.archbase.validation.fluentvalidator.StringPredicate.stringEmptyOrNull; import model.br.com.archbase.validation.fluentvalidator.Boy import model.br.com.archbase.validation.fluentvalidator.Gender; import br.com.archbase.validation.fluentvalidator.AbstractArchbaseValidator; class KotlinValidatorBoy : AbstractValidator { constructor() : super(); override fun rules() { ruleFor(Boy::getGender) .must(equalTo(Gender.MALE)) .`when`(not(nullValue())) .withMessage("gender of boy must be MALE") .withFieldName("gender") .critical(); ruleFor(Boy::getName) .must(stringContains("John")) .`when`(not(stringEmptyOrNull())) .withMessage("child name must contains key John") .withFieldName("name"); } } ``` -------------------------------- ### Build with Local Profile Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/CLAUDE.md Builds the project with a local profile, including GPG signing, sources, and Javadoc. ```bash # Build with local profile (includes GPG signing, sources, and javadoc) mvn clean install -P local ``` -------------------------------- ### Get User by Username Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/guides/code-examples.md Retrieves details of a specific user by their username. Requires VIEW permission on USER_MANAGEMENT. ```APIDOC ## GET /api/v1/users/by-username/{username} ### Description Returns user details by username. ### Method GET ### Endpoint /api/v1/users/by-username/{username} ### Parameters #### Path Parameters - **username** (string) - Required - Username ### Response #### Success Response (200) - **id** (string) - User ID - **username** (string) - User's username - **email** (string) - User's email address #### Response Example { "id": "1", "username": "user1", "email": "user1@example.com" } ``` -------------------------------- ### Get User by ID Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/guides/code-examples.md Retrieves details of a specific user by their ID. Requires VIEW permission on USER_MANAGEMENT. ```APIDOC ## GET /api/v1/users/{id} ### Description Returns user details by ID. ### Method GET ### Endpoint /api/v1/users/{id} ### Parameters #### Path Parameters - **id** (string) - Required - User ID ### Response #### Success Response (200) - **id** (string) - User ID - **username** (string) - User's username - **email** (string) - User's email address #### Response Example { "id": "1", "username": "user1", "email": "user1@example.com" } ``` -------------------------------- ### JIT Provisioning Flow for Active Users Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/keycloak/research/keycloak-archbase-integration-strategies.md Describes the step-by-step process when an active user logs in, including JWT interception, cache checks, and user synchronization with Keycloak. ```text 1. Usuário autentica no Keycloak → Recebe token JWT com roles e groups 2. Primeira requisição do dia ao Archbase → JWT Filter intercepta → Extrai claim "sub" (externalId) → Verifica cache: MISS (primeira vez no dia) → Dispara User Sync Service: • Busca UserEntity por externalId • Atualiza email se mudou • Extrai roles do token • Extrai groups do token • Cria GroupEntity se não existirem • Atualiza vínculos UserGroupEntity • Salva timestamp no cache (TTL: 15 min) → Requisição prossegue normalmente 3. Próximas requisições (dentro de 15 min) → JWT Filter intercepta → Verifica cache: HIT → Pula sincronização → Performance otimizada 4. Requisição após 15 min → Cache expirado → Sincronização incremental novamente ``` -------------------------------- ### PredicateBuilder.from() Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-validation/documentation/8-predicate-builder.md Creates a PredicateBuilder from an initial predicate. This is the starting point for building more complex predicates using logical AND and OR operations. ```APIDOC ## PredicateBuilder.from() ### Description Creates a PredicateBuilder instance initialized with a given predicate. This method serves as the entry point for constructing predicate chains. ### Method Signature ```java from(final Predicate predicate) ``` ### Parameters * **predicate** (Predicate) - Required - The initial predicate to start building from. ### Example ```java private static Predicate isGirl() { return PredicateBuilder.from(not(nullValue())).and(instanceOf(Girl.class)); } ``` ``` -------------------------------- ### Build with Maven Central Profile Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/CLAUDE.md Builds the project including GPG signing, sources, and Javadoc, suitable for publishing to Maven Central. ```bash # Build with Maven Central profile (includes GPG signing, sources, and javadoc) mvn clean install -P maven-central ``` -------------------------------- ### Clean Build All Modules Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/CLAUDE.md Use this command to perform a clean build of all modules in the project. ```bash # Clean build all modules mvn clean install ``` -------------------------------- ### ProfileEntity Creation and Permission Assignment Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/entities/core-entities.md Shows how to create a ProfileEntity and assign multiple permissions to it. A user assigned this profile will inherit all associated permissions. ```java // Criar perfil ProfileEntity adminProfile = ProfileEntity.builder() .code("ADMIN") .name("Administrador") .description("Acesso completo ao sistema") .build(); // Atribuir múltiplas permissões ao perfil List permissions = Arrays.asList( createPermission(adminProfile, viewUsersAction), createPermission(adminProfile, createUsersAction), createPermission(adminProfile, editUsersAction), createPermission(adminProfile, deleteUsersAction) ); // Usuário recebe o perfil user.setProfile(adminProfile); // Agora o usuário herda todas as permissões do perfil ``` -------------------------------- ### Recommended Database Indexes for Permissions Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/entities/permission-entities.md SQL statements for creating indexes on the permission table to optimize performance for security and context-based queries. ```sql CREATE INDEX idx_permission_security_action ON SEGURANCA_PERMISSAO(ID_SEGURANCA, ID_ACAO); CREATE INDEX idx_permission_context ON SEGURANCA_PERMISSAO(TENTANT_ID, COMPANY_ID, PROJECT_ID); ``` -------------------------------- ### Creating a Predicate from a single Predicate Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-validation/documentation/8-predicate-builder.md Use `from(Predicate predicate)` to initialize a PredicateBuilder with an existing predicate. This is useful for starting a chain of predicate operations. ```java private static Predicate isGirl() { return PredicateBuilder.from(not(nullValue())).and(instanceOf(Girl.class)); } ``` -------------------------------- ### Scheduled Synchronization Cron Expression Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/keycloak/research/keycloak-archbase-integration-strategies.md Example of a cron expression for scheduling a synchronization job. This specific expression schedules the job to run daily at 2 AM. ```java @Scheduled(cron = "0 0 2 * * ?") ``` -------------------------------- ### Archbase and Keycloak Profile Mapping Scenario Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/keycloak/research/archbase-comparison.md Illustrates how Archbase user and profile entities can map to Keycloak users and realm roles. ```text Archbase: UserEntity: joao.silva ProfileEntity: ADMIN Keycloak: User: joao.silva Realm Roles: [ADMIN] ``` -------------------------------- ### Custom Error Handling for Collection Size Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-validation/documentation/5-builder-methods.md Example of using handlerInvalidField to create a custom error when a collection does not have a size of 1. This applies when the collection is not empty. ```java ruleFor(Entity::getCollection) .must(hasSize(1)) .when(not(empty())) .handlerInvalidField(new HandlerInvalidField>() { @Override public Collection handle(final Collection instance) { return Collections.singletonList(Error.create("collection", "collection must be size 1", "404", instance.getCollection())); } }); ``` -------------------------------- ### Create User with Specific Permissions Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/guides/code-examples.md This snippet shows how to create a new user and assign them specific view, create, and update permissions with varying scopes (company-wide or project-specific). ```Java UserEntity user = UserEntity.builder() .id(UUID.randomUUID().toString()) .code("USR_JOHN_DOE") .name("John Doe") .description("Usuário de teste para demonstração") .userName("john.doe") .email("john.doe@example.com") .password(passwordEncoder.encode("SenhaSegura@2024")) .isAdministrator(false) .accountDeactivated(false) .accountLocked(false) .allowPasswordChange(true) .allowMultipleLogins(false) .passwordNeverExpires(false) .unlimitedAccessHours(true) .changePasswordOnNextLogin(false) .tenantId("TENANT_ABC") .createEntityDate(LocalDateTime.now()) .createdByUser("SYSTEM") .build(); userRepository.save(user); // === PASSO 4: Atribuir Permissões ao Usuário === // Permissões conectam usuários a ações específicas em recursos // Permissão VIEW - Escopo: toda a empresa COMPANY_BR // Esta permissão permite visualizar usuários em todos os projetos da empresa PermissionEntity viewPermission = PermissionEntity.builder() .id(UUID.randomUUID().toString()) .code("PERM_VIEW_USER_BR") .security(user) .action(viewAction) .tenantId("TENANT_ABC") .companyId("COMPANY_BR") .projectId(null) // null = Todos os projetos da empresa .createEntityDate(LocalDateTime.now()) .createdByUser("SYSTEM") .build(); permissionRepository.save(viewPermission); // Permissão CREATE - Escopo: projeto específico PROJECT_001 // Esta permissão permite criar usuários apenas no projeto 001 PermissionEntity createPermission = PermissionEntity.builder() .id(UUID.randomUUID().toString()) .code("PERM_CREATE_USER_PROJ1") .security(user) .action(createAction) .tenantId("TENANT_ABC") .companyId("COMPANY_BR") .projectId("PROJECT_001") // Restrito ao projeto 001 .createEntityDate(LocalDateTime.now()) .createdByUser("SYSTEM") .build(); permissionRepository.save(createPermission); // Permissão UPDATE - Escopo: projeto específico PROJECT_001 PermissionEntity updatePermission = PermissionEntity.builder() .id(UUID.randomUUID().toString()) .code("PERM_UPDATE_USER_PROJ1") .security(user) .action(updateAction) .tenantId("TENANT_ABC") .companyId("COMPANY_BR") .projectId("PROJECT_001") .createEntityDate(LocalDateTime.now()) .createdByUser("SYSTEM") .build(); permissionRepository.save(updatePermission); System.out.println("✓ Usuário criado com sucesso!"); System.out.println(" - Username: john.doe"); System.out.println(" - Email: john.doe@example.com"); System.out.println(" - Pode VISUALIZAR usuários em toda empresa COMPANY_BR"); System.out.println(" - Pode CRIAR usuários apenas no PROJECT_001"); System.out.println(" - Pode ATUALIZAR usuários apenas no PROJECT_001"); return user.getId(); ``` -------------------------------- ### Hybrid Authentication Flow Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/keycloak/research/archbase-comparison.md Step-by-step process for user authentication in a hybrid Archbase and Keycloak setup, detailing redirection, JWT issuance, and claim processing. ```text 1. Usuário acessa Aplicação 2. Aplicação redireciona para Keycloak (login) 3. Keycloak autentica e emite JWT 4. Aplicação recebe JWT e valida assinatura 5. Archbase extrai claims do JWT e: - Cria contexto de segurança local - Mapeia roles do Keycloak para Groups/Profiles - Aplica multi-tenancy se aplicável - Valida permissões contextuais ``` -------------------------------- ### Controller with Explicit Contexts Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/guides/code-examples.md Demonstrates how to define controllers with specific permission contexts for endpoints. Useful when endpoints require permissions in fixed contexts independent of the authenticated user. ```java package com.example.api.controller; import br.com.archbase.security.annotation.HasPermission; import com.example.api.dto.ProjectDto; import com.example.api.service.ProjectService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; /** * Controller com contextos explícitos em alguns endpoints. * * Útil quando endpoints específicos requerem permissões em * contextos fixos independente do usuário autenticado. */ @RestController @RequestMapping("/api/v1/projects") public class ProjectController { @Autowired private ProjectService projectService; /** * Lista projetos globais (sem restrição de company). * * Contexto: Apenas tenant é verificado, company e project são ignorados */ @GetMapping("/global") @HasPermission( action = "VIEW", resource = "PROJECT", description = "View global projects across all companies" // companyId e projectId omitidos = contexto global no tenant ) public ResponseEntity> listGlobalProjects() { List projects = projectService.findGlobalProjects(); return ResponseEntity.ok(projects); } /** * Lista projetos de uma empresa específica. * * Contexto: Empresa BR fixa */ @GetMapping("/company-br") @HasPermission( action = "VIEW", resource = "PROJECT", description = "View projects in company BR only", companyId = "COMPANY_BR" // Contexto fixo ) public ResponseEntity> listCompanyBRProjects() { List projects = projectService.findByCompany("COMPANY_BR"); return ResponseEntity.ok(projects); } /** * Operação administrativa - requer permissão em contexto de admin. * * Contexto: Tenant ADMIN, Company ADMIN */ @PostMapping("/admin/maintenance") @HasPermission( action = "EXECUTE", resource = "ADMIN_OPERATIONS", description = "Execute administrative maintenance", tenantId = "ADMIN_TENANT", companyId = "ADMIN_COMPANY" ) public ResponseEntity executeMaintenanceTask() { projectService.runMaintenanceTask(); return ResponseEntity.ok().build(); } } ``` -------------------------------- ### Create API Token Entity Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/architecture/authentication-system.md Example of creating an API Token entity with a long expiration date and setting it to be activated. This token is intended for service-to-service integrations. ```java ApiTokenEntity apiToken = ApiTokenEntity.builder() .id(UUID.randomUUID().toString()) .name("Integração Sistema Externo") .description("Token para integração com sistema de pagamento") .user(user) // Usuário associado (herda permissões) .token(generateSecureToken()) // Token único e aleatório .activated(true) // Deve ser explicitamente ativado .revoked(false) .expirationDate(LocalDateTime.now().plusYears(1)) // Longa duração .build(); apiTokenRepository.save(apiToken); ``` -------------------------------- ### Custom Error Handling for Field Equality Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-validation/documentation/5-builder-methods.md Example of using handlerInvalidField to create custom errors when two fields are not equal. This applies when the fields are not null or empty. ```java ruleFor(entity -> entity) .must(stringEquals(Entity::getField1, Entity::getField2)) .when(not(stringEmptyOrNull(Entity::getField1)).and(not(stringEmptyOrNull(Entity::getField2)))) .handlerInvalidField(new HandlerInvalidField() { @Override public Collection handle(final Entity instance) { final Erro field1 = Error.create("field1", "field1 must be equal field2", "404", instance.getField1()); final Erro field2 = Error.create("field2", "field2 must be equal field1", "404", instance.getField2()); return Arrays.asList(field1, field2); } }); ``` -------------------------------- ### Archbase Authentication Flow Diagram Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/readme-security.md Illustrates the step-by-step process of authentication within the Archbase framework, from client login to the final enriched response. ```text 1. Cliente faz login com contexto ↓ 2. ArchbaseAuthenticationController recebe request ↓ 3. AuthenticationBusinessDelegate.preAuthenticate() (se existir) ↓ 4. ArchbaseAuthenticationService.authenticate() ↓ 5. AuthenticationBusinessDelegate.postAuthenticate() (se existir) ↓ 6. AuthenticationResponseEnricher.enrich() (todos os enrichers) ↓ 7. AuthenticationBusinessDelegate.enrichAuthenticationResponse() (se existir) ↓ 8. Retorna resposta enriquecida ao cliente ``` -------------------------------- ### Set Environment Variables for Secrets Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/guides/code-examples.md Demonstrates how to set environment variables for sensitive information like JWT secrets and allowed CORS origins in a production environment. Also shows how to enable HTTPS. ```bash # Use variáveis de ambiente em produção export JWT_SECRET="your-very-long-and-secure-secret-key-minimum-256-bits" export CORS_ORIGINS="https://app.example.com,https://admin.example.com" export REQUIRE_HTTPS=true # Ou use AWS Secrets Manager, Azure Key Vault, etc. ``` -------------------------------- ### Archbase Multi-Tenancy to Keycloak Client/Attribute Mapping Scenario Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/keycloak/research/archbase-comparison.md Compares Archbase's permission entity for multi-tenancy with Keycloak's options using clients or custom user attributes. ```text Archbase: PermissionEntity: (tenant-123, company-456) Action: VIEW, Resource: REPORT Keycloak: // Não existe equivalente direto // Opção 1: Client por tenant/company Client: tenant-123-company-456 Client Roles: [view_report] // Opção 2: Atributos customizados User Attribute: tenant = "tenant-123" User Attribute: company = "company-456" Role: view_report // Validação no nível da aplicação ``` -------------------------------- ### Busca de Usuário Após Autenticação Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/architecture/authentication-system.md Código que busca o objeto completo do usuário no repositório após a autenticação bem-sucedida das credenciais, garantindo que o usuário exista. ```java var user = repository.findByEmail(request.getEmail()) .orElseThrow(() -> new ArchbaseValidationException("Usuário não encontrado")); ``` -------------------------------- ### External API Client with API Token Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/guides/code-examples.md A Java client using RestTemplate to make GET and POST requests to an external API, including API token authentication. ```java package com.example.integration.client; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.*; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; /** * Cliente para chamar API externa usando API Token. * * Exemplo de uso de API Token para integração service-to-service. */ @Component public class ExternalApiClient { @Value("${external.api.base-url}") private String baseUrl; @Value("${external.api.token}") private String apiToken; private final RestTemplate restTemplate; public ExternalApiClient() { this.restTemplate = new RestTemplate(); } /** * Exemplo de chamada GET com API Token. */ public String getData(String endpoint) { HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", "ApiToken " + apiToken); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity entity = new HttpEntity<>(headers); ResponseEntity response = restTemplate.exchange( baseUrl + endpoint, HttpMethod.GET, entity, String.class ); return response.getBody(); } /** * Exemplo de chamada POST com API Token. */ public T postData(String endpoint, Object requestBody, Class responseType) { HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", "ApiToken " + apiToken); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity entity = new HttpEntity<>(requestBody, headers); ResponseEntity response = restTemplate.exchange( baseUrl + endpoint, HttpMethod.POST, entity, responseType ); return response.getBody(); } } ``` -------------------------------- ### Extract JWT from Authorization Header Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/architecture/authentication-system.md Extracts the JWT from the 'Authorization' header, expecting the 'Bearer ' format. This code snippet assumes the header is already validated to start with 'Bearer '. ```java final String jwt = authHeader.substring(7); // Remove "Bearer " final String userEmail = jwtService.extractUsername(jwt); ``` -------------------------------- ### GroupEntity Creation and Permission Assignment Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/entities/core-entities.md Demonstrates how to create a GroupEntity and assign a PermissionEntity to it. Users belonging to this group will automatically inherit the assigned permission. ```java // Criar grupo GroupEntity salesTeam = GroupEntity.builder() .code("SALES_TEAM") .name("Equipe de Vendas") .description("Todos os vendedores da empresa") .build(); // Atribuir permissão ao grupo PermissionEntity permission = PermissionEntity.builder() .security(salesTeam) .action(viewCustomersAction) .build(); // Todos os usuários do grupo herdam a permissão automaticamente ``` -------------------------------- ### Iniciar Autenticação Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/keycloak/research/entities-guide.md Initiates the authentication process by redirecting the user to Keycloak's authorization endpoint. This step requests an authorization code. ```APIDOC ## GET /realms/minha-aplicacao/protocol/openid-connect/auth ### Description Initiates the authentication process by requesting an authorization code from Keycloak. ### Method GET ### Endpoint /realms/minha-aplicacao/protocol/openid-connect/auth ### Parameters #### Query Parameters - **response_type** (code) - Required - Requests an authorization code. - **client_id** (string) - Required - The identifier of the application. - **redirect_uri** (string) - Required - The URI where Keycloak will redirect the user after authentication. - **scope** (string) - Optional - Specifies the information to request (e.g., openid, email, profile). - **state** (string) - Optional - A value to protect against CSRF attacks. ``` -------------------------------- ### Create User Source: https://github.com/edsonmartins/archbase-app-framework/blob/main/archbase-security/docs/guides/code-examples.md Creates a new user with the provided details. Requires CREATE permission on USER_MANAGEMENT. ```APIDOC ## POST /api/v1/users ### Description Creates a new user. ### Method POST ### Endpoint /api/v1/users ### Parameters #### Request Body - **username** (string) - Required - User's username - **email** (string) - Required - User's email address - **password** (string) - Required - User's password ### Request Example { "username": "newuser", "email": "newuser@example.com", "password": "securepassword" } ### Response #### Success Response (201) - **id** (string) - User ID - **username** (string) - User's username - **email** (string) - User's email address #### Response Example { "id": "2", "username": "newuser", "email": "newuser@example.com" } ```