From 2afd3e1580930045944194f4a5a204a8f6136a41 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 15 Feb 2023 19:44:32 +0000 Subject: [PATCH] Updating events to include a proper friendly map of audited events. --- .../backend-core/src/events/publishers/app.ts | 11 +++ .../src/events/publishers/auth.ts | 6 +- .../src/events/publishers/backup.ts | 5 +- .../src/events/publishers/group.ts | 14 ++- .../src/events/publishers/user.ts | 17 +++- packages/backend-core/src/utils/utils.ts | 3 +- packages/types/src/sdk/events/app.ts | 11 +++ packages/types/src/sdk/events/auth.ts | 2 + packages/types/src/sdk/events/backup.ts | 2 + packages/types/src/sdk/events/event.ts | 98 ++++++++++++++++++- packages/types/src/sdk/events/user.ts | 15 ++- packages/types/src/sdk/events/userGroup.ts | 11 +++ .../worker/src/api/controllers/global/auth.ts | 6 +- packages/worker/src/sdk/users/users.ts | 2 +- 14 files changed, 187 insertions(+), 16 deletions(-) diff --git a/packages/backend-core/src/events/publishers/app.ts b/packages/backend-core/src/events/publishers/app.ts index 90da21f3f5..a4d578bb4f 100644 --- a/packages/backend-core/src/events/publishers/app.ts +++ b/packages/backend-core/src/events/publishers/app.ts @@ -19,6 +19,7 @@ const created = async (app: App, timestamp?: string | number) => { const properties: AppCreatedEvent = { appId: app.appId, version: app.version, + name: app.name, } await publishEvent(Event.APP_CREATED, properties, timestamp) } @@ -27,6 +28,7 @@ async function updated(app: App) { const properties: AppUpdatedEvent = { appId: app.appId, version: app.version, + name: app.name, } await publishEvent(Event.APP_UPDATED, properties) } @@ -34,6 +36,7 @@ async function updated(app: App) { async function deleted(app: App) { const properties: AppDeletedEvent = { appId: app.appId, + name: app.name, } await publishEvent(Event.APP_DELETED, properties) } @@ -41,6 +44,7 @@ async function deleted(app: App) { async function published(app: App, timestamp?: string | number) { const properties: AppPublishedEvent = { appId: app.appId, + name: app.name, } await publishEvent(Event.APP_PUBLISHED, properties, timestamp) } @@ -48,6 +52,7 @@ async function published(app: App, timestamp?: string | number) { async function unpublished(app: App) { const properties: AppUnpublishedEvent = { appId: app.appId, + name: app.name, } await publishEvent(Event.APP_UNPUBLISHED, properties) } @@ -55,6 +60,7 @@ async function unpublished(app: App) { async function fileImported(app: App) { const properties: AppFileImportedEvent = { appId: app.appId, + name: app.name, } await publishEvent(Event.APP_FILE_IMPORTED, properties) } @@ -63,6 +69,7 @@ async function templateImported(app: App, templateKey: string) { const properties: AppTemplateImportedEvent = { appId: app.appId, templateKey, + name: app.name, } await publishEvent(Event.APP_TEMPLATE_IMPORTED, properties) } @@ -76,6 +83,7 @@ async function versionUpdated( appId: app.appId, currentVersion, updatedToVersion, + name: app.name, } await publishEvent(Event.APP_VERSION_UPDATED, properties) } @@ -89,6 +97,7 @@ async function versionReverted( appId: app.appId, currentVersion, revertedToVersion, + name: app.name, } await publishEvent(Event.APP_VERSION_REVERTED, properties) } @@ -96,6 +105,7 @@ async function versionReverted( async function reverted(app: App) { const properties: AppRevertedEvent = { appId: app.appId, + name: app.name, } await publishEvent(Event.APP_REVERTED, properties) } @@ -103,6 +113,7 @@ async function reverted(app: App) { async function exported(app: App) { const properties: AppExportedEvent = { appId: app.appId, + name: app.name, } await publishEvent(Event.APP_EXPORTED, properties) } diff --git a/packages/backend-core/src/events/publishers/auth.ts b/packages/backend-core/src/events/publishers/auth.ts index 4436045599..5527e02a34 100644 --- a/packages/backend-core/src/events/publishers/auth.ts +++ b/packages/backend-core/src/events/publishers/auth.ts @@ -12,19 +12,21 @@ import { } from "@budibase/types" import { identification } from ".." -async function login(source: LoginSource) { +async function login(source: LoginSource, email: string) { const identity = await identification.getCurrentIdentity() const properties: LoginEvent = { userId: identity.id, source, + email, } await publishEvent(Event.AUTH_LOGIN, properties) } -async function logout() { +async function logout(email: string) { const identity = await identification.getCurrentIdentity() const properties: LogoutEvent = { userId: identity.id, + email, } await publishEvent(Event.AUTH_LOGOUT, properties) } diff --git a/packages/backend-core/src/events/publishers/backup.ts b/packages/backend-core/src/events/publishers/backup.ts index 12263fe1ff..d7d87f09f1 100644 --- a/packages/backend-core/src/events/publishers/backup.ts +++ b/packages/backend-core/src/events/publishers/backup.ts @@ -13,6 +13,7 @@ async function appBackupRestored(backup: AppBackup) { appId: backup.appId, restoreId: backup._id!, backupCreatedAt: backup.timestamp, + name: backup.name as string, } await publishEvent(Event.APP_BACKUP_RESTORED, properties) @@ -22,13 +23,15 @@ async function appBackupTriggered( appId: string, backupId: string, type: AppBackupType, - trigger: AppBackupTrigger + trigger: AppBackupTrigger, + name: string ) { const properties: AppBackupTriggeredEvent = { appId: appId, backupId, type, trigger, + name, } await publishEvent(Event.APP_BACKUP_TRIGGERED, properties) } diff --git a/packages/backend-core/src/events/publishers/group.ts b/packages/backend-core/src/events/publishers/group.ts index d79920562b..d8de4ccba4 100644 --- a/packages/backend-core/src/events/publishers/group.ts +++ b/packages/backend-core/src/events/publishers/group.ts @@ -8,12 +8,14 @@ import { GroupUsersAddedEvent, GroupUsersDeletedEvent, GroupAddedOnboardingEvent, + GroupPermissionsEditedEvent, UserGroupRoles, } from "@budibase/types" async function created(group: UserGroup, timestamp?: number) { const properties: GroupCreatedEvent = { groupId: group._id as string, + name: group.name, } await publishEvent(Event.USER_GROUP_CREATED, properties, timestamp) } @@ -21,6 +23,7 @@ async function created(group: UserGroup, timestamp?: number) { async function updated(group: UserGroup) { const properties: GroupUpdatedEvent = { groupId: group._id as string, + name: group.name, } await publishEvent(Event.USER_GROUP_UPDATED, properties) } @@ -28,6 +31,7 @@ async function updated(group: UserGroup) { async function deleted(group: UserGroup) { const properties: GroupDeletedEvent = { groupId: group._id as string, + name: group.name, } await publishEvent(Event.USER_GROUP_DELETED, properties) } @@ -36,6 +40,7 @@ async function usersAdded(count: number, group: UserGroup) { const properties: GroupUsersAddedEvent = { count, groupId: group._id as string, + name: group.name, } await publishEvent(Event.USER_GROUP_USERS_ADDED, properties) } @@ -44,6 +49,7 @@ async function usersDeleted(count: number, group: UserGroup) { const properties: GroupUsersDeletedEvent = { count, groupId: group._id as string, + name: group.name, } await publishEvent(Event.USER_GROUP_USERS_REMOVED, properties) } @@ -56,9 +62,11 @@ async function createdOnboarding(groupId: string) { await publishEvent(Event.USER_GROUP_ONBOARDING, properties) } -async function permissionsEdited(roles: UserGroupRoles) { - const properties: UserGroupRoles = { - ...roles, +async function permissionsEdited(group: UserGroup) { + const properties: GroupPermissionsEditedEvent = { + permissions: group.roles!, + name: group.name, + groupId: group._id as string, } await publishEvent(Event.USER_GROUP_PERMISSIONS_EDITED, properties) } diff --git a/packages/backend-core/src/events/publishers/user.ts b/packages/backend-core/src/events/publishers/user.ts index 1fe50149b5..ec43dbbf00 100644 --- a/packages/backend-core/src/events/publishers/user.ts +++ b/packages/backend-core/src/events/publishers/user.ts @@ -19,6 +19,7 @@ import { async function created(user: User, timestamp?: number) { const properties: UserCreatedEvent = { userId: user._id as string, + email: user.email, } await publishEvent(Event.USER_CREATED, properties, timestamp) } @@ -26,6 +27,7 @@ async function created(user: User, timestamp?: number) { async function updated(user: User) { const properties: UserUpdatedEvent = { userId: user._id as string, + email: user.email, } await publishEvent(Event.USER_UPDATED, properties) } @@ -33,6 +35,7 @@ async function updated(user: User) { async function deleted(user: User) { const properties: UserDeletedEvent = { userId: user._id as string, + email: user.email, } await publishEvent(Event.USER_DELETED, properties) } @@ -40,6 +43,7 @@ async function deleted(user: User) { export async function onboardingComplete(user: User) { const properties: UserOnboardingEvent = { userId: user._id as string, + email: user.email, } await publishEvent(Event.USER_ONBOARDING_COMPLETE, properties) } @@ -49,6 +53,7 @@ export async function onboardingComplete(user: User) { async function permissionAdminAssigned(user: User, timestamp?: number) { const properties: UserPermissionAssignedEvent = { userId: user._id as string, + email: user.email, } await publishEvent( Event.USER_PERMISSION_ADMIN_ASSIGNED, @@ -60,6 +65,7 @@ async function permissionAdminAssigned(user: User, timestamp?: number) { async function permissionAdminRemoved(user: User) { const properties: UserPermissionRemovedEvent = { userId: user._id as string, + email: user.email, } await publishEvent(Event.USER_PERMISSION_ADMIN_REMOVED, properties) } @@ -67,6 +73,7 @@ async function permissionAdminRemoved(user: User) { async function permissionBuilderAssigned(user: User, timestamp?: number) { const properties: UserPermissionAssignedEvent = { userId: user._id as string, + email: user.email, } await publishEvent( Event.USER_PERMISSION_BUILDER_ASSIGNED, @@ -78,20 +85,22 @@ async function permissionBuilderAssigned(user: User, timestamp?: number) { async function permissionBuilderRemoved(user: User) { const properties: UserPermissionRemovedEvent = { userId: user._id as string, + email: user.email, } await publishEvent(Event.USER_PERMISSION_BUILDER_REMOVED, properties) } // INVITE -async function invited() { - const properties: UserInvitedEvent = {} +async function invited(email: string) { + const properties: UserInvitedEvent = { email } await publishEvent(Event.USER_INVITED, properties) } async function inviteAccepted(user: User) { const properties: UserInviteAcceptedEvent = { userId: user._id as string, + email: user.email, } await publishEvent(Event.USER_INVITED_ACCEPTED, properties) } @@ -101,6 +110,7 @@ async function inviteAccepted(user: User) { async function passwordForceReset(user: User) { const properties: UserPasswordForceResetEvent = { userId: user._id as string, + email: user.email, } await publishEvent(Event.USER_PASSWORD_FORCE_RESET, properties) } @@ -108,6 +118,7 @@ async function passwordForceReset(user: User) { async function passwordUpdated(user: User) { const properties: UserPasswordUpdatedEvent = { userId: user._id as string, + email: user.email, } await publishEvent(Event.USER_PASSWORD_UPDATED, properties) } @@ -115,6 +126,7 @@ async function passwordUpdated(user: User) { async function passwordResetRequested(user: User) { const properties: UserPasswordResetRequestedEvent = { userId: user._id as string, + email: user.email, } await publishEvent(Event.USER_PASSWORD_RESET_REQUESTED, properties) } @@ -122,6 +134,7 @@ async function passwordResetRequested(user: User) { async function passwordReset(user: User) { const properties: UserPasswordResetEvent = { userId: user._id as string, + email: user.email, } await publishEvent(Event.USER_PASSWORD_RESET, properties) } diff --git a/packages/backend-core/src/utils/utils.ts b/packages/backend-core/src/utils/utils.ts index c608686431..0556a80c74 100644 --- a/packages/backend-core/src/utils/utils.ts +++ b/packages/backend-core/src/utils/utils.ts @@ -227,6 +227,7 @@ export async function getBuildersCount() { */ export async function platformLogout(opts: PlatformLogoutOpts) { const ctx = opts.ctx + const email = ctx.user?.email! const userId = opts.userId const keepActiveSession = opts.keepActiveSession @@ -247,7 +248,7 @@ export async function platformLogout(opts: PlatformLogoutOpts) { const sessionIds = sessions.map(({ sessionId }) => sessionId) await invalidateSessions(userId, { sessionIds, reason: "logout" }) - await events.auth.logout() + await events.auth.logout(email) await userCache.invalidateUser(userId) } diff --git a/packages/types/src/sdk/events/app.ts b/packages/types/src/sdk/events/app.ts index 73d491070f..7b63a4f0cd 100644 --- a/packages/types/src/sdk/events/app.ts +++ b/packages/types/src/sdk/events/app.ts @@ -3,50 +3,61 @@ import { BaseEvent } from "./event" export interface AppCreatedEvent extends BaseEvent { appId: string version: string + name: string } export interface AppUpdatedEvent extends BaseEvent { appId: string version: string + name: string } export interface AppDeletedEvent extends BaseEvent { appId: string + name: string } export interface AppPublishedEvent extends BaseEvent { appId: string + name: string } export interface AppUnpublishedEvent extends BaseEvent { appId: string + name: string } export interface AppFileImportedEvent extends BaseEvent { appId: string + name: string } export interface AppTemplateImportedEvent extends BaseEvent { appId: string templateKey: string + name: string } export interface AppVersionUpdatedEvent extends BaseEvent { appId: string currentVersion: string updatedToVersion: string + name: string } export interface AppVersionRevertedEvent extends BaseEvent { appId: string currentVersion: string revertedToVersion: string + name: string } export interface AppRevertedEvent extends BaseEvent { appId: string + name: string } export interface AppExportedEvent extends BaseEvent { appId: string + name: string } diff --git a/packages/types/src/sdk/events/auth.ts b/packages/types/src/sdk/events/auth.ts index eb9f3148a3..a98e1ca889 100644 --- a/packages/types/src/sdk/events/auth.ts +++ b/packages/types/src/sdk/events/auth.ts @@ -7,10 +7,12 @@ export type SSOType = ConfigType.OIDC | ConfigType.GOOGLE export interface LoginEvent extends BaseEvent { userId: string source: LoginSource + email: string } export interface LogoutEvent extends BaseEvent { userId: string + email: string } export interface SSOCreatedEvent extends BaseEvent { diff --git a/packages/types/src/sdk/events/backup.ts b/packages/types/src/sdk/events/backup.ts index 1dddc109cc..23863cf8ac 100644 --- a/packages/types/src/sdk/events/backup.ts +++ b/packages/types/src/sdk/events/backup.ts @@ -5,6 +5,7 @@ export interface AppBackupRestoreEvent extends BaseEvent { appId: string restoreId: string backupCreatedAt: string + name: string } export interface AppBackupTriggeredEvent extends BaseEvent { @@ -12,4 +13,5 @@ export interface AppBackupTriggeredEvent extends BaseEvent { appId: string trigger: AppBackupTrigger type: AppBackupType + name: string } diff --git a/packages/types/src/sdk/events/event.ts b/packages/types/src/sdk/events/event.ts index 614dd18ded..f7a2051dfc 100644 --- a/packages/types/src/sdk/events/event.ts +++ b/packages/types/src/sdk/events/event.ts @@ -182,8 +182,102 @@ export enum Event { ENVIRONMENT_VARIABLE_UPGRADE_PANEL_OPENED = "environment_variable:upgrade_panel_opened", } -export const AuditedEventFriendlyName = { - [Event.USER_CREATED]: "user created", +export class AuditedEventFriendlyName { + // USER + static USER_CREATED = "User {{ email }} created" + static USER_UPDATED = "User {{ email }} updated" + static USER_DELETED = "User {{ email }} deleted" + static USER_PERMISSION_ADMIN_ASSIGNED = "User {{ email }} admin role assigned" + static USER_PERMISSION_ADMIN_REMOVED = "User {{ email }} admin role removed" + static USER_PERMISSION_BUILDER_ASSIGNED = + "User {{ email }} builder role assigned" + static USER_PERMISSION_BUILDER_REMOVED = + "User {{ email }} builder role removed" + static USER_INVITED = "User {{ email }} invited" + static USER_INVITED_ACCEPTED = "User {{ email }} accepted invite" + static USER_PASSWORD_UPDATED = "User {{ email }} password updated" + static USER_PASSWORD_RESET_REQUESTED = + "User {{ email }} password reset requested" + static USER_PASSWORD_RESET = "User {{ email }} password reset" + static USER_GROUP_CREATED = "User group {{ name }} created" + static USER_GROUP_UPDATED = "User group {{ name }} updated" + static USER_GROUP_DELETED = "User group {{ name }} deleted" + static USER_GROUP_USERS_ADDED = + "User group {{ name }} {{ count }} users added" + static USER_GROUP_USERS_REMOVED = + "User group {{ name }} {{ count }} users removed" + static USER_GROUP_PERMISSIONS_EDITED = + "User group {{ name }} permissions edited" + + // EMAIL + static EMAIL_SMTP_CREATED = "Email configuration created" + static EMAIL_SMTP_UPDATED = "Email configuration updated" + + // AUTH + static AUTH_SSO_CREATED = "SSO configuration created" + static AUTH_SSO_UPDATED = "SSO configuration updated" + static AUTH_SSO_ACTIVATED = "SSO configuration activated" + static AUTH_SSO_DEACTIVATED = "SSO configuration deactivated" + static AUTH_LOGIN = "User {{ email }} logged in" + static AUTH_LOGOUT = "User {{ email }} logged out" + + // ORG + static ORG_NAME_UPDATED = "Organisation name updated" + static ORG_LOGO_UPDATED = "Organisation logo updated" + static ORG_PLATFORM_URL_UPDATED = "Organisation platform URL updated" + + // APP + static APP_CREATED = "App {{ name }} created" + static APP_UPDATED = "App {{ name }} updated" + static APP_DELETED = "App {{ name }} deleted" + static APP_PUBLISHED = "App {{ name }} published" + static APP_UNPUBLISHED = "App {{ name }} unpublished" + static APP_TEMPLATE_IMPORTED = "App {{ name }} template imported" + static APP_FILE_IMPORTED = "App {{ name }} file imported" + static APP_VERSION_UPDATED = "App {{ name }} version updated" + static APP_VERSION_REVERTED = "App {{ name }} version reverted" + static APP_REVERTED = "App {{ name }} reverted" + static APP_EXPORTED = "App {{ name }} exported" + static APP_BACKUP_RESTORED = "App backup {{ name }} restored" + static APP_BACKUP_TRIGGERED = "App backup {{ name }} triggered" + + // DATASOURCE + static DATASOURCE_CREATED = "Datasource created" + static DATASOURCE_UPDATED = "Datasource updated" + static DATASOURCE_DELETED = "Datasource deleted" + + // QUERY + static QUERY_CREATED = "Query created" + static QUERY_UPDATED = "Query updated" + static QUERY_DELETED = "Query deleted" + static QUERY_IMPORT = "Query import" + + // TABLE + static TABLE_CREATED = "Table created" + static TABLE_UPDATED = "Table updated" + static TABLE_DELETED = "Table deleted" + static TABLE_EXPORTED = "Table exported" + static TABLE_IMPORTED = "Table imported" + static TABLE_DATA_IMPORTED = "Data imported to table" + + // ROWS + static ROWS_CREATED = "Rows created" + static ROWS_IMPORTED = "Rows imported" + + // AUTOMATION + static AUTOMATION_CREATED = "Automation created" + static AUTOMATION_DELETED = "Automation deleted" + + // SCREEN + static SCREEN_CREATED = "Screen created" + static SCREEN_DELETED = "Screen deleted" + + // COMPONENT + static COMPONENT_CREATED = "Component created" + static COMPONENT_DELETED = "Component deleted" + + static ENVIRONMENT_VARIABLE_CREATED = "Environment variable created" + static ENVIRONMENT_VARIABLE_DELETED = "Environment variable deleted" } // properties added at the final stage of the event pipeline diff --git a/packages/types/src/sdk/events/user.ts b/packages/types/src/sdk/events/user.ts index 3f8f72801c..1322934d45 100644 --- a/packages/types/src/sdk/events/user.ts +++ b/packages/types/src/sdk/events/user.ts @@ -2,47 +2,60 @@ import { BaseEvent } from "./event" export interface UserCreatedEvent extends BaseEvent { userId: string + email: string } export interface UserUpdatedEvent extends BaseEvent { userId: string + email: string } export interface UserDeletedEvent extends BaseEvent { userId: string + email: string } export interface UserOnboardingEvent extends BaseEvent { userId: string step?: string + email: string } export interface UserPermissionAssignedEvent extends BaseEvent { userId: string + email: string } export interface UserPermissionRemovedEvent extends BaseEvent { userId: string + email: string } -export interface UserInvitedEvent extends BaseEvent {} +export interface UserInvitedEvent extends BaseEvent { + email: string +} export interface UserInviteAcceptedEvent extends BaseEvent { userId: string + email: string } export interface UserPasswordForceResetEvent extends BaseEvent { userId: string + email: string } export interface UserPasswordUpdatedEvent extends BaseEvent { userId: string + email: string } export interface UserPasswordResetRequestedEvent extends BaseEvent { userId: string + email: string } export interface UserPasswordResetEvent extends BaseEvent { userId: string + email: string } diff --git a/packages/types/src/sdk/events/userGroup.ts b/packages/types/src/sdk/events/userGroup.ts index 2ce642e274..57deef4c20 100644 --- a/packages/types/src/sdk/events/userGroup.ts +++ b/packages/types/src/sdk/events/userGroup.ts @@ -2,27 +2,38 @@ import { BaseEvent } from "./event" export interface GroupCreatedEvent extends BaseEvent { groupId: string + name: string } export interface GroupUpdatedEvent extends BaseEvent { groupId: string + name: string } export interface GroupDeletedEvent extends BaseEvent { groupId: string + name: string } export interface GroupUsersAddedEvent extends BaseEvent { count: number groupId: string + name: string } export interface GroupUsersDeletedEvent extends BaseEvent { count: number groupId: string + name: string } export interface GroupAddedOnboardingEvent extends BaseEvent { groupId: string onboarding: boolean } + +export interface GroupPermissionsEditedEvent extends BaseEvent { + permissions: Record + name: string + groupId: string +} diff --git a/packages/worker/src/api/controllers/global/auth.ts b/packages/worker/src/api/controllers/global/auth.ts index e6d3c329d7..7491a47bb3 100644 --- a/packages/worker/src/api/controllers/global/auth.ts +++ b/packages/worker/src/api/controllers/global/auth.ts @@ -54,7 +54,7 @@ export const authenticate = async (ctx: any, next: any) => { async (err: any, user: User, info: any) => { await authInternal(ctx, user, err, info) await context.identity.doInUserContext(user, async () => { - await events.auth.login("local") + await events.auth.login("local", user.email) }) ctx.status = 200 } @@ -208,7 +208,7 @@ export const googleAuth = async (ctx: any, next: any) => { async (err: any, user: User, info: any) => { await authInternal(ctx, user, err, info) await context.identity.doInUserContext(user, async () => { - await events.auth.login("google-internal") + await events.auth.login("google-internal", user.email) }) ctx.redirect("/") } @@ -272,7 +272,7 @@ export const oidcAuth = async (ctx: any, next: any) => { async (err: any, user: any, info: any) => { await authInternal(ctx, user, err, info) await context.identity.doInUserContext(user, async () => { - await events.auth.login("oidc") + await events.auth.login("oidc", user.email) }) ctx.redirect("/") } diff --git a/packages/worker/src/sdk/users/users.ts b/packages/worker/src/sdk/users/users.ts index 8410d0b2e0..617f07d404 100644 --- a/packages/worker/src/sdk/users/users.ts +++ b/packages/worker/src/sdk/users/users.ts @@ -623,7 +623,7 @@ export const invite = async ( } await sendEmail(user.email, EmailTemplatePurpose.INVITATION, opts) response.successful.push({ email: user.email }) - await events.user.invited() + await events.user.invited(user.email) } catch (e) { console.error(`Failed to send email invitation email=${user.email}`, e) response.unsuccessful.push({