@open-mercato/enterprise 0.4.6-develop-15c18897fc → 0.4.6-develop-34aa847ce6
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.js +1 -1
- package/dist/index.js.map +2 -2
- package/dist/modules/sso/acl.js +11 -0
- package/dist/modules/sso/acl.js.map +7 -0
- package/dist/modules/sso/api/admin-context.js +27 -0
- package/dist/modules/sso/api/admin-context.js.map +7 -0
- package/dist/modules/sso/api/callback/oidc/route.js +103 -0
- package/dist/modules/sso/api/callback/oidc/route.js.map +7 -0
- package/dist/modules/sso/api/config/[id]/activate/route.js +49 -0
- package/dist/modules/sso/api/config/[id]/activate/route.js.map +7 -0
- package/dist/modules/sso/api/config/[id]/domains/route.js +96 -0
- package/dist/modules/sso/api/config/[id]/domains/route.js.map +7 -0
- package/dist/modules/sso/api/config/[id]/route.js +103 -0
- package/dist/modules/sso/api/config/[id]/route.js.map +7 -0
- package/dist/modules/sso/api/config/[id]/test/route.js +41 -0
- package/dist/modules/sso/api/config/[id]/test/route.js.map +7 -0
- package/dist/modules/sso/api/config/route.js +83 -0
- package/dist/modules/sso/api/config/route.js.map +7 -0
- package/dist/modules/sso/api/error-handler.js +28 -0
- package/dist/modules/sso/api/error-handler.js.map +7 -0
- package/dist/modules/sso/api/hrd/route.js +52 -0
- package/dist/modules/sso/api/hrd/route.js.map +7 -0
- package/dist/modules/sso/api/initiate/route.js +66 -0
- package/dist/modules/sso/api/initiate/route.js.map +7 -0
- package/dist/modules/sso/api/scim/context.js +68 -0
- package/dist/modules/sso/api/scim/context.js.map +7 -0
- package/dist/modules/sso/api/scim/logs/route.js +65 -0
- package/dist/modules/sso/api/scim/logs/route.js.map +7 -0
- package/dist/modules/sso/api/scim/tokens/[id]/route.js +42 -0
- package/dist/modules/sso/api/scim/tokens/[id]/route.js.map +7 -0
- package/dist/modules/sso/api/scim/tokens/route.js +83 -0
- package/dist/modules/sso/api/scim/tokens/route.js.map +7 -0
- package/dist/modules/sso/api/scim/v2/ServiceProviderConfig/route.js +42 -0
- package/dist/modules/sso/api/scim/v2/ServiceProviderConfig/route.js.map +7 -0
- package/dist/modules/sso/api/scim/v2/Users/[id]/route.js +94 -0
- package/dist/modules/sso/api/scim/v2/Users/[id]/route.js.map +7 -0
- package/dist/modules/sso/api/scim/v2/Users/route.js +86 -0
- package/dist/modules/sso/api/scim/v2/Users/route.js.map +7 -0
- package/dist/modules/sso/backend/page.js +173 -0
- package/dist/modules/sso/backend/page.js.map +7 -0
- package/dist/modules/sso/backend/page.meta.js +31 -0
- package/dist/modules/sso/backend/page.meta.js.map +7 -0
- package/dist/modules/sso/backend/sso/config/[id]/page.js +749 -0
- package/dist/modules/sso/backend/sso/config/[id]/page.js.map +7 -0
- package/dist/modules/sso/backend/sso/config/[id]/page.meta.js +19 -0
- package/dist/modules/sso/backend/sso/config/[id]/page.meta.js.map +7 -0
- package/dist/modules/sso/backend/sso/config/new/page.js +381 -0
- package/dist/modules/sso/backend/sso/config/new/page.js.map +7 -0
- package/dist/modules/sso/backend/sso/config/new/page.meta.js +19 -0
- package/dist/modules/sso/backend/sso/config/new/page.meta.js.map +7 -0
- package/dist/modules/sso/data/entities.js +299 -0
- package/dist/modules/sso/data/entities.js.map +7 -0
- package/dist/modules/sso/data/validators.js +114 -0
- package/dist/modules/sso/data/validators.js.map +7 -0
- package/dist/modules/sso/di.js +26 -0
- package/dist/modules/sso/di.js.map +7 -0
- package/dist/modules/sso/events.js +24 -0
- package/dist/modules/sso/events.js.map +7 -0
- package/dist/modules/sso/i18n/de.json +146 -0
- package/dist/modules/sso/i18n/en.json +146 -0
- package/dist/modules/sso/i18n/es.json +146 -0
- package/dist/modules/sso/i18n/pl.json +146 -0
- package/dist/modules/sso/index.js +11 -0
- package/dist/modules/sso/index.js.map +7 -0
- package/dist/modules/sso/lib/domains.js +30 -0
- package/dist/modules/sso/lib/domains.js.map +7 -0
- package/dist/modules/sso/lib/oidc-provider.js +140 -0
- package/dist/modules/sso/lib/oidc-provider.js.map +7 -0
- package/dist/modules/sso/lib/registry.js +15 -0
- package/dist/modules/sso/lib/registry.js.map +7 -0
- package/dist/modules/sso/lib/scim-filter.js +43 -0
- package/dist/modules/sso/lib/scim-filter.js.map +7 -0
- package/dist/modules/sso/lib/scim-mapper.js +49 -0
- package/dist/modules/sso/lib/scim-mapper.js.map +7 -0
- package/dist/modules/sso/lib/scim-patch.js +63 -0
- package/dist/modules/sso/lib/scim-patch.js.map +7 -0
- package/dist/modules/sso/lib/scim-response.js +34 -0
- package/dist/modules/sso/lib/scim-response.js.map +7 -0
- package/dist/modules/sso/lib/scim-utils.js +9 -0
- package/dist/modules/sso/lib/scim-utils.js.map +7 -0
- package/dist/modules/sso/lib/state-cookie.js +67 -0
- package/dist/modules/sso/lib/state-cookie.js.map +7 -0
- package/dist/modules/sso/lib/types.js +1 -0
- package/dist/modules/sso/lib/types.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260219000000_sso.js +20 -0
- package/dist/modules/sso/migrations/Migration20260219000000_sso.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260222000000_sso_add_name.js +13 -0
- package/dist/modules/sso/migrations/Migration20260222000000_sso_add_name.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260222000001_sso_partial_unique_org.js +15 -0
- package/dist/modules/sso/migrations/Migration20260222000001_sso_partial_unique_org.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260223000000_scim_tables.js +22 -0
- package/dist/modules/sso/migrations/Migration20260223000000_scim_tables.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260224000000_sso_external_id.js +15 -0
- package/dist/modules/sso/migrations/Migration20260224000000_sso_external_id.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260224100000_sso_role_grants.js +17 -0
- package/dist/modules/sso/migrations/Migration20260224100000_sso_role_grants.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260224200000_drop_default_role_id.js +13 -0
- package/dist/modules/sso/migrations/Migration20260224200000_drop_default_role_id.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260225000000_sso_identities_partial_unique.js +23 -0
- package/dist/modules/sso/migrations/Migration20260225000000_sso_identities_partial_unique.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260305000000_sso_role_grants_org_id.js +14 -0
- package/dist/modules/sso/migrations/Migration20260305000000_sso_role_grants_org_id.js.map +7 -0
- package/dist/modules/sso/services/accountLinkingService.js +298 -0
- package/dist/modules/sso/services/accountLinkingService.js.map +7 -0
- package/dist/modules/sso/services/hrdService.js +18 -0
- package/dist/modules/sso/services/hrdService.js.map +7 -0
- package/dist/modules/sso/services/scimService.js +372 -0
- package/dist/modules/sso/services/scimService.js.map +7 -0
- package/dist/modules/sso/services/scimTokenService.js +94 -0
- package/dist/modules/sso/services/scimTokenService.js.map +7 -0
- package/dist/modules/sso/services/ssoConfigService.js +254 -0
- package/dist/modules/sso/services/ssoConfigService.js.map +7 -0
- package/dist/modules/sso/services/ssoService.js +125 -0
- package/dist/modules/sso/services/ssoService.js.map +7 -0
- package/dist/modules/sso/setup.js +47 -0
- package/dist/modules/sso/setup.js.map +7 -0
- package/dist/modules/sso/subscribers/user-deleted-cleanup.js +21 -0
- package/dist/modules/sso/subscribers/user-deleted-cleanup.js.map +7 -0
- package/dist/modules/sso/widgets/injection/login-sso/widget.client.js +106 -0
- package/dist/modules/sso/widgets/injection/login-sso/widget.client.js.map +7 -0
- package/dist/modules/sso/widgets/injection/login-sso/widget.js +16 -0
- package/dist/modules/sso/widgets/injection/login-sso/widget.js.map +7 -0
- package/dist/modules/sso/widgets/injection-table.js +14 -0
- package/dist/modules/sso/widgets/injection-table.js.map +7 -0
- package/package.json +5 -4
- package/src/index.ts +1 -1
- package/src/modules/sso/acl.ts +7 -0
- package/src/modules/sso/api/admin-context.ts +36 -0
- package/src/modules/sso/api/callback/oidc/route.ts +115 -0
- package/src/modules/sso/api/config/[id]/activate/route.ts +53 -0
- package/src/modules/sso/api/config/[id]/domains/route.ts +107 -0
- package/src/modules/sso/api/config/[id]/route.ts +114 -0
- package/src/modules/sso/api/config/[id]/test/route.ts +44 -0
- package/src/modules/sso/api/config/route.ts +88 -0
- package/src/modules/sso/api/error-handler.ts +36 -0
- package/src/modules/sso/api/hrd/route.ts +55 -0
- package/src/modules/sso/api/initiate/route.ts +70 -0
- package/src/modules/sso/api/scim/context.ts +85 -0
- package/src/modules/sso/api/scim/logs/route.ts +69 -0
- package/src/modules/sso/api/scim/tokens/[id]/route.ts +45 -0
- package/src/modules/sso/api/scim/tokens/route.ts +89 -0
- package/src/modules/sso/api/scim/v2/ServiceProviderConfig/route.ts +40 -0
- package/src/modules/sso/api/scim/v2/Users/[id]/route.ts +103 -0
- package/src/modules/sso/api/scim/v2/Users/route.ts +94 -0
- package/src/modules/sso/backend/page.meta.ts +29 -0
- package/src/modules/sso/backend/page.tsx +232 -0
- package/src/modules/sso/backend/sso/config/[id]/page.meta.ts +15 -0
- package/src/modules/sso/backend/sso/config/[id]/page.tsx +1024 -0
- package/src/modules/sso/backend/sso/config/new/page.meta.ts +15 -0
- package/src/modules/sso/backend/sso/config/new/page.tsx +463 -0
- package/src/modules/sso/data/entities.ts +240 -0
- package/src/modules/sso/data/validators.ts +140 -0
- package/src/modules/sso/di.ts +25 -0
- package/src/modules/sso/docs/entra-id-setup.md +281 -0
- package/src/modules/sso/docs/google-workspace-setup.md +174 -0
- package/src/modules/sso/docs/sso-overview.md +218 -0
- package/src/modules/sso/docs/sso-security-audit-2026-02-27.md +118 -0
- package/src/modules/sso/docs/zitadel-setup.md +195 -0
- package/src/modules/sso/events.ts +21 -0
- package/src/modules/sso/i18n/de.json +146 -0
- package/src/modules/sso/i18n/en.json +146 -0
- package/src/modules/sso/i18n/es.json +146 -0
- package/src/modules/sso/i18n/pl.json +146 -0
- package/src/modules/sso/index.ts +7 -0
- package/src/modules/sso/lib/domains.ts +31 -0
- package/src/modules/sso/lib/oidc-provider.ts +196 -0
- package/src/modules/sso/lib/registry.ts +13 -0
- package/src/modules/sso/lib/scim-filter.ts +62 -0
- package/src/modules/sso/lib/scim-mapper.ts +88 -0
- package/src/modules/sso/lib/scim-patch.ts +88 -0
- package/src/modules/sso/lib/scim-response.ts +40 -0
- package/src/modules/sso/lib/scim-utils.ts +5 -0
- package/src/modules/sso/lib/state-cookie.ts +79 -0
- package/src/modules/sso/lib/types.ts +50 -0
- package/src/modules/sso/migrations/.snapshot-open-mercato.json +912 -0
- package/src/modules/sso/migrations/Migration20260219000000_sso.ts +21 -0
- package/src/modules/sso/migrations/Migration20260222000000_sso_add_name.ts +13 -0
- package/src/modules/sso/migrations/Migration20260222000001_sso_partial_unique_org.ts +15 -0
- package/src/modules/sso/migrations/Migration20260223000000_scim_tables.ts +24 -0
- package/src/modules/sso/migrations/Migration20260224000000_sso_external_id.ts +15 -0
- package/src/modules/sso/migrations/Migration20260224100000_sso_role_grants.ts +18 -0
- package/src/modules/sso/migrations/Migration20260224200000_drop_default_role_id.ts +13 -0
- package/src/modules/sso/migrations/Migration20260225000000_sso_identities_partial_unique.ts +25 -0
- package/src/modules/sso/migrations/Migration20260305000000_sso_role_grants_org_id.ts +14 -0
- package/src/modules/sso/services/accountLinkingService.ts +386 -0
- package/src/modules/sso/services/hrdService.ts +22 -0
- package/src/modules/sso/services/scimService.ts +461 -0
- package/src/modules/sso/services/scimTokenService.ts +136 -0
- package/src/modules/sso/services/ssoConfigService.ts +337 -0
- package/src/modules/sso/services/ssoService.ts +167 -0
- package/src/modules/sso/setup.ts +56 -0
- package/src/modules/sso/subscribers/user-deleted-cleanup.ts +33 -0
- package/src/modules/sso/widgets/injection/login-sso/widget.client.tsx +130 -0
- package/src/modules/sso/widgets/injection/login-sso/widget.ts +16 -0
- package/src/modules/sso/widgets/injection-table.ts +12 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { scimJson } from "../../../../lib/scim-response.js";
|
|
2
|
+
const metadata = {};
|
|
3
|
+
async function GET() {
|
|
4
|
+
return scimJson({
|
|
5
|
+
schemas: ["urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig"],
|
|
6
|
+
documentationUri: "https://open-mercato.com/docs/scim",
|
|
7
|
+
patch: { supported: true },
|
|
8
|
+
bulk: { supported: false, maxOperations: 0, maxPayloadSize: 0 },
|
|
9
|
+
filter: { supported: true, maxResults: 200 },
|
|
10
|
+
changePassword: { supported: false },
|
|
11
|
+
sort: { supported: false },
|
|
12
|
+
etag: { supported: false },
|
|
13
|
+
authenticationSchemes: [
|
|
14
|
+
{
|
|
15
|
+
type: "oauthbearertoken",
|
|
16
|
+
name: "OAuth Bearer Token",
|
|
17
|
+
description: "Authentication scheme using the OAuth Bearer Token standard",
|
|
18
|
+
specUri: "https://www.rfc-editor.org/info/rfc6750",
|
|
19
|
+
primary: true
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
const openApi = {
|
|
25
|
+
tag: "SCIM",
|
|
26
|
+
summary: "SCIM Service Provider Configuration",
|
|
27
|
+
methods: {
|
|
28
|
+
GET: {
|
|
29
|
+
summary: "Get SCIM service provider configuration",
|
|
30
|
+
description: "Returns SCIM 2.0 ServiceProviderConfig. No authentication required \u2014 used by identity providers during connection testing.",
|
|
31
|
+
tags: ["SSO", "SCIM"],
|
|
32
|
+
responses: [{ status: 200, description: "SCIM ServiceProviderConfig" }],
|
|
33
|
+
errors: []
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
export {
|
|
38
|
+
GET,
|
|
39
|
+
metadata,
|
|
40
|
+
openApi
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../src/modules/sso/api/scim/v2/ServiceProviderConfig/route.ts"],
|
|
4
|
+
"sourcesContent": ["import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { scimJson } from '../../../../lib/scim-response'\n\nexport const metadata = {}\n\nexport async function GET() {\n return scimJson({\n schemas: ['urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig'],\n documentationUri: 'https://open-mercato.com/docs/scim',\n patch: { supported: true },\n bulk: { supported: false, maxOperations: 0, maxPayloadSize: 0 },\n filter: { supported: true, maxResults: 200 },\n changePassword: { supported: false },\n sort: { supported: false },\n etag: { supported: false },\n authenticationSchemes: [\n {\n type: 'oauthbearertoken',\n name: 'OAuth Bearer Token',\n description: 'Authentication scheme using the OAuth Bearer Token standard',\n specUri: 'https://www.rfc-editor.org/info/rfc6750',\n primary: true,\n },\n ],\n })\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'SCIM',\n summary: 'SCIM Service Provider Configuration',\n methods: {\n GET: {\n summary: 'Get SCIM service provider configuration',\n description: 'Returns SCIM 2.0 ServiceProviderConfig. No authentication required \u2014 used by identity providers during connection testing.',\n tags: ['SSO', 'SCIM'],\n responses: [{ status: 200, description: 'SCIM ServiceProviderConfig' }],\n errors: [],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,gBAAgB;AAElB,MAAM,WAAW,CAAC;AAEzB,eAAsB,MAAM;AAC1B,SAAO,SAAS;AAAA,IACd,SAAS,CAAC,6DAA6D;AAAA,IACvE,kBAAkB;AAAA,IAClB,OAAO,EAAE,WAAW,KAAK;AAAA,IACzB,MAAM,EAAE,WAAW,OAAO,eAAe,GAAG,gBAAgB,EAAE;AAAA,IAC9D,QAAQ,EAAE,WAAW,MAAM,YAAY,IAAI;AAAA,IAC3C,gBAAgB,EAAE,WAAW,MAAM;AAAA,IACnC,MAAM,EAAE,WAAW,MAAM;AAAA,IACzB,MAAM,EAAE,WAAW,MAAM;AAAA,IACzB,uBAAuB;AAAA,MACrB;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,QACb,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,KAAK;AAAA,MACH,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO,MAAM;AAAA,MACpB,WAAW,CAAC,EAAE,QAAQ,KAAK,aAAa,6BAA6B,CAAC;AAAA,MACtE,QAAQ,CAAC;AAAA,IACX;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
|
|
2
|
+
import { resolveScimContext } from "../../../context.js";
|
|
3
|
+
import { parseScimPatchOperations } from "../../../../../lib/scim-patch.js";
|
|
4
|
+
import { scimJson } from "../../../../../lib/scim-response.js";
|
|
5
|
+
import { handleScimApiError } from "../../../../error-handler.js";
|
|
6
|
+
const metadata = {};
|
|
7
|
+
async function GET(req, ctx) {
|
|
8
|
+
try {
|
|
9
|
+
const { id } = await ctx.params;
|
|
10
|
+
const scimCtx = await resolveScimContext(req);
|
|
11
|
+
if (!scimCtx.ok) return scimCtx.response;
|
|
12
|
+
const baseUrl = new URL(req.url).origin;
|
|
13
|
+
const container = await createRequestContainer();
|
|
14
|
+
const service = container.resolve("scimService");
|
|
15
|
+
const resource = await service.getUser(id, scimCtx.scope, baseUrl);
|
|
16
|
+
return scimJson(resource);
|
|
17
|
+
} catch (err) {
|
|
18
|
+
return handleScimApiError(err, "SCIM Users API");
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async function PATCH(req, ctx) {
|
|
22
|
+
try {
|
|
23
|
+
const { id } = await ctx.params;
|
|
24
|
+
const scimCtx = await resolveScimContext(req);
|
|
25
|
+
if (!scimCtx.ok) return scimCtx.response;
|
|
26
|
+
const body = await req.json();
|
|
27
|
+
const operations = parseScimPatchOperations(body);
|
|
28
|
+
const baseUrl = new URL(req.url).origin;
|
|
29
|
+
const container = await createRequestContainer();
|
|
30
|
+
const service = container.resolve("scimService");
|
|
31
|
+
const resource = await service.patchUser(id, operations, scimCtx.scope, baseUrl);
|
|
32
|
+
return scimJson(resource);
|
|
33
|
+
} catch (err) {
|
|
34
|
+
return handleScimApiError(err, "SCIM Users API");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async function DELETE(req, ctx) {
|
|
38
|
+
try {
|
|
39
|
+
const { id } = await ctx.params;
|
|
40
|
+
const scimCtx = await resolveScimContext(req);
|
|
41
|
+
if (!scimCtx.ok) return scimCtx.response;
|
|
42
|
+
const container = await createRequestContainer();
|
|
43
|
+
const service = container.resolve("scimService");
|
|
44
|
+
await service.deleteUser(id, scimCtx.scope);
|
|
45
|
+
return new Response(null, { status: 204 });
|
|
46
|
+
} catch (err) {
|
|
47
|
+
return handleScimApiError(err, "SCIM Users API");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const openApi = {
|
|
51
|
+
tag: "SCIM",
|
|
52
|
+
summary: "SCIM User by ID",
|
|
53
|
+
methods: {
|
|
54
|
+
GET: {
|
|
55
|
+
summary: "Get SCIM user",
|
|
56
|
+
description: "Returns a single provisioned user by SCIM ID.",
|
|
57
|
+
tags: ["SSO", "SCIM"],
|
|
58
|
+
responses: [{ status: 200, description: "SCIM User resource" }],
|
|
59
|
+
errors: [
|
|
60
|
+
{ status: 401, description: "Unauthorized" },
|
|
61
|
+
{ status: 404, description: "User not found" }
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
PATCH: {
|
|
65
|
+
summary: "Patch SCIM user",
|
|
66
|
+
description: "Updates user attributes via SCIM PatchOp. Supports active/inactive toggling.",
|
|
67
|
+
tags: ["SSO", "SCIM"],
|
|
68
|
+
responses: [{ status: 200, description: "Updated SCIM User resource" }],
|
|
69
|
+
errors: [
|
|
70
|
+
{ status: 400, description: "Invalid PatchOp" },
|
|
71
|
+
{ status: 401, description: "Unauthorized" },
|
|
72
|
+
{ status: 404, description: "User not found" }
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
DELETE: {
|
|
76
|
+
summary: "Delete SCIM user",
|
|
77
|
+
description: "Deactivates the user and revokes sessions.",
|
|
78
|
+
tags: ["SSO", "SCIM"],
|
|
79
|
+
responses: [{ status: 204, description: "No content" }],
|
|
80
|
+
errors: [
|
|
81
|
+
{ status: 401, description: "Unauthorized" },
|
|
82
|
+
{ status: 404, description: "User not found" }
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
export {
|
|
88
|
+
DELETE,
|
|
89
|
+
GET,
|
|
90
|
+
PATCH,
|
|
91
|
+
metadata,
|
|
92
|
+
openApi
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../../src/modules/sso/api/scim/v2/Users/%5Bid%5D/route.ts"],
|
|
4
|
+
"sourcesContent": ["import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { resolveScimContext } from '../../../context'\nimport { ScimService } from '../../../../../services/scimService'\nimport { parseScimPatchOperations } from '../../../../../lib/scim-patch'\nimport { scimJson } from '../../../../../lib/scim-response'\nimport { handleScimApiError } from '../../../../error-handler'\n\nexport const metadata = {}\n\ntype RouteContext = { params: Promise<{ id: string }> }\n\nexport async function GET(req: Request, ctx: RouteContext) {\n try {\n const { id } = await ctx.params\n const scimCtx = await resolveScimContext(req)\n if (!scimCtx.ok) return scimCtx.response\n\n const baseUrl = new URL(req.url).origin\n const container = await createRequestContainer()\n const service = container.resolve<ScimService>('scimService')\n const resource = await service.getUser(id, scimCtx.scope, baseUrl)\n\n return scimJson(resource)\n } catch (err) {\n return handleScimApiError(err, 'SCIM Users API')\n }\n}\n\nexport async function PATCH(req: Request, ctx: RouteContext) {\n try {\n const { id } = await ctx.params\n const scimCtx = await resolveScimContext(req)\n if (!scimCtx.ok) return scimCtx.response\n\n const body = await req.json()\n const operations = parseScimPatchOperations(body)\n const baseUrl = new URL(req.url).origin\n\n const container = await createRequestContainer()\n const service = container.resolve<ScimService>('scimService')\n const resource = await service.patchUser(id, operations, scimCtx.scope, baseUrl)\n\n return scimJson(resource)\n } catch (err) {\n return handleScimApiError(err, 'SCIM Users API')\n }\n}\n\nexport async function DELETE(req: Request, ctx: RouteContext) {\n try {\n const { id } = await ctx.params\n const scimCtx = await resolveScimContext(req)\n if (!scimCtx.ok) return scimCtx.response\n\n const container = await createRequestContainer()\n const service = container.resolve<ScimService>('scimService')\n await service.deleteUser(id, scimCtx.scope)\n\n return new Response(null, { status: 204 })\n } catch (err) {\n return handleScimApiError(err, 'SCIM Users API')\n }\n}\n\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'SCIM',\n summary: 'SCIM User by ID',\n methods: {\n GET: {\n summary: 'Get SCIM user',\n description: 'Returns a single provisioned user by SCIM ID.',\n tags: ['SSO', 'SCIM'],\n responses: [{ status: 200, description: 'SCIM User resource' }],\n errors: [\n { status: 401, description: 'Unauthorized' },\n { status: 404, description: 'User not found' },\n ],\n },\n PATCH: {\n summary: 'Patch SCIM user',\n description: 'Updates user attributes via SCIM PatchOp. Supports active/inactive toggling.',\n tags: ['SSO', 'SCIM'],\n responses: [{ status: 200, description: 'Updated SCIM User resource' }],\n errors: [\n { status: 400, description: 'Invalid PatchOp' },\n { status: 401, description: 'Unauthorized' },\n { status: 404, description: 'User not found' },\n ],\n },\n DELETE: {\n summary: 'Delete SCIM user',\n description: 'Deactivates the user and revokes sessions.',\n tags: ['SSO', 'SCIM'],\n responses: [{ status: 204, description: 'No content' }],\n errors: [\n { status: 401, description: 'Unauthorized' },\n { status: 404, description: 'User not found' },\n ],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
|
|
2
|
+
import { resolveScimContext } from "../../context.js";
|
|
3
|
+
import { handleScimApiError } from "../../../error-handler.js";
|
|
4
|
+
import { scimUserPayloadSchema } from "../../../../data/validators.js";
|
|
5
|
+
import { buildScimError, scimJson as scimJsonResponse } from "../../../../lib/scim-response.js";
|
|
6
|
+
const metadata = {};
|
|
7
|
+
async function POST(req) {
|
|
8
|
+
try {
|
|
9
|
+
const ctx = await resolveScimContext(req);
|
|
10
|
+
if (!ctx.ok) return ctx.response;
|
|
11
|
+
const body = await req.json();
|
|
12
|
+
const parsed = scimUserPayloadSchema.safeParse(body);
|
|
13
|
+
if (!parsed.success) {
|
|
14
|
+
return scimJsonResponse(
|
|
15
|
+
buildScimError(400, parsed.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join("; "), "invalidValue"),
|
|
16
|
+
400
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
const baseUrl = new URL(req.url).origin;
|
|
20
|
+
const container = await createRequestContainer();
|
|
21
|
+
const service = container.resolve("scimService");
|
|
22
|
+
const { resource, status } = await service.createUser(parsed.data, ctx.scope, baseUrl);
|
|
23
|
+
const headers = {};
|
|
24
|
+
if (status === 201) {
|
|
25
|
+
headers.Location = resource.meta.location;
|
|
26
|
+
}
|
|
27
|
+
return scimJsonResponse(resource, status);
|
|
28
|
+
} catch (err) {
|
|
29
|
+
return handleScimApiError(err, "SCIM Users API");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function GET(req) {
|
|
33
|
+
try {
|
|
34
|
+
const ctx = await resolveScimContext(req);
|
|
35
|
+
if (!ctx.ok) return ctx.response;
|
|
36
|
+
const url = new URL(req.url);
|
|
37
|
+
const filter = url.searchParams.get("filter");
|
|
38
|
+
const startIndex = Math.max(1, parseInt(url.searchParams.get("startIndex") ?? "1", 10) || 1);
|
|
39
|
+
const count = Math.min(200, Math.max(1, parseInt(url.searchParams.get("count") ?? "100", 10) || 100));
|
|
40
|
+
const baseUrl = url.origin;
|
|
41
|
+
const container = await createRequestContainer();
|
|
42
|
+
const service = container.resolve("scimService");
|
|
43
|
+
const result = await service.listUsers(filter, startIndex, count, ctx.scope, baseUrl);
|
|
44
|
+
return scimJsonResponse(result);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
return handleScimApiError(err, "SCIM Users API");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const openApi = {
|
|
50
|
+
tag: "SCIM",
|
|
51
|
+
summary: "SCIM Users",
|
|
52
|
+
methods: {
|
|
53
|
+
POST: {
|
|
54
|
+
summary: "Create SCIM user",
|
|
55
|
+
description: "Provisions a new user via SCIM 2.0. Supports idempotency via externalId.",
|
|
56
|
+
tags: ["SSO", "SCIM"],
|
|
57
|
+
responses: [
|
|
58
|
+
{ status: 201, description: "User created" },
|
|
59
|
+
{ status: 200, description: "User already exists (idempotent)" }
|
|
60
|
+
],
|
|
61
|
+
errors: [
|
|
62
|
+
{ status: 400, description: "Invalid payload" },
|
|
63
|
+
{ status: 401, description: "Unauthorized" },
|
|
64
|
+
{ status: 403, description: "SSO config inactive" },
|
|
65
|
+
{ status: 409, description: "Conflict \u2014 user already linked" }
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
GET: {
|
|
69
|
+
summary: "List SCIM users",
|
|
70
|
+
description: "Lists provisioned users with optional SCIM filter (eq operator).",
|
|
71
|
+
tags: ["SSO", "SCIM"],
|
|
72
|
+
responses: [{ status: 200, description: "SCIM ListResponse" }],
|
|
73
|
+
errors: [
|
|
74
|
+
{ status: 401, description: "Unauthorized" },
|
|
75
|
+
{ status: 403, description: "SSO config inactive" }
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
export {
|
|
81
|
+
GET,
|
|
82
|
+
POST,
|
|
83
|
+
metadata,
|
|
84
|
+
openApi
|
|
85
|
+
};
|
|
86
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../src/modules/sso/api/scim/v2/Users/route.ts"],
|
|
4
|
+
"sourcesContent": ["import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { resolveScimContext } from '../../context'\nimport { ScimService } from '../../../../services/scimService'\nimport { handleScimApiError } from '../../../error-handler'\nimport { scimUserPayloadSchema } from '../../../../data/validators'\nimport { buildScimError, scimJson as scimJsonResponse } from '../../../../lib/scim-response'\n\nexport const metadata = {}\n\nexport async function POST(req: Request) {\n try {\n const ctx = await resolveScimContext(req)\n if (!ctx.ok) return ctx.response\n\n const body = await req.json()\n const parsed = scimUserPayloadSchema.safeParse(body)\n if (!parsed.success) {\n return scimJsonResponse(\n buildScimError(400, parsed.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join('; '), 'invalidValue'),\n 400,\n )\n }\n\n const baseUrl = new URL(req.url).origin\n\n const container = await createRequestContainer()\n const service = container.resolve<ScimService>('scimService')\n const { resource, status } = await service.createUser(parsed.data, ctx.scope, baseUrl)\n\n const headers: Record<string, string> = {}\n if (status === 201) {\n headers.Location = resource.meta.location\n }\n\n return scimJsonResponse(resource, status)\n } catch (err) {\n return handleScimApiError(err, 'SCIM Users API')\n }\n}\n\nexport async function GET(req: Request) {\n try {\n const ctx = await resolveScimContext(req)\n if (!ctx.ok) return ctx.response\n\n const url = new URL(req.url)\n const filter = url.searchParams.get('filter')\n const startIndex = Math.max(1, parseInt(url.searchParams.get('startIndex') ?? '1', 10) || 1)\n const count = Math.min(200, Math.max(1, parseInt(url.searchParams.get('count') ?? '100', 10) || 100))\n const baseUrl = url.origin\n\n const container = await createRequestContainer()\n const service = container.resolve<ScimService>('scimService')\n const result = await service.listUsers(filter, startIndex, count, ctx.scope, baseUrl)\n\n return scimJsonResponse(result)\n } catch (err) {\n return handleScimApiError(err, 'SCIM Users API')\n }\n}\n\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'SCIM',\n summary: 'SCIM Users',\n methods: {\n POST: {\n summary: 'Create SCIM user',\n description: 'Provisions a new user via SCIM 2.0. Supports idempotency via externalId.',\n tags: ['SSO', 'SCIM'],\n responses: [\n { status: 201, description: 'User created' },\n { status: 200, description: 'User already exists (idempotent)' },\n ],\n errors: [\n { status: 400, description: 'Invalid payload' },\n { status: 401, description: 'Unauthorized' },\n { status: 403, description: 'SSO config inactive' },\n { status: 409, description: 'Conflict \u2014 user already linked' },\n ],\n },\n GET: {\n summary: 'List SCIM users',\n description: 'Lists provisioned users with optional SCIM filter (eq operator).',\n tags: ['SSO', 'SCIM'],\n responses: [{ status: 200, description: 'SCIM ListResponse' }],\n errors: [\n { status: 401, description: 'Unauthorized' },\n { status: 403, description: 'SSO config inactive' },\n ],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { useRouter } from "next/navigation";
|
|
5
|
+
import { Page, PageBody } from "@open-mercato/ui/backend/Page";
|
|
6
|
+
import { DataTable } from "@open-mercato/ui/backend/DataTable";
|
|
7
|
+
import { RowActions } from "@open-mercato/ui/backend/RowActions";
|
|
8
|
+
import { Button } from "@open-mercato/ui/primitives/button";
|
|
9
|
+
import { apiCall, apiCallOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
|
|
10
|
+
import { flash } from "@open-mercato/ui/backend/FlashMessages";
|
|
11
|
+
import { useConfirmDialog } from "@open-mercato/ui/backend/confirm-dialog";
|
|
12
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
13
|
+
import Link from "next/link";
|
|
14
|
+
const fallback = { items: [], total: 0, totalPages: 1 };
|
|
15
|
+
function SsoConfigListPage() {
|
|
16
|
+
const router = useRouter();
|
|
17
|
+
const t = useT();
|
|
18
|
+
const [data, setData] = React.useState(fallback);
|
|
19
|
+
const [isLoading, setIsLoading] = React.useState(true);
|
|
20
|
+
const [page, setPage] = React.useState(1);
|
|
21
|
+
const [search, setSearch] = React.useState("");
|
|
22
|
+
const { confirm, ConfirmDialogElement } = useConfirmDialog();
|
|
23
|
+
const isSuperAdmin = !!data.isSuperAdmin;
|
|
24
|
+
const fetchData = React.useCallback(async () => {
|
|
25
|
+
setIsLoading(true);
|
|
26
|
+
const params = new URLSearchParams();
|
|
27
|
+
params.set("page", String(page));
|
|
28
|
+
params.set("pageSize", "50");
|
|
29
|
+
if (search) params.set("search", search);
|
|
30
|
+
const call = await apiCall(`/api/sso/config?${params}`, void 0, { fallback });
|
|
31
|
+
if (call.ok && call.result) {
|
|
32
|
+
setData(call.result);
|
|
33
|
+
}
|
|
34
|
+
setIsLoading(false);
|
|
35
|
+
}, [page, search]);
|
|
36
|
+
React.useEffect(() => {
|
|
37
|
+
fetchData();
|
|
38
|
+
}, [fetchData]);
|
|
39
|
+
const handleDelete = async (row) => {
|
|
40
|
+
if (row.isActive) {
|
|
41
|
+
flash(t("sso.admin.error.deleteActive", "Cannot delete an active SSO configuration \u2014 deactivate it first"), "error");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const confirmed = await confirm({
|
|
45
|
+
title: t("sso.admin.delete.title", "Delete SSO Configuration"),
|
|
46
|
+
text: t("sso.admin.delete.confirm", "Are you sure? This will remove the SSO configuration. Users with linked SSO identities will need to use password login."),
|
|
47
|
+
confirmText: t("common.delete", "Delete"),
|
|
48
|
+
variant: "destructive"
|
|
49
|
+
});
|
|
50
|
+
if (!confirmed) return;
|
|
51
|
+
await apiCallOrThrow(`/api/sso/config/${row.id}`, { method: "DELETE" }, {
|
|
52
|
+
errorMessage: t("sso.admin.error.deleteFailed", "Failed to delete SSO configuration")
|
|
53
|
+
});
|
|
54
|
+
flash(t("sso.admin.delete.success", "SSO configuration deleted"), "success");
|
|
55
|
+
fetchData();
|
|
56
|
+
};
|
|
57
|
+
const handleToggleActivation = async (row) => {
|
|
58
|
+
try {
|
|
59
|
+
await apiCallOrThrow(
|
|
60
|
+
`/api/sso/config/${row.id}/activate`,
|
|
61
|
+
{
|
|
62
|
+
method: "POST",
|
|
63
|
+
headers: { "content-type": "application/json" },
|
|
64
|
+
body: JSON.stringify({ active: !row.isActive })
|
|
65
|
+
},
|
|
66
|
+
{ errorMessage: t("sso.admin.error.activationFailed", "Failed to update activation status") }
|
|
67
|
+
);
|
|
68
|
+
flash(
|
|
69
|
+
row.isActive ? t("sso.admin.deactivated", "SSO configuration deactivated") : t("sso.admin.activated", "SSO configuration activated"),
|
|
70
|
+
"success"
|
|
71
|
+
);
|
|
72
|
+
fetchData();
|
|
73
|
+
} catch {
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const handleTestConnection = async (row) => {
|
|
77
|
+
try {
|
|
78
|
+
const call = await apiCallOrThrow(
|
|
79
|
+
`/api/sso/config/${row.id}/test`,
|
|
80
|
+
{ method: "POST" },
|
|
81
|
+
{ errorMessage: t("sso.admin.error.testFailed", "Connection test failed") }
|
|
82
|
+
);
|
|
83
|
+
if (call.result?.ok) {
|
|
84
|
+
flash(t("sso.admin.test.success", "Discovery successful \u2014 issuer is reachable"), "success");
|
|
85
|
+
} else {
|
|
86
|
+
flash(call.result?.error || t("sso.admin.test.failed", "Discovery failed"), "error");
|
|
87
|
+
}
|
|
88
|
+
} catch {
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
const columns = React.useMemo(() => {
|
|
92
|
+
const cols = [
|
|
93
|
+
{
|
|
94
|
+
accessorKey: "name",
|
|
95
|
+
header: t("sso.admin.column.name", "Name"),
|
|
96
|
+
cell: ({ row }) => row.original.name || row.original.issuer || "\u2014"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
accessorKey: "protocol",
|
|
100
|
+
header: t("sso.admin.column.protocol", "Protocol"),
|
|
101
|
+
cell: ({ row }) => row.original.protocol.toUpperCase()
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
accessorKey: "allowedDomains",
|
|
105
|
+
header: t("sso.admin.column.domains", "Domains"),
|
|
106
|
+
cell: ({ row }) => row.original.allowedDomains.join(", ") || "\u2014"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
accessorKey: "isActive",
|
|
110
|
+
header: t("sso.admin.column.status", "Status"),
|
|
111
|
+
cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: `inline-flex items-center rounded-full px-2 py-1 text-xs font-medium ${row.original.isActive ? "bg-green-50 text-green-700" : "bg-gray-100 text-gray-600"}`, children: row.original.isActive ? t("sso.admin.status.active", "Active") : t("sso.admin.status.inactive", "Inactive") })
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
accessorKey: "createdAt",
|
|
115
|
+
header: t("sso.admin.column.created", "Created"),
|
|
116
|
+
cell: ({ row }) => new Date(row.original.createdAt).toLocaleDateString()
|
|
117
|
+
}
|
|
118
|
+
];
|
|
119
|
+
return cols;
|
|
120
|
+
}, [t, isSuperAdmin]);
|
|
121
|
+
const hasConfigs = data.items.length > 0 || search;
|
|
122
|
+
const canCreateNew = isSuperAdmin || data.items.length === 0;
|
|
123
|
+
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsxs(PageBody, { children: [
|
|
124
|
+
!hasConfigs && !isLoading ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-16 text-center", children: [
|
|
125
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: t("sso.admin.empty.title", "No SSO configured") }),
|
|
126
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground mb-4 max-w-md", children: t("sso.admin.empty.description", "Configure Single Sign-On to let your users authenticate with your identity provider.") }),
|
|
127
|
+
/* @__PURE__ */ jsx(Button, { asChild: true, children: /* @__PURE__ */ jsx(Link, { href: "/backend/sso/config/new", children: t("sso.admin.empty.cta", "Configure SSO") }) })
|
|
128
|
+
] }) : /* @__PURE__ */ jsx(
|
|
129
|
+
DataTable,
|
|
130
|
+
{
|
|
131
|
+
title: t("sso.admin.title", "Single Sign-On"),
|
|
132
|
+
actions: canCreateNew ? /* @__PURE__ */ jsx(Button, { asChild: true, size: "sm", children: /* @__PURE__ */ jsx(Link, { href: "/backend/sso/config/new", children: t("sso.admin.new", "New SSO Config") }) }) : void 0,
|
|
133
|
+
columns,
|
|
134
|
+
data: data.items,
|
|
135
|
+
searchValue: search,
|
|
136
|
+
onSearchChange: (value) => {
|
|
137
|
+
setSearch(value);
|
|
138
|
+
setPage(1);
|
|
139
|
+
},
|
|
140
|
+
searchPlaceholder: t("sso.admin.search", "Search by name or issuer..."),
|
|
141
|
+
onRowClick: (row) => router.push(`/backend/sso/config/${row.id}`),
|
|
142
|
+
rowActions: (row) => /* @__PURE__ */ jsx(
|
|
143
|
+
RowActions,
|
|
144
|
+
{
|
|
145
|
+
items: [
|
|
146
|
+
{ id: "edit", label: t("common.edit", "Edit"), onSelect: () => router.push(`/backend/sso/config/${row.id}`) },
|
|
147
|
+
{ id: "test", label: t("sso.admin.action.test", "Verify Discovery"), onSelect: () => handleTestConnection(row) },
|
|
148
|
+
{
|
|
149
|
+
id: "toggle",
|
|
150
|
+
label: row.isActive ? t("sso.admin.action.deactivate", "Deactivate") : t("sso.admin.action.activate", "Activate"),
|
|
151
|
+
onSelect: () => handleToggleActivation(row)
|
|
152
|
+
},
|
|
153
|
+
{ id: "delete", label: t("common.delete", "Delete"), destructive: true, onSelect: () => handleDelete(row) }
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
),
|
|
157
|
+
pagination: {
|
|
158
|
+
page,
|
|
159
|
+
pageSize: 50,
|
|
160
|
+
total: data.total,
|
|
161
|
+
totalPages: data.totalPages,
|
|
162
|
+
onPageChange: setPage
|
|
163
|
+
},
|
|
164
|
+
isLoading
|
|
165
|
+
}
|
|
166
|
+
),
|
|
167
|
+
ConfirmDialogElement
|
|
168
|
+
] }) });
|
|
169
|
+
}
|
|
170
|
+
export {
|
|
171
|
+
SsoConfigListPage as default
|
|
172
|
+
};
|
|
173
|
+
//# sourceMappingURL=page.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/sso/backend/page.tsx"],
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport React from 'react'\nimport { useRouter } from 'next/navigation'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { apiCall, apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport Link from 'next/link'\n\ninterface SsoConfigRow {\n id: string\n name: string | null\n protocol: string\n issuer: string | null\n allowedDomains: string[]\n isActive: boolean\n hasClientSecret: boolean\n organizationId: string\n tenantId: string | null\n createdAt: string\n}\n\ninterface ListResponse {\n items: SsoConfigRow[]\n total: number\n totalPages: number\n isSuperAdmin?: boolean\n}\n\nconst fallback: ListResponse = { items: [], total: 0, totalPages: 1 }\n\nexport default function SsoConfigListPage() {\n const router = useRouter()\n const t = useT()\n\n const [data, setData] = React.useState<ListResponse>(fallback)\n const [isLoading, setIsLoading] = React.useState(true)\n const [page, setPage] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n\n const isSuperAdmin = !!data.isSuperAdmin\n\n const fetchData = React.useCallback(async () => {\n setIsLoading(true)\n const params = new URLSearchParams()\n params.set('page', String(page))\n params.set('pageSize', '50')\n if (search) params.set('search', search)\n\n const call = await apiCall<ListResponse>(`/api/sso/config?${params}`, undefined, { fallback })\n if (call.ok && call.result) {\n setData(call.result)\n }\n setIsLoading(false)\n }, [page, search])\n\n React.useEffect(() => { fetchData() }, [fetchData])\n\n const handleDelete = async (row: SsoConfigRow) => {\n if (row.isActive) {\n flash(t('sso.admin.error.deleteActive', 'Cannot delete an active SSO configuration \u2014 deactivate it first'), 'error')\n return\n }\n\n const confirmed = await confirm({\n title: t('sso.admin.delete.title', 'Delete SSO Configuration'),\n text: t('sso.admin.delete.confirm', 'Are you sure? This will remove the SSO configuration. Users with linked SSO identities will need to use password login.'),\n confirmText: t('common.delete', 'Delete'),\n variant: 'destructive',\n })\n\n if (!confirmed) return\n\n await apiCallOrThrow(`/api/sso/config/${row.id}`, { method: 'DELETE' }, {\n errorMessage: t('sso.admin.error.deleteFailed', 'Failed to delete SSO configuration'),\n })\n flash(t('sso.admin.delete.success', 'SSO configuration deleted'), 'success')\n fetchData()\n }\n\n const handleToggleActivation = async (row: SsoConfigRow) => {\n try {\n await apiCallOrThrow(\n `/api/sso/config/${row.id}/activate`,\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ active: !row.isActive }),\n },\n { errorMessage: t('sso.admin.error.activationFailed', 'Failed to update activation status') },\n )\n flash(\n row.isActive\n ? t('sso.admin.deactivated', 'SSO configuration deactivated')\n : t('sso.admin.activated', 'SSO configuration activated'),\n 'success',\n )\n fetchData()\n } catch {\n // apiCallOrThrow already flashes the error\n }\n }\n\n const handleTestConnection = async (row: SsoConfigRow) => {\n try {\n const call = await apiCallOrThrow<{ ok: boolean; error?: string }>(\n `/api/sso/config/${row.id}/test`,\n { method: 'POST' },\n { errorMessage: t('sso.admin.error.testFailed', 'Connection test failed') },\n )\n if (call.result?.ok) {\n flash(t('sso.admin.test.success', 'Discovery successful \u2014 issuer is reachable'), 'success')\n } else {\n flash(call.result?.error || t('sso.admin.test.failed', 'Discovery failed'), 'error')\n }\n } catch {\n // apiCallOrThrow already flashes the error\n }\n }\n\n const columns = React.useMemo<ColumnDef<SsoConfigRow>[]>(() => {\n const cols: ColumnDef<SsoConfigRow>[] = [\n {\n accessorKey: 'name',\n header: t('sso.admin.column.name', 'Name'),\n cell: ({ row }) => row.original.name || row.original.issuer || '\u2014',\n },\n {\n accessorKey: 'protocol',\n header: t('sso.admin.column.protocol', 'Protocol'),\n cell: ({ row }) => row.original.protocol.toUpperCase(),\n },\n {\n accessorKey: 'allowedDomains',\n header: t('sso.admin.column.domains', 'Domains'),\n cell: ({ row }) => row.original.allowedDomains.join(', ') || '\u2014',\n },\n {\n accessorKey: 'isActive',\n header: t('sso.admin.column.status', 'Status'),\n cell: ({ row }) => (\n <span className={`inline-flex items-center rounded-full px-2 py-1 text-xs font-medium ${row.original.isActive ? 'bg-green-50 text-green-700' : 'bg-gray-100 text-gray-600'}`}>\n {row.original.isActive\n ? t('sso.admin.status.active', 'Active')\n : t('sso.admin.status.inactive', 'Inactive')}\n </span>\n ),\n },\n {\n accessorKey: 'createdAt',\n header: t('sso.admin.column.created', 'Created'),\n cell: ({ row }) => new Date(row.original.createdAt).toLocaleDateString(),\n },\n ]\n\n return cols\n }, [t, isSuperAdmin])\n\n const hasConfigs = data.items.length > 0 || search\n const canCreateNew = isSuperAdmin || data.items.length === 0\n\n return (\n <Page>\n <PageBody>\n {!hasConfigs && !isLoading ? (\n <div className=\"flex flex-col items-center justify-center py-16 text-center\">\n <h3 className=\"text-lg font-semibold mb-2\">\n {t('sso.admin.empty.title', 'No SSO configured')}\n </h3>\n <p className=\"text-muted-foreground mb-4 max-w-md\">\n {t('sso.admin.empty.description', 'Configure Single Sign-On to let your users authenticate with your identity provider.')}\n </p>\n <Button asChild>\n <Link href=\"/backend/sso/config/new\">\n {t('sso.admin.empty.cta', 'Configure SSO')}\n </Link>\n </Button>\n </div>\n ) : (\n <DataTable<SsoConfigRow>\n title={t('sso.admin.title', 'Single Sign-On')}\n actions={canCreateNew ? (\n <Button asChild size=\"sm\">\n <Link href=\"/backend/sso/config/new\">\n {t('sso.admin.new', 'New SSO Config')}\n </Link>\n </Button>\n ) : undefined}\n columns={columns}\n data={data.items}\n searchValue={search}\n onSearchChange={(value) => { setSearch(value); setPage(1) }}\n searchPlaceholder={t('sso.admin.search', 'Search by name or issuer...')}\n onRowClick={(row) => router.push(`/backend/sso/config/${row.id}`)}\n rowActions={(row) => (\n <RowActions\n items={[\n { id: 'edit', label: t('common.edit', 'Edit'), onSelect: () => router.push(`/backend/sso/config/${row.id}`) },\n { id: 'test', label: t('sso.admin.action.test', 'Verify Discovery'), onSelect: () => handleTestConnection(row) },\n {\n id: 'toggle',\n label: row.isActive\n ? t('sso.admin.action.deactivate', 'Deactivate')\n : t('sso.admin.action.activate', 'Activate'),\n onSelect: () => handleToggleActivation(row),\n },\n { id: 'delete', label: t('common.delete', 'Delete'), destructive: true, onSelect: () => handleDelete(row) },\n ]}\n />\n )}\n pagination={{\n page,\n pageSize: 50,\n total: data.total,\n totalPages: data.totalPages,\n onPageChange: setPage,\n }}\n isLoading={isLoading}\n />\n )}\n {ConfirmDialogElement}\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
const ssoIcon = React.createElement(
|
|
3
|
+
"svg",
|
|
4
|
+
{
|
|
5
|
+
width: 16,
|
|
6
|
+
height: 16,
|
|
7
|
+
viewBox: "0 0 24 24",
|
|
8
|
+
fill: "none",
|
|
9
|
+
stroke: "currentColor",
|
|
10
|
+
strokeWidth: 2,
|
|
11
|
+
strokeLinecap: "round",
|
|
12
|
+
strokeLinejoin: "round"
|
|
13
|
+
},
|
|
14
|
+
React.createElement("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" })
|
|
15
|
+
);
|
|
16
|
+
const metadata = {
|
|
17
|
+
requireAuth: true,
|
|
18
|
+
requireFeatures: ["sso.config.view"],
|
|
19
|
+
pageTitle: "Single Sign-On",
|
|
20
|
+
pageTitleKey: "sso.admin.title",
|
|
21
|
+
pageGroup: "Auth",
|
|
22
|
+
pageGroupKey: "settings.sections.auth",
|
|
23
|
+
pageOrder: 520,
|
|
24
|
+
icon: ssoIcon,
|
|
25
|
+
pageContext: "settings",
|
|
26
|
+
breadcrumb: [{ label: "Single Sign-On", labelKey: "sso.admin.title" }]
|
|
27
|
+
};
|
|
28
|
+
export {
|
|
29
|
+
metadata
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=page.meta.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/sso/backend/page.meta.ts"],
|
|
4
|
+
"sourcesContent": ["import React from 'react'\n\nconst ssoIcon = React.createElement(\n 'svg',\n {\n width: 16,\n height: 16,\n viewBox: '0 0 24 24',\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: 2,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n },\n React.createElement('path', { d: 'M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z' }),\n)\n\nexport const metadata = {\n requireAuth: true,\n requireFeatures: ['sso.config.view'],\n pageTitle: 'Single Sign-On',\n pageTitleKey: 'sso.admin.title',\n pageGroup: 'Auth',\n pageGroupKey: 'settings.sections.auth',\n pageOrder: 520,\n icon: ssoIcon,\n pageContext: 'settings' as const,\n breadcrumb: [{ label: 'Single Sign-On', labelKey: 'sso.admin.title' }],\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,WAAW;AAElB,MAAM,UAAU,MAAM;AAAA,EACpB;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,eAAe;AAAA,IACf,gBAAgB;AAAA,EAClB;AAAA,EACA,MAAM,cAAc,QAAQ,EAAE,GAAG,8CAA8C,CAAC;AAClF;AAEO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,iBAAiB;AAAA,EACnC,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,MAAM;AAAA,EACN,aAAa;AAAA,EACb,YAAY,CAAC,EAAE,OAAO,kBAAkB,UAAU,kBAAkB,CAAC;AACvE;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|