import { tap, expect } from '@git.zone/tstest/tapbundle'; import { TypedRequest } from '@api.global/typedrequest'; import { OpsServer } from '../ts/opsserver/index.js'; import { DcRouterDb } from '../ts/db/index.js'; import * as plugins from '../ts/plugins.js'; import * as interfaces from '../ts_interfaces/index.js'; const testPort = 3110; const baseUrl = `http://localhost:${testPort}/typedrequest`; const bootstrapPassword = 'temporary-bootstrap-password'; const persistedPassword = 'persisted-admin-password'; let previousAdminPassword: string | undefined; let opsServer: OpsServer; let testDb: DcRouterDb; let storagePath: string; let dbName: string; let bootstrapIdentity: interfaces.data.IIdentity; let persistedIdentity: interfaces.data.IIdentity; let createdUserId: string; const createStatusRequest = () => new TypedRequest( baseUrl, 'getAdminBootstrapStatus', ); const createLoginRequest = () => new TypedRequest( baseUrl, 'adminLoginWithUsernameAndPassword', ); const createFakeDcRouter = (portArg: number, dcRouterDbArg?: DcRouterDb) => ({ options: { opsServerPort: portArg, dbConfig: { enabled: true }, adminAuth: { idpClient: { loginWithEmailAndPassword: async () => ({ jwt: 'idp-jwt', refreshToken: 'idp-refresh-token', user: { id: 'idp-user-1', data: { name: 'Wrong IdP User', username: 'wrong@example.com', email: 'wrong@example.com', status: 'active', connectedOrgs: [], }, }, }), stop: async () => {}, }, }, }, typedrouter: new plugins.typedrequest.TypedRouter(), dcRouterDb: dcRouterDbArg, }); const restartOpsServer = async () => { await opsServer.stop(); opsServer = new OpsServer(createFakeDcRouter(testPort, testDb) as any); await opsServer.start(); }; tap.test('setup db-backed OpsServer admin bootstrap test', async () => { previousAdminPassword = process.env.DCROUTER_ADMIN_PASSWORD; process.env.DCROUTER_ADMIN_PASSWORD = bootstrapPassword; storagePath = plugins.path.join( plugins.os.tmpdir(), `dcrouter-admin-bootstrap-${Date.now()}-${Math.random().toString(16).slice(2)}`, ); DcRouterDb.resetInstance(); dbName = `dcrouter-admin-bootstrap-${Date.now()}-${Math.random().toString(16).slice(2)}`; testDb = DcRouterDb.getInstance({ storagePath, dbName, }); await testDb.start(); await testDb.getDb().mongoDb.createCollection('__test_init'); opsServer = new OpsServer(createFakeDcRouter(testPort, testDb) as any); await opsServer.start(); }); tap.test('reports bootstrap required without auto-persisting an admin', async () => { const status = await createStatusRequest().fire({}); expect(status.dbEnabled).toEqual(true); expect(status.dbReady).toEqual(true); expect(status.hasPersistentAdmin).toEqual(false); expect(status.needsBootstrap).toEqual(true); expect(status.ephemeralAdminAvailable).toEqual(true); expect(status.idpGlobalConfigured).toEqual(true); }); tap.test('allows temporary bootstrap admin login before persisted admin exists', async () => { const response = await createLoginRequest().fire({ username: 'admin', password: bootstrapPassword, }); if (!response.identity) { throw new Error('Expected bootstrap login identity'); } bootstrapIdentity = response.identity; expect(bootstrapIdentity.role).toEqual('admin'); }); tap.test('creates the initial persisted admin explicitly', async () => { const request = new TypedRequest( baseUrl, 'createInitialAdminUser', ); const response = await request.fire({ identity: bootstrapIdentity, email: 'Admin@Example.com', name: 'Persisted Admin', password: persistedPassword, enableIdpGlobalAuth: true, }); expect(response.success).toEqual(true); expect(response.user?.role).toEqual('admin'); expect(response.user?.authSources).toContain('local'); expect(response.user?.authSources).toContain('idp.global'); if (!response.identity) { throw new Error('Expected persisted admin identity'); } persistedIdentity = response.identity; }); tap.test('disables bootstrap mode after persisted admin exists', async () => { const status = await createStatusRequest().fire({}); expect(status.hasPersistentAdmin).toEqual(true); expect(status.needsBootstrap).toEqual(false); expect(status.ephemeralAdminAvailable).toEqual(false); }); tap.test('rejects the old temporary admin after persisted admin creation', async () => { let rejected = false; try { await createLoginRequest().fire({ username: 'admin', password: bootstrapPassword, }); } catch { rejected = true; } expect(rejected).toEqual(true); }); tap.test('rejects the old temporary admin identity after persisted admin creation', async () => { const request = new TypedRequest( baseUrl, 'verifyIdentity', ); const response = await request.fire({ identity: bootstrapIdentity }); expect(response.valid).toEqual(false); }); tap.test('authenticates the persisted admin locally by normalized email', async () => { const response = await createLoginRequest().fire({ username: 'admin@example.com', password: persistedPassword, authSource: 'local', }); if (!response.identity) { throw new Error('Expected persisted admin login identity'); } expect(response.identity.userId).toEqual(persistedIdentity.userId); }); tap.test('persists users across OpsServer restart', async () => { const oldPersistedIdentity = persistedIdentity; await restartOpsServer(); const verifyRequest = new TypedRequest( baseUrl, 'verifyIdentity', ); const verifyResponse = await verifyRequest.fire({ identity: oldPersistedIdentity }); expect(verifyResponse.valid).toEqual(false); const loginResponse = await createLoginRequest().fire({ username: 'admin@example.com', password: persistedPassword, authSource: 'local', }); if (!loginResponse.identity) { throw new Error('Expected persisted admin login identity after restart'); } expect(loginResponse.identity.userId).toEqual(oldPersistedIdentity.userId); persistedIdentity = loginResponse.identity; }); tap.test('rejects idp.global login when IdP email does not match local account', async () => { let rejected = false; try { await createLoginRequest().fire({ username: 'admin@example.com', password: 'idp-password', authSource: 'idp.global', }); } catch { rejected = true; } expect(rejected).toEqual(true); }); tap.test('creates a persisted non-admin user explicitly', async () => { const request = new TypedRequest(baseUrl, 'createUser'); const response = await request.fire({ identity: persistedIdentity, email: 'operator@example.com', name: 'Operator User', role: 'user', password: 'operator-password', }); expect(response.success).toEqual(true); expect(response.user?.role).toEqual('user'); expect(response.user?.email).toEqual('operator@example.com'); if (!response.user?.id) { throw new Error('Expected created user id'); } createdUserId = response.user.id; }); tap.test('rejects deleting the current persisted admin user', async () => { const request = new TypedRequest(baseUrl, 'deleteUser'); const response = await request.fire({ identity: persistedIdentity, id: persistedIdentity.userId, }); expect(response.success).toEqual(false); }); tap.test('deletes a persisted non-current user', async () => { const request = new TypedRequest(baseUrl, 'deleteUser'); const response = await request.fire({ identity: persistedIdentity, id: createdUserId, }); expect(response.success).toEqual(true); }); tap.test('lists persisted users without password material', async () => { const request = new TypedRequest(baseUrl, 'listUsers'); const response = await request.fire({ identity: persistedIdentity }); expect(response.users.length).toEqual(1); expect(response.users[0].email).toEqual('Admin@Example.com'); expect((response.users[0] as any).password).toBeUndefined(); }); tap.test('rejects temporary bootstrap admin when persisted-user database is unavailable', async () => { await testDb.stop(); const status = await createStatusRequest().fire({}); expect(status.dbEnabled).toEqual(true); expect(status.dbReady).toEqual(false); expect(status.needsBootstrap).toEqual(false); expect(status.ephemeralAdminAvailable).toEqual(false); let rejected = false; try { await createLoginRequest().fire({ username: 'admin', password: bootstrapPassword, }); } catch { rejected = true; } expect(rejected).toEqual(true); }); tap.test('cleanup db-backed OpsServer admin bootstrap test', async () => { await opsServer.stop(); await testDb.stop(); DcRouterDb.resetInstance(); await plugins.fs.promises.rm(storagePath, { recursive: true, force: true }); if (previousAdminPassword === undefined) { delete process.env.DCROUTER_ADMIN_PASSWORD; } else { process.env.DCROUTER_ADMIN_PASSWORD = previousAdminPassword; } }); tap.test('does not offer bootstrap while configured database is unavailable', async () => { const unavailablePort = 3111; const unavailableBaseUrl = `http://localhost:${unavailablePort}/typedrequest`; const previousUnavailableAdminPassword = process.env.DCROUTER_ADMIN_PASSWORD; process.env.DCROUTER_ADMIN_PASSWORD = 'unavailable-bootstrap-password'; DcRouterDb.resetInstance(); const unavailableOpsServer = new OpsServer(createFakeDcRouter(unavailablePort) as any); try { await unavailableOpsServer.start(); const status = await new TypedRequest( unavailableBaseUrl, 'getAdminBootstrapStatus', ).fire({}); expect(status.dbEnabled).toEqual(true); expect(status.dbReady).toEqual(false); expect(status.needsBootstrap).toEqual(false); expect(status.ephemeralAdminAvailable).toEqual(false); let rejected = false; try { await new TypedRequest( unavailableBaseUrl, 'adminLoginWithUsernameAndPassword', ).fire({ username: 'admin', password: 'unavailable-bootstrap-password', }); } catch { rejected = true; } expect(rejected).toEqual(true); } finally { await unavailableOpsServer.stop(); DcRouterDb.resetInstance(); if (previousUnavailableAdminPassword === undefined) { delete process.env.DCROUTER_ADMIN_PASSWORD; } else { process.env.DCROUTER_ADMIN_PASSWORD = previousUnavailableAdminPassword; } } }); export default tap.start();