diff --git a/backend/common/archive.js b/backend/common/archive.js new file mode 100644 index 0000000..960d9e6 --- /dev/null +++ b/backend/common/archive.js @@ -0,0 +1,53 @@ +import axios from "axios"; +import { getPool } from "../db/index.js"; + +export async function getArchiveServers(config) { + if (!config.archiveList || config.archiveList == "false") { + return; + } + + const client = await getPool(); + try { + const settingsResult = await client.query(` + SELECT id FROM system.settings LIMIT 1 + `); + if (settingsResult.rows.length === 0) { + return; + } + const sessionId = settingsResult.rows[0].id; + + const result = await client.query(` + SELECT + (SELECT COUNT(*)::int FROM public.agreement) AS agreement, + (SELECT COUNT(*)::int FROM public.audit) AS audit, + (SELECT COUNT(*)::int FROM public.entity) AS entity, + (SELECT COUNT(*)::int FROM public.event) AS event, + (SELECT COUNT(*)::int FROM public.usage) AS usage, + (SELECT COUNT(*)::int FROM public.user) AS user + `); + + if (!result.rows[0]) { + return; + } + + const payload = { + sessionId, + timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, + publicCoreUrl: config.publicCoreUrl, + tables: Object.entries(result.rows[0]).map(([tableName, recordCount]) => ({ tableName, recordCount })), + }; + + const proto = 'https' + const host = 'archive-list'; + const domain = 'jlinc'; + const tld = 'io'; + const res = await axios.post( + `${proto}://${host}.${domain}.${tld}/api/v1/archive`, + payload, + ); + + return res.data; + } finally { + client.release(); + } +} \ No newline at end of file diff --git a/backend/common/config.js b/backend/common/config.js index 29da4df..d06af14 100644 --- a/backend/common/config.js +++ b/backend/common/config.js @@ -2,6 +2,7 @@ const DEFAULT_KEY_CACHE = { ttlMs: 30 * 60 * 1000, max: 10_000 }; const config = { debug: false, + archiveList: true, dashboard: { core: {}, audit: {}, keyCache: { ...DEFAULT_KEY_CACHE } }, }; @@ -22,6 +23,7 @@ export async function loadConfig() { config.authModules[type] = getModuleConfig(); } } + if (process.env.ARCHIVE_LIST) config.archiveList = process.env.ARCHIVE_LIST; config.appModules = {}; let appModules = [ 'core', diff --git a/backend/db/migrations/000022 - system-identity.sql b/backend/db/migrations/000022 - system-identity.sql new file mode 100644 index 0000000..4be6c67 --- /dev/null +++ b/backend/db/migrations/000022 - system-identity.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS system.settings ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + created_ts TIMESTAMPTZ NOT NULL DEFAULT NOW() +); +INSERT INTO system.settings (id) +SELECT gen_random_uuid() +WHERE NOT EXISTS (SELECT 1 FROM system.settings); +CREATE INDEX idx__system__settings__id ON system.settings (id); diff --git a/backend/http/index.js b/backend/http/index.js index b011fa8..454a60a 100644 --- a/backend/http/index.js +++ b/backend/http/index.js @@ -4,8 +4,9 @@ import { loadPep } from "../modules/pep/index.js"; import swaggerUi from "swagger-ui-express"; import swaggerDocument from "./api/v1/swagger.json" with { type: "json" }; import { getConfig } from "../common/config.js"; -import { core } from "../modules/core/index.js" -import { getAgreements } from "../http/agreements.js" +import { core } from "../modules/core/index.js"; +import { getAgreements } from "../http/agreements.js"; +import { getArchiveServers } from "../common/archive.js"; import express from "express"; import session from "express-session"; @@ -66,6 +67,7 @@ async function renderPrivateUI(req, res, config) { export async function initHTTP(app) { const config = getConfig(); + const archiveServers = await getArchiveServers(config); passport.serializeUser(function (user, done) { done(null, user);