import { tap, expect } from '@git.zone/tstest/tapbundle'; import { Alert } from '../ts/reception/classes.alert.js'; import { AlertManager } from '../ts/reception/classes.alertmanager.js'; import { AlertRule } from '../ts/reception/classes.alertrule.js'; import { PassportDevice } from '../ts/reception/classes.passportdevice.js'; import { Role } from '../ts/reception/classes.role.js'; import { User } from '../ts/reception/classes.user.js'; const getNestedValue = (targetArg: any, pathArg: string) => { return pathArg.split('.').reduce((currentArg, keyArg) => currentArg?.[keyArg], targetArg); }; const matchesQuery = (targetArg: any, queryArg: Record) => { return Object.entries(queryArg).every(([keyArg, valueArg]) => getNestedValue(targetArg, keyArg) === valueArg); }; const createTestAlertManager = () => { const alerts = new Map(); const alertRules = new Map(); const users = new Map(); const roles = new Map(); const passportDevices = new Map(); const deliveredHints: string[] = []; const manager = new AlertManager({ db: { smartdataDb: {} }, typedrouter: { addTypedRouter: () => undefined }, jwtManager: { verifyJWTAndGetData: async (jwtArg: string) => ({ data: { userId: jwtArg, }, }), }, userManager: { CUser: { getInstance: async (queryArg: Record) => { return Array.from(users.values()).find((docArg) => matchesQuery(docArg, queryArg)) || null; }, getInstances: async () => Array.from(users.values()), }, }, roleManager: { CRole: { getInstance: async (queryArg: Record) => { return Array.from(roles.values()).find((docArg) => matchesQuery(docArg, queryArg)) || null; }, }, getAllRolesForOrg: async (organizationIdArg: string) => Array.from(roles.values()).filter((roleArg) => roleArg.data.organizationId === organizationIdArg), }, passportManager: { authenticatePassportDeviceRequest: async (requestArg: { deviceId: string }) => { return passportDevices.get(requestArg.deviceId)!; }, getPassportDevicesForUser: async (userIdArg: string) => Array.from(passportDevices.values()).filter( (deviceArg) => deviceArg.data.userId === userIdArg && deviceArg.data.status === 'active' ), }, passportPushManager: { deliverAlertHint: async (_passportDeviceArg: PassportDevice, alertArg: Alert) => { deliveredHints.push(alertArg.data.notification.hintId); alertArg.data.notification = { ...alertArg.data.notification, status: 'sent', attemptCount: alertArg.data.notification.attemptCount + 1, deliveredAt: Date.now(), lastError: null, }; await alertArg.save(); return true; }, }, } as any); const originalAlertSave = Alert.prototype.save; const originalAlertDelete = Alert.prototype.delete; const originalAlertRuleSave = AlertRule.prototype.save; const originalAlertRuleDelete = AlertRule.prototype.delete; (Alert.prototype as Alert & { save: () => Promise }).save = async function () { alerts.set(this.id, this); }; (Alert.prototype as Alert & { delete: () => Promise }).delete = async function () { alerts.delete(this.id); }; (AlertRule.prototype as AlertRule & { save: () => Promise }).save = async function () { alertRules.set(this.id, this); }; (AlertRule.prototype as AlertRule & { delete: () => Promise }).delete = async function () { alertRules.delete(this.id); }; (manager as any).CAlert = { getInstance: async (queryArg: Record) => { return Array.from(alerts.values()).find((docArg) => matchesQuery(docArg, queryArg)) || null; }, getInstances: async (queryArg: Record) => { return Array.from(alerts.values()).filter((docArg) => matchesQuery(docArg, queryArg)); }, }; (manager as any).CAlertRule = { getInstance: async (queryArg: Record) => { return Array.from(alertRules.values()).find((docArg) => matchesQuery(docArg, queryArg)) || null; }, getInstances: async () => Array.from(alertRules.values()), }; return { manager, alerts, alertRules, users, roles, passportDevices, deliveredHints, restore: () => { Alert.prototype.save = originalAlertSave; Alert.prototype.delete = originalAlertDelete; AlertRule.prototype.save = originalAlertRuleSave; AlertRule.prototype.delete = originalAlertRuleDelete; }, }; }; const addUser = ( usersArg: Map, optionsArg: { id: string; email: string; isGlobalAdmin?: boolean } ) => { const user = new User(); user.id = optionsArg.id; user.data = { name: optionsArg.email, username: optionsArg.email, email: optionsArg.email, status: 'active', connectedOrgs: [], isGlobalAdmin: optionsArg.isGlobalAdmin, }; usersArg.set(user.id, user); return user; }; const addPassportDevice = ( passportDevicesArg: Map, optionsArg: { id: string; userId: string; label: string } ) => { const device = new PassportDevice(); device.id = optionsArg.id; device.data = { userId: optionsArg.userId, label: optionsArg.label, platform: 'ios', status: 'active', publicKeyAlgorithm: 'p256', publicKeyX963Base64: 'public-key', capabilities: { gps: true, nfc: true, push: true, }, pushRegistration: { provider: 'apns', token: `${optionsArg.id}-token`, topic: 'global.idp.swiftapp', environment: 'development', registeredAt: Date.now(), }, createdAt: Date.now(), lastSeenAt: Date.now(), }; passportDevicesArg.set(device.id, device); return device; }; tap.test('creates global admin access alerts with the built-in fallback rule', async () => { const { manager, users, passportDevices, alerts, deliveredHints, restore } = createTestAlertManager(); try { addUser(users, { id: 'admin-1', email: 'admin-1@example.com', isGlobalAdmin: true }); addPassportDevice(passportDevices, { id: 'device-1', userId: 'admin-1', label: 'Admin Phone' }); const createdAlerts = await manager.createAlertsForEvent({ category: 'admin', eventType: 'global_admin_access', severity: 'high', title: 'Global admin console accessed', body: 'A global admin accessed the console.', actorUserId: 'admin-1', relatedEntityType: 'global-admin-console', }); expect(createdAlerts).toHaveLength(1); expect(alerts.size).toEqual(1); expect(createdAlerts[0].data.notification.status).toEqual('sent'); expect(deliveredHints).toHaveLength(1); } finally { restore(); } }); tap.test('routes organization-scoped alerts to org admins by rule', async () => { const { manager, users, roles, passportDevices, restore } = createTestAlertManager(); try { addUser(users, { id: 'owner-1', email: 'owner@example.com' }); addUser(users, { id: 'viewer-1', email: 'viewer@example.com' }); addPassportDevice(passportDevices, { id: 'owner-device', userId: 'owner-1', label: 'Owner Phone' }); const ownerRole = new Role(); ownerRole.id = 'role-owner'; ownerRole.data = { userId: 'owner-1', organizationId: 'org-1', roles: ['owner'], }; roles.set(ownerRole.id, ownerRole); const viewerRole = new Role(); viewerRole.id = 'role-viewer'; viewerRole.data = { userId: 'viewer-1', organizationId: 'org-1', roles: ['viewer'], }; roles.set(viewerRole.id, viewerRole); const rule = new AlertRule(); rule.id = 'org-admin-rule'; rule.data = { scope: 'organization', organizationId: 'org-1', eventType: 'org_security_notice', minimumSeverity: 'medium', recipientMode: 'org_admins', recipientUserIds: [], push: true, enabled: true, createdByUserId: 'owner-1', createdAt: Date.now(), updatedAt: Date.now(), }; await rule.save(); const createdAlerts = await manager.createAlertsForEvent({ category: 'security', eventType: 'org_security_notice', severity: 'high', title: 'Organization security event', body: 'A sensitive organization event occurred.', actorUserId: 'viewer-1', organizationId: 'org-1', }); expect(createdAlerts).toHaveLength(1); expect(createdAlerts[0].data.recipientUserId).toEqual('owner-1'); } finally { restore(); } }); tap.test('lists alerts, resolves hint lookups, and marks alerts seen', async () => { const { manager, alerts, restore } = createTestAlertManager(); try { const alert = new Alert(); alert.id = 'alert-1'; alert.data = { recipientUserId: 'user-1', category: 'security', eventType: 'global_admin_access', severity: 'high', title: 'Important alert', body: 'Please inspect this alert.', notification: { hintId: 'hint-1', status: 'sent', attemptCount: 1, createdAt: Date.now(), deliveredAt: Date.now(), seenAt: null, lastError: null, }, createdAt: Date.now(), seenAt: null, dismissedAt: null, }; await alert.save(); const listedAlerts = await manager.listAlertsForUser('user-1'); expect(listedAlerts).toHaveLength(1); const hintAlert = await manager.getAlertByHint('user-1', 'hint-1'); expect(hintAlert?.id).toEqual('alert-1'); const seenAlert = await manager.markAlertSeen('user-1', 'hint-1'); expect(seenAlert.data.notification.status).toEqual('seen'); expect(seenAlert.data.seenAt).toBeGreaterThan(0); expect(alerts.get('alert-1')?.data.notification.status).toEqual('seen'); } finally { restore(); } }); export default tap.start();