Hub Database Models
Hub uses MongoDB as its primary database, with PostgreSQL as an alternative. The data layer provides 17 models covering authentication, content storage, communication, and system management.
Database Drivers
| Driver | File | Purpose |
|---|---|---|
MongoDriver | DAO/Mongoose/MongoContext.ts | Primary MongoDB driver via Mongoose. Default for all deployments |
PostgresDriver | DAO/Postgres/PostgresContext.ts | Alternative PostgreSQL driver for environments where MongoDB is unavailable |
The active driver is selected by the Loader's initDbDriver() method (defaults to MongoDriver). Connection parameters come from dbConfigs.dev or dbConfigs.prod depending on the environment mode. See Hub Configuration for details.
Connection lifecycle (MongoDriver)
The HTTP server starts listening before the DB connection is established — the Hub Loader launches MongoDriver.Open(config, true) as a fire-and-forget task, and the frontend is served an HTTP 503 until the environment state reaches LOADED. Facts that matter when diagnosing DB-related symptoms:
- All mongoose models are registered before
connect(), so operations issued before the initial connect completes are buffered by mongoose and rejected afterbufferTimeoutMS(set to 5 s inOpen(); mongoose default would be 10 s). A... buffering timed outerror is therefore a never-connected-since-boot signature — mongoose disables buffering permanently after the first successful connect, and a later outage instead surfaces driver-levelMongoServerSelectionErrorafter ~5 s plus aMongoDB disconnected, reconnecting...log line. - With
$autoReconnect = true(the Loader's mode) the initial connect retries every failure class (refused, DNS, auth, selection timeout) in a 5 s loop until it succeeds, so a DB that comes up late heals without a server restart. With$autoReconnect = false(unit tests /MongoTestRunner) a single attempt returnsfalse. - Recovery after an established connection drops is left entirely to the mongodb driver topology; the
errorevent handler only logs (mongoose 9Connection.close()is promise-only and no manual reconnect is attempted).
Authorization DB traffic and anonymous requests
Every REST/LCP request passes AuthManager.IsAuthorizedFor, which resolves grants from the in-memory FOR_ALL_USERS registrations extended by AppSettings.DefaultAccessibleMethods/DefaultGroupAccess. The AppSettings lists are cached in authCache (getAppSettingsAccessDefaults) instead of a per-request AppSettings.Find({}); the cache is dropped by resetAuthCache() and by SaveAppSettings/SyncAppSettings (AuthManager.InvalidateAuthCache). Requests without any session token are evaluated against public grants only, memoized under a reserved __anonymous__ cache key — an anonymous request to a public route (e.g. the Sentry tunnel /api/sentry) performs no DB round-trip after the first evaluation and keeps working during a DB outage via the in-memory defaults. Note the caches are process-local: in multi-instance deployments an AppSettings change is picked up by other instances only after their cache reset or restart.
Models Reference
All models are in DAO/Models/ and extend the commons BaseModel with @Entity and @Property decorators.
Authentication & Authorization
| Model | Collection | Purpose |
|---|---|---|
User | users | User accounts — username, email, password (hashed), groups, auth tokens, 2FA secret, profile image, SSO tokens, audit log, ColorScheme (see Extending Hub GUI) |
AuthToken | authtokens | Standalone auth tokens — name, token hash, creation date, expiry. Used for agent registration and API access |
Group | groups | Permission groups — name, description, authorized methods list, system flag. Groups define what @Extern methods users can call |
Organization | organizations | Company/organization structure — name, profile, image, member users, hierarchy |
AuthEntry | authentries | Auth provider configurations (OAuth2, LDAP, CAS, etc.) |
SSOTokens | ssotokens | Single sign-on token storage for OAuth2 providers |
TokenPayload | tokenpayloads | JWT payload structure for token encoding/decoding |
UserAuditLog | userauditlogs | Per-user activity tracking — action, timestamp, IP, details |
Content & Storage
| Model | Collection | Purpose |
|---|---|---|
FileEntry | fileentries | File metadata — storage type (DATABASE, FILESYSTEM, STANDALONE), owner, size, MIME type, path. Binary data stored separately in DataBlob or filesystem |
DataBlob | datablobs | Binary data storage for large objects. Referenced by FileEntry when StorageType is DATABASE |
ConfigEntry | configentries | Configuration storage — key-value pairs with optional file attachments. Used by ConfigurationsManager |
BuildPackage | buildpackages | Software build/deployment artifact metadata |
Communication
| Model | Collection | Purpose |
|---|---|---|
EmailRecord | emailrecords | Outgoing email queue — recipient, type, URL, environment data, active flag. Processed by MailEngine loop |
WebhookRecord | webhookrecords | Webhook delivery queue — adapter type, owner ID, code, active flag, deleted flag. Processed by WebhooksManager loop |
Sendmail | sendmails | Email template configuration and static content |
System
| Model | Collection | Purpose |
|---|---|---|
LogEntry | logentries | System audit logs — message, trace back, user, tags, timestamps. Managed by SystemLog, auto-cleaned by maxAge config |
AppSettings | appsettings | Global application settings — version, last modified, feature flags. Singleton per deployment, stored under the fixed _id EnvironmentHelper.APP_SETTINGS_ID ("appSettings") |
EnvironmentHelper.getAppSettings() never does a check-then-insert: the first access inserts the document under the fixed _id, so concurrent first accesses (several instances booting, the cron worker thread, requests served while the main thread still boots) end in one insert and the losers read the winner back on the duplicate-key error. Documents that earlier versions stored under a random id are folded into the singleton on first access: every field takes the value of the most recently modified document that does not hold the default, a conflict is settled by the last write and reported once to SystemLog (warning, so it reaches Sentry once) together with the discarded values, and the legacy documents are removed. Soft-deleted documents are left untouched.
Converters
Converters transform full model instances to lightweight references for API responses, reducing payload size and preventing circular references.
| Converter | Purpose |
|---|---|
AuthTokenToRefConverter | Converts AuthToken to reference (id, name, expiry) |
FileEntryToRefConverter | Converts FileEntry to reference (id, size, type, path) |
GroupToRefConverter | Converts Group to reference (id, name) |
GroupListToRefConverter | Converts array of Group to array of references |
Database Upgrade System
The Loader's onDbConnected() method checks if the stored AppSettings.Version matches the application version. When a version mismatch is detected:
- Calls
onDbUpgrade($oldVersion)with the old version string - Uses
StringUtils.VersionIsLower()to determine which migrations to run - Migrations run sequentially — each handles a specific version boundary
- Returns
trueon success;falsecauses application exit
Solution projects override onDbUpgrade() to add their own migrations:
protected async onDbUpgrade($oldVersion : string) : Promise<boolean> {
if (StringUtils.VersionIsLower($oldVersion, "2025.1.0")) {
// migration logic for version 2025.1.0
}
return await super.onDbUpgrade($oldVersion);
}
Always call super.onDbUpgrade() to ensure Hub's base migrations also run.
See also: Models Overview | GraphQL API | Hub Configuration