Main body of PR comments, switching event handling to be a publisher of async events, a generic event; then adding a new async document update processor, which can later be converted to be part of the event processing pipeline.
This commit is contained in:
parent
0ba5887d9c
commit
ef5bcc4b66
|
@ -1 +1,29 @@
|
||||||
export * from "./updates"
|
import { asyncEventQueue, init as initQueue } from "../events/asyncEvents"
|
||||||
|
import {
|
||||||
|
ProcessorMap,
|
||||||
|
default as DocumentUpdateProcessor,
|
||||||
|
} from "../events/processors/async/DocumentUpdateProcessor"
|
||||||
|
|
||||||
|
let processingPromise: Promise<void>
|
||||||
|
let documentProcessor: DocumentUpdateProcessor
|
||||||
|
|
||||||
|
export function init(processors: ProcessorMap) {
|
||||||
|
if (!asyncEventQueue) {
|
||||||
|
initQueue()
|
||||||
|
}
|
||||||
|
if (!documentProcessor) {
|
||||||
|
documentProcessor = new DocumentUpdateProcessor(processors)
|
||||||
|
}
|
||||||
|
// if not processing in this instance, kick it off
|
||||||
|
if (!processingPromise) {
|
||||||
|
processingPromise = asyncEventQueue.process(async job => {
|
||||||
|
const { event, identity, properties, timestamp } = job.data
|
||||||
|
await documentProcessor.processEvent(
|
||||||
|
event,
|
||||||
|
identity,
|
||||||
|
properties,
|
||||||
|
timestamp
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
import { createQueue, JobQueue } from "../queue"
|
|
||||||
import BullQueue from "bull"
|
|
||||||
import { DocumentType, SEPARATOR } from "../constants"
|
|
||||||
import { doInContext, doInTenant } from "../context"
|
|
||||||
|
|
||||||
type DocUpdateEvent = {
|
|
||||||
id: string
|
|
||||||
tenantId: string
|
|
||||||
appId?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Processor = (update: DocUpdateEvent) => Promise<void>
|
|
||||||
|
|
||||||
const processors: { types: DocumentType[]; processor: Processor }[] = []
|
|
||||||
let queue: BullQueue.Queue
|
|
||||||
let processingPromise: Promise<void>
|
|
||||||
|
|
||||||
export function init() {
|
|
||||||
queue = createQueue<DocUpdateEvent>(JobQueue.DOC_UPDATE)
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function shutdown() {
|
|
||||||
if (queue) {
|
|
||||||
await queue.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function update(opts: DocUpdateEvent) {
|
|
||||||
if (!queue) {
|
|
||||||
init()
|
|
||||||
}
|
|
||||||
await queue.add(opts)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleJob(data: DocUpdateEvent) {
|
|
||||||
for (let { types, processor } of processors) {
|
|
||||||
if (types.find(type => data.id.startsWith(`${type}${SEPARATOR}`))) {
|
|
||||||
const context = data.appId || data.tenantId
|
|
||||||
const contextFn = data.appId ? doInContext : doInTenant
|
|
||||||
await contextFn(context, async () => {
|
|
||||||
await processor(data)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function process(types: DocumentType[], processor: Processor) {
|
|
||||||
if (!queue) {
|
|
||||||
init()
|
|
||||||
}
|
|
||||||
// add to processor list
|
|
||||||
processors.push({
|
|
||||||
types,
|
|
||||||
processor,
|
|
||||||
})
|
|
||||||
// if not processing in this instance, kick it off
|
|
||||||
if (!processingPromise) {
|
|
||||||
processingPromise = queue.process(async job => {
|
|
||||||
await handleJob(job.data)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./queue"
|
||||||
|
export * from "./publisher"
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { AsyncEvents } from "@budibase/types"
|
||||||
|
import { EventPayload, asyncEventQueue, init } from "./queue"
|
||||||
|
|
||||||
|
export async function publishAsyncEvent(payload: EventPayload) {
|
||||||
|
if (!asyncEventQueue) {
|
||||||
|
init()
|
||||||
|
}
|
||||||
|
const { event, identity } = payload
|
||||||
|
if (AsyncEvents.indexOf(event) !== -1 && identity.tenantId) {
|
||||||
|
await asyncEventQueue.add(payload)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import BullQueue from "bull"
|
||||||
|
import { createQueue, JobQueue } from "../../queue"
|
||||||
|
import { Event, Identity } from "@budibase/types"
|
||||||
|
|
||||||
|
export interface EventPayload {
|
||||||
|
event: Event
|
||||||
|
identity: Identity
|
||||||
|
properties: any
|
||||||
|
timestamp?: string | number
|
||||||
|
}
|
||||||
|
|
||||||
|
export let asyncEventQueue: BullQueue.Queue
|
||||||
|
|
||||||
|
export function init() {
|
||||||
|
asyncEventQueue = createQueue<EventPayload>(JobQueue.DOC_UPDATE)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function shutdown() {
|
||||||
|
if (asyncEventQueue) {
|
||||||
|
await asyncEventQueue.close()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
import {
|
||||||
|
Event,
|
||||||
|
UserCreatedEvent,
|
||||||
|
UserUpdatedEvent,
|
||||||
|
UserDeletedEvent,
|
||||||
|
UserPermissionAssignedEvent,
|
||||||
|
UserPermissionRemovedEvent,
|
||||||
|
GroupCreatedEvent,
|
||||||
|
GroupUpdatedEvent,
|
||||||
|
GroupDeletedEvent,
|
||||||
|
GroupUsersAddedEvent,
|
||||||
|
GroupUsersDeletedEvent,
|
||||||
|
GroupPermissionsEditedEvent,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
|
const getEventProperties: Record<
|
||||||
|
string,
|
||||||
|
(properties: any) => string | undefined
|
||||||
|
> = {
|
||||||
|
[Event.USER_CREATED]: (properties: UserCreatedEvent) => properties.userId,
|
||||||
|
[Event.USER_UPDATED]: (properties: UserUpdatedEvent) => properties.userId,
|
||||||
|
[Event.USER_DELETED]: (properties: UserDeletedEvent) => properties.userId,
|
||||||
|
[Event.USER_PERMISSION_ADMIN_ASSIGNED]: (
|
||||||
|
properties: UserPermissionAssignedEvent
|
||||||
|
) => properties.userId,
|
||||||
|
[Event.USER_PERMISSION_ADMIN_REMOVED]: (
|
||||||
|
properties: UserPermissionRemovedEvent
|
||||||
|
) => properties.userId,
|
||||||
|
[Event.USER_PERMISSION_BUILDER_ASSIGNED]: (
|
||||||
|
properties: UserPermissionAssignedEvent
|
||||||
|
) => properties.userId,
|
||||||
|
[Event.USER_PERMISSION_BUILDER_REMOVED]: (
|
||||||
|
properties: UserPermissionRemovedEvent
|
||||||
|
) => properties.userId,
|
||||||
|
[Event.USER_GROUP_CREATED]: (properties: GroupCreatedEvent) =>
|
||||||
|
properties.groupId,
|
||||||
|
[Event.USER_GROUP_UPDATED]: (properties: GroupUpdatedEvent) =>
|
||||||
|
properties.groupId,
|
||||||
|
[Event.USER_GROUP_DELETED]: (properties: GroupDeletedEvent) =>
|
||||||
|
properties.groupId,
|
||||||
|
[Event.USER_GROUP_USERS_ADDED]: (properties: GroupUsersAddedEvent) =>
|
||||||
|
properties.groupId,
|
||||||
|
[Event.USER_GROUP_USERS_REMOVED]: (properties: GroupUsersDeletedEvent) =>
|
||||||
|
properties.groupId,
|
||||||
|
[Event.USER_GROUP_PERMISSIONS_EDITED]: (
|
||||||
|
properties: GroupPermissionsEditedEvent
|
||||||
|
) => properties.groupId,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDocumentId(event: Event, properties: any) {
|
||||||
|
const extractor = getEventProperties[event]
|
||||||
|
if (!extractor) {
|
||||||
|
throw new Error("Event does not have a method of document ID extraction")
|
||||||
|
}
|
||||||
|
return extractor(properties)
|
||||||
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
import { Event, AuditedEventFriendlyName } from "@budibase/types"
|
import { Event } from "@budibase/types"
|
||||||
import { processors } from "./processors"
|
import { processors } from "./processors"
|
||||||
import identification from "./identification"
|
import identification from "./identification"
|
||||||
import * as backfill from "./backfill"
|
import * as backfill from "./backfill"
|
||||||
|
import { publishAsyncEvent } from "./asyncEvents"
|
||||||
|
|
||||||
export const publishEvent = async (
|
export const publishEvent = async (
|
||||||
event: Event,
|
event: Event,
|
||||||
|
@ -12,6 +13,15 @@ export const publishEvent = async (
|
||||||
const identity = await identification.getCurrentIdentity()
|
const identity = await identification.getCurrentIdentity()
|
||||||
|
|
||||||
const backfilling = await backfill.isBackfillingEvent(event)
|
const backfilling = await backfill.isBackfillingEvent(event)
|
||||||
|
|
||||||
|
// send off async events if required
|
||||||
|
await publishAsyncEvent({
|
||||||
|
event,
|
||||||
|
identity,
|
||||||
|
properties,
|
||||||
|
timestamp,
|
||||||
|
})
|
||||||
|
|
||||||
// no backfill - send the event and exit
|
// no backfill - send the event and exit
|
||||||
if (!backfilling) {
|
if (!backfilling) {
|
||||||
await processors.processEvent(event, identity, properties, timestamp)
|
await processors.processEvent(event, identity, properties, timestamp)
|
||||||
|
|
|
@ -6,6 +6,8 @@ export * as backfillCache from "./backfill"
|
||||||
|
|
||||||
import { processors } from "./processors"
|
import { processors } from "./processors"
|
||||||
|
|
||||||
|
export function initAsyncEvents() {}
|
||||||
|
|
||||||
export const shutdown = () => {
|
export const shutdown = () => {
|
||||||
processors.shutdown()
|
processors.shutdown()
|
||||||
console.log("Events shutdown")
|
console.log("Events shutdown")
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
import { Event, Identity, Group, DocumentUpdateEvents } from "@budibase/types"
|
|
||||||
import { EventProcessor } from "./types"
|
|
||||||
import * as docUpdates from "../../docUpdates"
|
|
||||||
import { getTenantId } from "../../context"
|
|
||||||
|
|
||||||
export default class DocumentUpdateProcessor implements EventProcessor {
|
|
||||||
async processEvent(
|
|
||||||
event: Event,
|
|
||||||
identity: Identity,
|
|
||||||
properties: any,
|
|
||||||
timestamp?: string
|
|
||||||
): Promise<void> {
|
|
||||||
// only user and group IDs supported right now - no app documents yet
|
|
||||||
if (DocumentUpdateEvents.indexOf(event) !== -1 && identity.tenantId) {
|
|
||||||
await docUpdates.update({
|
|
||||||
id: this.getId(properties),
|
|
||||||
tenantId: getTenantId(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getId(properties: any) {
|
|
||||||
let possibleProps = ["groupId", "userId"]
|
|
||||||
for (let prop of possibleProps) {
|
|
||||||
if (properties[prop]) {
|
|
||||||
return properties[prop]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async identify(identity: Identity, timestamp?: string | number) {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
async identifyGroup(group: Group, timestamp?: string | number) {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
shutdown(): void {
|
|
||||||
docUpdates.shutdown()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -25,22 +25,28 @@ export default class Processor implements EventProcessor {
|
||||||
timestamp?: string | number
|
timestamp?: string | number
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
for (const eventProcessor of this.processors) {
|
for (const eventProcessor of this.processors) {
|
||||||
|
if (eventProcessor.identify) {
|
||||||
await eventProcessor.identify(identity, timestamp)
|
await eventProcessor.identify(identity, timestamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async identifyGroup(
|
async identifyGroup(
|
||||||
identity: Group,
|
identity: Group,
|
||||||
timestamp?: string | number
|
timestamp?: string | number
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
for (const eventProcessor of this.processors) {
|
for (const eventProcessor of this.processors) {
|
||||||
|
if (eventProcessor.identifyGroup) {
|
||||||
await eventProcessor.identifyGroup(identity, timestamp)
|
await eventProcessor.identifyGroup(identity, timestamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
shutdown() {
|
shutdown() {
|
||||||
for (const eventProcessor of this.processors) {
|
for (const eventProcessor of this.processors) {
|
||||||
|
if (eventProcessor.shutdown) {
|
||||||
eventProcessor.shutdown()
|
eventProcessor.shutdown()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { EventProcessor } from "../types"
|
||||||
|
import { Event, Identity, DocUpdateEvent } from "@budibase/types"
|
||||||
|
import { DocumentType, SEPARATOR } from "../../../constants"
|
||||||
|
import { doInTenant } from "../../../context"
|
||||||
|
import { getDocumentId } from "../../documentId"
|
||||||
|
import { shutdown } from "../../asyncEvents"
|
||||||
|
|
||||||
|
export type Processor = (update: DocUpdateEvent) => Promise<void>
|
||||||
|
export type ProcessorMap = { types: DocumentType[]; processor: Processor }[]
|
||||||
|
|
||||||
|
export default class DocumentUpdateProcessor implements EventProcessor {
|
||||||
|
processors: ProcessorMap = []
|
||||||
|
|
||||||
|
constructor(processors: ProcessorMap) {
|
||||||
|
this.processors = processors
|
||||||
|
}
|
||||||
|
|
||||||
|
async processEvent(
|
||||||
|
event: Event,
|
||||||
|
identity: Identity,
|
||||||
|
properties: any,
|
||||||
|
timestamp?: string | number
|
||||||
|
) {
|
||||||
|
const tenantId = identity.tenantId
|
||||||
|
const docId = getDocumentId(event, properties)
|
||||||
|
if (!tenantId || !docId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for (let { types, processor } of this.processors) {
|
||||||
|
if (types.find(type => docId.startsWith(`${type}${SEPARATOR}`))) {
|
||||||
|
await doInTenant(tenantId, async () => {
|
||||||
|
await processor({
|
||||||
|
id: docId,
|
||||||
|
tenantId,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shutdown() {
|
||||||
|
return shutdown()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,12 @@
|
||||||
import AnalyticsProcessor from "./AnalyticsProcessor"
|
import AnalyticsProcessor from "./AnalyticsProcessor"
|
||||||
import LoggingProcessor from "./LoggingProcessor"
|
import LoggingProcessor from "./LoggingProcessor"
|
||||||
import AuditLogsProcessor from "./AuditLogsProcessor"
|
import AuditLogsProcessor from "./AuditLogsProcessor"
|
||||||
import DocumentUpdateProcessor from "./DocumentUpdateProcessor"
|
|
||||||
import Processors from "./Processors"
|
import Processors from "./Processors"
|
||||||
import { AuditLogFn } from "@budibase/types"
|
import { AuditLogFn } from "@budibase/types"
|
||||||
|
|
||||||
export const analyticsProcessor = new AnalyticsProcessor()
|
export const analyticsProcessor = new AnalyticsProcessor()
|
||||||
const loggingProcessor = new LoggingProcessor()
|
const loggingProcessor = new LoggingProcessor()
|
||||||
const auditLogsProcessor = new AuditLogsProcessor()
|
const auditLogsProcessor = new AuditLogsProcessor()
|
||||||
const documentUpdateProcessor = new DocumentUpdateProcessor()
|
|
||||||
|
|
||||||
export function init(auditingFn: AuditLogFn) {
|
export function init(auditingFn: AuditLogFn) {
|
||||||
return AuditLogsProcessor.init(auditingFn)
|
return AuditLogsProcessor.init(auditingFn)
|
||||||
|
@ -18,5 +16,4 @@ export const processors = new Processors([
|
||||||
analyticsProcessor,
|
analyticsProcessor,
|
||||||
loggingProcessor,
|
loggingProcessor,
|
||||||
auditLogsProcessor,
|
auditLogsProcessor,
|
||||||
documentUpdateProcessor,
|
|
||||||
])
|
])
|
||||||
|
|
|
@ -12,7 +12,7 @@ export interface EventProcessor {
|
||||||
properties: any,
|
properties: any,
|
||||||
timestamp?: string | number
|
timestamp?: string | number
|
||||||
): Promise<void>
|
): Promise<void>
|
||||||
identify(identity: Identity, timestamp?: string | number): Promise<void>
|
identify?(identity: Identity, timestamp?: string | number): Promise<void>
|
||||||
identifyGroup(group: Group, timestamp?: string | number): Promise<void>
|
identifyGroup?(group: Group, timestamp?: string | number): Promise<void>
|
||||||
shutdown(): void
|
shutdown?(): void
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
import { constants, docUpdates, logging } from "@budibase/backend-core"
|
||||||
|
import { sdk as proSdk } from "@budibase/pro"
|
||||||
|
import { DocUpdateEvent } from "@budibase/types"
|
||||||
|
import { syncUsersToAllApps } from "../sdk/app/applications/sync"
|
||||||
|
|
||||||
|
type UpdateCallback = (docId: string) => void
|
||||||
|
|
||||||
|
function userGroupUpdates(updateCb?: UpdateCallback) {
|
||||||
|
const types = [constants.DocumentType.USER, constants.DocumentType.GROUP]
|
||||||
|
const processor = async (update: DocUpdateEvent) => {
|
||||||
|
try {
|
||||||
|
const docId = update.id
|
||||||
|
const isGroup = docId.startsWith(constants.DocumentType.GROUP)
|
||||||
|
let userIds: string[]
|
||||||
|
if (isGroup) {
|
||||||
|
const group = await proSdk.groups.get(docId)
|
||||||
|
userIds = group.users?.map(user => user._id) || []
|
||||||
|
} else {
|
||||||
|
userIds = [docId]
|
||||||
|
}
|
||||||
|
if (userIds.length > 0) {
|
||||||
|
await syncUsersToAllApps(userIds)
|
||||||
|
}
|
||||||
|
if (updateCb) {
|
||||||
|
updateCb(docId)
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
// if something not found - no changes to perform
|
||||||
|
if (err?.status === 404) {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
logging.logAlert("Failed to perform user/group app sync", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { types, processor }
|
||||||
|
}
|
||||||
|
|
||||||
|
export function init(updateCb?: UpdateCallback) {
|
||||||
|
const processors = [userGroupUpdates(updateCb)]
|
||||||
|
docUpdates.init(processors)
|
||||||
|
}
|
|
@ -2,4 +2,5 @@ import BudibaseEmitter from "./BudibaseEmitter"
|
||||||
|
|
||||||
const emitter = new BudibaseEmitter()
|
const emitter = new BudibaseEmitter()
|
||||||
|
|
||||||
|
export { init } from "./docUpdates"
|
||||||
export default emitter
|
export default emitter
|
||||||
|
|
|
@ -82,7 +82,7 @@ async function syncUsersToApp(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function syncUsersToAllApps(userIds: string[]) {
|
export async function syncUsersToAllApps(userIds: string[]) {
|
||||||
// list of users, if one has been deleted it will be undefined in array
|
// list of users, if one has been deleted it will be undefined in array
|
||||||
const users = (await getGlobalUsers(userIds, {
|
const users = (await getGlobalUsers(userIds, {
|
||||||
noProcessing: true,
|
noProcessing: true,
|
||||||
|
@ -113,36 +113,6 @@ async function syncUsersToAllApps(userIds: string[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initUserGroupSync(updateCb?: (docId: string) => void) {
|
|
||||||
const types = [constants.DocumentType.USER, constants.DocumentType.GROUP]
|
|
||||||
docUpdates.process(types, async update => {
|
|
||||||
try {
|
|
||||||
const docId = update.id
|
|
||||||
const isGroup = docId.startsWith(constants.DocumentType.GROUP)
|
|
||||||
let userIds: string[]
|
|
||||||
if (isGroup) {
|
|
||||||
const group = await proSdk.groups.get(docId)
|
|
||||||
userIds = group.users?.map(user => user._id) || []
|
|
||||||
} else {
|
|
||||||
userIds = [docId]
|
|
||||||
}
|
|
||||||
if (userIds.length > 0) {
|
|
||||||
await syncUsersToAllApps(userIds)
|
|
||||||
}
|
|
||||||
if (updateCb) {
|
|
||||||
updateCb(docId)
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
|
||||||
// if something not found - no changes to perform
|
|
||||||
if (err?.status === 404) {
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
logging.logAlert("Failed to perform user/group app sync", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function syncApp(
|
export async function syncApp(
|
||||||
appId: string,
|
appId: string,
|
||||||
opts?: { automationOnly?: boolean }
|
opts?: { automationOnly?: boolean }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import TestConfiguration from "../../../../tests/utilities/TestConfiguration"
|
import TestConfiguration from "../../../../tests/utilities/TestConfiguration"
|
||||||
import { events, context, roles, constants } from "@budibase/backend-core"
|
import { events, context, roles, constants } from "@budibase/backend-core"
|
||||||
import { initUserGroupSync } from "../sync"
|
import { init } from "../../../../events"
|
||||||
import { rawUserMetadata } from "../../../users/utils"
|
import { rawUserMetadata } from "../../../users/utils"
|
||||||
import EventEmitter from "events"
|
import EventEmitter from "events"
|
||||||
import { UserGroup, UserMetadata, UserRoles, User } from "@budibase/types"
|
import { UserGroup, UserMetadata, UserRoles, User } from "@budibase/types"
|
||||||
|
@ -35,7 +35,7 @@ function waitForUpdate(opts: { group?: boolean }) {
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
app = await config.init("syncApp")
|
app = await config.init("syncApp")
|
||||||
initUserGroupSync(updateCb)
|
init(updateCb)
|
||||||
})
|
})
|
||||||
|
|
||||||
async function createUser(email: string, roles: UserRoles, builder?: boolean) {
|
async function createUser(email: string, roles: UserRoles, builder?: boolean) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import fs from "fs"
|
||||||
import { watch } from "./watch"
|
import { watch } from "./watch"
|
||||||
import * as automations from "./automations"
|
import * as automations from "./automations"
|
||||||
import * as fileSystem from "./utilities/fileSystem"
|
import * as fileSystem from "./utilities/fileSystem"
|
||||||
import eventEmitter from "./events"
|
import { default as eventEmitter, init as eventInit } from "./events"
|
||||||
import * as migrations from "./migrations"
|
import * as migrations from "./migrations"
|
||||||
import * as bullboard from "./automations/bullboard"
|
import * as bullboard from "./automations/bullboard"
|
||||||
import * as pro from "@budibase/pro"
|
import * as pro from "@budibase/pro"
|
||||||
|
@ -63,7 +63,7 @@ export async function startup(app?: any, server?: any) {
|
||||||
eventEmitter.emitPort(env.PORT)
|
eventEmitter.emitPort(env.PORT)
|
||||||
fileSystem.init()
|
fileSystem.init()
|
||||||
await redis.init()
|
await redis.init()
|
||||||
sdk.applications.initUserGroupSync()
|
eventInit()
|
||||||
|
|
||||||
// run migrations on startup if not done via http
|
// run migrations on startup if not done via http
|
||||||
// not recommended in a clustered environment
|
// not recommended in a clustered environment
|
||||||
|
|
|
@ -186,7 +186,7 @@ export enum Event {
|
||||||
AUDIT_LOGS_DOWNLOADED = "audit_log:downloaded",
|
AUDIT_LOGS_DOWNLOADED = "audit_log:downloaded",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DocumentUpdateEvents: Event[] = [
|
export const AsyncEvents: Event[] = [
|
||||||
Event.USER_CREATED,
|
Event.USER_CREATED,
|
||||||
Event.USER_UPDATED,
|
Event.USER_UPDATED,
|
||||||
Event.USER_DELETED,
|
Event.USER_DELETED,
|
||||||
|
@ -399,3 +399,9 @@ export interface BaseEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TableExportFormat = "json" | "csv"
|
export type TableExportFormat = "json" | "csv"
|
||||||
|
|
||||||
|
export type DocUpdateEvent = {
|
||||||
|
id: string
|
||||||
|
tenantId: string
|
||||||
|
appId?: string
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue