From 3b186b19e6c0fbd1410d45dc8e610ca050b34b87 Mon Sep 17 00:00:00 2001 From: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Date: Wed, 7 Aug 2024 12:01:51 -0400 Subject: [PATCH] fix: SCIM improvements (#16103) * Add error logging for body * Use user repository --- apps/web/pages/api/scim/v2.0/[...directory].ts | 14 +++++++++++++- .../features/ee/dsync/lib/handleGroupEvents.ts | 2 -- packages/features/ee/dsync/lib/handleUserEvents.ts | 3 ++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/apps/web/pages/api/scim/v2.0/[...directory].ts b/apps/web/pages/api/scim/v2.0/[...directory].ts index 4bec6db766..b20f9dc6ed 100644 --- a/apps/web/pages/api/scim/v2.0/[...directory].ts +++ b/apps/web/pages/api/scim/v2.0/[...directory].ts @@ -4,16 +4,28 @@ import type { NextApiRequest, NextApiResponse } from "next"; import handleGroupEvents from "@calcom/features/ee/dsync/lib/handleGroupEvents"; import handleUserEvents from "@calcom/features/ee/dsync/lib/handleUserEvents"; import jackson from "@calcom/features/ee/sso/lib/jackson"; +import logger from "@calcom/lib/logger"; import prisma from "@calcom/prisma"; // This is the handler for the SCIM API requests export default async function handler(req: NextApiRequest, res: NextApiResponse) { + const log = logger.getSubLogger({ prefix: ["[scim]"] }); const { dsyncController } = await jackson(); const { method, query, body } = req; const [directoryId, path, resourceId] = query.directory as string[]; + let responseBody: object | undefined = undefined; + + if (body) { + try { + responseBody = JSON.parse(body); + } catch (e) { + log.error(`Error parsing SCIM event for directoryId ${directoryId} with error: ${e} and body ${body}`); + } + } + // Handle the SCIM API requests const request: DirectorySyncRequest = { method: method as string, @@ -21,7 +33,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) resourceId, apiSecret: extractAuthToken(req), resourceType: path === "Users" ? "users" : "groups", - body: body ? JSON.parse(body) : undefined, + body: responseBody, query: { count: req.query.count ? parseInt(req.query.count as string) : undefined, startIndex: req.query.startIndex ? parseInt(req.query.startIndex as string) : undefined, diff --git a/packages/features/ee/dsync/lib/handleGroupEvents.ts b/packages/features/ee/dsync/lib/handleGroupEvents.ts index efa58f5c41..73f1d127d4 100644 --- a/packages/features/ee/dsync/lib/handleGroupEvents.ts +++ b/packages/features/ee/dsync/lib/handleGroupEvents.ts @@ -1,6 +1,5 @@ import type { DirectorySyncEvent, Group } from "@boxyhq/saml-jackson"; -import jackson from "@calcom/features/ee/sso/lib/jackson"; import { createAProfileForAnExistingUser } from "@calcom/lib/createAProfileForAnExistingUser"; import { getTranslation } from "@calcom/lib/server/i18n"; import prisma from "@calcom/prisma"; @@ -14,7 +13,6 @@ import { import createUsersAndConnectToOrg from "./users/createUsersAndConnectToOrg"; const handleGroupEvents = async (event: DirectorySyncEvent, organizationId: number) => { - const { dsyncController } = await jackson(); // Find the group name associated with the event const eventData = event.data as Group; diff --git a/packages/features/ee/dsync/lib/handleUserEvents.ts b/packages/features/ee/dsync/lib/handleUserEvents.ts index f301467c28..64165a95e7 100644 --- a/packages/features/ee/dsync/lib/handleUserEvents.ts +++ b/packages/features/ee/dsync/lib/handleUserEvents.ts @@ -2,6 +2,7 @@ import type { DirectorySyncEvent, User } from "@boxyhq/saml-jackson"; import removeUserFromOrg from "@calcom/features/ee/dsync/lib/removeUserFromOrg"; import { getTranslation } from "@calcom/lib/server/i18n"; +import { UserRepository } from "@calcom/lib/server/repository/user"; import prisma from "@calcom/prisma"; import { IdentityProvider } from "@calcom/prisma/enums"; import { getTeamOrThrow } from "@calcom/trpc/server/routers/viewer/teams/inviteMember/utils"; @@ -25,7 +26,7 @@ const handleUserEvents = async (event: DirectorySyncEvent, organizationId: numbe }); // User is already a part of that org - if (user?.organizationId && eventData.active) { + if (user && UserRepository.isAMemberOfOrganization({ user, organizationId }) && eventData.active) { return; }