@eaera-com/cms-sdk 0.1.67 → 0.1.68
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/LICENSE +28 -15
- package/THIRD-PARTY-NOTICES.md +135 -0
- package/dist/chunks/_shared-DZlTUzoa.js +0 -1
- package/dist/chunks/auth.constant-CMI1lqQc.js +0 -1
- package/dist/chunks/authz.constant-BAarvacV.js +0 -1
- package/dist/chunks/http.constant-BzH5tJTG.js +0 -1
- package/dist/chunks/mt5Retcode-DlZLQOLA.js +0 -1
- package/dist/chunks/storage.constant-CVWam5ls.js +0 -1
- package/dist/common/helpers/format.js +0 -1
- package/dist/common/helpers/mt5Retcode.js +0 -1
- package/dist/index.js +2 -3
- package/dist/nuxt.js +0 -1
- package/dist/runtime/plugin.js +0 -1
- package/dist/server/auth/cbs-callback.post.js +0 -1
- package/dist/server/auth/cbs-start.post.js +0 -1
- package/dist/server/auth/idp-callback.get.js +0 -1
- package/dist/server/auth/idp-link.post.js +0 -1
- package/dist/server/auth/idp-login.get.js +0 -1
- package/dist/server/auth/idp-unlink.delete.js +0 -1
- package/dist/server/auth/login.post.js +0 -1
- package/dist/server/auth/logout.post.js +0 -1
- package/dist/server/auth/refresh.post.js +0 -1
- package/dist/server/authz/portal-access.get.js +0 -1
- package/dist/server/clear-token.delete.js +0 -1
- package/dist/server/persist.post.js +0 -1
- package/dist/server/set-token.post.js +0 -1
- package/package.json +3 -2
- package/dist/chunks/_shared-DZlTUzoa.js.map +0 -1
- package/dist/chunks/auth.constant-CMI1lqQc.js.map +0 -1
- package/dist/chunks/authz.constant-BAarvacV.js.map +0 -1
- package/dist/chunks/http.constant-BzH5tJTG.js.map +0 -1
- package/dist/chunks/mt5Retcode-DlZLQOLA.js.map +0 -1
- package/dist/chunks/storage.constant-CVWam5ls.js.map +0 -1
- package/dist/common/helpers/format.js.map +0 -1
- package/dist/common/helpers/mt5Retcode.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/nuxt.js.map +0 -1
- package/dist/runtime/plugin.js.map +0 -1
- package/dist/server/auth/cbs-callback.post.js.map +0 -1
- package/dist/server/auth/cbs-start.post.js.map +0 -1
- package/dist/server/auth/idp-callback.get.js.map +0 -1
- package/dist/server/auth/idp-link.post.js.map +0 -1
- package/dist/server/auth/idp-login.get.js.map +0 -1
- package/dist/server/auth/idp-unlink.delete.js.map +0 -1
- package/dist/server/auth/login.post.js.map +0 -1
- package/dist/server/auth/logout.post.js.map +0 -1
- package/dist/server/auth/refresh.post.js.map +0 -1
- package/dist/server/authz/portal-access.get.js.map +0 -1
- package/dist/server/clear-token.delete.js.map +0 -1
- package/dist/server/persist.post.js.map +0 -1
- package/dist/server/set-token.post.js.map +0 -1
package/dist/nuxt.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nuxt.js","sources":["../src/nuxt.ts"],"sourcesContent":["import {\n addPlugin,\n addServerHandler,\n createResolver,\n defineNuxtModule,\n useLogger,\n} from '@nuxt/kit';\nimport type { RequestCasing, ResponseCasing } from './common/constants/http.constant';\nimport type { StorageName } from './common/constants/storage.constant';\n\nexport interface IModuleOptions {\n /**\n * Names of `runtimeConfig.public` keys holding each endpoint URL.\n * Default reads `cmsUrl`, `reportUrl`, `poolTradingUrl`.\n */\n endpoints?: Record<string, string>;\n clientId?: string;\n /** Storage backend name. Default 'cookie'. */\n storage?: StorageName;\n /** Use fake data until the backend is ready. Default false. */\n mock?: boolean;\n timeout?: number;\n retry?: number;\n /** Response casing to request from the backend (`x-response-casing`). Default camel. */\n responseCasing?: ResponseCasing;\n /** Request casing declared to the backend (`x-request-casing`). Default camel. */\n requestCasing?: RequestCasing;\n /**\n * Topics to subscribe to automatically after the WS connection opens.\n * Server-side permissions still apply (FEAT-010 §5.4).\n *\n * Defaults to `[]` (consumer-driven via `useWsStore().subscribe([...])`).\n */\n wsTopics?: string[];\n /**\n * Auto-open the WebSocket on app mount (client-only). Default `true`.\n * Set `false` for consumers that prefer explicit `useWsStore().open()`.\n */\n wsAutoOpen?: boolean;\n /**\n * Portal id used by the portal-scoped authz flows\n * (`useAuthzStore().loadPortalAccess()` → `GET /api/v1/authz/me/portals/{portal}`).\n * e.g. `'people'` for People Hub, `'backoffice'` for the admin portal.\n */\n portal?: string;\n}\n\nconst SERVER_HANDLERS: Array<[route: string, file: string]> = [\n ['/api/cms/set-token', 'server/set-token.post.js'],\n ['/api/cms/clear-token', 'server/clear-token.delete.js'],\n ['/api/cms/login', 'server/auth/login.post.js'],\n ['/api/cms/logout', 'server/auth/logout.post.js'],\n ['/api/cms/refresh', 'server/auth/refresh.post.js'],\n ['/api/cms/cbs-start', 'server/auth/cbs-start.post.js'],\n ['/api/cms/cbs-callback', 'server/auth/cbs-callback.post.js'],\n ['/api/cms/idp-login', 'server/auth/idp-login.get.js'],\n ['/api/cms/idp-callback', 'server/auth/idp-callback.get.js'],\n ['/api/cms/idp-link', 'server/auth/idp-link.post.js'],\n ['/api/cms/idp-unlink', 'server/auth/idp-unlink.delete.js'],\n ['/api/cms/portal-access', 'server/authz/portal-access.get.js'],\n ['/api/cms-sdk/persist', 'server/persist.post.js'],\n];\n\n/**\n * Nuxt module: registers a plugin that builds the CMS SDK from runtime\n * config and provides it as `$cms` / `useNuxtApp().$cms`. Also attaches the\n * SDK to the auth Pinia store and installs persistence.\n *\n * Consumer config:\n * ```ts\n * export default defineNuxtConfig({\n * modules: ['@eaera-com/cms-sdk/nuxt'],\n * runtimeConfig: { public: { cmsUrl: 'https://...', clientId: 'web' } },\n * cmsSdk: { storage: 'cookie', mock: true },\n * })\n * ```\n */\nexport default defineNuxtModule<IModuleOptions>({\n meta: {\n name: '@eaera-com/cms-sdk',\n configKey: 'cmsSdk',\n compatibility: { nuxt: '^3.0.0 || ^4.0.0' },\n },\n defaults: {\n endpoints: { cms: 'cmsUrl', report: 'reportUrl', poolTrading: 'poolTradingUrl' },\n clientId: 'clientId',\n storage: 'cookie',\n mock: false,\n wsTopics: [],\n wsAutoOpen: true,\n },\n setup(options, nuxt) {\n const logger = useLogger('cms-sdk');\n const { resolve } = createResolver(import.meta.url);\n\n nuxt.options.runtimeConfig.public ??= {};\n (nuxt.options.runtimeConfig.public as Record<string, unknown>).cmsSdkOptions = options;\n\n for (const [route, file] of SERVER_HANDLERS) {\n addServerHandler({ route, handler: resolve(file) });\n }\n\n addPlugin({ src: resolve('runtime/plugin.js') });\n\n if (options.mock) {\n logger.warn('cms-sdk: mock mode is ON — domain services return fake data.');\n }\n },\n});\n"],"names":[],"mappings":";;AA+CA,MAAM,eAAA,GAAwD;AAAA,EAC5D,CAAC,sBAAsB,0BAA0B,CAAA;AAAA,EACjD,CAAC,wBAAwB,8BAA8B,CAAA;AAAA,EACvD,CAAC,kBAAkB,2BAA2B,CAAA;AAAA,EAC9C,CAAC,mBAAmB,4BAA4B,CAAA;AAAA,EAChD,CAAC,oBAAoB,6BAA6B,CAAA;AAAA,EAClD,CAAC,sBAAsB,+BAA+B,CAAA;AAAA,EACtD,CAAC,yBAAyB,kCAAkC,CAAA;AAAA,EAC5D,CAAC,sBAAsB,8BAA8B,CAAA;AAAA,EACrD,CAAC,yBAAyB,iCAAiC,CAAA;AAAA,EAC3D,CAAC,qBAAqB,8BAA8B,CAAA;AAAA,EACpD,CAAC,uBAAuB,kCAAkC,CAAA;AAAA,EAC1D,CAAC,0BAA0B,mCAAmC,CAAA;AAAA,EAC9D,CAAC,wBAAwB,wBAAwB;AACnD,CAAA;AAgBA,aAAe,gBAAA,CAAiC;AAAA,EAC9C,IAAA,EAAM;AAAA,IACJ,IAAA,EAAM,oBAAA;AAAA,IACN,SAAA,EAAW,QAAA;AAAA,IACX,aAAA,EAAe,EAAE,IAAA,EAAM,kBAAA;AAAmB,GAC5C;AAAA,EACA,QAAA,EAAU;AAAA,IACR,WAAW,EAAE,GAAA,EAAK,UAAU,MAAA,EAAQ,WAAA,EAAa,aAAa,gBAAA,EAAiB;AAAA,IAC/E,QAAA,EAAU,UAAA;AAAA,IACV,OAAA,EAAS,QAAA;AAAA,IACT,IAAA,EAAM,KAAA;AAAA,IACN,UAAU,EAAC;AAAA,IACX,UAAA,EAAY;AAAA,GACd;AAAA,EACA,KAAA,CAAM,SAAS,IAAA,EAAM;AACnB,IAAA,MAAM,MAAA,GAAS,UAAU,SAAS,CAAA;AAClC,IAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,cAAA,CAAe,YAAY,GAAG,CAAA;AAElD,IAAA,IAAA,CAAK,OAAA,CAAQ,aAAA,CAAc,MAAA,KAAW,EAAC;AACvC,IAAC,IAAA,CAAK,OAAA,CAAQ,aAAA,CAAc,MAAA,CAAmC,aAAA,GAAgB,OAAA;AAE/E,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,IAAI,CAAA,IAAK,eAAA,EAAiB;AAC3C,MAAA,gBAAA,CAAiB,EAAE,KAAA,EAAO,OAAA,EAAS,OAAA,CAAQ,IAAI,GAAG,CAAA;AAAA,IACpD;AAEA,IAAA,SAAA,CAAU,EAAE,GAAA,EAAK,OAAA,CAAQ,mBAAmB,GAAG,CAAA;AAE/C,IAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,MAAA,CAAO,KAAK,8DAA8D,CAAA;AAAA,IAC5E;AAAA,EACF;AACF,CAAC,CAAA;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["../../src/runtime/cookie-storage.ts","../../src/runtime/token-cookie-options.ts","../../src/runtime/plugin.ts"],"sourcesContent":["type UseCookieFn = <T>(key: string, opts?: Record<string, unknown>) => { value: T | null };\n\nfunction buildOpts(httpOnly: boolean) {\n return httpOnly\n ? { httpOnly: true, secure: true, sameSite: 'lax', path: '/' }\n : { secure: true, sameSite: 'lax', path: '/' };\n}\n\nexport function createCookieStorage(useCookie: UseCookieFn) {\n return {\n getItem(key: string): string | null {\n return useCookie<string>(key).value;\n },\n setItem(key: string, value: string, opts?: { httpOnly?: boolean }) {\n useCookie(key, buildOpts(!!opts?.httpOnly)).value = value;\n },\n removeItem(key: string, opts?: { httpOnly?: boolean }) {\n useCookie<null>(key, buildOpts(!!opts?.httpOnly)).value = null;\n },\n };\n}\n","export const TOKEN_COOKIE_OPTIONS = {\n httpOnly: true,\n secure: true,\n sameSite: 'lax' as const,\n path: '/',\n maxAge: 60 * 60 * 24 * 30,\n};\n","import {\n createCmsSDK,\n createPersistPlugin,\n TOKEN_STORAGE_KEY,\n useAuthStore,\n useAuthzStore,\n useContentStore,\n useExecutionsStore,\n useGovStore,\n useHistoryStore,\n useKalshiStore,\n useLlmProvidersStore,\n useLlmStore,\n usePeopleStore,\n useRulesStore,\n useSettingsStore,\n useWsStore,\n} from '@eaera-com/cms-sdk';\nimport { $fetch } from 'ofetch';\nimport { watch } from 'vue';\nimport { defineNuxtPlugin, useCookie, useRuntimeConfig } from '#app';\n\nimport { createCookieStorage } from './cookie-storage';\nimport { TOKEN_COOKIE_OPTIONS } from './token-cookie-options';\n\nconst STORE_ATTACHMENTS = [\n { name: 'auth', get: useAuthStore },\n { name: 'authz', get: useAuthzStore },\n { name: 'content', get: useContentStore },\n { name: 'history', get: useHistoryStore },\n { name: 'kalshi', get: useKalshiStore },\n { name: 'rules', get: useRulesStore },\n { name: 'executions', get: useExecutionsStore },\n { name: 'settings', get: useSettingsStore },\n { name: 'llm', get: useLlmStore },\n { name: 'llm-providers', get: useLlmProvidersStore },\n { name: 'gov', get: useGovStore },\n { name: 'people', get: usePeopleStore },\n { name: 'ws', get: useWsStore },\n] as const;\n\nfunction attachStores(pinia: any, sdk: any): { authStore: any; authzStore: any; wsStore: any } {\n let authStore: any;\n let authzStore: any;\n let wsStore: any;\n\n for (const { name, get } of STORE_ATTACHMENTS) {\n try {\n const store = get(pinia);\n store?.setSdk?.(sdk);\n if (name === 'auth') authStore = store;\n if (name === 'authz') authzStore = store;\n if (name === 'ws') wsStore = store;\n } catch (e) {\n console.warn(`[cms-sdk] could not attach SDK to ${name} store:`, e);\n }\n }\n\n return { authStore, authzStore, wsStore };\n}\n\nexport default defineNuxtPlugin(async (nuxtApp: any) => {\n const config = useRuntimeConfig();\n const opts = config.public?.cmsSdkOptions ?? {};\n const pub = config.public ?? {};\n\n // --- Resolve endpoints from runtimeConfig keys ---\n const endpoints: Record<string, string> = {};\n for (const [name, runtimeKey] of Object.entries(\n (opts.endpoints as Record<string, string>) ?? { cms: 'cmsUrl' }\n )) {\n const url = pub[runtimeKey as string];\n if (url) endpoints[name] = url;\n }\n\n const wsUrl = pub.wsUrl || pub.cmsWsUrl;\n if (wsUrl) endpoints.ws = wsUrl;\n\n // --- Token lifecycle (httpOnly cookie set/clear via /api/cms/* routes) ---\n let sdkInstance: any = null;\n\n const onToken = async (token: string | null) => {\n if (!sdkInstance) return;\n if (token) sdkInstance.tokenManager.set(token);\n else sdkInstance.tokenManager.clear();\n\n if (import.meta.server) {\n const { setCookie, deleteCookie } = await import('h3');\n const event = nuxtApp.ssrContext?.event;\n if (token) setCookie(event, TOKEN_STORAGE_KEY, token, TOKEN_COOKIE_OPTIONS);\n else deleteCookie(event, TOKEN_STORAGE_KEY, { path: TOKEN_COOKIE_OPTIONS.path });\n } else if (token) {\n await $fetch('/api/cms/set-token', { method: 'POST', body: { token } });\n } else {\n await $fetch('/api/cms/clear-token', { method: 'DELETE' });\n }\n };\n\n const authRoute = $fetch.create({ baseURL: '/api/cms' });\n\n const refresh = async () => {\n try {\n const res = (await $fetch('/api/cms/refresh', { method: 'POST' })) as { token?: string };\n return res.token ?? null;\n } catch {\n return null;\n }\n };\n\n // --- Create SDK instance ---\n const sdk = createCmsSDK({\n endpoints: endpoints as any,\n clientId: opts.clientId ? pub[opts.clientId] : undefined,\n credentials: { storage: 'memory' },\n mock: !!opts.mock,\n timeout: opts.timeout,\n retry: opts.retry,\n onToken,\n refresh,\n responseCasing: opts.responseCasing,\n requestCasing: opts.requestCasing,\n authRoute,\n portal: opts.portal,\n });\n sdkInstance = sdk;\n\n // --- Pinia wiring ---\n const pinia = nuxtApp.$pinia;\n if (!pinia) {\n console.warn('[cms-sdk] Pinia is not available — register @pinia/nuxt before this module.');\n return { provide: { cms: sdk, ws: sdk.ws } };\n }\n\n try {\n pinia.use(\n createPersistPlugin({\n storage: createCookieStorage(useCookie),\n httpEndpoint: '/api/cms-sdk/persist',\n ssr: import.meta.server,\n })\n );\n } catch (e) {\n console.warn('[cms-sdk] persistence plugin install failed:', e);\n }\n\n const { authStore, authzStore, wsStore } = attachStores(pinia, sdk);\n\n // Seed the authz store's default portal id (module option `cmsSdk.portal`)\n // so `loadPortalAccess()` needs no per-call portal argument.\n try {\n authzStore?.setPortal?.(opts.portal ?? '');\n } catch (e) {\n console.warn('[cms-sdk] could not seed authz portal:', e);\n }\n\n // --- Seed token manager ---\n try {\n if (import.meta.server) {\n const token = useCookie(TOKEN_STORAGE_KEY).value;\n if (token) sdk.tokenManager.set(token);\n } else if (authStore?.accessToken) {\n sdk.tokenManager.set(authStore.accessToken);\n }\n } catch (e) {\n console.warn('[cms-sdk] could not seed token manager:', e);\n }\n\n // --- FEAT-010: open WS + auto-subscribe on the client ---\n if (!import.meta.server && sdk.ws && wsStore) {\n try {\n const topics = (opts.wsTopics as string[] | undefined) ?? [];\n const subscribeDeclarativeTopics = (): void => {\n if (topics.length) wsStore.subscribe(topics);\n };\n if (opts.wsAutoOpen !== false) wsStore.open();\n subscribeDeclarativeTopics();\n\n // Re-login flow: the user authenticates AFTER the app has booted\n // (the WS was opened with no token, so the server dropped it for\n // `auth_timeout`). We watch `authStore.isLoggedIn` and force a fresh\n // handshake on every false → true transition so the new token is\n // sent and previously-subscribed topics are replayed automatically\n // by the WS client's `flushSubscriptions` on `auth_ok`. On logout\n // (true → false) we close cleanly so the old session is dropped\n // server-side instead of staying authenticated until `auth_expired`.\n // Anonymous-safe topics survive a logout → anonymous reconnect: only\n // `symbol:<server>:<SYMBOL>` and `mt5:events:<server>:tick` are admitted\n // on an anonymous connection (ws-guide §11.3). Everything else\n // (account/order/position/user-scoped) is dropped before the close so it\n // is not replayed onto the anonymous socket as `sub_error` spam or leaked\n // across users.\n const isAnonSafeTopic = (t: string): boolean =>\n t.startsWith('symbol:') || (t.startsWith('mt5:events:') && t.endsWith(':tick'));\n const selectiveUnsubscribeNonAnon = (): void => {\n const toRemove = [...wsStore.subscribed].filter((t) => !isAnonSafeTopic(t));\n if (toRemove.length) wsStore.unsubscribe(toRemove);\n };\n\n if (authStore) {\n // Tracks the authenticated user id so a silent cross-user re-login\n // (e.g. super-app injecting a different user's token without a logout)\n // can tear down the previous user's non-anonymous topics.\n let lastSeenUserId: string | number | null | undefined = authStore.authUser?.id ?? null;\n\n // Re-login / token-rotation while ALREADY authenticated: the\n // `isLoggedIn` boolean does not transition here, so without this the\n // socket would keep the stale token until the server pushed\n // `auth_expired`. `login()` / `loginWithTokenAndUser()` only bump the\n // epoch when the user was already logged in (the initial login is\n // covered by the transition watcher below), and `refreshToken()` always\n // bumps it — so this watcher fires exactly once per explicit\n // re-handshake and never duplicates the transition watcher.\n watch(\n () => authStore.loginEpoch,\n () => {\n const currentUserId = authStore.authUser?.id ?? null;\n if (currentUserId !== lastSeenUserId) {\n selectiveUnsubscribeNonAnon();\n lastSeenUserId = currentUserId;\n }\n wsStore.reopen();\n subscribeDeclarativeTopics();\n }\n );\n watch(\n () => authStore.isLoggedIn,\n (loggedIn, previous) => {\n if (loggedIn) {\n wsStore.reopen();\n subscribeDeclarativeTopics();\n } else if (previous === true) {\n // Drop user-scoped topics (keep anon-safe market data), then\n // establish a fresh anonymous connection so live symbol ticks\n // keep streaming after logout.\n selectiveUnsubscribeNonAnon();\n wsStore.close('user-logout');\n wsStore.open();\n }\n }\n );\n }\n } catch (e) {\n console.warn('[cms-sdk] WS open/subscribe failed:', e);\n }\n }\n\n return { provide: { cms: sdk, ws: sdk.ws } };\n});\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cbs-callback.post.js","sources":["../../../src/server/auth/cbs-callback.post.ts"],"sourcesContent":["import {\n defineEventHandler,\n readBody,\n parseCookies,\n getRequestHeader,\n setCookie,\n createError,\n} from 'h3';\nimport { $fetch } from 'ofetch';\nimport { AUTH_ENDPOINT } from '../../common/constants/auth.constant';\nimport { HTTP_HEADER } from '../../common/constants/http.constant';\nimport {\n readSdkConfig,\n REFRESH_TOKEN_STORAGE_KEY,\n TOKEN_COOKIE_OPTIONS,\n TOKEN_STORAGE_KEY,\n} from './_shared';\n\n/**\n * Thin auth proxy: POST /api/cms/cbs-callback → backend POST /api/v1/auth/oauth/cbs/callback.\n *\n * Completes a \"Login with CBS\" attempt. Forwards `{ code, state, stateKey }`;\n * the backend verifies PKCE/state, exchanges the code for a CBS JWT, JIT-links\n * the CBS identity to a CMS user, and mints a CMS session JWT (RS256) + refresh\n * token. This route stores both as httpOnly cookies and returns the body\n * augmented with a `token` field so the client can mirror the access token in\n * memory (the httpOnly cookie is the durable copy used for SSR).\n */\nexport default defineEventHandler(async (event) => {\n const { cmsUrl, clientId } = readSdkConfig(event);\n if (!cmsUrl) throw createError({ statusCode: 500, message: 'CMS URL not configured' });\n\n const body = await readBody(event);\n const cookies = parseCookies(event);\n const userAgent = getRequestHeader(event, HTTP_HEADER.USER_AGENT) || '';\n\n try {\n const response = await $fetch.raw(AUTH_ENDPOINT.CBS_CALLBACK, {\n baseURL: cmsUrl,\n method: 'POST',\n body,\n headers: {\n [HTTP_HEADER.CLIENT_ID]: clientId || '',\n [HTTP_HEADER.DEVICE_ID]: cookies.device_id || '',\n [HTTP_HEADER.DEVICE_IP]: cookies.device_ip || '',\n [HTTP_HEADER.USER_AGENT]: userAgent,\n },\n });\n const data = (response._data ?? {}) as Record<string, unknown>;\n const token =\n (data.accessToken as string | undefined) ?? (data.access_token as string | undefined) ?? '';\n const refreshToken =\n (data.refreshToken as string | undefined) ?? (data.refresh_token as string | undefined) ?? '';\n if (token) setCookie(event, TOKEN_STORAGE_KEY, token, TOKEN_COOKIE_OPTIONS);\n if (refreshToken)\n setCookie(event, REFRESH_TOKEN_STORAGE_KEY, refreshToken, TOKEN_COOKIE_OPTIONS);\n return { ...data, token };\n } catch (err: any) {\n throw createError({\n statusCode: err?.response?.status || err?.statusCode || 500,\n message: err?.data?.error || err?.data?.message || err?.message || 'CBS callback failed',\n data: err?.data,\n });\n }\n});\n"],"names":[],"mappings":";;;;;;;AA4BA,yBAAe,kBAAA,CAAmB,OAAO,KAAA,KAAU;AACjD,EAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAS,GAAI,cAAc,KAAK,CAAA;AAChD,EAAA,IAAI,CAAC,QAAQ,MAAM,WAAA,CAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,wBAAA,EAA0B,CAAA;AAErF,EAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,KAAK,CAAA;AACjC,EAAA,MAAM,OAAA,GAAU,aAAa,KAAK,CAAA;AAClC,EAAA,MAAM,SAAA,GAAY,gBAAA,CAAiB,KAAA,EAAO,WAAA,CAAY,UAAU,CAAA,IAAK,EAAA;AAErE,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,MAAM,MAAA,CAAO,GAAA,CAAI,cAAc,YAAA,EAAc;AAAA,MAC5D,OAAA,EAAS,MAAA;AAAA,MACT,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA;AAAA,MACA,OAAA,EAAS;AAAA,QACP,CAAC,WAAA,CAAY,SAAS,GAAG,QAAA,IAAY,EAAA;AAAA,QACrC,CAAC,WAAA,CAAY,SAAS,GAAG,QAAQ,SAAA,IAAa,EAAA;AAAA,QAC9C,CAAC,WAAA,CAAY,SAAS,GAAG,QAAQ,SAAA,IAAa,EAAA;AAAA,QAC9C,CAAC,WAAA,CAAY,UAAU,GAAG;AAAA;AAC5B,KACD,CAAA;AACD,IAAA,MAAM,IAAA,GAAQ,QAAA,CAAS,KAAA,IAAS,EAAC;AACjC,IAAA,MAAM,KAAA,GACH,IAAA,CAAK,WAAA,IAAuC,IAAA,CAAK,YAAA,IAAuC,EAAA;AAC3F,IAAA,MAAM,YAAA,GACH,IAAA,CAAK,YAAA,IAAwC,IAAA,CAAK,aAAA,IAAwC,EAAA;AAC7F,IAAA,IAAI,KAAA,EAAO,SAAA,CAAU,KAAA,EAAO,iBAAA,EAAmB,OAAO,oBAAoB,CAAA;AAC1E,IAAA,IAAI,YAAA;AACF,MAAA,SAAA,CAAU,KAAA,EAAO,yBAAA,EAA2B,YAAA,EAAc,oBAAoB,CAAA;AAChF,IAAA,OAAO,EAAE,GAAG,IAAA,EAAM,KAAA,EAAM;AAAA,EAC1B,SAAS,GAAA,EAAU;AACjB,IAAA,MAAM,WAAA,CAAY;AAAA,MAChB,UAAA,EAAY,GAAA,EAAK,QAAA,EAAU,MAAA,IAAU,KAAK,UAAA,IAAc,GAAA;AAAA,MACxD,OAAA,EAAS,KAAK,IAAA,EAAM,KAAA,IAAS,KAAK,IAAA,EAAM,OAAA,IAAW,KAAK,OAAA,IAAW,qBAAA;AAAA,MACnE,MAAM,GAAA,EAAK;AAAA,KACZ,CAAA;AAAA,EACH;AACF,CAAC,CAAA;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cbs-start.post.js","sources":["../../../src/server/auth/cbs-start.post.ts"],"sourcesContent":["import { defineEventHandler, parseCookies, getRequestHeader, createError } from 'h3';\nimport { $fetch } from 'ofetch';\nimport { AUTH_ENDPOINT } from '../../common/constants/auth.constant';\nimport { HTTP_HEADER } from '../../common/constants/http.constant';\nimport { readSdkConfig } from './_shared';\n\n/**\n * Thin auth proxy: POST /api/cms/cbs-start → backend POST /api/v1/auth/oauth/cbs/start.\n *\n * Initialises a \"Login with CBS\" attempt. The backend generates the PKCE\n * verifier + state (kept server-side, never exposed to the browser) and returns\n * `{ authorizeUrl, stateKey, redirectTarget }`. No cookie is set here — the CMS\n * session JWT is only minted on `/cbs-callback`.\n *\n * Used by the silent-login iframe handshake: the webtrade iframe calls this to\n * obtain the CBS `authorizeUrl` it hands to the super-app parent (which opens\n * the top-level popup that carries the CBS session cookie).\n */\nexport default defineEventHandler(async (event) => {\n const { cmsUrl, clientId } = readSdkConfig(event);\n if (!cmsUrl) throw createError({ statusCode: 500, message: 'CMS URL not configured' });\n\n const cookies = parseCookies(event);\n const userAgent = getRequestHeader(event, HTTP_HEADER.USER_AGENT) || '';\n\n try {\n const data = (await $fetch(AUTH_ENDPOINT.CBS_START, {\n baseURL: cmsUrl,\n method: 'POST',\n body: {},\n headers: {\n [HTTP_HEADER.CLIENT_ID]: clientId || '',\n [HTTP_HEADER.DEVICE_ID]: cookies.device_id || '',\n [HTTP_HEADER.DEVICE_IP]: cookies.device_ip || '',\n [HTTP_HEADER.USER_AGENT]: userAgent,\n },\n })) as Record<string, unknown>;\n return data;\n } catch (err: any) {\n throw createError({\n statusCode: err?.response?.status || err?.statusCode || 500,\n message: err?.data?.error || err?.data?.message || err?.message || 'CBS start failed',\n data: err?.data,\n });\n }\n});\n"],"names":[],"mappings":";;;;;;AAkBA,sBAAe,kBAAA,CAAmB,OAAO,KAAA,KAAU;AACjD,EAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAS,GAAI,cAAc,KAAK,CAAA;AAChD,EAAA,IAAI,CAAC,QAAQ,MAAM,WAAA,CAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,wBAAA,EAA0B,CAAA;AAErF,EAAA,MAAM,OAAA,GAAU,aAAa,KAAK,CAAA;AAClC,EAAA,MAAM,SAAA,GAAY,gBAAA,CAAiB,KAAA,EAAO,WAAA,CAAY,UAAU,CAAA,IAAK,EAAA;AAErE,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAQ,MAAM,MAAA,CAAO,aAAA,CAAc,SAAA,EAAW;AAAA,MAClD,OAAA,EAAS,MAAA;AAAA,MACT,MAAA,EAAQ,MAAA;AAAA,MACR,MAAM,EAAC;AAAA,MACP,OAAA,EAAS;AAAA,QACP,CAAC,WAAA,CAAY,SAAS,GAAG,QAAA,IAAY,EAAA;AAAA,QACrC,CAAC,WAAA,CAAY,SAAS,GAAG,QAAQ,SAAA,IAAa,EAAA;AAAA,QAC9C,CAAC,WAAA,CAAY,SAAS,GAAG,QAAQ,SAAA,IAAa,EAAA;AAAA,QAC9C,CAAC,WAAA,CAAY,UAAU,GAAG;AAAA;AAC5B,KACD,CAAA;AACD,IAAA,OAAO,IAAA;AAAA,EACT,SAAS,GAAA,EAAU;AACjB,IAAA,MAAM,WAAA,CAAY;AAAA,MAChB,UAAA,EAAY,GAAA,EAAK,QAAA,EAAU,MAAA,IAAU,KAAK,UAAA,IAAc,GAAA;AAAA,MACxD,OAAA,EAAS,KAAK,IAAA,EAAM,KAAA,IAAS,KAAK,IAAA,EAAM,OAAA,IAAW,KAAK,OAAA,IAAW,kBAAA;AAAA,MACnE,MAAM,GAAA,EAAK;AAAA,KACZ,CAAA;AAAA,EACH;AACF,CAAC,CAAA;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"idp-callback.get.js","sources":["../../../src/server/auth/idp-callback.get.ts"],"sourcesContent":["import {\n defineEventHandler,\n parseCookies,\n getQuery,\n getRequestHeader,\n setCookie,\n createError,\n} from 'h3';\nimport { $fetch } from 'ofetch';\nimport { AUTH_ENDPOINT } from '../../common/constants/auth.constant';\nimport { HTTP_HEADER } from '../../common/constants/http.constant';\nimport {\n readSdkConfig,\n REFRESH_TOKEN_STORAGE_KEY,\n TOKEN_COOKIE_OPTIONS,\n TOKEN_STORAGE_KEY,\n} from './_shared';\n\n/**\n * Thin auth proxy: GET /api/cms/idp-callback → backend GET /api/auth/{provider}/callback.\n *\n * Completes an IdP SSO login: the backend verifies the one-use state, exchanges\n * the authorization code with the provider, and mints a CMS JWT (resolved via\n * JWKS — usable as a normal Bearer credential) + refresh token. This route\n * stores both as httpOnly cookies and returns the body augmented with a\n * `token` field so the client can mirror the access token in memory.\n */\nexport default defineEventHandler(async (event) => {\n const { cmsUrl, clientId } = readSdkConfig(event);\n if (!cmsUrl) throw createError({ statusCode: 500, message: 'CMS URL not configured' });\n\n const query = getQuery(event) as Record<string, string>;\n const provider = (query.provider ?? '').trim();\n const code = (query.code ?? '').trim();\n const state = (query.state ?? '').trim();\n const redirectUri = (query.redirect_uri ?? '').trim();\n if (!provider) throw createError({ statusCode: 400, message: 'provider is required' });\n if (!code || !state || !redirectUri) {\n throw createError({ statusCode: 400, message: 'code, state and redirect_uri are required' });\n }\n\n const cookies = parseCookies(event);\n const userAgent = getRequestHeader(event, HTTP_HEADER.USER_AGENT) || '';\n\n try {\n const data = (await $fetch(AUTH_ENDPOINT.idpCallback(provider), {\n baseURL: cmsUrl,\n method: 'GET',\n query: { code, state, redirect_uri: redirectUri },\n headers: {\n [HTTP_HEADER.CLIENT_ID]: clientId || '',\n [HTTP_HEADER.DEVICE_ID]: cookies.device_id || '',\n [HTTP_HEADER.DEVICE_IP]: cookies.device_ip || '',\n [HTTP_HEADER.USER_AGENT]: userAgent,\n },\n })) as Record<string, unknown>;\n const token =\n (data.accessToken as string | undefined) ?? (data.access_token as string | undefined) ?? '';\n const refreshToken =\n (data.refreshToken as string | undefined) ?? (data.refresh_token as string | undefined) ?? '';\n if (token) setCookie(event, TOKEN_STORAGE_KEY, token, TOKEN_COOKIE_OPTIONS);\n if (refreshToken)\n setCookie(event, REFRESH_TOKEN_STORAGE_KEY, refreshToken, TOKEN_COOKIE_OPTIONS);\n return { ...data, token };\n } catch (err: any) {\n // The CMS nests the real error one level down:\n // `{ error: \"HTTPException\", detail: { error, errorDescription } }`.\n const beData = (err?.data ?? {}) as Record<string, any>;\n const detail = (beData.detail ?? {}) as Record<string, any>;\n const message = detail.errorDescription ?? detail.error ?? beData.error ?? err?.message;\n throw createError({\n statusCode: err?.response?.status || err?.statusCode || 500,\n message: message || 'IdP callback failed',\n data: beData,\n });\n }\n});\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"idp-link.post.js","sources":["../../../src/server/auth/idp-link.post.ts"],"sourcesContent":["import { defineEventHandler, readBody, parseCookies, createError } from 'h3';\nimport { $fetch } from 'ofetch';\nimport { AUTH_ENDPOINT } from '../../common/constants/auth.constant';\nimport { HTTP_HEADER } from '../../common/constants/http.constant';\nimport { readSdkConfig, TOKEN_STORAGE_KEY } from './_shared';\n\n/**\n * Thin auth proxy: POST /api/cms/idp-link → backend POST /api/auth/{provider}/link.\n *\n * Links the CURRENTLY signed-in CMS user to the IdP provider. The backend\n * requires an authenticated caller, so the httpOnly access-token cookie is\n * forwarded as `Authorization: Bearer <token>`.\n */\nexport default defineEventHandler(async (event) => {\n const { cmsUrl, clientId } = readSdkConfig(event);\n if (!cmsUrl) throw createError({ statusCode: 500, message: 'CMS URL not configured' });\n\n const body = (await readBody(event).catch(() => ({}))) as { provider?: string };\n const provider = (body.provider ?? '').trim();\n if (!provider) throw createError({ statusCode: 400, message: 'provider is required' });\n\n const cookies = parseCookies(event);\n const token = cookies[TOKEN_STORAGE_KEY] || '';\n if (!token) throw createError({ statusCode: 401, message: 'Not authenticated' });\n\n try {\n return await $fetch(AUTH_ENDPOINT.idpLink(provider), {\n baseURL: cmsUrl,\n method: 'POST',\n headers: {\n [HTTP_HEADER.CLIENT_ID]: clientId || '',\n [HTTP_HEADER.AUTHORIZATION]: `Bearer ${token}`,\n },\n });\n } catch (err: any) {\n // The CMS nests the real error one level down:\n // `{ error: \"HTTPException\", detail: { error, errorDescription } }`.\n const beData = (err?.data ?? {}) as Record<string, any>;\n const detail = (beData.detail ?? {}) as Record<string, any>;\n const message = detail.errorDescription ?? detail.error ?? beData.error ?? err?.message;\n throw createError({\n statusCode: err?.response?.status || err?.statusCode || 500,\n message: message || 'IdP link failed',\n data: beData,\n });\n }\n});\n"],"names":[],"mappings":";;;;;;;AAaA,qBAAe,kBAAA,CAAmB,OAAO,KAAA,KAAU;AACjD,EAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAS,GAAI,cAAc,KAAK,CAAA;AAChD,EAAA,IAAI,CAAC,QAAQ,MAAM,WAAA,CAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,wBAAA,EAA0B,CAAA;AAErF,EAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,KAAK,EAAE,KAAA,CAAM,OAAO,EAAC,CAAE,CAAA;AACpD,EAAA,MAAM,QAAA,GAAA,CAAY,IAAA,CAAK,QAAA,IAAY,EAAA,EAAI,IAAA,EAAK;AAC5C,EAAA,IAAI,CAAC,UAAU,MAAM,WAAA,CAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,sBAAA,EAAwB,CAAA;AAErF,EAAA,MAAM,OAAA,GAAU,aAAa,KAAK,CAAA;AAClC,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,iBAAiB,CAAA,IAAK,EAAA;AAC5C,EAAA,IAAI,CAAC,OAAO,MAAM,WAAA,CAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,mBAAA,EAAqB,CAAA;AAE/E,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,MAAA,CAAO,aAAA,CAAc,OAAA,CAAQ,QAAQ,CAAA,EAAG;AAAA,MACnD,OAAA,EAAS,MAAA;AAAA,MACT,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,CAAC,WAAA,CAAY,SAAS,GAAG,QAAA,IAAY,EAAA;AAAA,QACrC,CAAC,WAAA,CAAY,aAAa,GAAG,UAAU,KAAK,CAAA;AAAA;AAC9C,KACD,CAAA;AAAA,EACH,SAAS,GAAA,EAAU;AAGjB,IAAA,MAAM,MAAA,GAAU,GAAA,EAAK,IAAA,IAAQ,EAAC;AAC9B,IAAA,MAAM,MAAA,GAAU,MAAA,CAAO,MAAA,IAAU,EAAC;AAClC,IAAA,MAAM,UAAU,MAAA,CAAO,gBAAA,IAAoB,OAAO,KAAA,IAAS,MAAA,CAAO,SAAS,GAAA,EAAK,OAAA;AAChF,IAAA,MAAM,WAAA,CAAY;AAAA,MAChB,UAAA,EAAY,GAAA,EAAK,QAAA,EAAU,MAAA,IAAU,KAAK,UAAA,IAAc,GAAA;AAAA,MACxD,SAAS,OAAA,IAAW,iBAAA;AAAA,MACpB,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACF,CAAC,CAAA;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"idp-login.get.js","sources":["../../../src/server/auth/idp-login.get.ts"],"sourcesContent":["import { defineEventHandler, parseCookies, getQuery, getRequestHeader, createError } from 'h3';\nimport { $fetch } from 'ofetch';\nimport { AUTH_ENDPOINT } from '../../common/constants/auth.constant';\nimport { HTTP_HEADER } from '../../common/constants/http.constant';\nimport { readSdkConfig } from './_shared';\n\n/**\n * Thin auth proxy: GET /api/cms/idp-login → backend GET /api/auth/{provider}/login.\n *\n * Initialises an IdP SSO login (Authorization Code + one-use state, TTL 600s).\n * The backend returns `{ authorization_url, state }`; no cookie is set here —\n * the CMS JWT is only minted on `/idp-callback`.\n */\nexport default defineEventHandler(async (event) => {\n const { cmsUrl, clientId } = readSdkConfig(event);\n if (!cmsUrl) throw createError({ statusCode: 500, message: 'CMS URL not configured' });\n\n const query = getQuery(event) as { provider?: string; redirect_uri?: string };\n const provider = (query.provider ?? '').trim();\n const redirectUri = (query.redirect_uri ?? '').trim();\n if (!provider) throw createError({ statusCode: 400, message: 'provider is required' });\n if (!redirectUri) throw createError({ statusCode: 400, message: 'redirect_uri is required' });\n\n const cookies = parseCookies(event);\n const userAgent = getRequestHeader(event, HTTP_HEADER.USER_AGENT) || '';\n\n try {\n const data = (await $fetch(AUTH_ENDPOINT.idpLogin(provider), {\n baseURL: cmsUrl,\n method: 'GET',\n query: { redirect_uri: redirectUri },\n headers: {\n [HTTP_HEADER.CLIENT_ID]: clientId || '',\n [HTTP_HEADER.DEVICE_ID]: cookies.device_id || '',\n [HTTP_HEADER.DEVICE_IP]: cookies.device_ip || '',\n [HTTP_HEADER.USER_AGENT]: userAgent,\n },\n })) as Record<string, unknown>;\n return data;\n } catch (err: any) {\n // The CMS nests the real error one level down:\n // `{ error: \"HTTPException\", detail: { error, errorDescription } }`.\n const beData = (err?.data ?? {}) as Record<string, any>;\n const detail = (beData.detail ?? {}) as Record<string, any>;\n const message = detail.errorDescription ?? detail.error ?? beData.error ?? err?.message;\n throw createError({\n statusCode: err?.response?.status || err?.statusCode || 500,\n message: message || 'IdP login init failed',\n data: beData,\n });\n }\n});\n"],"names":[],"mappings":";;;;;;AAaA,qBAAe,kBAAA,CAAmB,OAAO,KAAA,KAAU;AACjD,EAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAS,GAAI,cAAc,KAAK,CAAA;AAChD,EAAA,IAAI,CAAC,QAAQ,MAAM,WAAA,CAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,wBAAA,EAA0B,CAAA;AAErF,EAAA,MAAM,KAAA,GAAQ,SAAS,KAAK,CAAA;AAC5B,EAAA,MAAM,QAAA,GAAA,CAAY,KAAA,CAAM,QAAA,IAAY,EAAA,EAAI,IAAA,EAAK;AAC7C,EAAA,MAAM,WAAA,GAAA,CAAe,KAAA,CAAM,YAAA,IAAgB,EAAA,EAAI,IAAA,EAAK;AACpD,EAAA,IAAI,CAAC,UAAU,MAAM,WAAA,CAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,sBAAA,EAAwB,CAAA;AACrF,EAAA,IAAI,CAAC,aAAa,MAAM,WAAA,CAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,0BAAA,EAA4B,CAAA;AAE5F,EAAA,MAAM,OAAA,GAAU,aAAa,KAAK,CAAA;AAClC,EAAA,MAAM,SAAA,GAAY,gBAAA,CAAiB,KAAA,EAAO,WAAA,CAAY,UAAU,CAAA,IAAK,EAAA;AAErE,EAAA,IAAI;AACF,IAAA,MAAM,OAAQ,MAAM,MAAA,CAAO,aAAA,CAAc,QAAA,CAAS,QAAQ,CAAA,EAAG;AAAA,MAC3D,OAAA,EAAS,MAAA;AAAA,MACT,MAAA,EAAQ,KAAA;AAAA,MACR,KAAA,EAAO,EAAE,YAAA,EAAc,WAAA,EAAY;AAAA,MACnC,OAAA,EAAS;AAAA,QACP,CAAC,WAAA,CAAY,SAAS,GAAG,QAAA,IAAY,EAAA;AAAA,QACrC,CAAC,WAAA,CAAY,SAAS,GAAG,QAAQ,SAAA,IAAa,EAAA;AAAA,QAC9C,CAAC,WAAA,CAAY,SAAS,GAAG,QAAQ,SAAA,IAAa,EAAA;AAAA,QAC9C,CAAC,WAAA,CAAY,UAAU,GAAG;AAAA;AAC5B,KACD,CAAA;AACD,IAAA,OAAO,IAAA;AAAA,EACT,SAAS,GAAA,EAAU;AAGjB,IAAA,MAAM,MAAA,GAAU,GAAA,EAAK,IAAA,IAAQ,EAAC;AAC9B,IAAA,MAAM,MAAA,GAAU,MAAA,CAAO,MAAA,IAAU,EAAC;AAClC,IAAA,MAAM,UAAU,MAAA,CAAO,gBAAA,IAAoB,OAAO,KAAA,IAAS,MAAA,CAAO,SAAS,GAAA,EAAK,OAAA;AAChF,IAAA,MAAM,WAAA,CAAY;AAAA,MAChB,UAAA,EAAY,GAAA,EAAK,QAAA,EAAU,MAAA,IAAU,KAAK,UAAA,IAAc,GAAA;AAAA,MACxD,SAAS,OAAA,IAAW,uBAAA;AAAA,MACpB,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACF,CAAC,CAAA;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"idp-unlink.delete.js","sources":["../../../src/server/auth/idp-unlink.delete.ts"],"sourcesContent":["import { defineEventHandler, parseCookies, getQuery, createError } from 'h3';\nimport { $fetch } from 'ofetch';\nimport { AUTH_ENDPOINT } from '../../common/constants/auth.constant';\nimport { HTTP_HEADER } from '../../common/constants/http.constant';\nimport { readSdkConfig, TOKEN_STORAGE_KEY } from './_shared';\n\n/**\n * Thin auth proxy: DELETE /api/cms/idp-unlink → backend DELETE /api/auth/{provider}/unlink.\n *\n * Unlinks the IdP provider from the CURRENTLY signed-in CMS user. The backend\n * requires an authenticated caller, so the httpOnly access-token cookie is\n * forwarded as `Authorization: Bearer <token>`.\n */\nexport default defineEventHandler(async (event) => {\n const { cmsUrl, clientId } = readSdkConfig(event);\n if (!cmsUrl) throw createError({ statusCode: 500, message: 'CMS URL not configured' });\n\n const query = getQuery(event) as { provider?: string };\n const provider = (query.provider ?? '').trim();\n if (!provider) throw createError({ statusCode: 400, message: 'provider is required' });\n\n const cookies = parseCookies(event);\n const token = cookies[TOKEN_STORAGE_KEY] || '';\n if (!token) throw createError({ statusCode: 401, message: 'Not authenticated' });\n\n try {\n return await $fetch(AUTH_ENDPOINT.idpUnlink(provider), {\n baseURL: cmsUrl,\n method: 'DELETE',\n headers: {\n [HTTP_HEADER.CLIENT_ID]: clientId || '',\n [HTTP_HEADER.AUTHORIZATION]: `Bearer ${token}`,\n },\n });\n } catch (err: any) {\n // The CMS nests the real error one level down:\n // `{ error: \"HTTPException\", detail: { error, errorDescription } }`.\n const beData = (err?.data ?? {}) as Record<string, any>;\n const detail = (beData.detail ?? {}) as Record<string, any>;\n const message = detail.errorDescription ?? detail.error ?? beData.error ?? err?.message;\n throw createError({\n statusCode: err?.response?.status || err?.statusCode || 500,\n message: message || 'IdP unlink failed',\n data: beData,\n });\n }\n});\n"],"names":[],"mappings":";;;;;;;AAaA,yBAAe,kBAAA,CAAmB,OAAO,KAAA,KAAU;AACjD,EAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAS,GAAI,cAAc,KAAK,CAAA;AAChD,EAAA,IAAI,CAAC,QAAQ,MAAM,WAAA,CAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,wBAAA,EAA0B,CAAA;AAErF,EAAA,MAAM,KAAA,GAAQ,SAAS,KAAK,CAAA;AAC5B,EAAA,MAAM,QAAA,GAAA,CAAY,KAAA,CAAM,QAAA,IAAY,EAAA,EAAI,IAAA,EAAK;AAC7C,EAAA,IAAI,CAAC,UAAU,MAAM,WAAA,CAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,sBAAA,EAAwB,CAAA;AAErF,EAAA,MAAM,OAAA,GAAU,aAAa,KAAK,CAAA;AAClC,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,iBAAiB,CAAA,IAAK,EAAA;AAC5C,EAAA,IAAI,CAAC,OAAO,MAAM,WAAA,CAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,mBAAA,EAAqB,CAAA;AAE/E,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,MAAA,CAAO,aAAA,CAAc,SAAA,CAAU,QAAQ,CAAA,EAAG;AAAA,MACrD,OAAA,EAAS,MAAA;AAAA,MACT,MAAA,EAAQ,QAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,CAAC,WAAA,CAAY,SAAS,GAAG,QAAA,IAAY,EAAA;AAAA,QACrC,CAAC,WAAA,CAAY,aAAa,GAAG,UAAU,KAAK,CAAA;AAAA;AAC9C,KACD,CAAA;AAAA,EACH,SAAS,GAAA,EAAU;AAGjB,IAAA,MAAM,MAAA,GAAU,GAAA,EAAK,IAAA,IAAQ,EAAC;AAC9B,IAAA,MAAM,MAAA,GAAU,MAAA,CAAO,MAAA,IAAU,EAAC;AAClC,IAAA,MAAM,UAAU,MAAA,CAAO,gBAAA,IAAoB,OAAO,KAAA,IAAS,MAAA,CAAO,SAAS,GAAA,EAAK,OAAA;AAChF,IAAA,MAAM,WAAA,CAAY;AAAA,MAChB,UAAA,EAAY,GAAA,EAAK,QAAA,EAAU,MAAA,IAAU,KAAK,UAAA,IAAc,GAAA;AAAA,MACxD,SAAS,OAAA,IAAW,mBAAA;AAAA,MACpB,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACF,CAAC,CAAA;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"login.post.js","sources":["../../../src/server/auth/login.post.ts"],"sourcesContent":["import {\n defineEventHandler,\n readBody,\n parseCookies,\n getRequestHeader,\n setCookie,\n createError,\n} from 'h3';\nimport { $fetch } from 'ofetch';\nimport { AUTH_ENDPOINT } from '../../common/constants/auth.constant';\nimport { HTTP_HEADER } from '../../common/constants/http.constant';\nimport {\n readSdkConfig,\n REFRESH_TOKEN_STORAGE_KEY,\n TOKEN_COOKIE_OPTIONS,\n TOKEN_STORAGE_KEY,\n} from './_shared';\n\n/**\n * Thin auth proxy: POST /api/cms/login → backend POST /api/auth/login.\n *\n * The real backend returns the access token in the response BODY as\n * `accessToken` (camelCase). This route reads it from the body, stores it as an\n * httpOnly cookie, and returns the body augmented with a `token` field so the\n * client can mirror the token in memory (the httpOnly cookie is the durable\n * copy used for SSR).\n *\n * Device id/ip and user-agent are forwarded from the incoming request.\n */\nexport default defineEventHandler(async (event) => {\n const { cmsUrl, clientId } = readSdkConfig(event);\n if (!cmsUrl) throw createError({ statusCode: 500, message: 'CMS URL not configured' });\n\n const body = ((await readBody(event)) ?? {}) as Record<string, unknown>;\n // Login body carries the portal client id (e.g. `people-hub`, camelCase).\n // Inject the module-configured id when the caller omitted it — server-side\n // value, consistent with the `X-Client-Id` header below.\n if (body.clientId == null && clientId) {\n body.clientId = clientId;\n }\n const cookies = parseCookies(event);\n const userAgent = getRequestHeader(event, HTTP_HEADER.USER_AGENT) || '';\n\n try {\n const response = await $fetch.raw(AUTH_ENDPOINT.LOGIN, {\n baseURL: cmsUrl,\n method: 'POST',\n body,\n headers: {\n [HTTP_HEADER.CLIENT_ID]: clientId || '',\n [HTTP_HEADER.DEVICE_ID]: cookies.device_id || '',\n [HTTP_HEADER.DEVICE_IP]: cookies.device_ip || '',\n [HTTP_HEADER.USER_AGENT]: userAgent,\n },\n });\n const data = (response._data ?? {}) as Record<string, unknown>;\n // camelCase is the backend default; fall back to snake_case just in case.\n const token =\n (data.accessToken as string | undefined) ?? (data.access_token as string | undefined) ?? '';\n const refreshToken =\n (data.refreshToken as string | undefined) ?? (data.refresh_token as string | undefined) ?? '';\n if (token) setCookie(event, TOKEN_STORAGE_KEY, token, TOKEN_COOKIE_OPTIONS);\n // Persist the refresh token as an httpOnly cookie so the SDK can rotate the\n // access token silently when it expires.\n if (refreshToken)\n setCookie(event, REFRESH_TOKEN_STORAGE_KEY, refreshToken, TOKEN_COOKIE_OPTIONS);\n return { ...data, token };\n } catch (err: any) {\n throw createError({\n statusCode: err?.response?.status || err?.statusCode || 500,\n message: err?.data?.error || err?.data?.message || err?.message || 'Login failed',\n data: err?.data,\n });\n }\n});\n"],"names":[],"mappings":";;;;;;;AA6BA,mBAAe,kBAAA,CAAmB,OAAO,KAAA,KAAU;AACjD,EAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAS,GAAI,cAAc,KAAK,CAAA;AAChD,EAAA,IAAI,CAAC,QAAQ,MAAM,WAAA,CAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,wBAAA,EAA0B,CAAA;AAErF,EAAA,MAAM,IAAA,GAAS,MAAM,QAAA,CAAS,KAAK,KAAM,EAAC;AAI1C,EAAA,IAAI,IAAA,CAAK,QAAA,IAAY,IAAA,IAAQ,QAAA,EAAU;AACrC,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAAA,EAClB;AACA,EAAA,MAAM,OAAA,GAAU,aAAa,KAAK,CAAA;AAClC,EAAA,MAAM,SAAA,GAAY,gBAAA,CAAiB,KAAA,EAAO,WAAA,CAAY,UAAU,CAAA,IAAK,EAAA;AAErE,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,MAAM,MAAA,CAAO,GAAA,CAAI,cAAc,KAAA,EAAO;AAAA,MACrD,OAAA,EAAS,MAAA;AAAA,MACT,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA;AAAA,MACA,OAAA,EAAS;AAAA,QACP,CAAC,WAAA,CAAY,SAAS,GAAG,QAAA,IAAY,EAAA;AAAA,QACrC,CAAC,WAAA,CAAY,SAAS,GAAG,QAAQ,SAAA,IAAa,EAAA;AAAA,QAC9C,CAAC,WAAA,CAAY,SAAS,GAAG,QAAQ,SAAA,IAAa,EAAA;AAAA,QAC9C,CAAC,WAAA,CAAY,UAAU,GAAG;AAAA;AAC5B,KACD,CAAA;AACD,IAAA,MAAM,IAAA,GAAQ,QAAA,CAAS,KAAA,IAAS,EAAC;AAEjC,IAAA,MAAM,KAAA,GACH,IAAA,CAAK,WAAA,IAAuC,IAAA,CAAK,YAAA,IAAuC,EAAA;AAC3F,IAAA,MAAM,YAAA,GACH,IAAA,CAAK,YAAA,IAAwC,IAAA,CAAK,aAAA,IAAwC,EAAA;AAC7F,IAAA,IAAI,KAAA,EAAO,SAAA,CAAU,KAAA,EAAO,iBAAA,EAAmB,OAAO,oBAAoB,CAAA;AAG1E,IAAA,IAAI,YAAA;AACF,MAAA,SAAA,CAAU,KAAA,EAAO,yBAAA,EAA2B,YAAA,EAAc,oBAAoB,CAAA;AAChF,IAAA,OAAO,EAAE,GAAG,IAAA,EAAM,KAAA,EAAM;AAAA,EAC1B,SAAS,GAAA,EAAU;AACjB,IAAA,MAAM,WAAA,CAAY;AAAA,MAChB,UAAA,EAAY,GAAA,EAAK,QAAA,EAAU,MAAA,IAAU,KAAK,UAAA,IAAc,GAAA;AAAA,MACxD,OAAA,EAAS,KAAK,IAAA,EAAM,KAAA,IAAS,KAAK,IAAA,EAAM,OAAA,IAAW,KAAK,OAAA,IAAW,cAAA;AAAA,MACnE,MAAM,GAAA,EAAK;AAAA,KACZ,CAAA;AAAA,EACH;AACF,CAAC,CAAA;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"logout.post.js","sources":["../../../src/server/auth/logout.post.ts"],"sourcesContent":["import { defineEventHandler, parseCookies, deleteCookie } from 'h3';\nimport { $fetch } from 'ofetch';\nimport { AUTH_ENDPOINT } from '../../common/constants/auth.constant';\nimport { HTTP_HEADER } from '../../common/constants/http.constant';\nimport {\n readSdkConfig,\n REFRESH_TOKEN_STORAGE_KEY,\n TOKEN_COOKIE_OPTIONS,\n TOKEN_STORAGE_KEY,\n} from './_shared';\n\n/**\n * Thin auth proxy: POST /api/cms/logout → backend POST /api/auth/logout.\n *\n * Best-effort backend logout using the token from the httpOnly cookie (the real\n * backend expects `Authorization: Bearer <jwt>`), then clears the cookie\n * regardless of backend outcome.\n */\nexport default defineEventHandler(async (event) => {\n const { cmsUrl, clientId } = readSdkConfig(event);\n const cookies = parseCookies(event);\n const token = cookies[TOKEN_STORAGE_KEY] || '';\n\n try {\n if (cmsUrl && token) {\n await $fetch.raw(AUTH_ENDPOINT.LOGOUT, {\n baseURL: cmsUrl,\n method: 'POST',\n headers: {\n // The cookie stores the raw JWT; the backend expects a bearer header.\n [HTTP_HEADER.AUTHORIZATION]: `Bearer ${token}`,\n [HTTP_HEADER.CLIENT_ID]: clientId || '',\n },\n });\n }\n } catch {\n // Backend logout failure should not prevent clearing the local cookie.\n }\n\n deleteCookie(event, TOKEN_STORAGE_KEY, { path: TOKEN_COOKIE_OPTIONS.path });\n deleteCookie(event, REFRESH_TOKEN_STORAGE_KEY, { path: TOKEN_COOKIE_OPTIONS.path });\n return { success: true };\n});\n"],"names":[],"mappings":";;;;;;;AAkBA,oBAAe,kBAAA,CAAmB,OAAO,KAAA,KAAU;AACjD,EAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAS,GAAI,cAAc,KAAK,CAAA;AAChD,EAAA,MAAM,OAAA,GAAU,aAAa,KAAK,CAAA;AAClC,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,iBAAiB,CAAA,IAAK,EAAA;AAE5C,EAAA,IAAI;AACF,IAAA,IAAI,UAAU,KAAA,EAAO;AACnB,MAAA,MAAM,MAAA,CAAO,GAAA,CAAI,aAAA,CAAc,MAAA,EAAQ;AAAA,QACrC,OAAA,EAAS,MAAA;AAAA,QACT,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS;AAAA;AAAA,UAEP,CAAC,WAAA,CAAY,aAAa,GAAG,UAAU,KAAK,CAAA,CAAA;AAAA,UAC5C,CAAC,WAAA,CAAY,SAAS,GAAG,QAAA,IAAY;AAAA;AACvC,OACD,CAAA;AAAA,IACH;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AAEA,EAAA,YAAA,CAAa,OAAO,iBAAA,EAAmB,EAAE,IAAA,EAAM,oBAAA,CAAqB,MAAM,CAAA;AAC1E,EAAA,YAAA,CAAa,OAAO,yBAAA,EAA2B,EAAE,IAAA,EAAM,oBAAA,CAAqB,MAAM,CAAA;AAClF,EAAA,OAAO,EAAE,SAAS,IAAA,EAAK;AACzB,CAAC,CAAA;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"refresh.post.js","sources":["../../../src/server/auth/refresh.post.ts"],"sourcesContent":["import { defineEventHandler, parseCookies, setCookie, createError } from 'h3';\nimport { $fetch } from 'ofetch';\nimport { AUTH_ENDPOINT } from '../../common/constants/auth.constant';\nimport { HTTP_HEADER, RESPONSE_CASING_VALUE } from '../../common/constants/http.constant';\nimport {\n readSdkConfig,\n REFRESH_TOKEN_STORAGE_KEY,\n TOKEN_COOKIE_OPTIONS,\n TOKEN_STORAGE_KEY,\n} from './_shared';\n\n/**\n * Thin auth proxy: POST /api/cms/refresh → backend POST /api/oauth/token.\n *\n * Exchanges the httpOnly `cms_refresh_token` cookie for a new access (+ refresh)\n * token via the backend OAuth token endpoint (`grant_type=refresh_token`), then\n * rotates both httpOnly cookies. Returns the new access token in the body\n * (`{ token }`) so the client can mirror it in memory.\n *\n * Request body casing: camelCase by default (`{ grantType, refreshToken }`);\n * when `requestCasing: 'snake'` is configured, sends snake_case keys +\n * `x-request-casing: snake`. Response keys are read with a snake fallback so\n * the proxy is robust to either casing.\n */\nexport default defineEventHandler(async (event) => {\n const { cmsUrl, clientId, requestCasing, responseCasing } = readSdkConfig(event);\n if (!cmsUrl) throw createError({ statusCode: 500, message: 'CMS URL not configured' });\n\n const cookies = parseCookies(event);\n const refreshToken = cookies[REFRESH_TOKEN_STORAGE_KEY] || '';\n if (!refreshToken) {\n throw createError({ statusCode: 401, message: 'No refresh token' });\n }\n\n const snake = requestCasing === RESPONSE_CASING_VALUE.SNAKE;\n const body = snake\n ? { grant_type: 'refresh_token', refresh_token: refreshToken }\n : { grantType: 'refresh_token', refreshToken };\n\n const headers: Record<string, string> = {\n [HTTP_HEADER.CLIENT_ID]: clientId || '',\n };\n if (snake) headers[HTTP_HEADER.REQUEST_CASING] = RESPONSE_CASING_VALUE.SNAKE;\n if (responseCasing === RESPONSE_CASING_VALUE.SNAKE) {\n headers[HTTP_HEADER.RESPONSE_CASING] = RESPONSE_CASING_VALUE.SNAKE;\n }\n\n try {\n const data = (await $fetch(AUTH_ENDPOINT.REFRESH, {\n baseURL: cmsUrl,\n method: 'POST',\n body,\n headers,\n })) as Record<string, unknown>;\n\n const token =\n (data.accessToken as string | undefined) ?? (data.access_token as string | undefined) ?? '';\n const newRefresh =\n (data.refreshToken as string | undefined) ?? (data.refresh_token as string | undefined) ?? '';\n\n if (token) setCookie(event, TOKEN_STORAGE_KEY, token, TOKEN_COOKIE_OPTIONS);\n if (newRefresh) setCookie(event, REFRESH_TOKEN_STORAGE_KEY, newRefresh, TOKEN_COOKIE_OPTIONS);\n\n return { ...data, token };\n } catch (err: any) {\n throw createError({\n statusCode: err?.response?.status || err?.statusCode || 401,\n message: err?.data?.error || err?.data?.message || err?.message || 'Token refresh failed',\n data: err?.data,\n });\n }\n});\n"],"names":[],"mappings":";;;;;;;AAwBA,qBAAe,kBAAA,CAAmB,OAAO,KAAA,KAAU;AACjD,EAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAU,eAAe,cAAA,EAAe,GAAI,cAAc,KAAK,CAAA;AAC/E,EAAA,IAAI,CAAC,QAAQ,MAAM,WAAA,CAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,wBAAA,EAA0B,CAAA;AAErF,EAAA,MAAM,OAAA,GAAU,aAAa,KAAK,CAAA;AAClC,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,yBAAyB,CAAA,IAAK,EAAA;AAC3D,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,MAAM,YAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,oBAAoB,CAAA;AAAA,EACpE;AAEA,EAAA,MAAM,KAAA,GAAQ,kBAAkB,qBAAA,CAAsB,KAAA;AACtD,EAAA,MAAM,IAAA,GAAO,KAAA,GACT,EAAE,UAAA,EAAY,eAAA,EAAiB,aAAA,EAAe,YAAA,EAAa,GAC3D,EAAE,SAAA,EAAW,eAAA,EAAiB,YAAA,EAAa;AAE/C,EAAA,MAAM,OAAA,GAAkC;AAAA,IACtC,CAAC,WAAA,CAAY,SAAS,GAAG,QAAA,IAAY;AAAA,GACvC;AACA,EAAA,IAAI,KAAA,EAAO,OAAA,CAAQ,WAAA,CAAY,cAAc,IAAI,qBAAA,CAAsB,KAAA;AACvE,EAAA,IAAI,cAAA,KAAmB,sBAAsB,KAAA,EAAO;AAClD,IAAA,OAAA,CAAQ,WAAA,CAAY,eAAe,CAAA,GAAI,qBAAA,CAAsB,KAAA;AAAA,EAC/D;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAQ,MAAM,MAAA,CAAO,aAAA,CAAc,OAAA,EAAS;AAAA,MAChD,OAAA,EAAS,MAAA;AAAA,MACT,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,MAAM,KAAA,GACH,IAAA,CAAK,WAAA,IAAuC,IAAA,CAAK,YAAA,IAAuC,EAAA;AAC3F,IAAA,MAAM,UAAA,GACH,IAAA,CAAK,YAAA,IAAwC,IAAA,CAAK,aAAA,IAAwC,EAAA;AAE7F,IAAA,IAAI,KAAA,EAAO,SAAA,CAAU,KAAA,EAAO,iBAAA,EAAmB,OAAO,oBAAoB,CAAA;AAC1E,IAAA,IAAI,UAAA,EAAY,SAAA,CAAU,KAAA,EAAO,yBAAA,EAA2B,YAAY,oBAAoB,CAAA;AAE5F,IAAA,OAAO,EAAE,GAAG,IAAA,EAAM,KAAA,EAAM;AAAA,EAC1B,SAAS,GAAA,EAAU;AACjB,IAAA,MAAM,WAAA,CAAY;AAAA,MAChB,UAAA,EAAY,GAAA,EAAK,QAAA,EAAU,MAAA,IAAU,KAAK,UAAA,IAAc,GAAA;AAAA,MACxD,OAAA,EAAS,KAAK,IAAA,EAAM,KAAA,IAAS,KAAK,IAAA,EAAM,OAAA,IAAW,KAAK,OAAA,IAAW,sBAAA;AAAA,MACnE,MAAM,GAAA,EAAK;AAAA,KACZ,CAAA;AAAA,EACH;AACF,CAAC,CAAA;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"portal-access.get.js","sources":["../../../src/server/authz/portal-access.get.ts"],"sourcesContent":["import { defineEventHandler, getQuery, parseCookies, createError } from 'h3';\nimport { $fetch } from 'ofetch';\nimport { AUTHZ_ENDPOINT } from '../../common/constants/authz.constant';\nimport { HTTP_HEADER } from '../../common/constants/http.constant';\nimport { readSdkConfig, TOKEN_STORAGE_KEY } from '../auth/_shared';\n\n/**\n * Thin authz proxy: GET /api/cms/portal-access?portal=people →\n * backend GET /api/v1/authz/me/portals/{portal}.\n *\n * Requires an authenticated caller: the httpOnly access-token cookie is\n * forwarded as `Authorization: Bearer` (same convention as the idp-link\n * route). The portal id comes from the `?portal=` query, falling back to\n * the module option `cmsSdk.portal`.\n *\n * The backend error codes survive in the thrown body's `data`, so clients\n * can branch on `UNAUTHENTICATED`, `INVALID_TOKEN_AUDIENCE` and\n * `PORTAL_ACCESS_DENIED` via the consumer-side `extractAuthError`.\n */\nexport default defineEventHandler(async (event) => {\n const { cmsUrl, clientId, portal: defaultPortal } = readSdkConfig(event);\n if (!cmsUrl) throw createError({ statusCode: 500, message: 'CMS URL not configured' });\n\n const query = getQuery(event) as { portal?: string };\n const portal = String(query.portal ?? defaultPortal ?? '').trim();\n if (!portal) {\n throw createError({\n statusCode: 400,\n message: 'portal is required (query param or cmsSdk.portal module option)',\n });\n }\n\n const cookies = parseCookies(event);\n const token = cookies[TOKEN_STORAGE_KEY] || '';\n if (!token) throw createError({ statusCode: 401, message: 'Not authenticated' });\n\n try {\n return await $fetch(AUTHZ_ENDPOINT.portalAccess(portal), {\n baseURL: cmsUrl,\n headers: {\n [HTTP_HEADER.CLIENT_ID]: clientId || '',\n [HTTP_HEADER.AUTHORIZATION]: `Bearer ${token}`,\n },\n });\n } catch (err: any) {\n // The CMS nests the real error one level down:\n // `{ error: \"HTTPException\", detail: { error, errorDescription } }`.\n const beData = (err?.data ?? {}) as Record<string, any>;\n const detail = (beData.detail ?? {}) as Record<string, any>;\n const message = detail.errorDescription ?? detail.error ?? beData.error ?? err?.message;\n throw createError({\n statusCode: err?.response?.status || err?.statusCode || 500,\n message: message || 'Portal access check failed',\n data: beData,\n });\n }\n});\n"],"names":[],"mappings":";;;;;;;AAmBA,yBAAe,kBAAA,CAAmB,OAAO,KAAA,KAAU;AACjD,EAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAU,QAAQ,aAAA,EAAc,GAAI,cAAc,KAAK,CAAA;AACvE,EAAA,IAAI,CAAC,QAAQ,MAAM,WAAA,CAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,wBAAA,EAA0B,CAAA;AAErF,EAAA,MAAM,KAAA,GAAQ,SAAS,KAAK,CAAA;AAC5B,EAAA,MAAM,SAAS,MAAA,CAAO,KAAA,CAAM,UAAU,aAAA,IAAiB,EAAE,EAAE,IAAA,EAAK;AAChE,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,WAAA,CAAY;AAAA,MAChB,UAAA,EAAY,GAAA;AAAA,MACZ,OAAA,EAAS;AAAA,KACV,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,OAAA,GAAU,aAAa,KAAK,CAAA;AAClC,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,iBAAiB,CAAA,IAAK,EAAA;AAC5C,EAAA,IAAI,CAAC,OAAO,MAAM,WAAA,CAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,mBAAA,EAAqB,CAAA;AAE/E,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,MAAA,CAAO,cAAA,CAAe,YAAA,CAAa,MAAM,CAAA,EAAG;AAAA,MACvD,OAAA,EAAS,MAAA;AAAA,MACT,OAAA,EAAS;AAAA,QACP,CAAC,WAAA,CAAY,SAAS,GAAG,QAAA,IAAY,EAAA;AAAA,QACrC,CAAC,WAAA,CAAY,aAAa,GAAG,UAAU,KAAK,CAAA;AAAA;AAC9C,KACD,CAAA;AAAA,EACH,SAAS,GAAA,EAAU;AAGjB,IAAA,MAAM,MAAA,GAAU,GAAA,EAAK,IAAA,IAAQ,EAAC;AAC9B,IAAA,MAAM,MAAA,GAAU,MAAA,CAAO,MAAA,IAAU,EAAC;AAClC,IAAA,MAAM,UAAU,MAAA,CAAO,gBAAA,IAAoB,OAAO,KAAA,IAAS,MAAA,CAAO,SAAS,GAAA,EAAK,OAAA;AAChF,IAAA,MAAM,WAAA,CAAY;AAAA,MAChB,UAAA,EAAY,GAAA,EAAK,QAAA,EAAU,MAAA,IAAU,KAAK,UAAA,IAAc,GAAA;AAAA,MACxD,SAAS,OAAA,IAAW,4BAAA;AAAA,MACpB,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACF,CAAC,CAAA;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"clear-token.delete.js","sources":["../../src/server/clear-token.delete.ts"],"sourcesContent":["import { defineEventHandler, deleteCookie } from 'h3';\nimport { COOKIE_DEFAULTS, TOKEN_STORAGE_KEY } from '../common/constants/storage.constant';\n\nexport default defineEventHandler(async (event) => {\n deleteCookie(event, TOKEN_STORAGE_KEY, {\n path: COOKIE_DEFAULTS.PATH,\n });\n return { success: true };\n});\n"],"names":[],"mappings":";;;AAGA,0BAAe,kBAAA,CAAmB,OAAO,KAAA,KAAU;AACjD,EAAA,YAAA,CAAa,OAAO,iBAAA,EAAmB;AAAA,IACrC,MAAM,eAAA,CAAgB;AAAA,GACvB,CAAA;AACD,EAAA,OAAO,EAAE,SAAS,IAAA,EAAK;AACzB,CAAC,CAAA;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"persist.post.js","sources":["../../src/server/persist.post.ts"],"sourcesContent":["import { defineEventHandler, readBody, setCookie, deleteCookie, createError } from 'h3';\nimport {\n PERSIST_ALLOWED_KEYS,\n PERSIST_MAX_BYTES,\n TOKEN_STORAGE_KEY,\n} from '../common/constants/storage.constant';\nimport { COOKIE_DEFAULTS } from '../common/constants/storage.constant';\n\n/**\n * Common persistence endpoint. The internal Pinia persistence plugin POSTs\n * client-side httpOnly writes here so the server sets the httpOnly cookie (a\n * client cannot set an httpOnly cookie itself).\n *\n * Security guards (mandatory):\n * - `key` must be in `PERSIST_ALLOWED_KEYS` (and never the token key).\n * - cookie options are fixed (httpOnly/secure/sameSite/path) — the client\n * cannot weaken them.\n * - value size is capped (< PERSIST_MAX_BYTES).\n */\nconst PERSIST_COOKIE_OPTIONS = {\n httpOnly: COOKIE_DEFAULTS.HTTP_ONLY,\n secure: COOKIE_DEFAULTS.SECURE,\n sameSite: COOKIE_DEFAULTS.SAME_SITE.toLowerCase() as 'lax',\n path: COOKIE_DEFAULTS.PATH,\n maxAge: COOKIE_DEFAULTS.MAX_AGE_SECONDS,\n};\n\nconst ALLOWED_KEYS = new Set<string>(PERSIST_ALLOWED_KEYS);\n\ninterface IPersistBody {\n key?: unknown;\n value?: unknown;\n}\n\nexport default defineEventHandler(async (event) => {\n const body = await readBody<IPersistBody>(event);\n const key = body?.key;\n const value = body?.value ?? null;\n\n if (typeof key !== 'string' || !ALLOWED_KEYS.has(key) || key === TOKEN_STORAGE_KEY) {\n throw createError({ statusCode: 400, message: 'Invalid persist key' });\n }\n\n if (value === null) {\n deleteCookie(event, key, { path: PERSIST_COOKIE_OPTIONS.path });\n return { ok: true };\n }\n\n if (typeof value !== 'string' || value.length >= PERSIST_MAX_BYTES) {\n throw createError({ statusCode: 400, message: 'Invalid or too large persist value' });\n }\n\n setCookie(event, key, value, PERSIST_COOKIE_OPTIONS);\n return { ok: true };\n});\n"],"names":[],"mappings":";;;AAmBA,MAAM,sBAAA,GAAyB;AAAA,EAC7B,UAAU,eAAA,CAAgB,SAAA;AAAA,EAC1B,QAAQ,eAAA,CAAgB,MAAA;AAAA,EACxB,QAAA,EAAU,eAAA,CAAgB,SAAA,CAAU,WAAA,EAAY;AAAA,EAChD,MAAM,eAAA,CAAgB,IAAA;AAAA,EACtB,QAAQ,eAAA,CAAgB;AAC1B,CAAA;AAEA,MAAM,YAAA,GAAe,IAAI,GAAA,CAAY,oBAAoB,CAAA;AAOzD,qBAAe,kBAAA,CAAmB,OAAO,KAAA,KAAU;AACjD,EAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAuB,KAAK,CAAA;AAC/C,EAAA,MAAM,MAAM,IAAA,EAAM,GAAA;AAClB,EAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,IAAS,IAAA;AAE7B,EAAA,IAAI,OAAO,QAAQ,QAAA,IAAY,CAAC,aAAa,GAAA,CAAI,GAAG,CAAA,IAAK,GAAA,KAAQ,iBAAA,EAAmB;AAClF,IAAA,MAAM,YAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,uBAAuB,CAAA;AAAA,EACvE;AAEA,EAAA,IAAI,UAAU,IAAA,EAAM;AAClB,IAAA,YAAA,CAAa,OAAO,GAAA,EAAK,EAAE,IAAA,EAAM,sBAAA,CAAuB,MAAM,CAAA;AAC9D,IAAA,OAAO,EAAE,IAAI,IAAA,EAAK;AAAA,EACpB;AAEA,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,UAAU,iBAAA,EAAmB;AAClE,IAAA,MAAM,YAAY,EAAE,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,sCAAsC,CAAA;AAAA,EACtF;AAEA,EAAA,SAAA,CAAU,KAAA,EAAO,GAAA,EAAK,KAAA,EAAO,sBAAsB,CAAA;AACnD,EAAA,OAAO,EAAE,IAAI,IAAA,EAAK;AACpB,CAAC,CAAA;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"set-token.post.js","sources":["../../src/server/set-token.post.ts"],"sourcesContent":["import { defineEventHandler, readBody, setCookie } from 'h3';\nimport { COOKIE_DEFAULTS, TOKEN_STORAGE_KEY } from '../common/constants/storage.constant';\n\nexport default defineEventHandler(async (event) => {\n try {\n const body = await readBody(event);\n const token = body?.token || body?.accessToken || '';\n\n if (!token) {\n event.node.res.statusCode = 400;\n return { error: 'Missing token in request body' };\n }\n\n setCookie(event, TOKEN_STORAGE_KEY, token, {\n httpOnly: COOKIE_DEFAULTS.HTTP_ONLY,\n secure: COOKIE_DEFAULTS.SECURE,\n sameSite: COOKIE_DEFAULTS.SAME_SITE.toLowerCase() as 'lax',\n path: COOKIE_DEFAULTS.PATH,\n maxAge: COOKIE_DEFAULTS.MAX_AGE_SECONDS,\n });\n\n return { success: true };\n } catch (err: any) {\n event.node.res.statusCode = err?.statusCode || 500;\n return { error: err?.message || 'Failed to set token' };\n }\n});\n"],"names":[],"mappings":";;;AAGA,sBAAe,kBAAA,CAAmB,OAAO,KAAA,KAAU;AACjD,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,KAAK,CAAA;AACjC,IAAA,MAAM,KAAA,GAAQ,IAAA,EAAM,KAAA,IAAS,IAAA,EAAM,WAAA,IAAe,EAAA;AAElD,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,KAAA,CAAM,IAAA,CAAK,IAAI,UAAA,GAAa,GAAA;AAC5B,MAAA,OAAO,EAAE,OAAO,+BAAA,EAAgC;AAAA,IAClD;AAEA,IAAA,SAAA,CAAU,KAAA,EAAO,mBAAmB,KAAA,EAAO;AAAA,MACzC,UAAU,eAAA,CAAgB,SAAA;AAAA,MAC1B,QAAQ,eAAA,CAAgB,MAAA;AAAA,MACxB,QAAA,EAAU,eAAA,CAAgB,SAAA,CAAU,WAAA,EAAY;AAAA,MAChD,MAAM,eAAA,CAAgB,IAAA;AAAA,MACtB,QAAQ,eAAA,CAAgB;AAAA,KACzB,CAAA;AAED,IAAA,OAAO,EAAE,SAAS,IAAA,EAAK;AAAA,EACzB,SAAS,GAAA,EAAU;AACjB,IAAA,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,UAAA,GAAa,GAAA,EAAK,UAAA,IAAc,GAAA;AAC/C,IAAA,OAAO,EAAE,KAAA,EAAO,GAAA,EAAK,OAAA,IAAW,qBAAA,EAAsB;AAAA,EACxD;AACF,CAAC,CAAA;;;;"}
|