Base de données & ORM

La hiérarchie des entités, le patron BaseService, les migrations, et les données de départ.

Sur cette page

Base de données & ORM

Hiérarchie des entités

Chaque entité étend BaseEntity (@mappedsuperclass, elle-même étendant cborm.models.ActiveEntity), qui ajoute automatiquement createdDate, modifiedDate, et un drapeau de suppression douce isActive à chaque table :

classDiagram
    class BaseEntity {
        +createdDate
        +modifiedDate
        +isActive
        +getId()
        +isLoaded()
        +appendToMemento()
    }
    class User
    class Role
    class Permission
    class APIToken
    class RememberToken
    class Passkey
    class Setting

    BaseEntity <|-- User
    BaseEntity <|-- Role
    BaseEntity <|-- Permission
    BaseEntity <|-- APIToken
    BaseEntity <|-- RememberToken
    BaseEntity <|-- Passkey
    BaseEntity <|-- Setting

    User "many" --> "many" Role : roles
    User "many" --> "many" Permission : à la carte
    User "1" --> "many" APIToken
    User "1" --> "many" RememberToken
    User "1" --> "many" Passkey
    Role "many" --> "many" Permission : role_permissions

dbcreate: "none" (défini dans le ormSettings de public/Application.bx) signifie que le schéma appartient exclusivement aux migrations — l'ORM ne génère ni ne modifie jamais automatiquement les tables.

Patron de la couche service

Chaque service étend BaseService (@singleton, étend cborm.models.VirtualEntityService), qui injecte qb, coldbox, wirebox, et cachebox:template, et fournit ensureSortOrder() :

component
    extends="BaseService"
    singleton
    threadSafe
{

    property name="qb"    inject="provider:QueryBuilder@qb";
    property name="cache" inject="cachebox:template";

    function list( struct criteria = {} ){
        return newCriteria()
            .when( criteria.search, function( c, term ){
                c.like( "name", "%#term#%" );
            } )
            .list();
    }

}
/**
 * A role: a named bundle of permissions.
 */
class extends="app.models.BaseEntity" table="roles" {

    property name="roleId" fieldtype="id" generator="uuid2" ormtype="string";
    property name="name" type="string";

    property name="permissions"
        fieldtype="many-to-many"
        cfc="Permission"
        linktable="role_permissions";

}
component extends="app.models.BaseService" singleton threadSafe {

    function getAllForLookup(){
        return newCriteria().resultTransformer( "distinct" ).list();
    }

}

Migrations

Propulsées par cfmigrations via le module CLI commandbox-migrations, configuré dans .cbmigrations.json (migrationsDirectory: resources/database/migrations/, seedsDirectory: resources/database/seeds/, connexion construite à partir des mêmes variables d'environnement DB_* que public/Application.bx).

box migrate up           # Run pending migrations
box migrate down         # Rollback the last batch
box migrate reset        # Rollback everything, then re-migrate
box migrate seed run     # Run database seeders

Les migrations s'exécutent dans l'ordre du nom de fichier/horodatage :

MigrationCrée
..._settings.bxsettings (PK GUID, name unique, value en longtext)
..._security.bxpermissions, roles, role_permissions (table de jonction à clé primaire composite, FK en cascade)
..._users.bxusers (PK GUID, email unique, pendingEmail nullable pour les demandes de changement d'email en libre-service, password nullable, preferences en JSON, booléen hasAvatar indiquant si un utilisateur a un avatar téléversé sur le disque cbfs assets), ainsi que user_roles, user_permissions, user_remember_tokens, user_api_tokens, user_action_tokens, user_passkeys, user_sso_identities — chaque table enfant liée par FK à users.userId avec ON DELETE CASCADE (voir Sécurité & Permissions et Frontend)
..._auditlogs.bxaudit_logs, des enregistrements d'activité en ajout seul avec sévérité/catégorie/action, métadonnées de l'acteur et de la requête, et index de requête

Données de départ

resources/database/seeds/AdminData.bx, exécuté via box migrate seed run, crée :

  • Un rôle Admin
  • 20 permissions réparties sur cinq ressources (users, roles, permissions, settings, auditlog), chacune avec read/write/delete/admin (auditlog utilise read/export/delete/admin) — toutes assignées au rôle Admin
  • Un utilisateur administrateur, admin@cbgenesis.com, assigné au rôle Admin, semé en attente de réinitialisation afin que le mot de passe public de démarrage doive être remplacé dès la première connexion

Voir Sécurité & Permissions pour savoir comment ces slugs sont imposés au niveau du handler.

Modifier cette page Télécharger le Markdown Dernière mise à jour Oct 1, 2026, 11:06:51 AM