mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
feat(ee): add enterprise audit logs settings page (#4111)
* feat(ee): add enterprise audit logs settings page with server-side search Add a new audit logs page under enterprise settings that displays all actions captured via recordAudit. Includes server-side search, resource type filtering, date range selection, and cursor-based pagination. - Add internal API route (app/api/audit-logs) with session auth - Extract shared query logic (buildFilterConditions, buildOrgScopeCondition, queryAuditLogs) into app/api/v1/audit-logs/query.ts - Refactor v1 and admin audit log routes to use shared query module - Add React Query hook with useInfiniteQuery and cursor pagination - Add audit logs UI with debounced search, combobox filters, expandable rows - Gate behind requiresHosted + requiresEnterprise navigation flags - Place all enterprise audit log code in ee/audit-logs/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * lint * fix(ee): fix build error and address PR review comments - Fix import path: @/lib/utils → @/lib/core/utils/cn - Guard against empty orgMemberIds array in buildOrgScopeCondition - Skip debounce effect on mount when search is already synced Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * lint * fix(ee): fix type error with unknown metadata in JSX expression Use ternary instead of && chain to prevent unknown type from being returned as ReactNode. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ee): align skeleton filter width with actual component layout Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * lint * feat(audit): add audit logging for passwords, credentials, and schedules - Add PASSWORD_RESET_REQUESTED audit on forget-password with user lookup - Add CREDENTIAL_CREATED/UPDATED/DELETED audit on credential CRUD routes with metadata (credentialType, providerId, updatedFields, envKey) - Add SCHEDULE_CREATED audit on schedule creation with cron/timezone metadata - Fix SCHEDULE_DELETED (was incorrectly using SCHEDULE_UPDATED for deletes) - Enhance existing schedule update/disable/reactivate audit with structured metadata (operation, updatedFields, sourceType, previousStatus) - Add CREDENTIAL resource type and Credential filter option to audit logs UI - Enhance password reset completed description with user email Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(audit): align metadata with established recordAudit patterns - Add actorName/actorEmail to all new credential and schedule audit calls to match the established pattern (e.g., api-keys, byok-keys, knowledge) - Add resourceId and resourceName to forget-password audit call - Enhance forget-password description with user email Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(testing): sync audit mock with new AuditAction and AuditResourceType entries Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(audit-logs): derive resource type filter from AuditResourceType Instead of maintaining a separate hardcoded list, the filter dropdown now derives its options directly from the AuditResourceType const object. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(audit): enrich all recordAudit calls with structured metadata - Move resource type filter options to ee/audit-logs/constants.ts (derived from AuditResourceType, no separate list to maintain) - Remove export from internal cursor helpers in query.ts - Add 5 new AuditAction entries: BYOK_KEY_UPDATED, ENVIRONMENT_DELETED, INVITATION_RESENT, WORKSPACE_UPDATED, ORG_INVITATION_RESENT - Enrich ~80 recordAudit calls across the codebase with structured metadata (knowledge bases, connectors, documents, workspaces, members, invitations, workflows, deployments, templates, MCP servers, credential sets, organizations, permission groups, files, tables, notifications, copilot operations) - Sync audit mock with all new entries Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(audit): remove redundant metadata fields duplicating top-level audit fields Remove metadata entries that duplicate resourceName, workspaceId, or other top-level recordAudit fields. Also remove noisy fileNames arrays from bulk document upload audits (kept fileCount). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(audit): split audit types from server-only log module Extract AuditAction, AuditResourceType, and their types into lib/audit/types.ts (client-safe, no @sim/db dependency). The server-only recordAudit stays in log.ts and re-exports the types for backwards compatibility. constants.ts now imports from types.ts directly, breaking the postgres -> tls client bundle chain. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(audit): escape LIKE wildcards in audit log search query Escape %, _, and \ characters in the search parameter before embedding in the LIKE pattern to prevent unintended broad matches. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(audit): use actual deletedCount in bulk API key revoke description The description was using keys.length (requested count) instead of deletedCount (actual count), which could differ if some keys didn't exist. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(audit-logs): fix OAuth label displaying as "Oauth" in filter dropdown ACRONYMS set stored 'OAuth' but lookup used toUpperCase() producing 'OAUTH' which never matched. Now store all acronyms uppercase and use a display override map for special casing like OAuth. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
6a4f5f2074
commit
30c5e82ab0
@@ -18,10 +18,13 @@ export const auditMock = {
|
||||
PERSONAL_API_KEY_CREATED: 'personal_api_key.created',
|
||||
PERSONAL_API_KEY_REVOKED: 'personal_api_key.revoked',
|
||||
BYOK_KEY_CREATED: 'byok_key.created',
|
||||
BYOK_KEY_UPDATED: 'byok_key.updated',
|
||||
BYOK_KEY_DELETED: 'byok_key.deleted',
|
||||
CHAT_DEPLOYED: 'chat.deployed',
|
||||
CHAT_UPDATED: 'chat.updated',
|
||||
CHAT_DELETED: 'chat.deleted',
|
||||
CREDENTIAL_CREATED: 'credential.created',
|
||||
CREDENTIAL_UPDATED: 'credential.updated',
|
||||
CREDENTIAL_DELETED: 'credential.deleted',
|
||||
CREDENTIAL_RENAMED: 'credential.renamed',
|
||||
CREDIT_PURCHASED: 'credit.purchased',
|
||||
@@ -43,6 +46,7 @@ export const auditMock = {
|
||||
DOCUMENT_UPDATED: 'document.updated',
|
||||
DOCUMENT_DELETED: 'document.deleted',
|
||||
ENVIRONMENT_UPDATED: 'environment.updated',
|
||||
ENVIRONMENT_DELETED: 'environment.deleted',
|
||||
FILE_UPLOADED: 'file.uploaded',
|
||||
FILE_UPDATED: 'file.updated',
|
||||
FILE_DELETED: 'file.deleted',
|
||||
@@ -55,6 +59,7 @@ export const auditMock = {
|
||||
FORM_UPDATED: 'form.updated',
|
||||
FORM_DELETED: 'form.deleted',
|
||||
INVITATION_ACCEPTED: 'invitation.accepted',
|
||||
INVITATION_RESENT: 'invitation.resent',
|
||||
INVITATION_REVOKED: 'invitation.revoked',
|
||||
CONNECTOR_CREATED: 'connector.created',
|
||||
CONNECTOR_UPDATED: 'connector.updated',
|
||||
@@ -75,6 +80,7 @@ export const auditMock = {
|
||||
NOTIFICATION_DELETED: 'notification.deleted',
|
||||
OAUTH_DISCONNECTED: 'oauth.disconnected',
|
||||
PASSWORD_RESET: 'password.reset',
|
||||
PASSWORD_RESET_REQUESTED: 'password.reset_requested',
|
||||
ORGANIZATION_CREATED: 'organization.created',
|
||||
ORGANIZATION_UPDATED: 'organization.updated',
|
||||
ORG_MEMBER_ADDED: 'org_member.added',
|
||||
@@ -85,12 +91,15 @@ export const auditMock = {
|
||||
ORG_INVITATION_REJECTED: 'org_invitation.rejected',
|
||||
ORG_INVITATION_CANCELLED: 'org_invitation.cancelled',
|
||||
ORG_INVITATION_REVOKED: 'org_invitation.revoked',
|
||||
ORG_INVITATION_RESENT: 'org_invitation.resent',
|
||||
PERMISSION_GROUP_CREATED: 'permission_group.created',
|
||||
PERMISSION_GROUP_UPDATED: 'permission_group.updated',
|
||||
PERMISSION_GROUP_DELETED: 'permission_group.deleted',
|
||||
PERMISSION_GROUP_MEMBER_ADDED: 'permission_group_member.added',
|
||||
PERMISSION_GROUP_MEMBER_REMOVED: 'permission_group_member.removed',
|
||||
SCHEDULE_CREATED: 'schedule.created',
|
||||
SCHEDULE_UPDATED: 'schedule.updated',
|
||||
SCHEDULE_DELETED: 'schedule.deleted',
|
||||
SKILL_CREATED: 'skill.created',
|
||||
SKILL_UPDATED: 'skill.updated',
|
||||
SKILL_DELETED: 'skill.deleted',
|
||||
@@ -115,6 +124,7 @@ export const auditMock = {
|
||||
WORKFLOW_DEPLOYMENT_REVERTED: 'workflow.deployment_reverted',
|
||||
WORKFLOW_VARIABLES_UPDATED: 'workflow.variables_updated',
|
||||
WORKSPACE_CREATED: 'workspace.created',
|
||||
WORKSPACE_UPDATED: 'workspace.updated',
|
||||
WORKSPACE_DELETED: 'workspace.deleted',
|
||||
WORKSPACE_DUPLICATED: 'workspace.duplicated',
|
||||
},
|
||||
@@ -124,6 +134,7 @@ export const auditMock = {
|
||||
BYOK_KEY: 'byok_key',
|
||||
CHAT: 'chat',
|
||||
CONNECTOR: 'connector',
|
||||
CREDENTIAL: 'credential',
|
||||
CREDENTIAL_SET: 'credential_set',
|
||||
CUSTOM_TOOL: 'custom_tool',
|
||||
DOCUMENT: 'document',
|
||||
|
||||
Reference in New Issue
Block a user