Skip to main content

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​

DriverFilePurpose
MongoDriverDAO/Mongoose/MongoContext.tsPrimary MongoDB driver via Mongoose. Default for all deployments
PostgresDriverDAO/Postgres/PostgresContext.tsAlternative 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 after bufferTimeoutMS (set to 5 s in Open(); mongoose default would be 10 s). A ... buffering timed out error is therefore a never-connected-since-boot signature — mongoose disables buffering permanently after the first successful connect, and a later outage instead surfaces driver-level MongoServerSelectionError after ~5 s plus a MongoDB 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 returns false.
  • Recovery after an established connection drops is left entirely to the mongodb driver topology; the error event handler only logs (mongoose 9 Connection.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​

ModelCollectionPurpose
UserusersUser accounts — username, email, password (hashed), groups, auth tokens, 2FA secret, profile image, SSO tokens, audit log, ColorScheme (see Extending Hub GUI)
AuthTokenauthtokensStandalone auth tokens — name, token hash, creation date, expiry. Used for agent registration and API access
GroupgroupsPermission groups — name, description, authorized methods list, system flag. Groups define what @Extern methods users can call
OrganizationorganizationsCompany/organization structure — name, profile, image, member users, hierarchy
AuthEntryauthentriesAuth provider configurations (OAuth2, LDAP, CAS, etc.)
SSOTokensssotokensSingle sign-on token storage for OAuth2 providers
TokenPayloadtokenpayloadsJWT payload structure for token encoding/decoding
UserAuditLoguserauditlogsPer-user activity tracking — action, timestamp, IP, details

Content & Storage​

ModelCollectionPurpose
FileEntryfileentriesFile metadata — storage type (DATABASE, FILESYSTEM, STANDALONE), owner, size, MIME type, path. Binary data stored separately in DataBlob or filesystem
DataBlobdatablobsBinary data storage for large objects. Referenced by FileEntry when StorageType is DATABASE
ConfigEntryconfigentriesConfiguration storage — key-value pairs with optional file attachments. Used by ConfigurationsManager
BuildPackagebuildpackagesSoftware build/deployment artifact metadata

Communication​

ModelCollectionPurpose
EmailRecordemailrecordsOutgoing email queue — recipient, type, URL, environment data, active flag. Processed by MailEngine loop
WebhookRecordwebhookrecordsWebhook delivery queue — adapter type, owner ID, code, active flag, deleted flag. Processed by WebhooksManager loop
SendmailsendmailsEmail template configuration and static content

System​

ModelCollectionPurpose
LogEntrylogentriesSystem audit logs — message, trace back, user, tags, timestamps. Managed by SystemLog, auto-cleaned by maxAge config
AppSettingsappsettingsGlobal 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.

ConverterPurpose
AuthTokenToRefConverterConverts AuthToken to reference (id, name, expiry)
FileEntryToRefConverterConverts FileEntry to reference (id, size, type, path)
GroupToRefConverterConverts Group to reference (id, name)
GroupListToRefConverterConverts 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:

  1. Calls onDbUpgrade($oldVersion) with the old version string
  2. Uses StringUtils.VersionIsLower() to determine which migrations to run
  3. Migrations run sequentially — each handles a specific version boundary
  4. Returns true on success; false causes 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);
}
warning

Always call super.onDbUpgrade() to ensure Hub's base migrations also run.


See also: Models Overview | GraphQL API | Hub Configuration