Skip to main content

Overview

sgivu-user manages users, roles, and permissions in the SGIVU ecosystem. It provides CRUD operations for users and persons, role and permission management, multi-criteria search, and support endpoints for the Authorization Server (username lookup for JWT issuance).

Technologies

  • Java: 21
  • Spring Boot: 4.0.1
  • Spring Security: Resource Server (JWT validation)
  • Spring Data JPA: PostgreSQL persistence
  • Flyway: Database migrations
  • Spring Cloud Config Client: Centralized configuration
  • Spring Cloud Eureka Client: Service registration
  • SpringDoc OpenAPI: Swagger UI documentation
  • MapStruct: DTO mapping
  • Lombok: Code generation

Prerequisites

  • JDK 21
  • Maven 3.9+
  • PostgreSQL database
  • sgivu-config and sgivu-discovery services running

Running the Service

Development with Docker Compose

cd infra/compose/sgivu-docker-compose
docker compose -f docker-compose.dev.yml up -d

Local Execution

./mvnw clean install -DskipTests
./mvnw spring-boot:run

Docker Build

./build-image.bash
docker build -t sgivu-user:local .

Security

Authentication

JWT Token Validation:
  • Tokens issued by sgivu-auth Authorization Server
  • Validation using NimbusJwtDecoder pointing to issuer
  • Resource Server configuration validates signature via JWKS endpoint

Authorization

Claims-Based Authorization:
  • rolesAndPermissions claim used for granular authorization
  • Required permissions per endpoint:
    • user:create - Create users
    • user:read - View users
    • user:update - Update users
    • user:delete - Delete users
    • person:create, person:read, person:update, person:delete - Person operations

Internal Service Authentication

X-Internal-Service-Key Header:
  • Allows sgivu-auth to query users by username during token issuance
  • Used for service-to-service authentication
  • Critical: Do not expose this key externally
The X-Internal-Service-Key header bypasses normal authentication. Ensure this key is:
  • Stored securely (environment variable or secret manager)
  • Only known to authorized services
  • Rotated regularly
  • Never logged or exposed in error messages

Custom Validators

PasswordStrength Validator:
  • Minimum length requirements
  • Complexity rules (uppercase, lowercase, numbers, special characters)
  • Applied on user creation and password updates
NoSpecialCharacters Validator:
  • Prevents special characters in specific fields
  • Applied to usernames and other text fields
  • Configurable character whitelist

Database Schema

Flyway Migrations

Location: src/main/resources/db/migration V1__initial_schema.sql creates:
  • permissions: System permissions catalog
  • roles: User roles
  • persons: Personal information
  • users: User accounts
Indexes:
  • users.username (unique)
  • persons.document_number (unique)
  • permissions.name (unique)
  • roles.name (unique)

Seed Data

Location: src/main/resources/db/seed/R__seed_data.sql Creates:
  • Admin user: steven with ADMIN role
  • Complete permissions catalog
  • Default roles (ADMIN, USER, etc.)
  • Sample person and address data
Repeatable migration (R__) runs on every startup if checksum changes. Use for reference data that may need updates.

API Endpoints

User Management

GET /v1/users
protected
List all users with paginationRequired Permission: user:readQuery Parameters:
  • page: Page number (default: 0)
  • size: Page size (default: 20)
  • sort: Sort field and direction
GET /v1/users/{id}
protected
Get user by IDRequired Permission: user:read
POST /v1/users
protected
Create new userRequired Permission: user:createValidations:
  • Unique username
  • Password strength requirements
  • Valid role assignments
PUT /v1/users/{id}
protected
Update existing userRequired Permission: user:update
DELETE /v1/users/{id}
protected
Delete user (soft delete)Required Permission: user:delete

Person Management

GET /v1/persons
protected
List persons with advanced searchRequired Permission: person:readSupports:
  • Multi-criteria filtering
  • Sorting and pagination
  • Search by document number, name, etc.
GET /v1/persons/{id}
protected
Get person by ID including addressesRequired Permission: person:read
POST /v1/persons
protected
Create person with optional addressesRequired Permission: person:create
PUT /v1/persons/{id}
protected
Update person informationRequired Permission: person:update
DELETE /v1/persons/{id}
protected
Delete personRequired Permission: person:delete

Internal Endpoints

GET /internal/users/by-username/{username}
internal
Query user by username for token issuanceAuthentication: Requires X-Internal-Service-Key headerUsed By: sgivu-auth during login flowReturns: User details with roles and permissions
Internal endpoints should not be exposed through the API Gateway. Configure gateway to block /internal/* paths.

Request/Response Examples

Create User

POST /v1/users
Authorization: Bearer <jwt-token>
Content-Type: application/json

{
  "username": "jdoe",
  "password": "SecureP@ssw0rd!",
  "email": "[email protected]",
  "personId": 123,
  "roleIds": [1, 2],
  "enabled": true
}

Response

{
  "id": 456,
  "username": "jdoe",
  "email": "[email protected]",
  "enabled": true,
  "person": {
    "id": 123,
    "firstName": "John",
    "lastName": "Doe",
    "documentNumber": "12345678"
  },
  "roles": [
    {
      "id": 1,
      "name": "USER",
      "permissions": ["user:read", "person:read"]
    },
    {
      "id": 2,
      "name": "MANAGER",
      "permissions": ["vehicle:create", "vehicle:update"]
    }
  ],
  "createdAt": "2024-03-06T10:30:00Z",
  "updatedAt": "2024-03-06T10:30:00Z"
}

Observability

Actuator Endpoints

  • /actuator/health: Service health status
  • /actuator/info: Application metadata
  • Additional endpoints configurable per environment

OpenAPI Documentation

Swagger UI: /swagger-ui/index.html Configuration: OpenApiConfig defines server URLs for different environments
@Configuration
public class OpenApiConfig {
    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
            .info(new Info()
                .title("SGIVU User Service API")
                .version("1.0"))
            .addServersItem(new Server()
                .url("http://localhost:8080")
                .description("API Gateway"));
    }
}

Distributed Tracing

Configured via sgivu-config:
  • Zipkin endpoint for trace export
  • Trace IDs propagated via headers
  • Integration with Micrometer

Testing

./mvnw test
Test Coverage:
  • Unit tests for services and validators
  • Integration tests for repositories
  • Controller tests with MockMvc
  • Security tests for permission checks

Troubleshooting

Symptoms: API requests return unauthorized or forbiddenSolutions:
  • Verify Bearer token is present and valid
  • Check token contains required authorities in rolesAndPermissions claim
  • Ensure token issuer matches configured Authorization Server
  • Verify user has assigned roles with necessary permissions
  • Check token hasn’t expired
Symptoms: Auth service can’t query users during loginSolutions:
  • Verify X-Internal-Service-Key header is present
  • Check internal key matches between auth and user services
  • Ensure internal endpoints aren’t blocked by gateway
  • Review network connectivity between services
  • Check Eureka service discovery is working
Symptoms: Service fails to start with Flyway errorsSolutions:
  • Verify PostgreSQL connection parameters
  • Check database exists and user has proper permissions
  • Review Flyway migration history table
  • Ensure migration scripts have correct syntax
  • Check for conflicts in seed data (duplicate keys)
Symptoms: User creation rejected with password errorsSolutions:
  • Review password strength requirements
  • Ensure password meets minimum length
  • Include required character types (uppercase, lowercase, numbers, special)
  • Check custom validator configuration
Symptoms: Constraint violation errors on creationSolutions:
  • Check uniqueness before creation
  • Handle duplicate key exceptions gracefully
  • Return clear error messages to clients
  • Consider soft delete for deactivated users

Environment Variables

VariableDescriptionExample
DB_HOSTPostgreSQL hostsgivu-postgres-user
DB_PORTPostgreSQL port5432
DB_NAMEDatabase namesgivu_user
DB_USERNAMEDatabase usernamesgivu_user
DB_PASSWORDDatabase passwordsecure_password
SERVICE_INTERNAL_SECRET_KEYInternal service keysecret-key-value
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URIAuth server issuerhttp://sgivu-auth:9000

Best Practices

Permission Model

Use fine-grained permissions for flexible access control

Password Policy

Enforce strong password requirements with custom validators

Audit Trail

Track createdAt/updatedAt for all entities

Soft Delete

Consider soft deletes to maintain data integrity

Auth Server

Queries user service for credential validation

Gateway

Routes user management API requests

Client Service

Similar entity management patterns

Build docs developers (and LLMs) love