@tinyrack/issuary-server 0.23.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/entrypoints/app.d.ts +0 -6
- package/dist/entrypoints/app.d.ts.map +1 -1
- package/dist/lib/config/branding.d.ts +0 -4
- package/dist/lib/config/branding.d.ts.map +1 -1
- package/dist/lib/config/branding.js +0 -14
- package/dist/lib/config/branding.js.map +1 -1
- package/dist/lib/config/resolved.d.ts +0 -2
- package/dist/lib/config/resolved.d.ts.map +1 -1
- package/dist/routes/api/config/get.d.ts +0 -4
- package/dist/routes/api/config/get.d.ts.map +1 -1
- package/dist/routes/api/config/get.js +0 -2
- package/dist/routes/api/config/get.js.map +1 -1
- package/dist/routes/api/config/index.d.ts +0 -4
- package/dist/routes/api/config/index.d.ts.map +1 -1
- package/dist/routes/api/index.d.ts +0 -4
- package/dist/routes/api/index.d.ts.map +1 -1
- package/dist/routes/index.d.ts +0 -4
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/schemas/response.d.ts +0 -2
- package/dist/schemas/response.d.ts.map +1 -1
- package/dist/schemas/response.js +0 -5
- package/dist/schemas/response.js.map +1 -1
- package/dist/services/container.d.ts +0 -2
- package/dist/services/container.d.ts.map +1 -1
- package/package.json +2 -1
- package/public/assets/2fa-BlpDkf-r.js +2 -0
- package/public/assets/{2fa-CCOTIHDZ.js.map → 2fa-BlpDkf-r.js.map} +1 -1
- package/public/assets/{2fa-B5vLgDXQ.js → 2fa-DIpGlpoI.js} +2 -2
- package/public/assets/{2fa-B5vLgDXQ.js.map → 2fa-DIpGlpoI.js.map} +1 -1
- package/public/assets/2fa-tzTSqiOS.js +2 -0
- package/public/assets/{2fa-C5vUVgr_.js.map → 2fa-tzTSqiOS.js.map} +1 -1
- package/public/assets/{2fa-BqsM_D-X.js → 2fa-waFAdIa0.js} +2 -2
- package/public/assets/{2fa-BqsM_D-X.js.map → 2fa-waFAdIa0.js.map} +1 -1
- package/public/assets/DialogHandle-ChG5Sj7T.js +2 -0
- package/public/assets/{DialogHandle-BmtK2pRn.js.map → DialogHandle-ChG5Sj7T.js.map} +1 -1
- package/public/assets/admin-Ii29X08B.js +2 -0
- package/public/assets/admin-Ii29X08B.js.map +1 -0
- package/public/assets/{admin-users-DvPbw1Vq.js → admin-users-d7tT-cjc.js} +2 -2
- package/public/assets/{admin-users-DvPbw1Vq.js.map → admin-users-d7tT-cjc.js.map} +1 -1
- package/public/assets/alert-leqyvHOp.js.map +1 -1
- package/public/assets/{auth-choice-row-BCGjuedo.js → auth-choice-row-DUvFyo7b.js} +2 -2
- package/public/assets/{auth-choice-row-BCGjuedo.js.map → auth-choice-row-DUvFyo7b.js.map} +1 -1
- package/public/assets/{auth-field-DD8kvl--.js → auth-field-BSlAWkbx.js} +2 -2
- package/public/assets/{auth-field-DD8kvl--.js.map → auth-field-BSlAWkbx.js.map} +1 -1
- package/public/assets/auth-layout-CcJy6dVY.js +2 -0
- package/public/assets/auth-layout-CcJy6dVY.js.map +1 -0
- package/public/assets/{auth-page-header-CIn2E4zI.js → auth-page-header-ZLhtQ7Et.js} +2 -2
- package/public/assets/auth-page-header-ZLhtQ7Et.js.map +1 -0
- package/public/assets/authorization-context-banner-DfkjwE93.js +2 -0
- package/public/assets/authorization-context-banner-DfkjwE93.js.map +1 -0
- package/public/assets/{avatar-BEQjf2x6.js → avatar-D-70MKp8.js} +2 -2
- package/public/assets/{avatar-BEQjf2x6.js.map → avatar-D-70MKp8.js.map} +1 -1
- package/public/assets/badge-CsOfUji0.js.map +1 -1
- package/public/assets/checkbox-C3UmXoKz.js +2 -0
- package/public/assets/{checkbox-gdHnSFQ-.js.map → checkbox-C3UmXoKz.js.map} +1 -1
- package/public/assets/config-DTQCUlfZ.js.map +1 -1
- package/public/assets/{consent-CfRbz2R7.js → consent-BJgO9pEV.js} +2 -2
- package/public/assets/{consent-CfRbz2R7.js.map → consent-BJgO9pEV.js.map} +1 -1
- package/public/assets/{consent-BqqFDdsr.js → consent-D_yGE8TR.js} +2 -2
- package/public/assets/{consent-BqqFDdsr.js.map → consent-D_yGE8TR.js.map} +1 -1
- package/public/assets/createLucideIcon-BPpAIXR_.js.map +1 -1
- package/public/assets/{email-CKKakxPJ.js → email-DAa8JGoC.js} +2 -2
- package/public/assets/{email-CKKakxPJ.js.map → email-DAa8JGoC.js.map} +1 -1
- package/public/assets/email-tzTSqiOS.js +2 -0
- package/public/assets/{email-C5vUVgr_.js.map → email-tzTSqiOS.js.map} +1 -1
- package/public/assets/{error-BMXxpgfR.js → error-Dj4QQ8vW.js} +2 -2
- package/public/assets/{error-BMXxpgfR.js.map → error-Dj4QQ8vW.js.map} +1 -1
- package/public/assets/field-CEs4ugVJ.js +3 -0
- package/public/assets/{field-Cn4H1CUj.js.map → field-CEs4ugVJ.js.map} +1 -1
- package/public/assets/{forgot-rO9sByfV.js → forgot-CYMAWPVu.js} +2 -2
- package/public/assets/{forgot-rO9sByfV.js.map → forgot-CYMAWPVu.js.map} +1 -1
- package/public/assets/forgot-tzTSqiOS.js +2 -0
- package/public/assets/{forgot-C5vUVgr_.js.map → forgot-tzTSqiOS.js.map} +1 -1
- package/public/assets/{index-CS23Ozt6.js → index-H6CJKjiN.js} +3 -3
- package/public/assets/{index-CS23Ozt6.js.map → index-H6CJKjiN.js.map} +1 -1
- package/public/assets/{index-DZyHRhbQ.css → index-kD9gQA-w.css} +1 -1
- package/public/assets/{initial-avatar-CtuDUz_W.js → initial-avatar-DjSqgENY.js} +2 -2
- package/public/assets/{initial-avatar-CtuDUz_W.js.map → initial-avatar-DjSqgENY.js.map} +1 -1
- package/public/assets/{input-CzQki7k6.js → input-BHPUSlfp.js} +2 -2
- package/public/assets/{input-CzQki7k6.js.map → input-BHPUSlfp.js.map} +1 -1
- package/public/assets/link-C-WdTj3F.js.map +1 -1
- package/public/assets/{login-nukebli4.js → login-CBinfk4L.js} +2 -2
- package/public/assets/{login-nukebli4.js.map → login-CBinfk4L.js.map} +1 -1
- package/public/assets/login-tzTSqiOS.js +2 -0
- package/public/assets/{login-C5vUVgr_.js.map → login-tzTSqiOS.js.map} +1 -1
- package/public/assets/{modal-BDQFucjz.js → modal-CwoBUXp3.js} +2 -2
- package/public/assets/{modal-BDQFucjz.js.map → modal-CwoBUXp3.js.map} +1 -1
- package/public/assets/{passkey-CynCz1Dt.js → passkey-Jw2CRzJp.js} +2 -2
- package/public/assets/{passkey-CynCz1Dt.js.map → passkey-Jw2CRzJp.js.map} +1 -1
- package/public/assets/{passkey-BE9JvJOP.js → passkey-V_tav53p.js} +2 -2
- package/public/assets/{passkey-BE9JvJOP.js.map → passkey-V_tav53p.js.map} +1 -1
- package/public/assets/passkey-tzTSqiOS.js +2 -0
- package/public/assets/{passkey-C5vUVgr_.js.map → passkey-tzTSqiOS.js.map} +1 -1
- package/public/assets/{password-RkUttbhD.js → password-6QOqTV_s.js} +2 -2
- package/public/assets/{password-RkUttbhD.js.map → password-6QOqTV_s.js.map} +1 -1
- package/public/assets/{password-strength-BeSOu_Ga.js → password-strength-DtGMHOD-.js} +2 -2
- package/public/assets/{password-strength-BeSOu_Ga.js.map → password-strength-DtGMHOD-.js.map} +1 -1
- package/public/assets/password-tzTSqiOS.js +2 -0
- package/public/assets/{password-C5vUVgr_.js.map → password-tzTSqiOS.js.map} +1 -1
- package/public/assets/pin-input-DdhzDNy9.js +2 -0
- package/public/assets/{pin-input-Cc-VkrQ3.js.map → pin-input-DdhzDNy9.js.map} +1 -1
- package/public/assets/{profile-B5NaJfeS.js → profile-DVjIWt8X.js} +2 -2
- package/public/assets/{profile-B5NaJfeS.js.map → profile-DVjIWt8X.js.map} +1 -1
- package/public/assets/profile-SHr6F-7b.js +2 -0
- package/public/assets/profile-SHr6F-7b.js.map +1 -0
- package/public/assets/provider-logos-u1YURWQr.js.map +1 -1
- package/public/assets/{recovery-PnUATiUi.js → recovery-CvNl-yt9.js} +2 -2
- package/public/assets/{recovery-PnUATiUi.js.map → recovery-CvNl-yt9.js.map} +1 -1
- package/public/assets/{register-DQXhru0_.js → register-SFXa5EeL.js} +2 -2
- package/public/assets/{register-DQXhru0_.js.map → register-SFXa5EeL.js.map} +1 -1
- package/public/assets/register-tzTSqiOS.js +2 -0
- package/public/assets/{register-C5vUVgr_.js.map → register-tzTSqiOS.js.map} +1 -1
- package/public/assets/{reset-CQgIa3yf.js → reset-l-pLzjwe.js} +2 -2
- package/public/assets/{reset-CQgIa3yf.js.map → reset-l-pLzjwe.js.map} +1 -1
- package/public/assets/reset-tzTSqiOS.js +2 -0
- package/public/assets/{reset-C5vUVgr_.js.map → reset-tzTSqiOS.js.map} +1 -1
- package/public/assets/{select-DqZynXSt.js → select-D2H87qXJ.js} +2 -2
- package/public/assets/{select-DqZynXSt.js.map → select-D2H87qXJ.js.map} +1 -1
- package/public/assets/select-tzTSqiOS.js +2 -0
- package/public/assets/{select-C5vUVgr_.js.map → select-tzTSqiOS.js.map} +1 -1
- package/public/assets/separator-B0Bvh1he.js.map +1 -1
- package/public/assets/shell-header-bar-BPgCjFPv.js +2 -0
- package/public/assets/shell-header-bar-BPgCjFPv.js.map +1 -0
- package/public/assets/{terms-BHDAgn-H.js → terms-D5rfQhog.js} +2 -2
- package/public/assets/{terms-BHDAgn-H.js.map → terms-D5rfQhog.js.map} +1 -1
- package/public/assets/{terms-B5NaJfeS.js → terms-DVjIWt8X.js} +2 -2
- package/public/assets/{terms-B5NaJfeS.js.map → terms-DVjIWt8X.js.map} +1 -1
- package/public/assets/{terms-checkbox-list-6jteUTIZ.js → terms-checkbox-list-BKJcS2pJ.js} +2 -2
- package/public/assets/{terms-checkbox-list-6jteUTIZ.js.map → terms-checkbox-list-BKJcS2pJ.js.map} +1 -1
- package/public/assets/{totp-ECvOUcFx.js → totp-BbQi-gsF.js} +2 -2
- package/public/assets/{totp-ECvOUcFx.js.map → totp-BbQi-gsF.js.map} +1 -1
- package/public/assets/{totp-CJtfVNEq.js → totp-wY0Zji8E.js} +2 -2
- package/public/assets/{totp-CJtfVNEq.js.map → totp-wY0Zji8E.js.map} +1 -1
- package/public/assets/{use-totp-setup-BbS3XcZA.js → use-totp-setup-OH_GTMxA.js} +3 -3
- package/public/assets/{use-totp-setup-BbS3XcZA.js.map → use-totp-setup-OH_GTMxA.js.map} +1 -1
- package/public/assets/{useAriaLabelledBy-ByuMi3Ry.js → useAriaLabelledBy-9o83pv9X.js} +2 -2
- package/public/assets/{useAriaLabelledBy-ByuMi3Ry.js.map → useAriaLabelledBy-9o83pv9X.js.map} +1 -1
- package/public/assets/useQuery-CI5Ukuae.js +2 -0
- package/public/assets/{useQuery-Ckxjmvtl.js.map → useQuery-CI5Ukuae.js.map} +1 -1
- package/public/assets/users-DqCnblEo.js +2 -0
- package/public/assets/users-DqCnblEo.js.map +1 -0
- package/public/index.html +2 -2
- package/public/assets/2fa-C5vUVgr_.js +0 -2
- package/public/assets/2fa-CCOTIHDZ.js +0 -2
- package/public/assets/DialogHandle-BmtK2pRn.js +0 -2
- package/public/assets/admin-BPijkLw-.js +0 -2
- package/public/assets/admin-BPijkLw-.js.map +0 -1
- package/public/assets/auth-layout-VtpryDof.js +0 -2
- package/public/assets/auth-layout-VtpryDof.js.map +0 -1
- package/public/assets/auth-page-header-CIn2E4zI.js.map +0 -1
- package/public/assets/authorization-context-banner-SOuBHWIb.js +0 -2
- package/public/assets/authorization-context-banner-SOuBHWIb.js.map +0 -1
- package/public/assets/checkbox-gdHnSFQ-.js +0 -2
- package/public/assets/email-C5vUVgr_.js +0 -2
- package/public/assets/field-Cn4H1CUj.js +0 -3
- package/public/assets/forgot-C5vUVgr_.js +0 -2
- package/public/assets/login-C5vUVgr_.js +0 -2
- package/public/assets/passkey-C5vUVgr_.js +0 -2
- package/public/assets/password-C5vUVgr_.js +0 -2
- package/public/assets/pin-input-Cc-VkrQ3.js +0 -2
- package/public/assets/profile-BcjsVYOx.js +0 -2
- package/public/assets/profile-BcjsVYOx.js.map +0 -1
- package/public/assets/register-C5vUVgr_.js +0 -2
- package/public/assets/reset-C5vUVgr_.js +0 -2
- package/public/assets/select-C5vUVgr_.js +0 -2
- package/public/assets/shell-header-bar-CjG5qvPg.js +0 -2
- package/public/assets/shell-header-bar-CjG5qvPg.js.map +0 -1
- package/public/assets/useQuery-Ckxjmvtl.js +0 -2
- package/public/assets/users-CmFxrCQT.js +0 -2
- package/public/assets/users-CmFxrCQT.js.map +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{q as e}from"./createLucideIcon-BPpAIXR_.js";import{I as t,M as n}from"./index-
|
|
2
|
-
//# sourceMappingURL=consent-
|
|
1
|
+
import{q as e}from"./createLucideIcon-BPpAIXR_.js";import{I as t,M as n}from"./index-H6CJKjiN.js";var r=e();function i(e){return(0,r.jsx)(t,{...e,onUnauthorized:()=>{let e=new URLSearchParams(window.location.search),t=Object.fromEntries(e.entries());window.location.href=n(t)}})}export{i as errorComponent};
|
|
2
|
+
//# sourceMappingURL=consent-BJgO9pEV.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consent-
|
|
1
|
+
{"version":3,"file":"consent-BJgO9pEV.js","names":["RouteErrorFallback","buildAuthorizeUrl","ConsentError","props","ErrorComponentProps","params","URLSearchParams","window","location","search","Object","fromEntries","entries","href","errorComponent"],"sources":["../../../frontend/src/routes/consent/index.tsx?tsr-split=errorComponent"],"sourcesContent":["import { useMutation, useSuspenseQuery } from '@tanstack/react-query';\nimport {\n createFileRoute,\n type ErrorComponentProps,\n} from '@tanstack/react-router';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { TRCard } from '@tinyrack/ui/components/card';\nimport { TRText } from '@tinyrack/ui/components/text';\nimport { ShieldCheckIcon, XIcon } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { z } from 'zod';\nimport { AuthPageHeader } from '#frontend/components/auth/auth-page-header.tsx';\nimport { InitialAvatar } from '#frontend/components/ui/initial-avatar.tsx';\nimport { RouteErrorFallback } from '#frontend/components/ui/route-error-fallback.tsx';\nimport { AuthLayout } from '#frontend/features/layout/auth-layout.tsx';\nimport {\n buildAuthorizeUrl,\n OAuthSearchSchema,\n} from '#frontend/libs/oauth-search.ts';\nimport {\n consentDecisionMutationOptions,\n getConsentInfoQueryOptions,\n} from '#frontend/queries/consent.ts';\n\nconst ConsentSearchSchema = OAuthSearchSchema.extend({\n client_id: z.string(),\n redirect_uri: z.string(),\n response_type: z.string(),\n});\n\nexport const Route = createFileRoute('/consent/')({\n component: Consent,\n errorComponent: ConsentError,\n validateSearch: ConsentSearchSchema,\n loaderDeps: ({ search }) => ({\n client_id: search.client_id,\n scope: search.scope,\n }),\n loader: async ({ context, deps }) => {\n await context.queryClient.ensureQueryData(\n getConsentInfoQueryOptions({\n client_id: deps.client_id,\n scope: deps.scope,\n }),\n );\n },\n});\n\nfunction ConsentError(props: ErrorComponentProps) {\n return (\n <RouteErrorFallback\n {...props}\n onUnauthorized={() => {\n // Re-enter the OAuth flow from the beginning so the\n // user can log in and be redirected back through\n // /oauth/authorize -> /consent/.\n const params = new URLSearchParams(window.location.search);\n const search = Object.fromEntries(params.entries());\n window.location.href = buildAuthorizeUrl(search);\n }}\n />\n );\n}\n\nfunction Consent() {\n const { t } = useTranslation();\n const search = Route.useSearch();\n\n const consentInfoQuery = useSuspenseQuery(\n getConsentInfoQueryOptions({\n client_id: search.client_id,\n scope: search.scope,\n }),\n );\n\n const consentMutation = useMutation({\n ...consentDecisionMutationOptions,\n onSuccess: (data) => {\n window.location.href = data.redirect_url;\n },\n });\n\n const handleAllow = () => {\n consentMutation.mutate({\n client_id: search.client_id,\n redirect_uri: search.redirect_uri,\n response_type: search.response_type,\n scope: search.scope,\n state: search.state,\n nonce: search.nonce,\n code_challenge: search.code_challenge,\n code_challenge_method: search.code_challenge_method,\n prompt: search.prompt,\n max_age: search.max_age,\n reauthenticated: search.reauthenticated,\n display: search.display,\n response_mode: search.response_mode,\n login_hint: search.login_hint,\n ui_locales: search.ui_locales,\n id_token_hint: search.id_token_hint,\n acr_values: search.acr_values,\n account_selected: search.account_selected,\n account_selection_state: search.account_selection_state,\n decision: 'allow',\n });\n };\n\n const handleDeny = () => {\n consentMutation.mutate({\n client_id: search.client_id,\n redirect_uri: search.redirect_uri,\n response_type: search.response_type,\n scope: search.scope,\n state: search.state,\n nonce: search.nonce,\n code_challenge: search.code_challenge,\n code_challenge_method: search.code_challenge_method,\n prompt: search.prompt,\n max_age: search.max_age,\n reauthenticated: search.reauthenticated,\n display: search.display,\n response_mode: search.response_mode,\n login_hint: search.login_hint,\n ui_locales: search.ui_locales,\n id_token_hint: search.id_token_hint,\n acr_values: search.acr_values,\n account_selected: search.account_selected,\n account_selection_state: search.account_selection_state,\n decision: 'deny',\n });\n };\n\n const { client, scopes, user } = consentInfoQuery.data;\n\n return (\n <AuthLayout width=\"wide\">\n <AuthPageHeader\n subtitle={t('consent.subtitle', { app: client.name })}\n title={t('consent.title')}\n />\n\n {/*\n Who is about to hand out access. The decision is meaningless without\n it, so it sits above the scopes rather than in fine print.\n */}\n <TRCard.Root padding=\"lg\" variant=\"outlined\">\n <TRCard.Content className=\"flex items-center gap-tinyrack-md\">\n <InitialAvatar email={user.email} size=\"sm\" />\n <span className=\"flex min-w-0 flex-col\">\n <TRText color=\"muted\" variant=\"caption\">\n {t('consent.loggedInAs')}\n </TRText>\n <TRText\n data-testid=\"consent-user-email\"\n truncate\n variant=\"body\"\n weight=\"medium\"\n >\n {user.email}\n </TRText>\n </span>\n </TRCard.Content>\n </TRCard.Root>\n\n {/* Requested permissions */}\n <div className=\"flex flex-col gap-tinyrack-sm\">\n <TRText as=\"h3\" variant=\"label\">\n {t('consent.permissions.title')}\n </TRText>\n <ul\n className=\"flex flex-col gap-tinyrack-xs\"\n data-testid=\"consent-scope-list\"\n >\n {scopes.map((scope: { name: string; description: string }) => (\n <li\n className=\"flex items-center gap-tinyrack-sm rounded-tinyrack-md bg-tinyrack-surface-muted px-tinyrack-md py-tinyrack-sm\"\n key={scope.name}\n >\n <ShieldCheckIcon\n aria-hidden\n className=\"size-tinyrack-lg shrink-0 text-tinyrack-info-foreground\"\n />\n <TRText variant=\"body\">\n {t(`consent.scope.${scope.name}`, {\n defaultValue: scope.description,\n })}\n </TRText>\n </li>\n ))}\n </ul>\n </div>\n\n {/*\n Sticky so the decision stays reachable when a client asks for a long\n list of scopes and the page scrolls.\n */}\n <div className=\"sticky bottom-0 flex gap-tinyrack-sm border-tinyrack-border border-t-tinyrack-default bg-tinyrack-surface/80 py-tinyrack-md backdrop-blur-sm\">\n <TRButton\n appearance=\"outline\"\n className=\"flex-1\"\n data-testid=\"consent-deny\"\n intent=\"neutral\"\n loading={consentMutation.isPending}\n loadingLabel={t('consent.deny')}\n onClick={handleDeny}\n type=\"button\"\n uiSize=\"lg\"\n >\n <XIcon aria-hidden className=\"size-tinyrack-lg\" />\n {t('consent.deny')}\n </TRButton>\n <TRButton\n className=\"flex-1\"\n data-testid=\"consent-allow\"\n intent=\"primary\"\n loading={consentMutation.isPending}\n loadingLabel={t('consent.allow')}\n onClick={handleAllow}\n type=\"button\"\n uiSize=\"lg\"\n >\n <ShieldCheckIcon aria-hidden className=\"size-tinyrack-lg\" />\n {t('consent.allow')}\n </TRButton>\n </div>\n </AuthLayout>\n );\n}\n"],"mappings":"4GAgDA,SAASE,EAAaC,EAA4B,CAChD,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,GAAIA,EACJ,mBAAsB,CAIpB,IAAME,EAAS,IAAIC,gBAAgBC,OAAOC,SAASC,MAAM,EACnDA,EAASC,OAAOC,YAAYN,EAAOO,QAAQ,CAAC,EAClDL,OAAOC,SAASK,KAAOZ,EAAkBQ,CAAM,CACjD,CAAE,CAAA,CAGR"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{i as e,n as t,q as n,s as r}from"./createLucideIcon-BPpAIXR_.js";import{t as i}from"./useMutation-BWZ0G4Td.js";import{
|
|
2
|
-
//# sourceMappingURL=consent-
|
|
1
|
+
import{i as e,n as t,q as n,s as r}from"./createLucideIcon-BPpAIXR_.js";import{t as i}from"./useMutation-BWZ0G4Td.js";import{P as a,nt as o}from"./shell-header-bar-BPgCjFPv.js";import{t as s}from"./shield-check-D_p8H0ni.js";import{B as c,_ as l,v as u,y as d}from"./index-H6CJKjiN.js";import{t as f}from"./auth-page-header-ZLhtQ7Et.js";import{t as p}from"./initial-avatar-DjSqgENY.js";import{t as m}from"./auth-layout-CcJy6dVY.js";var h=n();function g(){let{t:n}=e(),g=l.useSearch(),_=o(d({client_id:g.client_id,scope:g.scope})),v=i({...u,onSuccess:e=>{window.location.href=e.redirect_url}}),y=()=>{v.mutate({client_id:g.client_id,redirect_uri:g.redirect_uri,response_type:g.response_type,scope:g.scope,state:g.state,nonce:g.nonce,code_challenge:g.code_challenge,code_challenge_method:g.code_challenge_method,prompt:g.prompt,max_age:g.max_age,reauthenticated:g.reauthenticated,display:g.display,response_mode:g.response_mode,login_hint:g.login_hint,ui_locales:g.ui_locales,id_token_hint:g.id_token_hint,acr_values:g.acr_values,account_selected:g.account_selected,account_selection_state:g.account_selection_state,decision:`allow`})},b=()=>{v.mutate({client_id:g.client_id,redirect_uri:g.redirect_uri,response_type:g.response_type,scope:g.scope,state:g.state,nonce:g.nonce,code_challenge:g.code_challenge,code_challenge_method:g.code_challenge_method,prompt:g.prompt,max_age:g.max_age,reauthenticated:g.reauthenticated,display:g.display,response_mode:g.response_mode,login_hint:g.login_hint,ui_locales:g.ui_locales,id_token_hint:g.id_token_hint,acr_values:g.acr_values,account_selected:g.account_selected,account_selection_state:g.account_selection_state,decision:`deny`})},{client:x,scopes:S,user:C}=_.data;return(0,h.jsxs)(m,{width:`wide`,children:[(0,h.jsx)(f,{subtitle:n(`consent.subtitle`,{app:x.name}),title:n(`consent.title`)}),(0,h.jsx)(c.Root,{padding:`lg`,variant:`outlined`,children:(0,h.jsxs)(c.Content,{className:`flex items-center gap-tinyrack-md`,children:[(0,h.jsx)(p,{email:C.email,size:`sm`}),(0,h.jsxs)(`span`,{className:`flex min-w-0 flex-col`,children:[(0,h.jsx)(t,{color:`muted`,variant:`caption`,children:n(`consent.loggedInAs`)}),(0,h.jsx)(t,{"data-testid":`consent-user-email`,truncate:!0,variant:`body`,weight:`medium`,children:C.email})]})]})}),(0,h.jsxs)(`div`,{className:`flex flex-col gap-tinyrack-sm`,children:[(0,h.jsx)(t,{as:`h3`,variant:`label`,children:n(`consent.permissions.title`)}),(0,h.jsx)(`ul`,{className:`flex flex-col gap-tinyrack-xs`,"data-testid":`consent-scope-list`,children:S.map(e=>(0,h.jsxs)(`li`,{className:`flex items-center gap-tinyrack-sm rounded-tinyrack-md bg-tinyrack-surface-muted px-tinyrack-md py-tinyrack-sm`,children:[(0,h.jsx)(s,{"aria-hidden":!0,className:`size-tinyrack-lg shrink-0 text-tinyrack-info-foreground`}),(0,h.jsx)(t,{variant:`body`,children:n(`consent.scope.${e.name}`,{defaultValue:e.description})})]},e.name))})]}),(0,h.jsxs)(`div`,{className:`sticky bottom-0 flex gap-tinyrack-sm border-tinyrack-border border-t-tinyrack-default bg-tinyrack-surface/80 py-tinyrack-md backdrop-blur-sm`,children:[(0,h.jsxs)(r,{appearance:`outline`,className:`flex-1`,"data-testid":`consent-deny`,intent:`neutral`,loading:v.isPending,loadingLabel:n(`consent.deny`),onClick:b,type:`button`,uiSize:`lg`,children:[(0,h.jsx)(a,{"aria-hidden":!0,className:`size-tinyrack-lg`}),n(`consent.deny`)]}),(0,h.jsxs)(r,{className:`flex-1`,"data-testid":`consent-allow`,intent:`primary`,loading:v.isPending,loadingLabel:n(`consent.allow`),onClick:y,type:`button`,uiSize:`lg`,children:[(0,h.jsx)(s,{"aria-hidden":!0,className:`size-tinyrack-lg`}),n(`consent.allow`)]})]})]})}export{g as component};
|
|
2
|
+
//# sourceMappingURL=consent-D_yGE8TR.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consent-BqqFDdsr.js","names":["useMutation","useSuspenseQuery","TRButton","TRCard","TRText","ShieldCheckIcon","XIcon","useTranslation","AuthPageHeader","InitialAvatar","AuthLayout","consentDecisionMutationOptions","getConsentInfoQueryOptions","Route","Consent","t","search","useSearch","consentInfoQuery","client_id","scope","consentMutation","onSuccess","data","window","location","href","redirect_url","handleAllow","mutate","redirect_uri","response_type","state","nonce","code_challenge","code_challenge_method","prompt","max_age","reauthenticated","display","response_mode","login_hint","ui_locales","id_token_hint","acr_values","account_selected","account_selection_state","decision","handleDeny","client","scopes","user","app","name","email","map","description","defaultValue","isPending","component"],"sources":["../../../frontend/src/routes/consent/index.tsx?tsr-split=component"],"sourcesContent":["import { useMutation, useSuspenseQuery } from '@tanstack/react-query';\nimport {\n createFileRoute,\n type ErrorComponentProps,\n} from '@tanstack/react-router';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { TRCard } from '@tinyrack/ui/components/card';\nimport { TRText } from '@tinyrack/ui/components/text';\nimport { ShieldCheckIcon, XIcon } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { z } from 'zod';\nimport { AuthPageHeader } from '#frontend/components/auth/auth-page-header.tsx';\nimport { InitialAvatar } from '#frontend/components/ui/initial-avatar.tsx';\nimport { RouteErrorFallback } from '#frontend/components/ui/route-error-fallback.tsx';\nimport { AuthLayout } from '#frontend/features/layout/auth-layout.tsx';\nimport {\n buildAuthorizeUrl,\n OAuthSearchSchema,\n} from '#frontend/libs/oauth-search.ts';\nimport {\n consentDecisionMutationOptions,\n getConsentInfoQueryOptions,\n} from '#frontend/queries/consent.ts';\n\nconst ConsentSearchSchema = OAuthSearchSchema.extend({\n client_id: z.string(),\n redirect_uri: z.string(),\n response_type: z.string(),\n});\n\nexport const Route = createFileRoute('/consent/')({\n component: Consent,\n errorComponent: ConsentError,\n validateSearch: ConsentSearchSchema,\n loaderDeps: ({ search }) => ({\n client_id: search.client_id,\n scope: search.scope,\n }),\n loader: async ({ context, deps }) => {\n await context.queryClient.ensureQueryData(\n getConsentInfoQueryOptions({\n client_id: deps.client_id,\n scope: deps.scope,\n }),\n );\n },\n});\n\nfunction ConsentError(props: ErrorComponentProps) {\n return (\n <RouteErrorFallback\n {...props}\n onUnauthorized={() => {\n // Re-enter the OAuth flow from the beginning so the\n // user can log in and be redirected back through\n // /oauth/authorize -> /consent/.\n const params = new URLSearchParams(window.location.search);\n const search = Object.fromEntries(params.entries());\n window.location.href = buildAuthorizeUrl(search);\n }}\n />\n );\n}\n\nfunction Consent() {\n const { t } = useTranslation();\n const search = Route.useSearch();\n\n const consentInfoQuery = useSuspenseQuery(\n getConsentInfoQueryOptions({\n client_id: search.client_id,\n scope: search.scope,\n }),\n );\n\n const consentMutation = useMutation({\n ...consentDecisionMutationOptions,\n onSuccess: (data) => {\n window.location.href = data.redirect_url;\n },\n });\n\n const handleAllow = () => {\n consentMutation.mutate({\n client_id: search.client_id,\n redirect_uri: search.redirect_uri,\n response_type: search.response_type,\n scope: search.scope,\n state: search.state,\n nonce: search.nonce,\n code_challenge: search.code_challenge,\n code_challenge_method: search.code_challenge_method,\n prompt: search.prompt,\n max_age: search.max_age,\n reauthenticated: search.reauthenticated,\n display: search.display,\n response_mode: search.response_mode,\n login_hint: search.login_hint,\n ui_locales: search.ui_locales,\n id_token_hint: search.id_token_hint,\n acr_values: search.acr_values,\n account_selected: search.account_selected,\n account_selection_state: search.account_selection_state,\n decision: 'allow',\n });\n };\n\n const handleDeny = () => {\n consentMutation.mutate({\n client_id: search.client_id,\n redirect_uri: search.redirect_uri,\n response_type: search.response_type,\n scope: search.scope,\n state: search.state,\n nonce: search.nonce,\n code_challenge: search.code_challenge,\n code_challenge_method: search.code_challenge_method,\n prompt: search.prompt,\n max_age: search.max_age,\n reauthenticated: search.reauthenticated,\n display: search.display,\n response_mode: search.response_mode,\n login_hint: search.login_hint,\n ui_locales: search.ui_locales,\n id_token_hint: search.id_token_hint,\n acr_values: search.acr_values,\n account_selected: search.account_selected,\n account_selection_state: search.account_selection_state,\n decision: 'deny',\n });\n };\n\n const { client, scopes, user } = consentInfoQuery.data;\n\n return (\n <AuthLayout width=\"wide\">\n <AuthPageHeader\n subtitle={t('consent.subtitle', { app: client.name })}\n title={t('consent.title')}\n />\n\n {/*\n Who is about to hand out access. The decision is meaningless without\n it, so it sits above the scopes rather than in fine print.\n */}\n <TRCard.Root padding=\"lg\" variant=\"outlined\">\n <TRCard.Content className=\"flex items-center gap-tinyrack-md\">\n <InitialAvatar email={user.email} size=\"sm\" />\n <span className=\"flex min-w-0 flex-col\">\n <TRText color=\"muted\" variant=\"caption\">\n {t('consent.loggedInAs')}\n </TRText>\n <TRText\n data-testid=\"consent-user-email\"\n truncate\n variant=\"body\"\n weight=\"medium\"\n >\n {user.email}\n </TRText>\n </span>\n </TRCard.Content>\n </TRCard.Root>\n\n {/* Requested permissions */}\n <div className=\"flex flex-col gap-tinyrack-sm\">\n <TRText as=\"h3\" variant=\"label\">\n {t('consent.permissions.title')}\n </TRText>\n <ul\n className=\"flex flex-col gap-tinyrack-xs\"\n data-testid=\"consent-scope-list\"\n >\n {scopes.map((scope: { name: string; description: string }) => (\n <li\n className=\"flex items-center gap-tinyrack-sm rounded-tinyrack-md bg-tinyrack-surface-muted px-tinyrack-md py-tinyrack-sm\"\n key={scope.name}\n >\n <ShieldCheckIcon\n aria-hidden\n className=\"size-tinyrack-lg shrink-0 text-tinyrack-info\"\n />\n <TRText variant=\"body\">\n {t(`consent.scope.${scope.name}`, {\n defaultValue: scope.description,\n })}\n </TRText>\n </li>\n ))}\n </ul>\n </div>\n\n {/*\n Sticky so the decision stays reachable when a client asks for a long\n list of scopes and the page scrolls.\n */}\n <div className=\"sticky bottom-0 flex gap-tinyrack-sm border-tinyrack-border border-t-tinyrack-default bg-tinyrack-surface/80 py-tinyrack-md backdrop-blur-sm\">\n <TRButton\n appearance=\"outline\"\n className=\"flex-1\"\n data-testid=\"consent-deny\"\n intent=\"neutral\"\n loading={consentMutation.isPending}\n loadingLabel={t('consent.deny')}\n onClick={handleDeny}\n type=\"button\"\n uiSize=\"lg\"\n >\n <XIcon aria-hidden className=\"size-tinyrack-lg\" />\n {t('consent.deny')}\n </TRButton>\n <TRButton\n className=\"flex-1\"\n data-testid=\"consent-allow\"\n intent=\"primary\"\n loading={consentMutation.isPending}\n loadingLabel={t('consent.allow')}\n onClick={handleAllow}\n type=\"button\"\n uiSize=\"lg\"\n >\n <ShieldCheckIcon aria-hidden className=\"size-tinyrack-lg\" />\n {t('consent.allow')}\n </TRButton>\n </div>\n </AuthLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"consent-D_yGE8TR.js","names":["useMutation","useSuspenseQuery","TRButton","TRCard","TRText","ShieldCheckIcon","XIcon","useTranslation","AuthPageHeader","InitialAvatar","AuthLayout","consentDecisionMutationOptions","getConsentInfoQueryOptions","Route","Consent","t","search","useSearch","consentInfoQuery","client_id","scope","consentMutation","onSuccess","data","window","location","href","redirect_url","handleAllow","mutate","redirect_uri","response_type","state","nonce","code_challenge","code_challenge_method","prompt","max_age","reauthenticated","display","response_mode","login_hint","ui_locales","id_token_hint","acr_values","account_selected","account_selection_state","decision","handleDeny","client","scopes","user","app","name","email","map","description","defaultValue","isPending","component"],"sources":["../../../frontend/src/routes/consent/index.tsx?tsr-split=component"],"sourcesContent":["import { useMutation, useSuspenseQuery } from '@tanstack/react-query';\nimport {\n createFileRoute,\n type ErrorComponentProps,\n} from '@tanstack/react-router';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { TRCard } from '@tinyrack/ui/components/card';\nimport { TRText } from '@tinyrack/ui/components/text';\nimport { ShieldCheckIcon, XIcon } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { z } from 'zod';\nimport { AuthPageHeader } from '#frontend/components/auth/auth-page-header.tsx';\nimport { InitialAvatar } from '#frontend/components/ui/initial-avatar.tsx';\nimport { RouteErrorFallback } from '#frontend/components/ui/route-error-fallback.tsx';\nimport { AuthLayout } from '#frontend/features/layout/auth-layout.tsx';\nimport {\n buildAuthorizeUrl,\n OAuthSearchSchema,\n} from '#frontend/libs/oauth-search.ts';\nimport {\n consentDecisionMutationOptions,\n getConsentInfoQueryOptions,\n} from '#frontend/queries/consent.ts';\n\nconst ConsentSearchSchema = OAuthSearchSchema.extend({\n client_id: z.string(),\n redirect_uri: z.string(),\n response_type: z.string(),\n});\n\nexport const Route = createFileRoute('/consent/')({\n component: Consent,\n errorComponent: ConsentError,\n validateSearch: ConsentSearchSchema,\n loaderDeps: ({ search }) => ({\n client_id: search.client_id,\n scope: search.scope,\n }),\n loader: async ({ context, deps }) => {\n await context.queryClient.ensureQueryData(\n getConsentInfoQueryOptions({\n client_id: deps.client_id,\n scope: deps.scope,\n }),\n );\n },\n});\n\nfunction ConsentError(props: ErrorComponentProps) {\n return (\n <RouteErrorFallback\n {...props}\n onUnauthorized={() => {\n // Re-enter the OAuth flow from the beginning so the\n // user can log in and be redirected back through\n // /oauth/authorize -> /consent/.\n const params = new URLSearchParams(window.location.search);\n const search = Object.fromEntries(params.entries());\n window.location.href = buildAuthorizeUrl(search);\n }}\n />\n );\n}\n\nfunction Consent() {\n const { t } = useTranslation();\n const search = Route.useSearch();\n\n const consentInfoQuery = useSuspenseQuery(\n getConsentInfoQueryOptions({\n client_id: search.client_id,\n scope: search.scope,\n }),\n );\n\n const consentMutation = useMutation({\n ...consentDecisionMutationOptions,\n onSuccess: (data) => {\n window.location.href = data.redirect_url;\n },\n });\n\n const handleAllow = () => {\n consentMutation.mutate({\n client_id: search.client_id,\n redirect_uri: search.redirect_uri,\n response_type: search.response_type,\n scope: search.scope,\n state: search.state,\n nonce: search.nonce,\n code_challenge: search.code_challenge,\n code_challenge_method: search.code_challenge_method,\n prompt: search.prompt,\n max_age: search.max_age,\n reauthenticated: search.reauthenticated,\n display: search.display,\n response_mode: search.response_mode,\n login_hint: search.login_hint,\n ui_locales: search.ui_locales,\n id_token_hint: search.id_token_hint,\n acr_values: search.acr_values,\n account_selected: search.account_selected,\n account_selection_state: search.account_selection_state,\n decision: 'allow',\n });\n };\n\n const handleDeny = () => {\n consentMutation.mutate({\n client_id: search.client_id,\n redirect_uri: search.redirect_uri,\n response_type: search.response_type,\n scope: search.scope,\n state: search.state,\n nonce: search.nonce,\n code_challenge: search.code_challenge,\n code_challenge_method: search.code_challenge_method,\n prompt: search.prompt,\n max_age: search.max_age,\n reauthenticated: search.reauthenticated,\n display: search.display,\n response_mode: search.response_mode,\n login_hint: search.login_hint,\n ui_locales: search.ui_locales,\n id_token_hint: search.id_token_hint,\n acr_values: search.acr_values,\n account_selected: search.account_selected,\n account_selection_state: search.account_selection_state,\n decision: 'deny',\n });\n };\n\n const { client, scopes, user } = consentInfoQuery.data;\n\n return (\n <AuthLayout width=\"wide\">\n <AuthPageHeader\n subtitle={t('consent.subtitle', { app: client.name })}\n title={t('consent.title')}\n />\n\n {/*\n Who is about to hand out access. The decision is meaningless without\n it, so it sits above the scopes rather than in fine print.\n */}\n <TRCard.Root padding=\"lg\" variant=\"outlined\">\n <TRCard.Content className=\"flex items-center gap-tinyrack-md\">\n <InitialAvatar email={user.email} size=\"sm\" />\n <span className=\"flex min-w-0 flex-col\">\n <TRText color=\"muted\" variant=\"caption\">\n {t('consent.loggedInAs')}\n </TRText>\n <TRText\n data-testid=\"consent-user-email\"\n truncate\n variant=\"body\"\n weight=\"medium\"\n >\n {user.email}\n </TRText>\n </span>\n </TRCard.Content>\n </TRCard.Root>\n\n {/* Requested permissions */}\n <div className=\"flex flex-col gap-tinyrack-sm\">\n <TRText as=\"h3\" variant=\"label\">\n {t('consent.permissions.title')}\n </TRText>\n <ul\n className=\"flex flex-col gap-tinyrack-xs\"\n data-testid=\"consent-scope-list\"\n >\n {scopes.map((scope: { name: string; description: string }) => (\n <li\n className=\"flex items-center gap-tinyrack-sm rounded-tinyrack-md bg-tinyrack-surface-muted px-tinyrack-md py-tinyrack-sm\"\n key={scope.name}\n >\n <ShieldCheckIcon\n aria-hidden\n className=\"size-tinyrack-lg shrink-0 text-tinyrack-info-foreground\"\n />\n <TRText variant=\"body\">\n {t(`consent.scope.${scope.name}`, {\n defaultValue: scope.description,\n })}\n </TRText>\n </li>\n ))}\n </ul>\n </div>\n\n {/*\n Sticky so the decision stays reachable when a client asks for a long\n list of scopes and the page scrolls.\n */}\n <div className=\"sticky bottom-0 flex gap-tinyrack-sm border-tinyrack-border border-t-tinyrack-default bg-tinyrack-surface/80 py-tinyrack-md backdrop-blur-sm\">\n <TRButton\n appearance=\"outline\"\n className=\"flex-1\"\n data-testid=\"consent-deny\"\n intent=\"neutral\"\n loading={consentMutation.isPending}\n loadingLabel={t('consent.deny')}\n onClick={handleDeny}\n type=\"button\"\n uiSize=\"lg\"\n >\n <XIcon aria-hidden className=\"size-tinyrack-lg\" />\n {t('consent.deny')}\n </TRButton>\n <TRButton\n className=\"flex-1\"\n data-testid=\"consent-allow\"\n intent=\"primary\"\n loading={consentMutation.isPending}\n loadingLabel={t('consent.allow')}\n onClick={handleAllow}\n type=\"button\"\n uiSize=\"lg\"\n >\n <ShieldCheckIcon aria-hidden className=\"size-tinyrack-lg\" />\n {t('consent.allow')}\n </TRButton>\n </div>\n </AuthLayout>\n );\n}\n"],"mappings":"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"}
|