@better-auth/scim 1.5.7-beta.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { t as PACKAGE_VERSION } from "./version-Cf5gNNxE.mjs";
1
2
  import { base64Url } from "@better-auth/utils/base64";
2
3
  import { APIError, createAuthEndpoint, createAuthMiddleware, sessionMiddleware } from "better-auth/api";
3
4
  import { APIError as APIError$1, HIDE_METADATA } from "better-auth";
@@ -613,7 +614,21 @@ const generateSCIMTokenBodySchema = z.object({
613
614
  });
614
615
  const getSCIMProviderConnectionQuerySchema = z.object({ providerId: z.string() });
615
616
  const deleteSCIMProviderConnectionBodySchema = z.object({ providerId: z.string() });
616
- async function getSCIMUserOrgIds(ctx, userId) {
617
+ function parseMemberRoles(role) {
618
+ return role.split(",").map((entry) => entry.trim()).filter(Boolean);
619
+ }
620
+ function hasRequiredRole(memberRole, requiredRole) {
621
+ return !requiredRole.length || parseMemberRoles(memberRole).some((role) => requiredRole.includes(role));
622
+ }
623
+ function resolveRequiredRoles(ctx, opts) {
624
+ if (opts.requiredRole) return opts.requiredRole;
625
+ const creatorRole = ctx.context.getPlugin("organization")?.options?.creatorRole;
626
+ return Array.from(new Set(["admin", creatorRole ?? "owner"]));
627
+ }
628
+ function isProviderOwnershipEnabled(opts) {
629
+ return opts.providerOwnership?.enabled ?? false;
630
+ }
631
+ async function getSCIMUserOrgMemberships(ctx, userId) {
617
632
  const members = await ctx.context.adapter.findMany({
618
633
  model: "member",
619
634
  where: [{
@@ -621,7 +636,7 @@ async function getSCIMUserOrgIds(ctx, userId) {
621
636
  value: userId
622
637
  }]
623
638
  });
624
- return new Set(members.map((m) => m.organizationId));
639
+ return new Map(members.map((member) => [member.organizationId, parseMemberRoles(member.role)]));
625
640
  }
626
641
  function normalizeSCIMProvider(provider) {
627
642
  return {
@@ -642,13 +657,15 @@ async function findOrganizationMember(ctx, userId, organizationId) {
642
657
  }]
643
658
  });
644
659
  }
645
- async function assertSCIMProviderAccess(ctx, userId, provider) {
660
+ async function assertSCIMProviderAccess(ctx, userId, provider, requiredRole) {
646
661
  if (provider.organizationId) {
647
662
  if (!ctx.context.hasPlugin("organization")) throw new APIError("FORBIDDEN", { message: "Organization plugin is required to access this SCIM provider" });
648
- if (!await findOrganizationMember(ctx, userId, provider.organizationId)) throw new APIError("FORBIDDEN", { message: "You must be a member of the organization to access this provider" });
663
+ const member = await findOrganizationMember(ctx, userId, provider.organizationId);
664
+ if (!member) throw new APIError("FORBIDDEN", { message: "You must be a member of the organization to access this provider" });
665
+ if (!hasRequiredRole(member.role, requiredRole)) throw new APIError("FORBIDDEN", { message: "Insufficient role for this operation" });
649
666
  } else if (provider.userId && provider.userId !== userId) throw new APIError("FORBIDDEN", { message: "You must be the owner to access this provider" });
650
667
  }
651
- async function checkSCIMProviderAccess(ctx, userId, providerId) {
668
+ async function checkSCIMProviderAccess(ctx, userId, providerId, requiredRole) {
652
669
  const provider = await ctx.context.adapter.findOne({
653
670
  model: "scimProvider",
654
671
  where: [{
@@ -657,7 +674,7 @@ async function checkSCIMProviderAccess(ctx, userId, providerId) {
657
674
  }]
658
675
  });
659
676
  if (!provider) throw new APIError("NOT_FOUND", { message: "SCIM provider not found" });
660
- await assertSCIMProviderAccess(ctx, userId, provider);
677
+ await assertSCIMProviderAccess(ctx, userId, provider, requiredRole);
661
678
  return provider;
662
679
  }
663
680
  const generateSCIMToken = (opts) => createAuthEndpoint("/scim/generate-token", {
@@ -681,12 +698,14 @@ const generateSCIMToken = (opts) => createAuthEndpoint("/scim/generate-token", {
681
698
  }, async (ctx) => {
682
699
  const { providerId, organizationId } = ctx.body;
683
700
  const user = ctx.context.session.user;
701
+ const requiredRole = resolveRequiredRoles(ctx, opts);
684
702
  if (providerId.includes(":")) throw new APIError("BAD_REQUEST", { message: "Provider id contains forbidden characters" });
685
703
  if (organizationId && !ctx.context.hasPlugin("organization")) throw new APIError("BAD_REQUEST", { message: "Restricting a token to an organization requires the organization plugin" });
686
704
  let member = null;
687
705
  if (organizationId) {
688
706
  member = await findOrganizationMember(ctx, user.id, organizationId);
689
707
  if (!member) throw new APIError("FORBIDDEN", { message: "You are not a member of the organization" });
708
+ if (!hasRequiredRole(member.role, requiredRole)) throw new APIError("FORBIDDEN", { message: "Insufficient role for this operation" });
690
709
  }
691
710
  const scimProvider = await ctx.context.adapter.findOne({
692
711
  model: "scimProvider",
@@ -699,7 +718,7 @@ const generateSCIMToken = (opts) => createAuthEndpoint("/scim/generate-token", {
699
718
  }] : []]
700
719
  });
701
720
  if (scimProvider) {
702
- await assertSCIMProviderAccess(ctx, user.id, scimProvider);
721
+ await assertSCIMProviderAccess(ctx, user.id, scimProvider, requiredRole);
703
722
  await ctx.context.adapter.delete({
704
723
  model: "scimProvider",
705
724
  where: [{
@@ -721,7 +740,7 @@ const generateSCIMToken = (opts) => createAuthEndpoint("/scim/generate-token", {
721
740
  providerId,
722
741
  organizationId,
723
742
  scimToken: await storeSCIMToken(ctx, opts, baseToken),
724
- ...opts.providerOwnership?.enabled ? { userId: user.id } : {}
743
+ ...isProviderOwnershipEnabled(opts) ? { userId: user.id } : {}
725
744
  }
726
745
  });
727
746
  if (opts.afterSCIMTokenGenerated) await opts.afterSCIMTokenGenerated({
@@ -733,13 +752,13 @@ const generateSCIMToken = (opts) => createAuthEndpoint("/scim/generate-token", {
733
752
  ctx.setStatus(201);
734
753
  return ctx.json({ scimToken });
735
754
  });
736
- const listSCIMProviderConnections = () => createAuthEndpoint("/scim/list-provider-connections", {
755
+ const listSCIMProviderConnections = (opts) => createAuthEndpoint("/scim/list-provider-connections", {
737
756
  method: "GET",
738
757
  use: [sessionMiddleware],
739
758
  metadata: { openapi: {
740
759
  operationId: "listSCIMProviderConnections",
741
760
  summary: "List SCIM providers",
742
- description: "Returns SCIM providers for organizations the user is a member of.",
761
+ description: "Returns SCIM providers the user owns or has the required org role for.",
743
762
  responses: { "200": {
744
763
  description: "List of SCIM providers",
745
764
  content: { "application/json": { schema: {
@@ -763,15 +782,18 @@ const listSCIMProviderConnections = () => createAuthEndpoint("/scim/list-provide
763
782
  } }
764
783
  }, async (ctx) => {
765
784
  const userId = ctx.context.session.user.id;
766
- const userOrgIds = ctx.context.hasPlugin("organization") ? await getSCIMUserOrgIds(ctx, userId) : /* @__PURE__ */ new Set();
785
+ const requiredRole = resolveRequiredRoles(ctx, opts);
786
+ const orgMemberships = ctx.context.hasPlugin("organization") ? await getSCIMUserOrgMemberships(ctx, userId) : /* @__PURE__ */ new Map();
767
787
  const providers = (await ctx.context.adapter.findMany({ model: "scimProvider" })).filter((p) => {
768
- if (p.organizationId) return userOrgIds.has(p.organizationId);
769
- if (p.userId === userId) return true;
770
- return !p.userId;
788
+ if (p.organizationId) {
789
+ const roles = orgMemberships.get(p.organizationId);
790
+ return roles ? !requiredRole.length || roles.some((role) => requiredRole.includes(role)) : false;
791
+ }
792
+ return p.userId === userId || !p.userId;
771
793
  }).map((p) => normalizeSCIMProvider(p));
772
794
  return ctx.json({ providers });
773
795
  });
774
- const getSCIMProviderConnection = () => createAuthEndpoint("/scim/get-provider-connection", {
796
+ const getSCIMProviderConnection = (opts) => createAuthEndpoint("/scim/get-provider-connection", {
775
797
  method: "GET",
776
798
  use: [sessionMiddleware],
777
799
  query: getSCIMProviderConnectionQuerySchema,
@@ -801,10 +823,10 @@ const getSCIMProviderConnection = () => createAuthEndpoint("/scim/get-provider-c
801
823
  }, async (ctx) => {
802
824
  const { providerId } = ctx.query;
803
825
  const userId = ctx.context.session.user.id;
804
- const provider = await checkSCIMProviderAccess(ctx, userId, providerId);
826
+ const provider = await checkSCIMProviderAccess(ctx, userId, providerId, resolveRequiredRoles(ctx, opts));
805
827
  return ctx.json(normalizeSCIMProvider(provider));
806
828
  });
807
- const deleteSCIMProviderConnection = () => createAuthEndpoint("/scim/delete-provider-connection", {
829
+ const deleteSCIMProviderConnection = (opts) => createAuthEndpoint("/scim/delete-provider-connection", {
808
830
  method: "POST",
809
831
  use: [sessionMiddleware],
810
832
  body: deleteSCIMProviderConnectionBodySchema,
@@ -827,7 +849,7 @@ const deleteSCIMProviderConnection = () => createAuthEndpoint("/scim/delete-prov
827
849
  }, async (ctx) => {
828
850
  const { providerId } = ctx.body;
829
851
  const userId = ctx.context.session.user.id;
830
- await checkSCIMProviderAccess(ctx, userId, providerId);
852
+ await checkSCIMProviderAccess(ctx, userId, providerId, resolveRequiredRoles(ctx, opts));
831
853
  await ctx.context.adapter.delete({
832
854
  model: "scimProvider",
833
855
  where: [{
@@ -1416,17 +1438,18 @@ const parseSCIMAPIUserFilter = (filter) => {
1416
1438
  const scim = (options) => {
1417
1439
  const opts = {
1418
1440
  storeSCIMToken: "plain",
1419
- providerOwnership: { enabled: false },
1420
1441
  ...options
1421
1442
  };
1443
+ const providerOwnershipEnabled = options?.providerOwnership?.enabled ?? false;
1422
1444
  const authMiddleware = authMiddlewareFactory(opts);
1423
1445
  return {
1424
1446
  id: "scim",
1447
+ version: PACKAGE_VERSION,
1425
1448
  endpoints: {
1426
1449
  generateSCIMToken: generateSCIMToken(opts),
1427
- listSCIMProviderConnections: listSCIMProviderConnections(),
1428
- getSCIMProviderConnection: getSCIMProviderConnection(),
1429
- deleteSCIMProviderConnection: deleteSCIMProviderConnection(),
1450
+ listSCIMProviderConnections: listSCIMProviderConnections(opts),
1451
+ getSCIMProviderConnection: getSCIMProviderConnection(opts),
1452
+ deleteSCIMProviderConnection: deleteSCIMProviderConnection(opts),
1430
1453
  getSCIMUser: getSCIMUser(authMiddleware),
1431
1454
  createSCIMUser: createSCIMUser(authMiddleware),
1432
1455
  patchSCIMUser: patchSCIMUser(authMiddleware),
@@ -1454,7 +1477,7 @@ const scim = (options) => {
1454
1477
  type: "string",
1455
1478
  required: false
1456
1479
  },
1457
- ...opts.providerOwnership?.enabled ? { userId: {
1480
+ ...providerOwnershipEnabled ? { userId: {
1458
1481
  type: "string",
1459
1482
  required: false
1460
1483
  } } : {}
@@ -1464,5 +1487,3 @@ const scim = (options) => {
1464
1487
  };
1465
1488
  //#endregion
1466
1489
  export { scim };
1467
-
1468
- //# sourceMappingURL=index.mjs.map
@@ -0,0 +1,5 @@
1
+ //#endregion
2
+ //#region src/version.ts
3
+ const PACKAGE_VERSION = "1.6.0";
4
+ //#endregion
5
+ export { PACKAGE_VERSION as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/scim",
3
- "version": "1.5.7-beta.1",
3
+ "version": "1.6.0",
4
4
  "description": "SCIM plugin for Better Auth",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -20,6 +20,7 @@
20
20
  "publishConfig": {
21
21
  "access": "public"
22
22
  },
23
+ "sideEffects": false,
23
24
  "files": [
24
25
  "dist"
25
26
  ],
@@ -49,23 +50,23 @@
49
50
  }
50
51
  },
51
52
  "dependencies": {
52
- "@better-auth/utils": "0.3.1",
53
- "better-call": "2.0.2",
54
53
  "zod": "^4.3.6"
55
54
  },
56
55
  "devDependencies": {
57
56
  "tsdown": "0.21.1",
58
- "@better-auth/core": "1.5.7-beta.1",
59
- "@better-auth/sso": "1.5.7-beta.1"
57
+ "@better-auth/core": "1.6.0",
58
+ "@better-auth/sso": "1.6.0"
60
59
  },
61
60
  "peerDependencies": {
62
- "@better-auth/core": "1.5.7-beta.1",
63
- "better-auth": "1.5.7-beta.1"
61
+ "@better-auth/utils": "0.4.0",
62
+ "better-call": "1.3.5",
63
+ "@better-auth/core": "^1.6.0",
64
+ "better-auth": "^1.6.0"
64
65
  },
65
66
  "scripts": {
66
67
  "build": "tsdown",
67
68
  "dev": "tsdown --watch",
68
- "lint:package": "publint run --strict",
69
+ "lint:package": "publint run --strict --pack false",
69
70
  "lint:types": "attw --profile esm-only --pack .",
70
71
  "typecheck": "tsc --project tsconfig.json",
71
72
  "test": "vitest",
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.mjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["import type { BetterAuthClientPlugin } from \"better-auth/client\";\nimport type { scim } from \"./index\";\n\nexport const scimClient = () => {\n\treturn {\n\t\tid: \"scim-client\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof scim>,\n\t} satisfies BetterAuthClientPlugin;\n};\n"],"mappings":";AAGA,MAAa,mBAAmB;AAC/B,QAAO;EACN,IAAI;EACJ,oBAAoB,EAAE;EACtB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":["APIError"],"sources":["../src/scim-error.ts","../src/scim-tokens.ts","../src/middlewares.ts","../src/mappings.ts","../src/patch-operations.ts","../src/user-schemas.ts","../src/scim-filters.ts","../src/scim-metadata.ts","../src/utils.ts","../src/scim-resources.ts","../src/routes.ts","../src/index.ts"],"sourcesContent":["import type { Status } from \"better-auth\";\nimport { APIError } from \"better-auth\";\nimport { statusCodes } from \"better-call\";\n\n/**\n * SCIM compliant error\n * See: https://datatracker.ietf.org/doc/html/rfc7644#section-3.12\n */\nexport class SCIMAPIError extends APIError {\n\tconstructor(\n\t\tstatus: keyof typeof statusCodes | Status = \"INTERNAL_SERVER_ERROR\",\n\t\toverrides: any = {},\n\t) {\n\t\tconst body = {\n\t\t\tschemas: [\"urn:ietf:params:scim:api:messages:2.0:Error\"],\n\t\t\tstatus: (typeof status === \"number\"\n\t\t\t\t? status\n\t\t\t\t: statusCodes[status]\n\t\t\t).toString(),\n\t\t\tdetail: overrides.detail,\n\t\t\t...overrides,\n\t\t};\n\t\tsuper(status, body);\n\t\tthis.message = body.detail ?? body.message;\n\t}\n}\n\nconst SCIMErrorOpenAPISchema = {\n\ttype: \"object\",\n\tproperties: {\n\t\tschemas: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\tstatus: {\n\t\t\ttype: \"string\",\n\t\t},\n\t\tdetail: {\n\t\t\ttype: \"string\",\n\t\t},\n\t\tscimType: {\n\t\t\ttype: \"string\",\n\t\t},\n\t},\n} as const;\n\nexport const SCIMErrorOpenAPISchemas = {\n\t\"400\": {\n\t\tdescription:\n\t\t\t\"Bad Request. Usually due to missing parameters, or invalid parameters\",\n\t\tcontent: {\n\t\t\t\"application/json\": {\n\t\t\t\tschema: SCIMErrorOpenAPISchema,\n\t\t\t},\n\t\t},\n\t},\n\t\"401\": {\n\t\tdescription: \"Unauthorized. Due to missing or invalid authentication.\",\n\t\tcontent: {\n\t\t\t\"application/json\": {\n\t\t\t\tschema: SCIMErrorOpenAPISchema,\n\t\t\t},\n\t\t},\n\t},\n\t\"403\": {\n\t\tdescription: \"Unauthorized. Due to missing or invalid authentication.\",\n\t\tcontent: {\n\t\t\t\"application/json\": {\n\t\t\t\tschema: SCIMErrorOpenAPISchema,\n\t\t\t},\n\t\t},\n\t},\n\t\"404\": {\n\t\tdescription: \"Not Found. The requested resource was not found.\",\n\t\tcontent: {\n\t\t\t\"application/json\": {\n\t\t\t\tschema: SCIMErrorOpenAPISchema,\n\t\t\t},\n\t\t},\n\t},\n\t\"429\": {\n\t\tdescription:\n\t\t\t\"Too Many Requests. You have exceeded the rate limit. Try again later.\",\n\t\tcontent: {\n\t\t\t\"application/json\": {\n\t\t\t\tschema: SCIMErrorOpenAPISchema,\n\t\t\t},\n\t\t},\n\t},\n\t\"500\": {\n\t\tdescription:\n\t\t\t\"Internal Server Error. This is a problem with the server that you cannot fix.\",\n\t\tcontent: {\n\t\t\t\"application/json\": {\n\t\t\t\tschema: SCIMErrorOpenAPISchema,\n\t\t\t},\n\t\t},\n\t},\n};\n","import { base64Url } from \"@better-auth/utils/base64\";\nimport { createHash } from \"@better-auth/utils/hash\";\nimport type { GenericEndpointContext } from \"better-auth\";\nimport { symmetricDecrypt, symmetricEncrypt } from \"better-auth/crypto\";\nimport type { SCIMOptions } from \"./types\";\n\nconst defaultKeyHasher = async (token: string) => {\n\tconst hash = await createHash(\"SHA-256\").digest(\n\t\tnew TextEncoder().encode(token),\n\t);\n\treturn base64Url.encode(new Uint8Array(hash), { padding: false });\n};\n\nexport async function storeSCIMToken(\n\tctx: GenericEndpointContext,\n\topts: SCIMOptions,\n\tscimToken: string,\n) {\n\tif (opts.storeSCIMToken === \"encrypted\") {\n\t\treturn await symmetricEncrypt({\n\t\t\tkey: ctx.context.secretConfig,\n\t\t\tdata: scimToken,\n\t\t});\n\t}\n\tif (opts.storeSCIMToken === \"hashed\") {\n\t\treturn await defaultKeyHasher(scimToken);\n\t}\n\tif (\n\t\ttypeof opts.storeSCIMToken === \"object\" &&\n\t\t\"hash\" in opts.storeSCIMToken\n\t) {\n\t\treturn await opts.storeSCIMToken.hash(scimToken);\n\t}\n\tif (\n\t\ttypeof opts.storeSCIMToken === \"object\" &&\n\t\t\"encrypt\" in opts.storeSCIMToken\n\t) {\n\t\treturn await opts.storeSCIMToken.encrypt(scimToken);\n\t}\n\n\treturn scimToken;\n}\n\nexport async function verifySCIMToken(\n\tctx: GenericEndpointContext,\n\topts: SCIMOptions,\n\tstoredSCIMToken: string,\n\tscimToken: string,\n): Promise<boolean> {\n\tif (opts.storeSCIMToken === \"encrypted\") {\n\t\treturn (\n\t\t\t(await symmetricDecrypt({\n\t\t\t\tkey: ctx.context.secretConfig,\n\t\t\t\tdata: storedSCIMToken,\n\t\t\t})) === scimToken\n\t\t);\n\t}\n\tif (opts.storeSCIMToken === \"hashed\") {\n\t\tconst hashedSCIMToken = await defaultKeyHasher(scimToken);\n\t\treturn hashedSCIMToken === storedSCIMToken;\n\t}\n\tif (\n\t\ttypeof opts.storeSCIMToken === \"object\" &&\n\t\t\"hash\" in opts.storeSCIMToken\n\t) {\n\t\tconst hashedSCIMToken = await opts.storeSCIMToken.hash(scimToken);\n\t\treturn hashedSCIMToken === storedSCIMToken;\n\t}\n\tif (\n\t\ttypeof opts.storeSCIMToken === \"object\" &&\n\t\t\"decrypt\" in opts.storeSCIMToken\n\t) {\n\t\tconst decryptedSCIMToken =\n\t\t\tawait opts.storeSCIMToken.decrypt(storedSCIMToken);\n\t\treturn decryptedSCIMToken === scimToken;\n\t}\n\n\treturn scimToken === storedSCIMToken;\n}\n","import { base64Url } from \"@better-auth/utils/base64\";\nimport { createAuthMiddleware } from \"better-auth/api\";\nimport { SCIMAPIError } from \"./scim-error\";\nimport { verifySCIMToken } from \"./scim-tokens\";\nimport type { SCIMOptions, SCIMProvider } from \"./types\";\n\nexport type AuthMiddleware = ReturnType<typeof authMiddlewareFactory>;\n\n/**\n * The middleware forces the endpoint to have a valid token\n */\nexport const authMiddlewareFactory = (opts: SCIMOptions) =>\n\tcreateAuthMiddleware(async (ctx) => {\n\t\tconst authHeader = ctx.headers?.get(\"Authorization\");\n\t\tconst authSCIMToken = authHeader?.replace(/^Bearer\\s+/i, \"\");\n\n\t\tif (!authSCIMToken) {\n\t\t\tthrow new SCIMAPIError(\"UNAUTHORIZED\", {\n\t\t\t\tdetail: \"SCIM token is required\",\n\t\t\t});\n\t\t}\n\n\t\tconst baseScimTokenParts = new TextDecoder()\n\t\t\t.decode(base64Url.decode(authSCIMToken))\n\t\t\t.split(\":\");\n\n\t\tconst [scimToken, providerId] = baseScimTokenParts;\n\t\tconst organizationId = baseScimTokenParts.slice(2).join(\":\");\n\n\t\tif (!scimToken || !providerId) {\n\t\t\tthrow new SCIMAPIError(\"UNAUTHORIZED\", {\n\t\t\t\tdetail: \"Invalid SCIM token\",\n\t\t\t});\n\t\t}\n\n\t\tlet scimProvider: Omit<SCIMProvider, \"id\"> | null =\n\t\t\topts.defaultSCIM?.find((p) => {\n\t\t\t\tif (p.providerId === providerId && !organizationId) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn !!(\n\t\t\t\t\tp.providerId === providerId &&\n\t\t\t\t\torganizationId &&\n\t\t\t\t\tp.organizationId === organizationId\n\t\t\t\t);\n\t\t\t}) ?? null;\n\n\t\tif (scimProvider) {\n\t\t\tif (scimProvider.scimToken === scimToken) {\n\t\t\t\treturn { authSCIMToken: scimProvider.scimToken, scimProvider };\n\t\t\t} else {\n\t\t\t\tthrow new SCIMAPIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tdetail: \"Invalid SCIM token\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tscimProvider = await ctx.context.adapter.findOne<SCIMProvider>({\n\t\t\tmodel: \"scimProvider\",\n\t\t\twhere: [\n\t\t\t\t{ field: \"providerId\", value: providerId },\n\t\t\t\t...(organizationId\n\t\t\t\t\t? [{ field: \"organizationId\", value: organizationId }]\n\t\t\t\t\t: []),\n\t\t\t],\n\t\t});\n\n\t\tif (!scimProvider) {\n\t\t\tthrow new SCIMAPIError(\"UNAUTHORIZED\", {\n\t\t\t\tdetail: \"Invalid SCIM token\",\n\t\t\t});\n\t\t}\n\n\t\tconst isValidToken = await verifySCIMToken(\n\t\t\tctx,\n\t\t\topts,\n\t\t\tscimProvider.scimToken,\n\t\t\tscimToken,\n\t\t);\n\n\t\tif (!isValidToken) {\n\t\t\tthrow new SCIMAPIError(\"UNAUTHORIZED\", {\n\t\t\t\tdetail: \"Invalid SCIM token\",\n\t\t\t});\n\t\t}\n\n\t\treturn { authSCIMToken: scimToken, scimProvider };\n\t});\n","import type { SCIMEmail, SCIMName } from \"./types\";\n\nexport const getAccountId = (userName: string, externalId?: string) => {\n\treturn externalId ?? userName;\n};\n\nconst getFormattedName = (name: SCIMName) => {\n\tif (name.givenName && name.familyName) {\n\t\treturn `${name.givenName} ${name.familyName}`;\n\t}\n\n\tif (name.givenName) {\n\t\treturn name.givenName;\n\t}\n\n\treturn name.familyName ?? \"\";\n};\n\nexport const getUserFullName = (email: string, name?: SCIMName) => {\n\tif (name) {\n\t\tconst formatted = name.formatted?.trim() ?? \"\";\n\t\tif (formatted.length > 0) {\n\t\t\treturn formatted;\n\t\t}\n\n\t\treturn getFormattedName(name) || email;\n\t}\n\n\treturn email;\n};\n\nexport const getUserPrimaryEmail = (userName: string, emails?: SCIMEmail[]) => {\n\treturn (\n\t\temails?.find((email) => email.primary)?.value ??\n\t\temails?.[0]?.value ??\n\t\tuserName\n\t);\n};\n","import type { User } from \"better-auth\";\nimport { getUserFullName } from \"./mappings\";\n\ntype Operation = {\n\top: \"add\" | \"remove\" | \"replace\";\n\tvalue: any;\n\tpath?: string;\n};\n\ntype Mapping = {\n\ttarget: string;\n\tresource: \"user\" | \"account\";\n\tmap: (user: User, op: Operation, resources: Resources) => any;\n};\n\ntype Resources = {\n\tuser: Record<string, any>;\n\taccount: Record<string, any>;\n};\n\nconst identity = (user: User, op: Operation, resources: Resources) => {\n\treturn op.value;\n};\n\nconst lowerCase = (user: User, op: Operation, resources: Resources) => {\n\treturn op.value.toLowerCase();\n};\n\nconst givenName = (user: User, op: Operation, resources: Resources) => {\n\tconst currentName = (resources.user.name as string) ?? user.name;\n\tconst familyName = currentName.split(\" \").slice(1).join(\" \").trim();\n\tconst givenName = op.value;\n\n\treturn getUserFullName(user.email, {\n\t\tgivenName,\n\t\tfamilyName,\n\t});\n};\n\nconst familyName = (user: User, op: Operation, resources: Resources) => {\n\tconst currentName = (resources.user.name as string) ?? user.name;\n\tconst givenName = (\n\t\tcurrentName.split(\" \").slice(0, -1).join(\" \") || currentName\n\t).trim();\n\tconst familyName = op.value;\n\treturn getUserFullName(user.email, {\n\t\tgivenName,\n\t\tfamilyName,\n\t});\n};\n\nconst userPatchMappings: Record<string, Mapping> = {\n\t\"/name/formatted\": { resource: \"user\", target: \"name\", map: identity },\n\t\"/name/givenName\": { resource: \"user\", target: \"name\", map: givenName },\n\t\"/name/familyName\": {\n\t\tresource: \"user\",\n\t\ttarget: \"name\",\n\t\tmap: familyName,\n\t},\n\t\"/externalId\": {\n\t\tresource: \"account\",\n\t\ttarget: \"accountId\",\n\t\tmap: identity,\n\t},\n\t\"/userName\": { resource: \"user\", target: \"email\", map: lowerCase },\n};\n\nconst normalizePath = (path: string): string => {\n\tconst withoutLeadingSlash = path.startsWith(\"/\") ? path.slice(1) : path;\n\treturn `/${withoutLeadingSlash.replaceAll(\".\", \"/\")}`;\n};\n\nconst isNestedObject = (value: unknown): value is Record<string, unknown> => {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n};\n\nconst applyMapping = (\n\tuser: User,\n\tresources: Resources,\n\tpath: string,\n\tvalue: unknown,\n\top: \"add\" | \"replace\",\n) => {\n\tconst normalizedPath = normalizePath(path);\n\tconst mapping = userPatchMappings[normalizedPath];\n\n\tif (!mapping) {\n\t\treturn;\n\t}\n\n\tconst newValue = mapping.map(\n\t\tuser,\n\t\t{\n\t\t\top,\n\t\t\tvalue,\n\t\t\tpath: normalizedPath,\n\t\t},\n\t\tresources,\n\t);\n\n\tif (op === \"add\" && mapping.resource === \"user\") {\n\t\tconst currentValue = (user as Record<string, unknown>)[mapping.target];\n\t\tif (currentValue === newValue) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\tresources[mapping.resource][mapping.target] = newValue;\n};\n\nconst applyPatchValue = (\n\tuser: User,\n\tresources: Resources,\n\tvalue: unknown,\n\top: \"add\" | \"replace\",\n\tpath?: string | undefined,\n) => {\n\tif (isNestedObject(value)) {\n\t\tfor (const [key, nestedValue] of Object.entries(value)) {\n\t\t\tconst nestedPath = path ? `${path}.${key}` : key;\n\t\t\tapplyPatchValue(user, resources, nestedValue, op, nestedPath);\n\t\t}\n\t} else if (path) {\n\t\tapplyMapping(user, resources, path, value, op);\n\t}\n};\n\nexport const buildUserPatch = (user: User, operations: Operation[]) => {\n\tconst userPatch: Record<string, any> = {};\n\tconst accountPatch: Record<string, any> = {};\n\tconst resources: Resources = { user: userPatch, account: accountPatch };\n\n\tfor (const operation of operations) {\n\t\tif (operation.op !== \"add\" && operation.op !== \"replace\") {\n\t\t\tcontinue;\n\t\t}\n\n\t\tapplyPatchValue(\n\t\t\tuser,\n\t\t\tresources,\n\t\t\toperation.value,\n\t\t\toperation.op,\n\t\t\toperation.path,\n\t\t);\n\t}\n\n\treturn resources;\n};\n","import * as z from \"zod\";\n\nexport const APIUserSchema = z.object({\n\tuserName: z.string().lowercase(),\n\texternalId: z.string().optional(),\n\tname: z\n\t\t.object({\n\t\t\tformatted: z.string().optional(),\n\t\t\tgivenName: z.string().optional(),\n\t\t\tfamilyName: z.string().optional(),\n\t\t})\n\t\t.optional(),\n\temails: z\n\t\t.array(\n\t\t\tz.object({\n\t\t\t\tvalue: z.email(),\n\t\t\t\tprimary: z.boolean().optional(),\n\t\t\t}),\n\t\t)\n\t\t.optional(),\n});\n\nexport const OpenAPIUserResourceSchema = {\n\ttype: \"object\",\n\tproperties: {\n\t\tid: { type: \"string\" },\n\t\tmeta: {\n\t\t\ttype: \"object\",\n\t\t\tproperties: {\n\t\t\t\tresourceType: { type: \"string\" },\n\t\t\t\tcreated: { type: \"string\", format: \"date-time\" },\n\t\t\t\tlastModified: { type: \"string\", format: \"date-time\" },\n\t\t\t\tlocation: { type: \"string\" },\n\t\t\t},\n\t\t},\n\t\tuserName: { type: \"string\" },\n\t\tname: {\n\t\t\ttype: \"object\",\n\t\t\tproperties: {\n\t\t\t\tformatted: { type: \"string\" },\n\t\t\t\tgivenName: { type: \"string\" },\n\t\t\t\tfamilyName: { type: \"string\" },\n\t\t\t},\n\t\t},\n\t\tdisplayName: { type: \"string\" },\n\t\tactive: { type: \"boolean\" },\n\t\temails: {\n\t\t\ttype: \"array\",\n\t\t\titems: {\n\t\t\t\ttype: \"object\",\n\t\t\t\tproperties: {\n\t\t\t\t\tvalue: { type: \"string\" },\n\t\t\t\t\tprimary: { type: \"boolean\" },\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tschemas: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t},\n} as const;\n\nexport const SCIMUserResourceSchema = {\n\tid: \"urn:ietf:params:scim:schemas:core:2.0:User\",\n\tschemas: [\"urn:ietf:params:scim:schemas:core:2.0:Schema\"],\n\tname: \"User\",\n\tdescription: \"User Account\",\n\tattributes: [\n\t\t{\n\t\t\tname: \"id\",\n\t\t\ttype: \"string\",\n\t\t\tmultiValued: false,\n\t\t\tdescription: \"Unique opaque identifier for the User\",\n\t\t\trequired: false,\n\t\t\tcaseExact: true,\n\t\t\tmutability: \"readOnly\",\n\t\t\treturned: \"default\",\n\t\t\tuniqueness: \"server\",\n\t\t},\n\t\t{\n\t\t\tname: \"userName\",\n\t\t\ttype: \"string\",\n\t\t\tmultiValued: false,\n\t\t\tdescription:\n\t\t\t\t\"Unique identifier for the User, typically used by the user to directly authenticate to the service provider\",\n\t\t\trequired: true,\n\t\t\tcaseExact: false,\n\t\t\tmutability: \"readWrite\",\n\t\t\treturned: \"default\",\n\t\t\tuniqueness: \"server\",\n\t\t},\n\t\t{\n\t\t\tname: \"displayName\",\n\t\t\ttype: \"string\",\n\t\t\tmultiValued: false,\n\t\t\tdescription:\n\t\t\t\t\"The name of the User, suitable for display to end-users. The name SHOULD be the full name of the User being described, if known.\",\n\t\t\trequired: false,\n\t\t\tcaseExact: true,\n\t\t\tmutability: \"readOnly\",\n\t\t\treturned: \"default\",\n\t\t\tuniqueness: \"none\",\n\t\t},\n\t\t{\n\t\t\tname: \"active\",\n\t\t\ttype: \"boolean\",\n\t\t\tmultiValued: false,\n\t\t\tdescription:\n\t\t\t\t\"A Boolean value indicating the User's administrative status.\",\n\t\t\trequired: false,\n\t\t\tmutability: \"readOnly\",\n\t\t\treturned: \"default\",\n\t\t},\n\t\t{\n\t\t\tname: \"name\",\n\t\t\ttype: \"complex\",\n\t\t\tmultiValued: false,\n\t\t\tdescription: \"The components of the user's real name.\",\n\t\t\trequired: false,\n\t\t\tsubAttributes: [\n\t\t\t\t{\n\t\t\t\t\tname: \"formatted\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tmultiValued: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"The full name, including all middlenames, titles, and suffixes as appropriate, formatted for display(e.g., 'Ms. Barbara J Jensen, III').\",\n\t\t\t\t\trequired: false,\n\t\t\t\t\tcaseExact: false,\n\t\t\t\t\tmutability: \"readWrite\",\n\t\t\t\t\treturned: \"default\",\n\t\t\t\t\tuniqueness: \"none\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"familyName\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tmultiValued: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"The family name of the User, or last name in most Western languages (e.g., 'Jensen' given the fullname 'Ms. Barbara J Jensen, III').\",\n\t\t\t\t\trequired: false,\n\t\t\t\t\tcaseExact: false,\n\t\t\t\t\tmutability: \"readWrite\",\n\t\t\t\t\treturned: \"default\",\n\t\t\t\t\tuniqueness: \"none\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"givenName\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tmultiValued: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"The given name of the User, or first name in most Western languages (e.g., 'Barbara' given the full name 'Ms. Barbara J Jensen, III').\",\n\t\t\t\t\trequired: false,\n\t\t\t\t\tcaseExact: false,\n\t\t\t\t\tmutability: \"readWrite\",\n\t\t\t\t\treturned: \"default\",\n\t\t\t\t\tuniqueness: \"none\",\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t{\n\t\t\tname: \"emails\",\n\t\t\ttype: \"complex\",\n\t\t\tmultiValued: true,\n\t\t\tdescription:\n\t\t\t\t\"Email addresses for the user. The value SHOULD be canonicalized by the service provider, e.g., 'bjensen@example.com' instead of 'bjensen@EXAMPLE.COM'. Canonical type values of 'work', 'home', and 'other'.\",\n\t\t\trequired: false,\n\t\t\tsubAttributes: [\n\t\t\t\t{\n\t\t\t\t\tname: \"value\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tmultiValued: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Email addresses for the user. The value SHOULD be canonicalized by the service provider, e.g., 'bjensen@example.com' instead of 'bjensen@EXAMPLE.COM'. Canonical type values of 'work', 'home', and 'other'.\",\n\t\t\t\t\trequired: false,\n\t\t\t\t\tcaseExact: false,\n\t\t\t\t\tmutability: \"readWrite\",\n\t\t\t\t\treturned: \"default\",\n\t\t\t\t\tuniqueness: \"server\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"primary\",\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tmultiValued: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"A Boolean value indicating the 'primary' or preferred attribute value for this attribute, e.g., the preferred mailing address or primary email address. The primary attribute value 'true' MUST appear no more than once.\",\n\t\t\t\t\trequired: false,\n\t\t\t\t\tmutability: \"readWrite\",\n\t\t\t\t\treturned: \"default\",\n\t\t\t\t},\n\t\t\t],\n\t\t\tmutability: \"readWrite\",\n\t\t\treturned: \"default\",\n\t\t\tuniqueness: \"none\",\n\t\t},\n\t],\n\tmeta: {\n\t\tresourceType: \"Schema\",\n\t\tlocation: \"/scim/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:User\",\n\t},\n};\n\nexport const SCIMUserResourceType = {\n\tschemas: [\"urn:ietf:params:scim:schemas:core:2.0:ResourceType\"],\n\tid: \"User\",\n\tname: \"User\",\n\tendpoint: \"/Users\",\n\tdescription: \"User Account\",\n\tschema: \"urn:ietf:params:scim:schemas:core:2.0:User\",\n\tmeta: {\n\t\tresourceType: \"ResourceType\",\n\t\tlocation: \"/scim/v2/ResourceTypes/User\",\n\t},\n};\n","import { SCIMUserResourceSchema } from \"./user-schemas\";\n\nexport type DBFilter = {\n\tfield: string;\n\tvalue: string | string[];\n\toperator?: any;\n};\n\nconst SCIMOperators: Record<string, string | undefined> = {\n\teq: \"eq\",\n};\n\nconst SCIMUserAttributes: Record<string, string | undefined> = {\n\tuserName: \"email\",\n};\n\nexport class SCIMParseError extends Error {}\n\nconst SCIMFilterRegex =\n\t/^\\s*(?<attribute>[^\\s]+)\\s+(?<op>eq|ne|co|sw|ew|pr)\\s*(?:(?<value>\"[^\"]*\"|[^\\s]+))?\\s*$/i;\n\nconst parseSCIMFilter = (filter: string) => {\n\tconst match = filter.match(SCIMFilterRegex);\n\tif (!match) {\n\t\tthrow new SCIMParseError(\"Invalid filter expression\");\n\t}\n\n\tconst attribute = match.groups?.attribute;\n\tconst op = match.groups?.op?.toLowerCase();\n\tconst value = match.groups?.value;\n\n\tif (!attribute || !op || !value) {\n\t\tthrow new SCIMParseError(\"Invalid filter expression\");\n\t}\n\n\tconst operator = SCIMOperators[op];\n\tif (!operator) {\n\t\tthrow new SCIMParseError(`The operator \"${op}\" is not supported`);\n\t}\n\n\treturn { attribute, operator, value };\n};\n\nexport const parseSCIMUserFilter = (filter: string) => {\n\tconst { attribute, operator, value } = parseSCIMFilter(filter);\n\n\tconst filters: DBFilter[] = [];\n\tconst targetAttribute = SCIMUserAttributes[attribute];\n\tconst resourceAttribute = SCIMUserResourceSchema.attributes.find(\n\t\t(attr) => attr.name === attribute,\n\t);\n\n\tif (!targetAttribute || !resourceAttribute) {\n\t\tthrow new SCIMParseError(`The attribute \"${attribute}\" is not supported`);\n\t}\n\n\tlet finalValue = value.replaceAll('\"', \"\");\n\tif (!resourceAttribute.caseExact) {\n\t\tfinalValue = finalValue.toLowerCase();\n\t}\n\n\tfilters.push({\n\t\tfield: targetAttribute,\n\t\tvalue: finalValue,\n\t\toperator,\n\t});\n\n\treturn filters;\n};\n","const MetadataFieldSupportOpenAPISchema = {\n\ttype: \"object\",\n\tproperties: {\n\t\tsupported: {\n\t\t\ttype: \"boolean\",\n\t\t},\n\t},\n};\n\nexport const ServiceProviderOpenAPISchema = {\n\ttype: \"object\",\n\tproperties: {\n\t\tpatch: MetadataFieldSupportOpenAPISchema,\n\t\tbulk: MetadataFieldSupportOpenAPISchema,\n\t\tfilter: MetadataFieldSupportOpenAPISchema,\n\t\tchangePassword: MetadataFieldSupportOpenAPISchema,\n\t\tsort: MetadataFieldSupportOpenAPISchema,\n\t\tetag: MetadataFieldSupportOpenAPISchema,\n\t\tauthenticationSchemes: {\n\t\t\ttype: \"array\",\n\t\t\titems: {\n\t\t\t\ttype: \"object\",\n\t\t\t\tproperties: {\n\t\t\t\t\tname: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t},\n\t\t\t\t\tdescription: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t},\n\t\t\t\t\tspecUri: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t},\n\t\t\t\t\ttype: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t},\n\t\t\t\t\tprimary: {\n\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tschemas: {\n\t\t\ttype: \"array\",\n\t\t\titems: {\n\t\t\t\ttype: \"string\",\n\t\t\t},\n\t\t},\n\t\tmeta: {\n\t\t\ttype: \"object\",\n\t\t\tproperties: {\n\t\t\t\tresourceType: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n} as const;\n\nexport const ResourceTypeOpenAPISchema = {\n\ttype: \"object\",\n\tproperties: {\n\t\tschemas: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\tid: { type: \"string\" },\n\t\tname: { type: \"string\" },\n\t\tendpoint: { type: \"string\" },\n\t\tdescription: { type: \"string\" },\n\t\tschema: { type: \"string\" },\n\t\tmeta: {\n\t\t\ttype: \"object\",\n\t\t\tproperties: {\n\t\t\t\tresourceType: { type: \"string\" },\n\t\t\t\tlocation: { type: \"string\" },\n\t\t\t},\n\t\t},\n\t},\n} as const;\n\nconst SCIMSchemaAttributesOpenAPISchema = {\n\ttype: \"object\",\n\tproperties: {\n\t\tname: { type: \"string\" },\n\t\ttype: { type: \"string\" },\n\t\tmultiValued: { type: \"boolean\" },\n\t\tdescription: { type: \"string\" },\n\t\trequired: { type: \"boolean\" },\n\t\tcaseExact: { type: \"boolean\" },\n\t\tmutability: { type: \"string\" },\n\t\treturned: { type: \"string\" },\n\t\tuniqueness: { type: \"string\" },\n\t},\n} as const;\n\nexport const SCIMSchemaOpenAPISchema = {\n\ttype: \"object\",\n\tproperties: {\n\t\tid: { type: \"string\" },\n\t\tschemas: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\tname: { type: \"string\" },\n\t\tdescription: { type: \"string\" },\n\t\tattributes: {\n\t\t\ttype: \"array\",\n\t\t\titems: {\n\t\t\t\t...SCIMSchemaAttributesOpenAPISchema,\n\t\t\t\tproperties: {\n\t\t\t\t\t...SCIMSchemaAttributesOpenAPISchema.properties,\n\t\t\t\t\tsubAttributes: {\n\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\titems: SCIMSchemaAttributesOpenAPISchema,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tmeta: {\n\t\t\ttype: \"object\",\n\t\t\tproperties: {\n\t\t\t\tresourceType: { type: \"string\" },\n\t\t\t\tlocation: { type: \"string\" },\n\t\t\t},\n\t\t\trequired: [\"resourceType\", \"location\"],\n\t\t},\n\t},\n} as const;\n","export const getResourceURL = (path: string, baseURL: string) => {\n\tconst normalizedBaseURL = baseURL.endsWith(\"/\") ? baseURL : `${baseURL}/`;\n\tconst normalizedPath = path.replace(/^\\/+/, \"\");\n\treturn new URL(normalizedPath, normalizedBaseURL).toString();\n};\n","import type { Account, User } from \"better-auth\";\nimport { SCIMUserResourceSchema } from \"./user-schemas\";\nimport { getResourceURL } from \"./utils\";\n\nexport const createUserResource = (\n\tbaseURL: string,\n\tuser: User,\n\taccount?: Account | null,\n) => {\n\treturn {\n\t\t// Common attributes\n\t\t// See https://datatracker.ietf.org/doc/html/rfc7643#section-3.1\n\n\t\tid: user.id,\n\t\texternalId: account?.accountId,\n\t\tmeta: {\n\t\t\tresourceType: \"User\",\n\t\t\tcreated: user.createdAt,\n\t\t\tlastModified: user.updatedAt,\n\t\t\tlocation: getResourceURL(`/scim/v2/Users/${user.id}`, baseURL),\n\t\t},\n\n\t\t// SCIM user resource\n\t\t// See https://datatracker.ietf.org/doc/html/rfc7643#section-4.1\n\n\t\tuserName: user.email,\n\t\tname: {\n\t\t\tformatted: user.name,\n\t\t},\n\t\tdisplayName: user.name,\n\t\tactive: true,\n\t\temails: [{ primary: true, value: user.email }],\n\t\tschemas: [SCIMUserResourceSchema.id],\n\t};\n};\n","import { base64Url } from \"@better-auth/utils/base64\";\nimport type {\n\tAccount,\n\tDBAdapter,\n\tGenericEndpointContext,\n\tUser,\n} from \"better-auth\";\nimport { HIDE_METADATA } from \"better-auth\";\nimport {\n\tAPIError,\n\tcreateAuthEndpoint,\n\tsessionMiddleware,\n} from \"better-auth/api\";\nimport { generateRandomString } from \"better-auth/crypto\";\nimport type { Member } from \"better-auth/plugins\";\nimport * as z from \"zod\";\nimport { getAccountId, getUserFullName, getUserPrimaryEmail } from \"./mappings\";\nimport type { AuthMiddleware } from \"./middlewares\";\nimport { buildUserPatch } from \"./patch-operations\";\nimport { SCIMAPIError, SCIMErrorOpenAPISchemas } from \"./scim-error\";\nimport type { DBFilter } from \"./scim-filters\";\nimport { parseSCIMUserFilter, SCIMParseError } from \"./scim-filters\";\nimport {\n\tResourceTypeOpenAPISchema,\n\tSCIMSchemaOpenAPISchema,\n\tServiceProviderOpenAPISchema,\n} from \"./scim-metadata\";\nimport { createUserResource } from \"./scim-resources\";\nimport { storeSCIMToken } from \"./scim-tokens\";\nimport type { SCIMOptions, SCIMProvider } from \"./types\";\nimport {\n\tAPIUserSchema,\n\tOpenAPIUserResourceSchema,\n\tSCIMUserResourceSchema,\n\tSCIMUserResourceType,\n} from \"./user-schemas\";\nimport { getResourceURL } from \"./utils\";\n\nconst supportedSCIMSchemas = [SCIMUserResourceSchema];\nconst supportedSCIMResourceTypes = [SCIMUserResourceType];\nconst supportedMediaTypes = [\"application/json\", \"application/scim+json\"];\n\nconst generateSCIMTokenBodySchema = z.object({\n\tproviderId: z.string().meta({ description: \"Unique provider identifier\" }),\n\torganizationId: z\n\t\t.string()\n\t\t.optional()\n\t\t.meta({ description: \"Optional organization id\" }),\n});\n\nconst getSCIMProviderConnectionQuerySchema = z.object({\n\tproviderId: z.string(),\n});\n\nconst deleteSCIMProviderConnectionBodySchema = z.object({\n\tproviderId: z.string(),\n});\n\nasync function getSCIMUserOrgIds(\n\tctx: GenericEndpointContext,\n\tuserId: string,\n): Promise<Set<string>> {\n\tconst members = await ctx.context.adapter.findMany<Member>({\n\t\tmodel: \"member\",\n\t\twhere: [{ field: \"userId\", value: userId }],\n\t});\n\treturn new Set(members.map((m) => m.organizationId));\n}\n\nfunction normalizeSCIMProvider(provider: SCIMProvider) {\n\treturn {\n\t\tid: provider.id,\n\t\tproviderId: provider.providerId,\n\t\torganizationId: provider.organizationId ?? null,\n\t};\n}\n\nasync function findOrganizationMember(\n\tctx: GenericEndpointContext,\n\tuserId: string,\n\torganizationId: string,\n): Promise<Member | null> {\n\treturn ctx.context.adapter.findOne<Member>({\n\t\tmodel: \"member\",\n\t\twhere: [\n\t\t\t{\n\t\t\t\tfield: \"userId\",\n\t\t\t\tvalue: userId,\n\t\t\t},\n\t\t\t{\n\t\t\t\tfield: \"organizationId\",\n\t\t\t\tvalue: organizationId,\n\t\t\t},\n\t\t],\n\t});\n}\n\nasync function assertSCIMProviderAccess(\n\tctx: GenericEndpointContext,\n\tuserId: string,\n\tprovider: SCIMProvider,\n): Promise<void> {\n\tif (provider.organizationId) {\n\t\tif (!ctx.context.hasPlugin(\"organization\")) {\n\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\tmessage: \"Organization plugin is required to access this SCIM provider\",\n\t\t\t});\n\t\t}\n\n\t\tconst member = await findOrganizationMember(\n\t\t\tctx,\n\t\t\tuserId,\n\t\t\tprovider.organizationId,\n\t\t);\n\n\t\tif (!member) {\n\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\tmessage:\n\t\t\t\t\t\"You must be a member of the organization to access this provider\",\n\t\t\t});\n\t\t}\n\t} else if (provider.userId && provider.userId !== userId) {\n\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\tmessage: \"You must be the owner to access this provider\",\n\t\t});\n\t}\n}\n\nasync function checkSCIMProviderAccess(\n\tctx: GenericEndpointContext,\n\tuserId: string,\n\tproviderId: string,\n): Promise<SCIMProvider> {\n\tconst provider = await ctx.context.adapter.findOne<SCIMProvider>({\n\t\tmodel: \"scimProvider\",\n\t\twhere: [{ field: \"providerId\", value: providerId }],\n\t});\n\n\tif (!provider) {\n\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\tmessage: \"SCIM provider not found\",\n\t\t});\n\t}\n\n\tawait assertSCIMProviderAccess(ctx, userId, provider);\n\n\treturn provider;\n}\n\nexport const generateSCIMToken = (opts: SCIMOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/generate-token\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: generateSCIMTokenBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tsummary: \"Generates a new SCIM token for the given provider\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Generates a new SCIM token to be used for SCIM operations\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"201\": {\n\t\t\t\t\t\t\tdescription: \"SCIM token response\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tscimToken: {\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"SCIM token\",\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tuse: [sessionMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst { providerId, organizationId } = ctx.body;\n\t\t\tconst user = ctx.context.session.user;\n\n\t\t\tif (providerId.includes(\":\")) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Provider id contains forbidden characters\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (organizationId && !ctx.context.hasPlugin(\"organization\")) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t\"Restricting a token to an organization requires the organization plugin\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tlet member: Member | null = null;\n\t\t\tif (organizationId) {\n\t\t\t\tmember = await findOrganizationMember(ctx, user.id, organizationId);\n\n\t\t\t\tif (!member) {\n\t\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\t\tmessage: \"You are not a member of the organization\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst scimProvider = await ctx.context.adapter.findOne<SCIMProvider>({\n\t\t\t\tmodel: \"scimProvider\",\n\t\t\t\twhere: [\n\t\t\t\t\t{ field: \"providerId\", value: providerId },\n\t\t\t\t\t...(organizationId\n\t\t\t\t\t\t? [{ field: \"organizationId\", value: organizationId }]\n\t\t\t\t\t\t: []),\n\t\t\t\t],\n\t\t\t});\n\n\t\t\tif (scimProvider) {\n\t\t\t\tawait assertSCIMProviderAccess(ctx, user.id, scimProvider);\n\t\t\t\tawait ctx.context.adapter.delete<SCIMProvider>({\n\t\t\t\t\tmodel: \"scimProvider\",\n\t\t\t\t\twhere: [{ field: \"id\", value: scimProvider.id }],\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst baseToken = generateRandomString(24);\n\t\t\tconst scimToken = base64Url.encode(\n\t\t\t\t`${baseToken}:${providerId}${organizationId ? `:${organizationId}` : \"\"}`,\n\t\t\t);\n\n\t\t\tif (opts.beforeSCIMTokenGenerated) {\n\t\t\t\tawait opts.beforeSCIMTokenGenerated({\n\t\t\t\t\tuser,\n\t\t\t\t\tmember,\n\t\t\t\t\tscimToken,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst newSCIMProvider = await ctx.context.adapter.create<SCIMProvider>({\n\t\t\t\tmodel: \"scimProvider\",\n\t\t\t\tdata: {\n\t\t\t\t\tproviderId: providerId,\n\t\t\t\t\torganizationId: organizationId,\n\t\t\t\t\tscimToken: await storeSCIMToken(ctx, opts, baseToken),\n\t\t\t\t\t...(opts.providerOwnership?.enabled ? { userId: user.id } : {}),\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (opts.afterSCIMTokenGenerated) {\n\t\t\t\tawait opts.afterSCIMTokenGenerated({\n\t\t\t\t\tuser,\n\t\t\t\t\tmember,\n\t\t\t\t\tscimToken,\n\t\t\t\t\tscimProvider: newSCIMProvider,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tctx.setStatus(201);\n\n\t\t\treturn ctx.json({\n\t\t\t\tscimToken,\n\t\t\t});\n\t\t},\n\t);\n\nexport const listSCIMProviderConnections = () =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/list-provider-connections\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"listSCIMProviderConnections\",\n\t\t\t\t\tsummary: \"List SCIM providers\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Returns SCIM providers for organizations the user is a member of.\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"List of SCIM providers\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tproviders: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tid: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tproviderId: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\torganizationId: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst userId = ctx.context.session.user.id;\n\t\t\tconst userOrgIds: Set<string> = ctx.context.hasPlugin(\"organization\")\n\t\t\t\t? await getSCIMUserOrgIds(ctx, userId)\n\t\t\t\t: new Set();\n\n\t\t\tconst allProviders = await ctx.context.adapter.findMany<SCIMProvider>({\n\t\t\t\tmodel: \"scimProvider\",\n\t\t\t});\n\n\t\t\tconst accessibleProviders = allProviders.filter((p) => {\n\t\t\t\tif (p.organizationId) return userOrgIds.has(p.organizationId); // org level access\n\t\t\t\tif (p.userId === userId) return true; // owner access\n\t\t\t\treturn !p.userId; // no org and no owner\n\t\t\t});\n\n\t\t\tconst providers = accessibleProviders.map((p) =>\n\t\t\t\tnormalizeSCIMProvider(p),\n\t\t\t);\n\n\t\t\treturn ctx.json({ providers });\n\t\t},\n\t);\n\nexport const getSCIMProviderConnection = () =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/get-provider-connection\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\tquery: getSCIMProviderConnectionQuerySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"getSCIMProviderConnection\",\n\t\t\t\t\tsummary: \"Get SCIM provider details\",\n\t\t\t\t\tdescription: \"Returns details for a specific SCIM provider\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"SCIM provider details\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tid: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\tproviderId: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\torganizationId: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"404\": {\n\t\t\t\t\t\t\tdescription: \"Provider not found\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"403\": {\n\t\t\t\t\t\t\tdescription: \"Access denied\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst { providerId } = ctx.query;\n\t\t\tconst userId = ctx.context.session.user.id;\n\n\t\t\tconst provider = await checkSCIMProviderAccess(ctx, userId, providerId);\n\n\t\t\treturn ctx.json(normalizeSCIMProvider(provider));\n\t\t},\n\t);\n\nexport const deleteSCIMProviderConnection = () =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/delete-provider-connection\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\tbody: deleteSCIMProviderConnectionBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"deleteSCIMProviderConnection\",\n\t\t\t\t\tsummary: \"Delete SCIM provider\",\n\t\t\t\t\tdescription: \"Deletes a SCIM provider and invalidates its token\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"SCIM provider deleted successfully\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tsuccess: { type: \"boolean\" },\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"404\": {\n\t\t\t\t\t\t\tdescription: \"Provider not found\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"403\": {\n\t\t\t\t\t\t\tdescription: \"Access denied\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst { providerId } = ctx.body;\n\t\t\tconst userId = ctx.context.session.user.id;\n\n\t\t\tawait checkSCIMProviderAccess(ctx, userId, providerId);\n\n\t\t\tawait ctx.context.adapter.delete<SCIMProvider>({\n\t\t\t\tmodel: \"scimProvider\",\n\t\t\t\twhere: [{ field: \"providerId\", value: providerId }],\n\t\t\t});\n\n\t\t\treturn ctx.json({ success: true });\n\t\t},\n\t);\n\nexport const createSCIMUser = (authMiddleware: AuthMiddleware) =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/v2/Users\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: APIUserSchema,\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\t\topenapi: {\n\t\t\t\t\tsummary: \"Create SCIM user.\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Provision a new user into the linked organization via SCIM. See https://datatracker.ietf.org/doc/html/rfc7644#section-3.3\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"201\": {\n\t\t\t\t\t\t\tdescription: \"SCIM user resource\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: OpenAPIUserResourceSchema,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tuse: [authMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst body = ctx.body;\n\t\t\tconst providerId = ctx.context.scimProvider.providerId;\n\t\t\tconst accountId = getAccountId(body.userName, body.externalId);\n\n\t\t\tconst existingAccount = await ctx.context.adapter.findOne<Account>({\n\t\t\t\tmodel: \"account\",\n\t\t\t\twhere: [\n\t\t\t\t\t{ field: \"accountId\", value: accountId },\n\t\t\t\t\t{ field: \"providerId\", value: providerId },\n\t\t\t\t],\n\t\t\t});\n\n\t\t\tif (existingAccount) {\n\t\t\t\tthrow new SCIMAPIError(\"CONFLICT\", {\n\t\t\t\t\tdetail: \"User already exists\",\n\t\t\t\t\tscimType: \"uniqueness\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst email = getUserPrimaryEmail(body.userName, body.emails);\n\t\t\tconst name = getUserFullName(email, body.name);\n\n\t\t\tconst existingUser = await ctx.context.adapter.findOne<User>({\n\t\t\t\tmodel: \"user\",\n\t\t\t\twhere: [{ field: \"email\", value: email }],\n\t\t\t});\n\n\t\t\tconst createAccount = (userId: string) =>\n\t\t\t\tctx.context.internalAdapter.createAccount({\n\t\t\t\t\tuserId: userId,\n\t\t\t\t\tproviderId: providerId,\n\t\t\t\t\taccountId: accountId,\n\t\t\t\t\taccessToken: \"\",\n\t\t\t\t\trefreshToken: \"\",\n\t\t\t\t});\n\n\t\t\tconst createUser = () =>\n\t\t\t\tctx.context.internalAdapter.createUser({\n\t\t\t\t\temail,\n\t\t\t\t\tname,\n\t\t\t\t});\n\n\t\t\tconst createOrgMembership = async (userId: string) => {\n\t\t\t\tconst organizationId = ctx.context.scimProvider.organizationId;\n\n\t\t\t\tif (organizationId) {\n\t\t\t\t\tconst isOrgMember = await ctx.context.adapter.findOne({\n\t\t\t\t\t\tmodel: \"member\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"organizationId\", value: organizationId },\n\t\t\t\t\t\t\t{ field: \"userId\", value: userId },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!isOrgMember) {\n\t\t\t\t\t\treturn await ctx.context.adapter.create<Member>({\n\t\t\t\t\t\t\tmodel: \"member\",\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tuserId: userId,\n\t\t\t\t\t\t\t\trole: \"member\",\n\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t\torganizationId,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tlet user: User;\n\t\t\tlet account: Account;\n\n\t\t\tif (existingUser) {\n\t\t\t\tuser = existingUser;\n\t\t\t\taccount = await ctx.context.adapter.transaction<Account>(async () => {\n\t\t\t\t\tconst account = await createAccount(user.id);\n\t\t\t\t\tawait createOrgMembership(user.id);\n\t\t\t\t\treturn account;\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t[user, account] = await ctx.context.adapter.transaction<\n\t\t\t\t\t[User, Account]\n\t\t\t\t>(async () => {\n\t\t\t\t\tconst user = await createUser();\n\t\t\t\t\tconst account = await createAccount(user.id);\n\t\t\t\t\tawait createOrgMembership(user.id);\n\t\t\t\t\treturn [user, account];\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst userResource = createUserResource(\n\t\t\t\tctx.context.baseURL,\n\t\t\t\tuser,\n\t\t\t\taccount,\n\t\t\t);\n\n\t\t\tctx.setStatus(201);\n\t\t\tctx.setHeader(\"location\", userResource.meta.location);\n\t\t\treturn ctx.json(userResource);\n\t\t},\n\t);\n\nexport const updateSCIMUser = (authMiddleware: AuthMiddleware) =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/v2/Users/:userId\",\n\t\t{\n\t\t\tmethod: \"PUT\",\n\t\t\tbody: APIUserSchema,\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\t\topenapi: {\n\t\t\t\t\tsummary: \"Update SCIM user.\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Updates an existing user into the linked organization via SCIM. See https://datatracker.ietf.org/doc/html/rfc7644#section-3.3\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"SCIM user resource\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: OpenAPIUserResourceSchema,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tuse: [authMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst body = ctx.body;\n\t\t\tconst userId = ctx.params.userId;\n\t\t\tconst { organizationId, providerId } = ctx.context.scimProvider;\n\t\t\tconst accountId = getAccountId(body.userName, body.externalId);\n\n\t\t\tconst { user, account } = await findUserById(ctx.context.adapter, {\n\t\t\t\tuserId,\n\t\t\t\tproviderId,\n\t\t\t\torganizationId,\n\t\t\t});\n\n\t\t\tif (!user) {\n\t\t\t\tthrow new SCIMAPIError(\"NOT_FOUND\", {\n\t\t\t\t\tdetail: \"User not found\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst [updatedUser, updatedAccount] =\n\t\t\t\tawait ctx.context.adapter.transaction<[User | null, Account | null]>(\n\t\t\t\t\tasync () => {\n\t\t\t\t\t\tconst email = getUserPrimaryEmail(body.userName, body.emails);\n\t\t\t\t\t\tconst name = getUserFullName(email, body.name);\n\n\t\t\t\t\t\tconst updatedUser = await ctx.context.internalAdapter.updateUser(\n\t\t\t\t\t\t\tuserId,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\temail,\n\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tconst updatedAccount =\n\t\t\t\t\t\t\tawait ctx.context.internalAdapter.updateAccount(account.id, {\n\t\t\t\t\t\t\t\taccountId,\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\treturn [updatedUser, updatedAccount];\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\tconst userResource = createUserResource(\n\t\t\t\tctx.context.baseURL,\n\t\t\t\tupdatedUser!,\n\t\t\t\tupdatedAccount,\n\t\t\t);\n\n\t\t\treturn ctx.json(userResource);\n\t\t},\n\t);\n\nconst listSCIMUsersQuerySchema = z\n\t.object({\n\t\tfilter: z.string().optional(),\n\t})\n\t.optional();\n\nexport const listSCIMUsers = (authMiddleware: AuthMiddleware) =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/v2/Users\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tquery: listSCIMUsersQuerySchema,\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\t\topenapi: {\n\t\t\t\t\tsummary: \"List SCIM users\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Returns all users provisioned via SCIM for the linked organization. See https://datatracker.ietf.org/doc/html/rfc7644#section-3.4.2\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"SCIM user list\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\ttotalResults: { type: \"number\" },\n\t\t\t\t\t\t\t\t\t\t\titemsPerPage: { type: \"number\" },\n\t\t\t\t\t\t\t\t\t\t\tstartIndex: { type: \"number\" },\n\t\t\t\t\t\t\t\t\t\t\tResources: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: OpenAPIUserResourceSchema,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tuse: [authMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst emptyListResponse = {\n\t\t\t\tschemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n\t\t\t\ttotalResults: 0,\n\t\t\t\tstartIndex: 1,\n\t\t\t\titemsPerPage: 0,\n\t\t\t\tResources: [],\n\t\t\t} as const;\n\n\t\t\tconst apiFilters: DBFilter[] = parseSCIMAPIUserFilter(ctx.query?.filter);\n\n\t\t\tctx.context.logger.info(\"Querying result with filters: \", apiFilters);\n\n\t\t\tconst providerId = ctx.context.scimProvider.providerId;\n\t\t\tconst accounts = await ctx.context.adapter.findMany<Account>({\n\t\t\t\tmodel: \"account\",\n\t\t\t\twhere: [{ field: \"providerId\", value: providerId }],\n\t\t\t});\n\n\t\t\tconst accountUserIds = accounts.map((account) => account.userId);\n\n\t\t\t// No accounts exist for this provider\n\n\t\t\tif (accountUserIds.length === 0) {\n\t\t\t\treturn ctx.json(emptyListResponse);\n\t\t\t}\n\n\t\t\tlet userFilters: DBFilter[] = [\n\t\t\t\t{ field: \"id\", value: accountUserIds, operator: \"in\" },\n\t\t\t];\n\n\t\t\tconst organizationId = ctx.context.scimProvider.organizationId;\n\t\t\tif (organizationId) {\n\t\t\t\tconst members = await ctx.context.adapter.findMany<Member>({\n\t\t\t\t\tmodel: \"member\",\n\t\t\t\t\twhere: [\n\t\t\t\t\t\t{ field: \"organizationId\", value: organizationId },\n\t\t\t\t\t\t{ field: \"userId\", value: accountUserIds, operator: \"in\" },\n\t\t\t\t\t],\n\t\t\t\t});\n\n\t\t\t\tconst memberUserIds = members.map((member) => member.userId);\n\n\t\t\t\t// No members exist for this organization\n\n\t\t\t\tif (memberUserIds.length === 0) {\n\t\t\t\t\treturn ctx.json(emptyListResponse);\n\t\t\t\t}\n\n\t\t\t\tuserFilters = [{ field: \"id\", value: memberUserIds, operator: \"in\" }];\n\t\t\t}\n\n\t\t\tconst users = await ctx.context.adapter.findMany<User>({\n\t\t\t\tmodel: \"user\",\n\t\t\t\twhere: [...userFilters, ...apiFilters],\n\t\t\t});\n\n\t\t\treturn ctx.json({\n\t\t\t\tschemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n\t\t\t\ttotalResults: users.length,\n\t\t\t\tstartIndex: 1,\n\t\t\t\titemsPerPage: users.length,\n\t\t\t\tResources: users.map((user) => {\n\t\t\t\t\tconst account = accounts.find((a) => a.userId === user.id);\n\t\t\t\t\treturn createUserResource(ctx.context.baseURL, user, account);\n\t\t\t\t}),\n\t\t\t});\n\t\t},\n\t);\n\nexport const getSCIMUser = (authMiddleware: AuthMiddleware) =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/v2/Users/:userId\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\t\topenapi: {\n\t\t\t\t\tsummary: \"Get SCIM user details\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Returns the provisioned SCIM user details. See https://datatracker.ietf.org/doc/html/rfc7644#section-3.4.1\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"SCIM user resource\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: OpenAPIUserResourceSchema,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tuse: [authMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst userId = ctx.params.userId;\n\t\t\tconst providerId = ctx.context.scimProvider.providerId;\n\t\t\tconst organizationId = ctx.context.scimProvider.organizationId;\n\n\t\t\tconst { user, account } = await findUserById(ctx.context.adapter, {\n\t\t\t\tuserId,\n\t\t\t\tproviderId,\n\t\t\t\torganizationId,\n\t\t\t});\n\n\t\t\tif (!user) {\n\t\t\t\tthrow new SCIMAPIError(\"NOT_FOUND\", {\n\t\t\t\t\tdetail: \"User not found\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn ctx.json(createUserResource(ctx.context.baseURL, user, account));\n\t\t},\n\t);\n\nconst patchSCIMUserBodySchema = z.object({\n\tschemas: z\n\t\t.array(z.string())\n\t\t.refine(\n\t\t\t(s) => s.includes(\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"),\n\t\t\t{\n\t\t\t\tmessage: \"Invalid schemas for PatchOp\",\n\t\t\t},\n\t\t),\n\tOperations: z.array(\n\t\tz.object({\n\t\t\top: z\n\t\t\t\t.string()\n\t\t\t\t.toLowerCase()\n\t\t\t\t.default(\"replace\")\n\t\t\t\t.pipe(z.enum([\"replace\", \"add\", \"remove\"])),\n\t\t\tpath: z.string().optional(),\n\t\t\tvalue: z.any(),\n\t\t}),\n\t),\n});\n\nexport const patchSCIMUser = (authMiddleware: AuthMiddleware) =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/v2/Users/:userId\",\n\t\t{\n\t\t\tmethod: \"PATCH\",\n\t\t\tbody: patchSCIMUserBodySchema,\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\t\topenapi: {\n\t\t\t\t\tsummary: \"Patch SCIM user\",\n\t\t\t\t\tdescription: \"Updates fields on a SCIM user record\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"204\": {\n\t\t\t\t\t\t\tdescription: \"Patch update applied correctly\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tuse: [authMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst userId = ctx.params.userId;\n\t\t\tconst organizationId = ctx.context.scimProvider.organizationId;\n\t\t\tconst providerId = ctx.context.scimProvider.providerId;\n\n\t\t\tconst { user, account } = await findUserById(ctx.context.adapter, {\n\t\t\t\tuserId,\n\t\t\t\tproviderId,\n\t\t\t\torganizationId,\n\t\t\t});\n\n\t\t\tif (!user) {\n\t\t\t\tthrow new SCIMAPIError(\"NOT_FOUND\", {\n\t\t\t\t\tdetail: \"User not found\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst { user: userPatch, account: accountPatch } = buildUserPatch(\n\t\t\t\tuser,\n\t\t\t\tctx.body.Operations,\n\t\t\t);\n\n\t\t\tif (\n\t\t\t\tObject.keys(userPatch).length === 0 &&\n\t\t\t\tObject.keys(accountPatch).length === 0\n\t\t\t) {\n\t\t\t\tthrow new SCIMAPIError(\"BAD_REQUEST\", {\n\t\t\t\t\tdetail: \"No valid fields to update\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tawait Promise.all([\n\t\t\t\tObject.keys(userPatch).length > 0\n\t\t\t\t\t? ctx.context.internalAdapter.updateUser(userId, {\n\t\t\t\t\t\t\t...userPatch,\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t})\n\t\t\t\t\t: Promise.resolve(),\n\t\t\t\tObject.keys(accountPatch).length > 0\n\t\t\t\t\t? ctx.context.internalAdapter.updateAccount(account.id, {\n\t\t\t\t\t\t\t...accountPatch,\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t})\n\t\t\t\t\t: Promise.resolve(),\n\t\t\t]);\n\n\t\t\tctx.setStatus(204);\n\t\t\treturn;\n\t\t},\n\t);\n\nexport const deleteSCIMUser = (authMiddleware: AuthMiddleware) =>\n\tcreateAuthEndpoint(\n\t\t\"/scim/v2/Users/:userId\",\n\t\t{\n\t\t\tmethod: \"DELETE\",\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t\tallowedMediaTypes: [...supportedMediaTypes, \"\"],\n\t\t\t\topenapi: {\n\t\t\t\t\tsummary: \"Delete SCIM user\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Deletes (or deactivates) a user within the linked organization.\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"204\": {\n\t\t\t\t\t\t\tdescription: \"Delete applied successfully\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tuse: [authMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst userId = ctx.params.userId;\n\t\t\tconst providerId = ctx.context.scimProvider.providerId;\n\t\t\tconst organizationId = ctx.context.scimProvider.organizationId;\n\n\t\t\tconst { user } = await findUserById(ctx.context.adapter, {\n\t\t\t\tuserId,\n\t\t\t\tproviderId,\n\t\t\t\torganizationId,\n\t\t\t});\n\n\t\t\tif (!user) {\n\t\t\t\tthrow new SCIMAPIError(\"NOT_FOUND\", {\n\t\t\t\t\tdetail: \"User not found\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tawait ctx.context.internalAdapter.deleteUser(userId);\n\n\t\t\tctx.setStatus(204);\n\t\t\treturn;\n\t\t},\n\t);\n\nexport const getSCIMServiceProviderConfig = createAuthEndpoint(\n\t\"/scim/v2/ServiceProviderConfig\",\n\t{\n\t\tmethod: \"GET\",\n\t\tmetadata: {\n\t\t\t...HIDE_METADATA,\n\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\topenapi: {\n\t\t\t\tsummary: \"SCIM Service Provider Configuration\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Standard SCIM metadata endpoint used by identity providers. See https://datatracker.ietf.org/doc/html/rfc7644#section-4\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"SCIM metadata object\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: ServiceProviderOpenAPISchema,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\treturn ctx.json({\n\t\t\tpatch: { supported: true },\n\t\t\tbulk: { supported: false },\n\t\t\tfilter: { supported: true },\n\t\t\tchangePassword: { supported: false },\n\t\t\tsort: { supported: false },\n\t\t\tetag: { supported: false },\n\t\t\tauthenticationSchemes: [\n\t\t\t\t{\n\t\t\t\t\tname: \"OAuth Bearer Token\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Authentication scheme using the Authorization header with a bearer token tied to an organization.\",\n\t\t\t\t\tspecUri: \"http://www.rfc-editor.org/info/rfc6750\",\n\t\t\t\t\ttype: \"oauthbearertoken\",\n\t\t\t\t\tprimary: true,\n\t\t\t\t},\n\t\t\t],\n\t\t\tschemas: [\"urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig\"],\n\t\t\tmeta: {\n\t\t\t\tresourceType: \"ServiceProviderConfig\",\n\t\t\t},\n\t\t});\n\t},\n);\n\nexport const getSCIMSchemas = createAuthEndpoint(\n\t\"/scim/v2/Schemas\",\n\t{\n\t\tmethod: \"GET\",\n\t\tmetadata: {\n\t\t\t...HIDE_METADATA,\n\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\topenapi: {\n\t\t\t\tsummary: \"SCIM Service Provider Configuration Schemas\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Standard SCIM metadata endpoint used by identity providers to acquire information about supported schemas. See https://datatracker.ietf.org/doc/html/rfc7644#section-4\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"SCIM metadata object\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\titems: SCIMSchemaOpenAPISchema,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\treturn ctx.json({\n\t\t\ttotalResults: supportedSCIMSchemas.length,\n\t\t\titemsPerPage: supportedSCIMSchemas.length,\n\t\t\tstartIndex: 1,\n\t\t\tschemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n\t\t\tResources: supportedSCIMSchemas.map((s) => {\n\t\t\t\treturn {\n\t\t\t\t\t...s,\n\t\t\t\t\tmeta: {\n\t\t\t\t\t\t...s.meta,\n\t\t\t\t\t\tlocation: getResourceURL(s.meta.location, ctx.context.baseURL),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}),\n\t\t});\n\t},\n);\n\nexport const getSCIMSchema = createAuthEndpoint(\n\t\"/scim/v2/Schemas/:schemaId\",\n\t{\n\t\tmethod: \"GET\",\n\t\tmetadata: {\n\t\t\t...HIDE_METADATA,\n\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\topenapi: {\n\t\t\t\tsummary: \"SCIM a Service Provider Configuration Schema\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Standard SCIM metadata endpoint used by identity providers to acquire information about a given schema. See https://datatracker.ietf.org/doc/html/rfc7644#section-4\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"SCIM metadata object\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: SCIMSchemaOpenAPISchema,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\tconst schema = supportedSCIMSchemas.find(\n\t\t\t(s) => s.id === ctx.params.schemaId,\n\t\t);\n\n\t\tif (!schema) {\n\t\t\tthrow new SCIMAPIError(\"NOT_FOUND\", {\n\t\t\t\tdetail: \"Schema not found\",\n\t\t\t});\n\t\t}\n\n\t\treturn ctx.json({\n\t\t\t...schema,\n\t\t\tmeta: {\n\t\t\t\t...schema.meta,\n\t\t\t\tlocation: getResourceURL(schema.meta.location, ctx.context.baseURL),\n\t\t\t},\n\t\t});\n\t},\n);\n\nexport const getSCIMResourceTypes = createAuthEndpoint(\n\t\"/scim/v2/ResourceTypes\",\n\t{\n\t\tmethod: \"GET\",\n\t\tmetadata: {\n\t\t\t...HIDE_METADATA,\n\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\topenapi: {\n\t\t\t\tsummary: \"SCIM Service Provider Supported Resource Types\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Standard SCIM metadata endpoint used by identity providers to get a list of server supported types. See https://datatracker.ietf.org/doc/html/rfc7644#section-4\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"SCIM metadata object\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\ttotalResults: { type: \"number\" },\n\t\t\t\t\t\t\t\t\t\titemsPerPage: { type: \"number\" },\n\t\t\t\t\t\t\t\t\t\tstartIndex: { type: \"number\" },\n\t\t\t\t\t\t\t\t\t\tResources: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\titems: ResourceTypeOpenAPISchema,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\treturn ctx.json({\n\t\t\ttotalResults: supportedSCIMResourceTypes.length,\n\t\t\titemsPerPage: supportedSCIMResourceTypes.length,\n\t\t\tstartIndex: 1,\n\t\t\tschemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n\t\t\tResources: supportedSCIMResourceTypes.map((s) => {\n\t\t\t\treturn {\n\t\t\t\t\t...s,\n\t\t\t\t\tmeta: {\n\t\t\t\t\t\t...s.meta,\n\t\t\t\t\t\tlocation: getResourceURL(s.meta.location, ctx.context.baseURL),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}),\n\t\t});\n\t},\n);\n\nexport const getSCIMResourceType = createAuthEndpoint(\n\t\"/scim/v2/ResourceTypes/:resourceTypeId\",\n\t{\n\t\tmethod: \"GET\",\n\t\tmetadata: {\n\t\t\t...HIDE_METADATA,\n\t\t\tallowedMediaTypes: supportedMediaTypes,\n\t\t\topenapi: {\n\t\t\t\tsummary: \"SCIM Service Provider Supported Resource Type\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Standard SCIM metadata endpoint used by identity providers to get a server supported type. See https://datatracker.ietf.org/doc/html/rfc7644#section-4\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"SCIM metadata object\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: ResourceTypeOpenAPISchema,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t...SCIMErrorOpenAPISchemas,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\tconst resourceType = supportedSCIMResourceTypes.find(\n\t\t\t(s) => s.id === ctx.params.resourceTypeId,\n\t\t);\n\n\t\tif (!resourceType) {\n\t\t\tthrow new SCIMAPIError(\"NOT_FOUND\", {\n\t\t\t\tdetail: \"Resource type not found\",\n\t\t\t});\n\t\t}\n\n\t\treturn ctx.json({\n\t\t\t...resourceType,\n\t\t\tmeta: {\n\t\t\t\t...resourceType.meta,\n\t\t\t\tlocation: getResourceURL(\n\t\t\t\t\tresourceType.meta.location,\n\t\t\t\t\tctx.context.baseURL,\n\t\t\t\t),\n\t\t\t},\n\t\t});\n\t},\n);\n\nconst findUserById = async (\n\tadapter: DBAdapter,\n\t{\n\t\tuserId,\n\t\tproviderId,\n\t\torganizationId,\n\t}: { userId: string; providerId: string; organizationId?: string },\n) => {\n\tconst account = await adapter.findOne<Account>({\n\t\tmodel: \"account\",\n\t\twhere: [\n\t\t\t{ field: \"userId\", value: userId },\n\t\t\t{ field: \"providerId\", value: providerId },\n\t\t],\n\t});\n\n\t// Disallows access to the resource\n\t// Account is not associated to the provider\n\n\tif (!account) {\n\t\treturn { user: null, account: null };\n\t}\n\n\tlet member: Member | null = null;\n\tif (organizationId) {\n\t\tmember = await adapter.findOne<Member>({\n\t\t\tmodel: \"member\",\n\t\t\twhere: [\n\t\t\t\t{ field: \"organizationId\", value: organizationId },\n\t\t\t\t{ field: \"userId\", value: userId },\n\t\t\t],\n\t\t});\n\t}\n\n\t// Disallows access to the resource\n\t// Token is restricted to an org and the member is not part of it\n\n\tif (organizationId && !member) {\n\t\treturn { user: null, account: null };\n\t}\n\n\tconst user = await adapter.findOne<User>({\n\t\tmodel: \"user\",\n\t\twhere: [{ field: \"id\", value: userId }],\n\t});\n\n\tif (!user) {\n\t\treturn { user: null, account: null };\n\t}\n\n\treturn { user, account };\n};\n\nconst parseSCIMAPIUserFilter = (filter?: string) => {\n\tlet filters: DBFilter[] = [];\n\n\ttry {\n\t\tfilters = filter ? parseSCIMUserFilter(filter) : [];\n\t} catch (error) {\n\t\tthrow new SCIMAPIError(\"BAD_REQUEST\", {\n\t\t\tdetail:\n\t\t\t\terror instanceof SCIMParseError ? error.message : \"Invalid SCIM filter\",\n\t\t\tscimType: \"invalidFilter\",\n\t\t});\n\t}\n\n\treturn filters;\n};\n","import type { BetterAuthPlugin } from \"better-auth\";\nimport { authMiddlewareFactory } from \"./middlewares\";\nimport {\n\tcreateSCIMUser,\n\tdeleteSCIMProviderConnection,\n\tdeleteSCIMUser,\n\tgenerateSCIMToken,\n\tgetSCIMProviderConnection,\n\tgetSCIMResourceType,\n\tgetSCIMResourceTypes,\n\tgetSCIMSchema,\n\tgetSCIMSchemas,\n\tgetSCIMServiceProviderConfig,\n\tgetSCIMUser,\n\tlistSCIMProviderConnections,\n\tlistSCIMUsers,\n\tpatchSCIMUser,\n\tupdateSCIMUser,\n} from \"./routes\";\nimport type { SCIMOptions } from \"./types\";\n\ndeclare module \"@better-auth/core\" {\n\tinterface BetterAuthPluginRegistry<AuthOptions, Options> {\n\t\tscim: {\n\t\t\tcreator: typeof scim;\n\t\t};\n\t}\n}\n\nexport const scim = (options?: SCIMOptions) => {\n\tconst opts = {\n\t\tstoreSCIMToken: \"plain\",\n\t\tproviderOwnership: { enabled: false },\n\t\t...options,\n\t} satisfies SCIMOptions;\n\n\tconst authMiddleware = authMiddlewareFactory(opts);\n\n\treturn {\n\t\tid: \"scim\",\n\t\tendpoints: {\n\t\t\tgenerateSCIMToken: generateSCIMToken(opts),\n\t\t\tlistSCIMProviderConnections: listSCIMProviderConnections(),\n\t\t\tgetSCIMProviderConnection: getSCIMProviderConnection(),\n\t\t\tdeleteSCIMProviderConnection: deleteSCIMProviderConnection(),\n\t\t\tgetSCIMUser: getSCIMUser(authMiddleware),\n\t\t\tcreateSCIMUser: createSCIMUser(authMiddleware),\n\t\t\tpatchSCIMUser: patchSCIMUser(authMiddleware),\n\t\t\tdeleteSCIMUser: deleteSCIMUser(authMiddleware),\n\t\t\tupdateSCIMUser: updateSCIMUser(authMiddleware),\n\t\t\tlistSCIMUsers: listSCIMUsers(authMiddleware),\n\t\t\tgetSCIMServiceProviderConfig,\n\t\t\tgetSCIMSchemas,\n\t\t\tgetSCIMSchema,\n\t\t\tgetSCIMResourceTypes,\n\t\t\tgetSCIMResourceType,\n\t\t},\n\t\tschema: {\n\t\t\tscimProvider: {\n\t\t\t\tfields: {\n\t\t\t\t\tproviderId: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tunique: true,\n\t\t\t\t\t},\n\t\t\t\t\tscimToken: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tunique: true,\n\t\t\t\t\t},\n\t\t\t\t\torganizationId: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\trequired: false,\n\t\t\t\t\t},\n\t\t\t\t\t...(opts.providerOwnership?.enabled\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tuserId: {\n\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\trequired: false,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {}),\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\toptions,\n\t} satisfies BetterAuthPlugin;\n};\n\nexport * from \"./types\";\n"],"mappings":"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ACC,MAAM;GACN,MAAM;GACN,aAAa;GACb,aACC;GACD,UAAU;GACV,WAAW;GACX,YAAY;GACZ,UAAU;GACV,YAAY;GACZ;EACD;GACC,MAAM;GACN,MAAM;GACN,aAAa;GACb,aACC;GACD,UAAU;GACV,WAAW;GACX,YAAY;GACZ,UAAU;GACV,YAAY;GACZ;EACD;GACC,MAAM;GACN,MAAM;GACN,aAAa;GACb,aACC;GACD,UAAU;GACV,YAAY;GACZ,UAAU;GACV;EACD;GACC,MAAM;GACN,MAAM;GACN,aAAa;GACb,aAAa;GACb,UAAU;GACV,eAAe;IACd;KACC,MAAM;KACN,MAAM;KACN,aAAa;KACb,aACC;KACD,UAAU;KACV,WAAW;KACX,YAAY;KACZ,UAAU;KACV,YAAY;KACZ;IACD;KACC,MAAM;KACN,MAAM;KACN,aAAa;KACb,aACC;KACD,UAAU;KACV,WAAW;KACX,YAAY;KACZ,UAAU;KACV,YAAY;KACZ;IACD;KACC,MAAM;KACN,MAAM;KACN,aAAa;KACb,aACC;KACD,UAAU;KACV,WAAW;KACX,YAAY;KACZ,UAAU;KACV,YAAY;KACZ;IACD;GACD;EACD;GACC,MAAM;GACN,MAAM;GACN,aAAa;GACb,aACC;GACD,UAAU;GACV,eAAe,CACd;IACC,MAAM;IACN,MAAM;IACN,aAAa;IACb,aACC;IACD,UAAU;IACV,WAAW;IACX,YAAY;IACZ,UAAU;IACV,YAAY;IACZ,EACD;IACC,MAAM;IACN,MAAM;IACN,aAAa;IACb,aACC;IACD,UAAU;IACV,YAAY;IACZ,UAAU;IACV,CACD;GACD,YAAY;GACZ,UAAU;GACV,YAAY;GACZ;EACD;CACD,MAAM;EACL,cAAc;EACd,UAAU;EACV;CACD;AAED,MAAa,uBAAuB;CACnC,SAAS,CAAC,qDAAqD;CAC/D,IAAI;CACJ,MAAM;CACN,UAAU;CACV,aAAa;CACb,QAAQ;CACR,MAAM;EACL,cAAc;EACd,UAAU;EACV;CACD;;;AC5MD,MAAM,gBAAoD,EACzD,IAAI,MACJ;AAED,MAAM,qBAAyD,EAC9D,UAAU,SACV;AAED,IAAa,iBAAb,cAAoC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"}