PrimebrickPrimebrick
  • Primebrick.dev
  • GitHub
  • Documentation
  • Services
  • Libraries
  • API Catalog
Resources
  • Landing Page
  • API Catalog
  • GitHub
PrimebrickPrimebrick

© 2026 Primebrick. MIT License.

github
Backend
    Audit SystemAuditable Joins and Display Name ResolutionAuditService and Delta CalculatorAuth Router: Login, Token Refresh, and User Management APIAuthentication and AuthorizationAuthentication Middleware and Token NormalizationCore ArchitectureCustomers API RouterCustomers Data Access LayerCustomers ModuleDatabase ManagementDocker Infrastructure and Casdoor SetupDomain Entity SystemExport LibraryGetting StartedGitFlow, Versioning, and CI HooksGlossaryInfrastructure and DevOpsMigration Patch Registry and ApplicationOpenAPI DocumentationOrganizations ModuleOverviewProject StructureRBAC Middleware and Permission SystemRepository and Query DSLSchema Snapshot and Diff SystemServer Bootstrap and Middleware PipelineUtility Scripts ReferenceREADME
Frontend
Microservices
powered by Zudoku
Backend

Organizations Module

Organizations Module

Relevant source files

The following files were used as context for generating this wiki page:

  • infra/init-db/01-create-casdoor-db.sql
  • src/modules/auth/config-repo.ts
  • src/modules/auth/config.ts
  • src/modules/auth/organization_entity.ts
  • src/modules/auth/organizations_dal.ts
  • src/modules/auth/organizations_router.ts

The Organizations Module manages the lifecycle of organizational entities within Primebrick, serving as a synchronized mirror of Casdoor organizations. It implements a Casdoor-first write strategy, ensuring that any changes to organizations are first committed to the Identity Provider (IDP) before being persisted in the local PostgreSQL database.

Architectural Overview

The module is built around the OrganizationEntity, which maps local UUIDs to Casdoor's idp_code (owner/name format). This decoupling allows the application to use immutable internal identifiers while maintaining compatibility with the external IDP.

Data Flow: Dual-Write Synchronization

When an organization is created or updated, the system performs a synchronous call to the Casdoor API. If the IDP operation fails, the local transaction is not committed (or the local write is not initiated), ensuring data consistency between Primebrick and Casdoor.

Organization Identity Mapping

FieldTypeRole
uuidstringInternal Primebrick identifier used for all foreign keys and API references src/modules/auth/organization_entity.ts:39-39.
idp_codestringCasdoor identifier (e.g., admin/acme). Immutable after creation src/modules/auth/organization_entity.ts:41-44.
idp_ownerstringThe owner prefix in Casdoor (usually the IDP organization name) src/modules/auth/organization_entity.ts:45-46.
idp_namestringThe specific organization name within the IDP src/modules/auth/organization_entity.ts:48-49.

Sources: src/modules/auth/organization_entity.ts:1-15, src/modules/auth/organizations_dal.ts:16-32


Code Entity Map: Router to DAL

The following diagram illustrates the relationship between the HTTP layer, the Data Access Layer (DAL), and the underlying Entity definitions.

Diagram: Organizations Module Component Mapping

Code
graph TD subgraph "HTTP Layer (organizations_router.ts)" R["organizationsRouter()"] M["GET /meta"] L["GET /list"] C["POST /create"] U["PUT /update/:uuid"] end subgraph "Data Access Layer (organizations_dal.ts)" DAL["OrganizationsDal"] DAL_L["listOrganizations()"] DAL_C["createOrganization()"] DAL_U["updateOrganization()"] DAL_GC["getUserCountForOrganization()"] end subgraph "Domain & Persistence" E["OrganizationEntity"] REPO["Repository (Generic)"] CAS["CasdoorApiClient"] end R --> DAL L --> DAL_L C --> DAL_C U --> DAL_U DAL_L --> REPO DAL_C --> CAS DAL_C --> REPO DAL_U --> CAS DAL_U --> REPO REPO -.-> E

Sources: src/modules/auth/organizations_router.ts:13-20, src/modules/auth/organizations_dal.ts:63-70


Data Access Layer (DAL)

The OrganizationsDal handles the complexity of joining audit trails and calculating aggregate data like user counts.

Key Methods

  • listOrganizations(query): Implements a complex pipeline using the Repository DSL. It filters by deletion status (EXCLUDED, ONLY, INCLUDED), performs ILIKE searches on display_name and idp_code, and executes a LEFT JOIN on UserProfileEntity to resolve audit user display names src/modules/auth/organizations_dal.ts:106-180.
  • getUserCountForOrganization(idpCode): Executes a direct count query against the user_profiles table to determine how many users belong to a specific organization src/modules/auth/organizations_dal.ts:254-263.
  • createOrganization(data): Generates a new uuid, assigns the current session actor to created_by, and persists the entity src/modules/auth/organizations_dal.ts:198-220.

Soft-Delete and Restore

The DAL implements soft-deletion by populating the deleted_at and deleted_by fields instead of removing the row.

  • Delete: repo.update sets the deletion timestamp and actor src/modules/auth/organizations_dal.ts:284-295.
  • Restore: Sets deleted_at and deleted_by to null src/modules/auth/organizations_dal.ts:303-314.

Sources: src/modules/auth/organizations_dal.ts:63-315


Casdoor Integration

The module uses CasdoorApiClient to synchronize changes. The client is initialized JIT (Just-In-Time) using credentials stored in the auth_configurations table src/modules/auth/organizations_router.ts:24-44.

Write Synchronization Logic:

  1. Validation: Request body is validated via Zod schemas in the router.
  2. IDP Write: The router calls getCasdoorClient() and invokes the IDP update/create.
  3. Local Write: If the IDP call succeeds, OrganizationsDal is called to update the PostgreSQL mirror.
  4. Audit: The Repository automatically calculates the delta and writes to the organizations_audit table.

Diagram: Create Organization Sequence

Code
sequenceDiagram participant Client participant Router as organizations_router participant IDP as CasdoorApiClient participant DAL as OrganizationsDal participant DB as PostgreSQL Client->>Router: POST /api/v1/entities/organization/create Router->>Router: validateBody(createSchema) Router->>IDP: addOrganization(data) Note over IDP: External API Call IDP-->>Router: Success Router->>DAL: createOrganization(data) DAL->>DB: INSERT INTO organizations DAL->>DB: INSERT INTO organizations_audit (delta) DB-->>DAL: OK DAL-->>Router: { uuid } Router-->>Client: 201 Created

Sources: src/modules/auth/organizations_router.ts:24-44, src/modules/auth/organizations_dal.ts:198-220, src/modules/auth/organization_entity.ts:32-34


Entity Configuration

The OrganizationEntity uses decorators to define its behavior within the Primebrick Domain System.

DecoratorPurpose
@Entity("organizations")Maps the class to the organizations table src/modules/auth/organization_entity.ts:32-32.
@AuditTrail()Enables automatic tracking of all changes in a shadow audit table src/modules/auth/organization_entity.ts:33-33.
@SynchronizableFieldMarks last_synced_at for tracking IDP synchronization state src/modules/auth/organization_entity.ts:57-59.
@AuditableFieldDefines standard fields like created_at, updated_by, and version for optimistic concurrency src/modules/auth/organization_entity.ts:62-75.
@DeletableFieldHooks into the soft-delete system src/modules/auth/organization_entity.ts:77-81.

Sources: src/modules/auth/organization_entity.ts:17-82


Last modified on July 13, 2026
OpenAPI DocumentationOverview
On this page
  • Architectural Overview
    • Data Flow: Dual-Write Synchronization
    • Organization Identity Mapping
  • Code Entity Map: Router to DAL
  • Data Access Layer (DAL)
    • Key Methods
    • Soft-Delete and Restore
  • Casdoor Integration
  • Entity Configuration