feat: add audit log demo data and passkey/API stub overrides

This commit is contained in:
shuaiplus
2026-07-09 20:51:12 +08:00
parent 39d9df78ea
commit bb3f866220
+260
View File
@@ -9,6 +9,7 @@ import type {
import type { import type {
AdminInvite, AdminInvite,
AdminUser, AdminUser,
AuditLogEntry,
AuthorizedDevice, AuthorizedDevice,
Cipher, Cipher,
Folder, Folder,
@@ -712,6 +713,233 @@ export const DEMO_BACKUP_SETTINGS: AdminBackupSettings = {
], ],
}; };
export const DEMO_AUDIT_LOGS: AuditLogEntry[] = [
{
id: 'demo-log-auth-login',
actorUserId: DEMO_USER_ID,
actorEmail: DEMO_PROFILE.email,
action: 'auth.login.success',
category: 'auth',
level: 'info',
targetType: null,
targetId: null,
targetUserEmail: null,
metadata: JSON.stringify({ ip: '203.0.113.42', device: 'Chrome 125 on Windows', location: 'San Francisco, US' }),
createdAt: '2026-07-08T14:32:10.000Z',
object: 'auditLog',
},
{
id: 'demo-log-auth-failed',
actorUserId: null,
actorEmail: 'unknown@example.com',
action: 'auth.login.failed',
category: 'auth',
level: 'warn',
targetType: null,
targetId: null,
targetUserEmail: null,
metadata: JSON.stringify({ ip: '198.51.100.7', reason: 'invalid_password', attemptCount: 3 }),
createdAt: '2026-07-08T13:15:00.000Z',
object: 'auditLog',
},
{
id: 'demo-log-auth-2fa',
actorUserId: DEMO_USER_ID,
actorEmail: DEMO_PROFILE.email,
action: 'auth.totp.enabled',
category: 'auth',
level: 'security',
targetType: null,
targetId: null,
targetUserEmail: null,
metadata: JSON.stringify({ ip: '203.0.113.42', trigger: 'user_initiated' }),
createdAt: '2026-07-07T09:00:00.000Z',
object: 'auditLog',
},
{
id: 'demo-log-auth-refresh-failed',
actorUserId: DEMO_USER_ID,
actorEmail: DEMO_PROFILE.email,
action: 'auth.refresh.failed.token_expired',
category: 'auth',
level: 'error',
targetType: null,
targetId: 'demo-device-browser',
targetUserEmail: null,
metadata: JSON.stringify({ ip: '203.0.113.42', device: 'Chrome 125 on Windows' }),
createdAt: '2026-07-06T18:45:30.000Z',
object: 'auditLog',
},
{
id: 'demo-log-security-password',
actorUserId: DEMO_USER_ID,
actorEmail: DEMO_PROFILE.email,
action: 'user.password.changed',
category: 'security',
level: 'security',
targetType: 'user',
targetId: DEMO_USER_ID,
targetUserEmail: DEMO_PROFILE.email,
metadata: JSON.stringify({ ip: '203.0.113.42', trigger: 'user_initiated' }),
createdAt: '2026-07-05T10:00:00.000Z',
object: 'auditLog',
},
{
id: 'demo-log-security-user-banned',
actorUserId: DEMO_USER_ID,
actorEmail: DEMO_PROFILE.email,
action: 'admin.user.banned',
category: 'security',
level: 'security',
targetType: 'user',
targetId: 'demo-user-003',
targetUserEmail: 'suspended@example.com',
metadata: JSON.stringify({ ip: '203.0.113.42', reason: 'violation_of_tos' }),
createdAt: '2026-07-04T16:20:00.000Z',
object: 'auditLog',
},
{
id: 'demo-log-security-user-register',
actorUserId: null,
actorEmail: 'newuser@example.com',
action: 'user.register.completed',
category: 'security',
level: 'info',
targetType: 'user',
targetId: 'demo-user-004',
targetUserEmail: 'newuser@example.com',
metadata: JSON.stringify({ ip: '192.0.2.55', invite: 'DEMO-INVITE-2026' }),
createdAt: '2026-07-03T08:30:00.000Z',
object: 'auditLog',
},
{
id: 'demo-log-device-trusted',
actorUserId: DEMO_USER_ID,
actorEmail: DEMO_PROFILE.email,
action: 'device.trusted.added',
category: 'device',
level: 'info',
targetType: 'device',
targetId: 'demo-device-mobile',
targetUserEmail: null,
metadata: JSON.stringify({ deviceName: 'iPhone', os: 'iOS 18', ip: '203.0.113.42' }),
createdAt: '2026-07-02T12:15:00.000Z',
object: 'auditLog',
},
{
id: 'demo-log-device-removed',
actorUserId: DEMO_USER_ID,
actorEmail: DEMO_PROFILE.email,
action: 'device.removed',
category: 'device',
level: 'warn',
targetType: 'device',
targetId: 'demo-device-old',
targetUserEmail: null,
metadata: JSON.stringify({ deviceName: 'Firefox on Linux', ip: '198.51.100.20', trigger: 'user_initiated' }),
createdAt: '2026-07-01T09:45:00.000Z',
object: 'auditLog',
},
{
id: 'demo-log-device-all-revoked',
actorUserId: DEMO_USER_ID,
actorEmail: DEMO_PROFILE.email,
action: 'device.all_trust_revoked',
category: 'device',
level: 'security',
targetType: null,
targetId: null,
targetUserEmail: null,
metadata: JSON.stringify({ ip: '203.0.113.42', trigger: 'password_change' }),
createdAt: '2026-07-01T09:00:00.000Z',
object: 'auditLog',
},
{
id: 'demo-log-data-backup',
actorUserId: DEMO_USER_ID,
actorEmail: DEMO_PROFILE.email,
action: 'admin.backup.run.completed',
category: 'data',
level: 'info',
targetType: null,
targetId: null,
targetUserEmail: null,
metadata: JSON.stringify({ fileName: 'nodewarden_backup_20260701_030000.zip', size: '1.2 MB', destination: 'Demo WebDAV' }),
createdAt: '2026-07-01T03:00:00.000Z',
object: 'auditLog',
},
{
id: 'demo-log-data-restore',
actorUserId: DEMO_USER_ID,
actorEmail: DEMO_PROFILE.email,
action: 'admin.backup.restore.completed',
category: 'data',
level: 'warn',
targetType: null,
targetId: null,
targetUserEmail: null,
metadata: JSON.stringify({ fileName: 'nodewarden_backup_20260628_030000.zip', checksum: 'verified' }),
createdAt: '2026-06-30T14:00:00.000Z',
object: 'auditLog',
},
{
id: 'demo-log-data-export',
actorUserId: DEMO_USER_ID,
actorEmail: DEMO_PROFILE.email,
action: 'admin.export.completed',
category: 'data',
level: 'info',
targetType: null,
targetId: null,
targetUserEmail: null,
metadata: JSON.stringify({ format: 'encrypted_json', totalItems: 24 }),
createdAt: '2026-06-28T11:30:00.000Z',
object: 'auditLog',
},
{
id: 'demo-log-system-settings',
actorUserId: DEMO_USER_ID,
actorEmail: DEMO_PROFILE.email,
action: 'admin.settings.updated',
category: 'system',
level: 'info',
targetType: null,
targetId: null,
targetUserEmail: null,
metadata: JSON.stringify({ changedKeys: ['signupsAllowed', 'kdfIterations'], ip: '203.0.113.42' }),
createdAt: '2026-06-25T08:00:00.000Z',
object: 'auditLog',
},
{
id: 'demo-log-system-invite',
actorUserId: DEMO_USER_ID,
actorEmail: DEMO_PROFILE.email,
action: 'admin.invite.created',
category: 'system',
level: 'info',
targetType: 'invite',
targetId: 'DEMO-INVITE-2026',
targetUserEmail: null,
metadata: JSON.stringify({ expiresIn: '168h', ip: '203.0.113.42' }),
createdAt: '2026-06-20T10:00:00.000Z',
object: 'auditLog',
},
{
id: 'demo-log-system-config',
actorUserId: DEMO_USER_ID,
actorEmail: DEMO_PROFILE.email,
action: 'admin.config.updated',
category: 'system',
level: 'warn',
targetType: null,
targetId: null,
targetUserEmail: null,
metadata: JSON.stringify({ changedKeys: ['smtp.host', 'smtp.port'], ip: '203.0.113.42' }),
createdAt: '2026-06-18T15:30:00.000Z',
object: 'auditLog',
},
];
function cloneJson<T>(value: T): T { function cloneJson<T>(value: T): T {
return JSON.parse(JSON.stringify(value)) as T; return JSON.parse(JSON.stringify(value)) as T;
} }
@@ -1212,6 +1440,38 @@ export function createDemoMainRoutesProps(base: AppMainRoutesProps, notify: Noti
onGetRecoveryCode: readonlyString, onGetRecoveryCode: readonlyString,
onGetApiKey: readonlyString, onGetApiKey: readonlyString,
onRotateApiKey: readonlyString, onRotateApiKey: readonlyString,
onListAccountPasskeys: async () => [],
onCreateAccountPasskey: async () => {
await readonly();
return null;
},
onEnableAccountPasskeyDirectUnlock: readonly,
onDeleteAccountPasskey: readonly,
onLoadAuditLogs: async (filters) => {
const limit = Number(filters.limit || 50) || 50;
const offset = Number(filters.offset || 0) || 0;
let filtered = DEMO_AUDIT_LOGS.filter((log) => {
if (filters.category && filters.category !== 'all' && log.category !== filters.category) return false;
if (filters.level && filters.level !== 'all' && log.level !== filters.level) return false;
if (filters.q) {
const q = filters.q.toLowerCase();
if (!log.action.toLowerCase().includes(q) && !(log.actorEmail || '').toLowerCase().includes(q)) return false;
}
if (filters.from && new Date(log.createdAt).getTime() < new Date(filters.from).getTime()) return false;
if (filters.to && new Date(log.createdAt).getTime() > new Date(filters.to).getTime()) return false;
return true;
});
filtered.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
const total = filtered.length;
const sliced = filtered.slice(offset, offset + limit);
return {
logs: sliced,
total,
limit,
offset: offset + sliced.length,
hasMore: offset + sliced.length < total,
};
},
onLockTimeoutChange: readonlyVoid, onLockTimeoutChange: readonlyVoid,
onSessionTimeoutActionChange: readonlyVoid, onSessionTimeoutActionChange: readonlyVoid,
onRefreshAuthorizedDevices: async () => { onRefreshAuthorizedDevices: async () => {