This repository has been archived on 2022-08-14. You can view files and clone it, but cannot push or open issues or pull requests.
outline/server/events.js

234 lines
5.1 KiB
JavaScript

// @flow
import * as Sentry from "@sentry/node";
import debug from "debug";
import services from "./services";
import { createQueue } from "./utils/queue";
const log = debug("services");
export type UserEvent =
| {
name: | "users.create" // eslint-disable-line
| "users.signin"
| "users.update"
| "users.suspend"
| "users.activate"
| "users.delete",
userId: string,
teamId: string,
actorId: string,
ip: string,
}
| {
name: "users.invite",
teamId: string,
actorId: string,
data: {
email: string,
name: string,
},
ip: string,
};
export type DocumentEvent =
| {
name: | "documents.create" // eslint-disable-line
| "documents.publish"
| "documents.delete"
| "documents.permanent_delete"
| "documents.pin"
| "documents.unpin"
| "documents.archive"
| "documents.unarchive"
| "documents.restore"
| "documents.star"
| "documents.unstar",
documentId: string,
collectionId: string,
teamId: string,
actorId: string,
ip: string,
data: {
title: string,
source?: "import",
},
}
| {
name: "documents.move",
documentId: string,
collectionId: string,
teamId: string,
actorId: string,
data: {
collectionIds: string[],
documentIds: string[],
},
ip: string,
}
| {
name: | "documents.update" // eslint-disable-line
| "documents.update.delayed"
| "documents.update.debounced",
documentId: string,
collectionId: string,
createdAt: string,
teamId: string,
actorId: string,
data: {
title: string,
autosave: boolean,
done: boolean,
},
ip: string,
}
| {
name: "documents.title_change",
documentId: string,
collectionId: string,
createdAt: string,
teamId: string,
actorId: string,
data: {
title: string,
previousTitle: string,
},
ip: string,
};
export type RevisionEvent = {
name: "revisions.create",
documentId: string,
collectionId: string,
teamId: string,
};
export type CollectionImportEvent = {
name: "collections.import",
modelId: string,
teamId: string,
actorId: string,
data: { type: "outline" },
ip: string,
};
export type CollectionEvent =
| {
name: | "collections.create" // eslint-disable-line
| "collections.update"
| "collections.delete",
collectionId: string,
teamId: string,
actorId: string,
data: { name: string },
ip: string,
}
| {
name: "collections.add_user" | "collections.remove_user",
userId: string,
collectionId: string,
teamId: string,
actorId: string,
ip: string,
}
| {
name: "collections.add_group" | "collections.remove_group",
collectionId: string,
teamId: string,
actorId: string,
data: { name: string, groupId: string },
ip: string,
}
| {
name: "collections.move",
collectionId: string,
teamId: string,
actorId: string,
data: { index: string },
ip: string,
};
export type GroupEvent =
| {
name: "groups.create" | "groups.delete" | "groups.update",
actorId: string,
modelId: string,
teamId: string,
data: { name: string },
ip: string,
}
| {
name: "groups.add_user" | "groups.remove_user",
actorId: string,
userId: string,
modelId: string,
teamId: string,
data: { name: string },
ip: string,
};
export type IntegrationEvent = {
name: "integrations.create" | "integrations.update",
modelId: string,
teamId: string,
actorId: string,
ip: string,
};
export type TeamEvent = {
name: "teams.update",
teamId: string,
actorId: string,
data: Object,
ip: string,
};
export type Event =
| UserEvent
| DocumentEvent
| CollectionEvent
| CollectionImportEvent
| IntegrationEvent
| GroupEvent
| RevisionEvent
| TeamEvent;
const globalEventsQueue = createQueue("global events");
const serviceEventsQueue = createQueue("service events");
// this queue processes global events and hands them off to service hooks
globalEventsQueue.process(async (job) => {
const names = Object.keys(services);
names.forEach((name) => {
const service = services[name];
if (service.on) {
serviceEventsQueue.add(
{ ...job.data, service: name },
{ removeOnComplete: true }
);
}
});
});
// this queue processes an individual event for a specific service
serviceEventsQueue.process(async (job) => {
const event = job.data;
const service = services[event.service];
if (service.on) {
log(`${event.service} processing ${event.name}`);
service.on(event).catch((error) => {
if (process.env.SENTRY_DSN) {
Sentry.withScope(function (scope) {
scope.setExtra("event", event);
Sentry.captureException(error);
});
} else {
throw error;
}
});
}
});
export default globalEventsQueue;