History

Parse WorkOS membership events with typed helpers

Rhys Sullivan committed 8 months ago

Commit 77bb45a1 parent 28def291 file · +38 −6Browse files

Unified · Split

executor/packages/database/src/auth/event_handlers.ts+38−6
@@ -16,6 +16,7 @@ import { · 15 unmodified lines
1616 } from "./memberships";
1717 import { ensureUniqueOrganizationSlug } from "./naming";
1818 import { seedWorkspaceMembersFromOrganization } from "./workspace_membership_projection";
19+import { asPayload } from "../lib/object";
1920
2021 type WorkosMembershipEventData = {
2122 id: string;
@@ -27,6 +28,30 @@ type WorkosMembershipEventData = { · 5 unmodified lines
2728 status?: string;
2829 };
2930
31+type ResolvedMembershipTarget = {
32+ account: Doc<"accounts"> | null;
33+ organization: Doc<"organizations"> | null;
34+ fallbackRole?: Doc<"workspaceMembers">["role"];
35+};
36+
37+function parseMembershipEventData(value: unknown): WorkosMembershipEventData | null {
38+ const record = asPayload(value);
39+ if (typeof record.id !== "string" || record.id.trim().length === 0) {
40+ return null;
41+ }
42+
43+ const role = asPayload(record.role);
44+ return {
45+ id: record.id,
46+ user_id: typeof record.user_id === "string" ? record.user_id : undefined,
47+ userId: typeof record.userId === "string" ? record.userId : undefined,
48+ organization_id: typeof record.organization_id === "string" ? record.organization_id : undefined,
49+ organizationId: typeof record.organizationId === "string" ? record.organizationId : undefined,
50+ role: typeof role.slug === "string" ? { slug: role.slug } : undefined,
51+ status: typeof record.status === "string" ? record.status : undefined,
52+ };
53+}
54+
3055 function deriveOrganizationRoleFromWorkosSlug(workosRoleSlug?: string): Doc<"organizationMembers">["role"] {
3156 return workosRoleSlug === "admin" ? "admin" : "member";
3257 }
@@ -34,7 +59,7 @@ function deriveOrganizationRoleFromWorkosSlug(workosRoleSlug?: string): Doc<"org · 1 unmodified line
3459 async function resolveMembershipAccountAndOrganization(
3560 ctx: Pick<MutationCtx, "db">,
3661 data: WorkosMembershipEventData,
37−) {
62+): Promise<ResolvedMembershipTarget> {
3863 const workosUserId = data.user_id ?? data.userId;
3964 const workosOrgId = data.organization_id ?? data.organizationId;
4065
@@ -48,7 +73,6 @@ async function resolveMembershipAccountAndOrganization( · 7 unmodified lines
4873 return {
4974 account,
5075 organization,
51− fallbackRole: undefined as Doc<"workspaceMembers">["role"] | undefined,
5276 };
5377 }
5478 }
@@ -61,7 +85,6 @@ async function resolveMembershipAccountAndOrganization( · 6 unmodified lines
6185 return {
6286 account: null,
6387 organization: null,
64− fallbackRole: undefined as Doc<"workspaceMembers">["role"] | undefined,
6588 };
6689 }
6790
@@ -251,7 +274,10 @@ export const workosEventHandlers = { · 183 unmodified lines
251274
252275 "organization_membership.created": async (ctx, event) => {
253276 const now = Date.now();
254− const data = event.data as WorkosMembershipEventData;
277+ const data = parseMembershipEventData(event.data);
278+ if (!data) {
279+ return;
280+ }
255281 const { account, organization } = await resolveMembershipAccountAndOrganization(ctx, data);
256282 if (!account || !organization) return;
257283
@@ -279,7 +305,10 @@ export const workosEventHandlers = { · 21 unmodified lines
279305
280306 "organization_membership.updated": async (ctx, event) => {
281307 const now = Date.now();
282− const data = event.data as WorkosMembershipEventData;
308+ const data = parseMembershipEventData(event.data);
309+ if (!data) {
310+ return;
311+ }
283312 const { account, organization } = await resolveMembershipAccountAndOrganization(ctx, data);
284313
285314 if (!account || !organization) {
@@ -310,7 +339,10 @@ export const workosEventHandlers = { · 24 unmodified lines
310339
311340 "organization_membership.deleted": async (ctx, event) => {
312341 const now = Date.now();
313− const data = event.data as WorkosMembershipEventData;
342+ const data = parseMembershipEventData(event.data);
343+ if (!data) {
344+ return;
345+ }
314346 const { account, organization, fallbackRole } = await resolveMembershipAccountAndOrganization(ctx, data);
315347 if (!account || !organization) {
316348 return;