diff --git a/server.js b/server.js index e94c54a..7acfde4 100644 --- a/server.js +++ b/server.js @@ -11,10 +11,16 @@ const issuerUrl = process.env.KEYCLOAK_ISSUER; const clientId = process.env.KEYCLOAK_CLIENT_ID; const clientSecret = process.env.KEYCLOAK_CLIENT_SECRET; const databaseUrl = process.env.DATABASE_URL; -const tenantId = process.env.TENANT_ID || 'shared-demo-tenant'; +const tenantId = process.env.TENANT_ID || 'demo-tenant'; const tenantMode = process.env.TENANT_DB_MODE || 'unknown'; -for (const [key, value] of Object.entries({ APP_URL: appUrl, KEYCLOAK_ISSUER: issuerUrl, KEYCLOAK_CLIENT_ID: clientId, KEYCLOAK_CLIENT_SECRET: clientSecret, DATABASE_URL: databaseUrl })) { +for (const [key, value] of Object.entries({ + APP_URL: appUrl, + KEYCLOAK_ISSUER: issuerUrl, + KEYCLOAK_CLIENT_ID: clientId, + KEYCLOAK_CLIENT_SECRET: clientSecret, + DATABASE_URL: databaseUrl, +})) { if (!value) throw new Error(`${key} is required`); } @@ -27,16 +33,6 @@ async function waitForDatabase() { for (let attempt = 1; attempt <= 45; attempt++) { try { await pool.query('SELECT 1'); - await pool.query(` - CREATE TABLE IF NOT EXISTS shared_tenant_visits ( - id BIGSERIAL PRIMARY KEY, - tenant_id TEXT NOT NULL, - subject TEXT NOT NULL, - username TEXT, - visited_at TIMESTAMPTZ NOT NULL DEFAULT NOW() - ) - `); - await pool.query('CREATE INDEX IF NOT EXISTS idx_shared_tenant_visits_tenant ON shared_tenant_visits (tenant_id)'); return; } catch (error) { lastError = error; @@ -117,32 +113,24 @@ async function main() { const user = req.session.user; const username = user.preferred_username || user.email || user.name || user.sub; - await pool.query( - 'INSERT INTO shared_tenant_visits (tenant_id, subject, username) VALUES ($1, $2, $3)', - [tenantId, user.sub, username] - ); - - const tenantCount = await pool.query('SELECT COUNT(*)::bigint AS count FROM shared_tenant_visits WHERE tenant_id = $1', [tenantId]); - const totalCount = await pool.query('SELECT COUNT(*)::bigint AS count FROM shared_tenant_visits'); - const tenantTotal = await pool.query('SELECT COUNT(DISTINCT tenant_id)::bigint AS count FROM shared_tenant_visits'); - const lastWrite = await pool.query('SELECT visited_at FROM shared_tenant_visits WHERE tenant_id = $1 ORDER BY id DESC LIMIT 1', [tenantId]); + const db = await pool.query('SELECT current_database() AS database, current_user AS role, NOW() AS checked_at'); + const info = db.rows[0]; res.type('html').send(` -
Keycloak authenticated this request, then the app wrote a tenant-scoped row into Arrowstack's shared PostgreSQL database.
+Keycloak authenticated this request and the application connected to PostgreSQL using its restricted runtime role.
| User | ${escapeHtml(username)} |
| Tenant | ${escapeHtml(tenantId)} |
| DB mode | ${escapeHtml(tenantMode)} |
| This tenant visits | ${escapeHtml(tenantCount.rows[0].count)} |
| All shared rows | ${escapeHtml(totalCount.rows[0].count)} |
| Distinct tenants in table | ${escapeHtml(tenantTotal.rows[0].count)} |
| Last write | ${escapeHtml(lastWrite.rows[0]?.visited_at || '')} |
| Database | ${escapeHtml(info.database)} |
| Runtime role | ${escapeHtml(info.role)} |
| DB check | ${escapeHtml(info.checked_at)} |
| Keycloak client | ${escapeHtml(clientId)} |