@owlmeans/web-oauth 0.1.18-rc.1
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/README.md +15 -0
- package/agent-meta/manifest.json +16 -0
- package/agent-meta/skills/web-oauth/SKILL.md +131 -0
- package/build/@/components/ui/button.d.ts +11 -0
- package/build/@/components/ui/button.d.ts.map +1 -0
- package/build/@/components/ui/button.js +32 -0
- package/build/@/components/ui/button.js.map +1 -0
- package/build/@/components/ui/card.d.ts +10 -0
- package/build/@/components/ui/card.d.ts.map +1 -0
- package/build/@/components/ui/card.js +25 -0
- package/build/@/components/ui/card.js.map +1 -0
- package/build/@/components/ui/input.d.ts +4 -0
- package/build/@/components/ui/input.d.ts.map +1 -0
- package/build/@/components/ui/input.js +7 -0
- package/build/@/components/ui/input.js.map +1 -0
- package/build/@/components/ui/label.d.ts +5 -0
- package/build/@/components/ui/label.d.ts.map +1 -0
- package/build/@/components/ui/label.js +8 -0
- package/build/@/components/ui/label.js.map +1 -0
- package/build/@/lib/utils.d.ts +3 -0
- package/build/@/lib/utils.d.ts.map +1 -0
- package/build/@/lib/utils.js +6 -0
- package/build/@/lib/utils.js.map +1 -0
- package/build/append.d.ts +14 -0
- package/build/append.d.ts.map +1 -0
- package/build/append.js +19 -0
- package/build/append.js.map +1 -0
- package/build/components/consent-screen.d.ts +12 -0
- package/build/components/consent-screen.d.ts.map +1 -0
- package/build/components/consent-screen.js +30 -0
- package/build/components/consent-screen.js.map +1 -0
- package/build/components/device-screen.d.ts +10 -0
- package/build/components/device-screen.d.ts.map +1 -0
- package/build/components/device-screen.js +48 -0
- package/build/components/device-screen.js.map +1 -0
- package/build/components/done-screen.d.ts +8 -0
- package/build/components/done-screen.d.ts.map +1 -0
- package/build/components/done-screen.js +18 -0
- package/build/components/done-screen.js.map +1 -0
- package/build/components/index.d.ts +4 -0
- package/build/components/index.d.ts.map +1 -0
- package/build/components/index.js +4 -0
- package/build/components/index.js.map +1 -0
- package/build/consts.d.ts +6 -0
- package/build/consts.d.ts.map +1 -0
- package/build/consts.js +6 -0
- package/build/consts.js.map +1 -0
- package/build/entrypoints.d.ts +8 -0
- package/build/entrypoints.d.ts.map +1 -0
- package/build/entrypoints.js +20 -0
- package/build/entrypoints.js.map +1 -0
- package/build/hooks/use-oauth-consent.d.ts +27 -0
- package/build/hooks/use-oauth-consent.d.ts.map +1 -0
- package/build/hooks/use-oauth-consent.js +128 -0
- package/build/hooks/use-oauth-consent.js.map +1 -0
- package/build/i18n/be.json +35 -0
- package/build/i18n/de.json +35 -0
- package/build/i18n/en.json +35 -0
- package/build/i18n/es.json +35 -0
- package/build/i18n/pl.json +35 -0
- package/build/i18n/ru.json +35 -0
- package/build/i18n/uk.json +35 -0
- package/build/i18n.d.ts +2 -0
- package/build/i18n.d.ts.map +1 -0
- package/build/i18n.js +17 -0
- package/build/i18n.js.map +1 -0
- package/build/index.d.ts +7 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +7 -0
- package/build/index.js.map +1 -0
- package/components.json +21 -0
- package/package.json +77 -0
- package/src/@/components/ui/button.tsx +60 -0
- package/src/@/components/ui/card.tsx +93 -0
- package/src/@/components/ui/input.tsx +22 -0
- package/src/@/components/ui/label.tsx +23 -0
- package/src/@/globals.css +57 -0
- package/src/@/lib/utils.ts +6 -0
- package/src/append.ts +24 -0
- package/src/components/consent-screen.tsx +95 -0
- package/src/components/device-screen.tsx +81 -0
- package/src/components/done-screen.tsx +30 -0
- package/src/components/index.ts +3 -0
- package/src/consts.ts +6 -0
- package/src/entrypoints.ts +22 -0
- package/src/hooks/use-oauth-consent.ts +163 -0
- package/src/i18n/be.json +35 -0
- package/src/i18n/de.json +35 -0
- package/src/i18n/en.json +35 -0
- package/src/i18n/es.json +35 -0
- package/src/i18n/pl.json +35 -0
- package/src/i18n/ru.json +35 -0
- package/src/i18n/uk.json +35 -0
- package/src/i18n.ts +18 -0
- package/src/index.ts +6 -0
- package/tests/consent.spec.ts +260 -0
- package/tests/context.ts +48 -0
- package/tests/device.spec.ts +64 -0
- package/tests/done.spec.ts +41 -0
- package/tests/harness/css.d.ts +1 -0
- package/tests/harness/frame.html +15 -0
- package/tests/harness/index.html +11 -0
- package/tests/harness/mount.tsx +89 -0
- package/tests/helpers.ts +97 -0
- package/tests/i18n.spec.ts +41 -0
- package/tests/languages.spec.ts +38 -0
- package/tests/package-boundary.spec.ts +19 -0
- package/tests/tsconfig.json +12 -0
- package/tsconfig.json +14 -0
package/README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!-- owlmeans:agent-guidance:start -->
|
|
2
|
+
## Agent guidance
|
|
3
|
+
|
|
4
|
+
This package ships embedded agent skills under `agent-meta/`. After installing your
|
|
5
|
+
`@owlmeans/*` packages, run the OwlMeans agent-skills installer to place them into
|
|
6
|
+
your project's skill store (`.agents/skills/`):
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.28
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The embedded files are version-matched to this package release. Do not edit them
|
|
13
|
+
directly — they are regenerated on each publish. To contribute guidance edits,
|
|
14
|
+
open a PR against the source monorepo.
|
|
15
|
+
<!-- owlmeans:agent-guidance:end -->
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 2,
|
|
3
|
+
"package": "@owlmeans/web-oauth",
|
|
4
|
+
"version": "0.1.18-rc.1",
|
|
5
|
+
"generatedAt": "2026-09-18T18:24:55.976Z",
|
|
6
|
+
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
|
+
"entries": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "skill",
|
|
10
|
+
"name": "web-oauth",
|
|
11
|
+
"category": "package-specific",
|
|
12
|
+
"file": "skills/web-oauth/SKILL.md",
|
|
13
|
+
"canonicalPath": ".agents/skills/web-oauth/SKILL.md"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: web-oauth
|
|
3
|
+
description: How to use @owlmeans/web-oauth — the browser half of OAuth sign-in: the consent, device-code and done screens, oauthEntrypoints, appendOAuthScreens, the useOAuthConsent hook, the suspend-then-dispatcher sign-in leg, the mandatory Tailwind @source line, the i18n resource and the data-testid contract. Auto-invoked when binding the OAuth screens in a web app, changing what the consent screen shows, diagnosing a person who is not returned to consent after signing in, or writing a test against these screens.
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
7
|
+
|
|
8
|
+
# @owlmeans/web-oauth
|
|
9
|
+
|
|
10
|
+
**Layer:** Web (React, shadcn + Tailwind v4)
|
|
11
|
+
**Install:** `"@owlmeans/web-oauth": "^0.1.18-rc.1"` in `dependencies`
|
|
12
|
+
**Contracts:** `@owlmeans/oauth` — aliases, `makeOAuthProtocols`, `oauthFlow`, `ConsentView`
|
|
13
|
+
**Server half:** `@owlmeans/server-oauth` (its `consentUrl`/`deviceUrl` must point at these screens)
|
|
14
|
+
|
|
15
|
+
## Key Exports
|
|
16
|
+
|
|
17
|
+
| Export | Description |
|
|
18
|
+
|--------|-------------|
|
|
19
|
+
| `oauthEntrypoints(opts?)` | `[bindScreen(consentScreen), bindScreen(deviceScreen), bindScreen(doneScreen)]` — spread into the app's entrypoint list. `opts` is `OAuthEntrypointOptions` (`parent?`, `path?`, `guard?`) |
|
|
20
|
+
| `appendOAuthScreens(ctx)` | Precondition check only: throws unless a `FLOW_STATE` resource is registered (call `appendFlowService` first). Returns the context |
|
|
21
|
+
| `OAuthConsentScreen` · `OAuthDeviceScreen` · `OAuthDoneScreen` | The screens (`RoutedComponent`s) |
|
|
22
|
+
| `useOAuthConsent(ref, aliases?)` | The headless logic: `{ stage, view, error, errorKind, approve, deny, switchAccount }` with `stage` in `checking | signing-in | loading | ready | deciding | done | error`; `errorKind` in `missing | not-found | expired | forbidden | failed` (`error` is the raw wire text, for a log — never rendered) |
|
|
23
|
+
| `OAUTH_I18N` (`'oauth'`) · `OAUTH_SUSPEND_TTL_MS` (10 min) | The library-tier i18n resource; how long a suspended sign-in stays valid |
|
|
24
|
+
|
|
25
|
+
The **consent API** (`load`/`approve`/`deny`) is bound by the *server* app, not here — the app binds
|
|
26
|
+
`loadConsent`/`approveConsent`/`denyConsent` from `@owlmeans/server-oauth` in its API context and
|
|
27
|
+
registers the same protocols in the web context's `bindAll` so `context.entrypoint(protocols.load)`
|
|
28
|
+
resolves. The three screens are `sticky`, parentless frontend routes (`/oauth/consent`,
|
|
29
|
+
`/oauth/device`, `/oauth/done`).
|
|
30
|
+
|
|
31
|
+
## Wiring
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import { appendOAuthScreens, oauthEntrypoints } from '@owlmeans/web-oauth'
|
|
35
|
+
|
|
36
|
+
appendFlowService(context) // registers FLOW_STATE
|
|
37
|
+
appendOAuthScreens(context)
|
|
38
|
+
// entrypoints: ...oauthEntrypoints({ parent: account.base }) — the SAME opts the server passed
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
An app that builds its entrypoints from shared `managerProtocols` binds the three screens with
|
|
42
|
+
`bindScreen(protocols.consentScreen, handler(OAuthConsentScreen))` etc. — the components are
|
|
43
|
+
exported for exactly that. Translations register as a side effect of importing the package.
|
|
44
|
+
|
|
45
|
+
## The `@source` line — a consumer rule
|
|
46
|
+
|
|
47
|
+
Tailwind's scanner reads the CSS root plus `@source` directives and excludes `node_modules`, so a
|
|
48
|
+
class used only inside this package never reaches the app's stylesheet and the screens render
|
|
49
|
+
unstyled with nothing in the app's own sources to blame. Every consuming app adds:
|
|
50
|
+
|
|
51
|
+
```css
|
|
52
|
+
@source "../../../node_modules/@owlmeans/web-oauth/src";
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Point at the shipped `src`, not `build`. Primitives (`button`, `card`, `input`, `label`) are private
|
|
56
|
+
under `src/@/` and imported only by relative specifiers — the consuming app's `@` alias is never part
|
|
57
|
+
of this package's runtime, and `tests/package-boundary.spec.ts` fails on any `from '@/…'`.
|
|
58
|
+
|
|
59
|
+
## The screens
|
|
60
|
+
|
|
61
|
+
- **Consent** — reads `?ref=` (a code grant's request id, or a device grant's user code; the server
|
|
62
|
+
resolves which). Nothing is shown until the app is known to be authenticated; signed in, it calls
|
|
63
|
+
`load`, shows the client's name and how it is known, the device name and `XXXX-XXXX` code, the
|
|
64
|
+
redirect host (code grant), a localhost warning, and the scopes; **Approve** / **Deny**. Approve
|
|
65
|
+
on a code grant does `window.location.href = redirect`; on a device grant it transits the flow to
|
|
66
|
+
**Done** with `kind`/`ref` in the query. **It refuses to render when framed**
|
|
67
|
+
(`window.top !== window.self`) — the approval click is exactly what a clickjacking overlay steals.
|
|
68
|
+
**Use another account** (`oauth-consent-switch`) signs the session out (`auth.update(undefined)`) and
|
|
69
|
+
goes through the same suspension, returning to this `ref`. Every failure is ONE translated sentence
|
|
70
|
+
in `oauth-consent-error`, chosen by `errorKind` (`error-missing`, `error-not-found`, `error-expired`,
|
|
71
|
+
`error-forbidden`, else the generic `error`) — the wire marker and stack are never shown. The kind is
|
|
72
|
+
read from the marker in the message (`request-expired`, `request-not-found`, `forbidden`).
|
|
73
|
+
- **Device** — RFC 8628's `verification_uri`. Opened bare it shows an input for the code; opened
|
|
74
|
+
with `?user_code=…` (`verification_uri_complete`) it goes straight on. Either way it runs the same
|
|
75
|
+
`verify` → `next` → `consent` transition, so the two entries converge before anything else runs.
|
|
76
|
+
- **Done** — "you may close this window". The device variant says the connector will catch up on
|
|
77
|
+
its own (`?kind=device`). Nothing to click; the MCP/CLI is polling.
|
|
78
|
+
|
|
79
|
+
## Signed out: suspend, dispatcher, come back
|
|
80
|
+
|
|
81
|
+
The consent screen never assumes a session. When `auth.authenticated()` is empty it builds
|
|
82
|
+
`makeFlowModel(oauthFlow)` (never the live flow slot), sets `ref`, transits the explicit `sign-in`
|
|
83
|
+
step, calls `suspendFlow(context, model, { expiresAt: now + OAUTH_SUSPEND_TTL_MS })` and sends the
|
|
84
|
+
browser to `DISPATCHER`. The chooser / Google / supervisor sign-in then lands through
|
|
85
|
+
`resumeSuspendedFlow` (the landing rule in `/login-plugins`, `/client-flow`) — back on the consent
|
|
86
|
+
screen with the **same `ref`**, now authenticated. What is stored is the destination entrypoint alias
|
|
87
|
+
plus the payload query, delete-on-read and expiry-checked, in `FLOW_STATE` (IndexedDB, so it survives
|
|
88
|
+
Google's full-page round trip). A plugin that still navigates to `HOME` instead of the landing breaks
|
|
89
|
+
this leg silently.
|
|
90
|
+
|
|
91
|
+
## `data-testid` contract
|
|
92
|
+
|
|
93
|
+
`oauth-consent-card`, `oauth-consent-client`, `oauth-consent-code`, `oauth-consent-approve`,
|
|
94
|
+
`oauth-consent-deny`, `oauth-consent-switch`, `oauth-consent-error`, `oauth-device-card`, `oauth-device-input`,
|
|
95
|
+
`oauth-device-submit`, `oauth-done-card`. Do not rename them — the end-to-end suites that drive
|
|
96
|
+
sign-in address these.
|
|
97
|
+
|
|
98
|
+
## i18n
|
|
99
|
+
|
|
100
|
+
Library-tier resource `oauth`, all seven languages (`en pl ru be uk es de`) under `src/i18n/`;
|
|
101
|
+
sections `consent`, `device`, `done`. `tests/i18n.spec.ts` fails when a language lacks a key English
|
|
102
|
+
has — add a key to all seven. An app overrides a string at its own tier; it does not fork a screen.
|
|
103
|
+
|
|
104
|
+
## Testing
|
|
105
|
+
|
|
106
|
+
Category D (`/testing-ui`) — `bun test ./tests` drives a real chromium against a real app, with only
|
|
107
|
+
the server absent:
|
|
108
|
+
|
|
109
|
+
- **Harness** (`tests/context.ts` boots Vite; `tests/harness/mount.tsx` is the app). It is the real
|
|
110
|
+
`@owlmeans/web-client` context (auth service, IndexedDB resources, History-API router, the real
|
|
111
|
+
dispatcher), the real flow service, `oauthEntrypoints()`, and the consent API bound with `bindAll`
|
|
112
|
+
under a backend parent declared on the harness's own origin. The context stays un-initialized so the
|
|
113
|
+
router compiles its routes.
|
|
114
|
+
- **Server stubs** are `page.route` answers on that origin (`tests/helpers.ts` `open(path, { stubs })`):
|
|
115
|
+
`load`/`approve`/`deny` return a `ConsentView`, a `{ redirect }`, or a refusal in the wire shape
|
|
116
|
+
`type|||message|||stack`. Nothing needs CORS and no live server is reached. `authenticate: true`
|
|
117
|
+
also answers the dispatcher's token exchange.
|
|
118
|
+
- **A signed-in visit** is `?bearer=<makeBearer(USER)>`: the harness writes the record the auth
|
|
119
|
+
service reads back (`idb-keyval` `auth:user`) BEFORE the app renders — services are not initialized
|
|
120
|
+
yet, so `context.auth().update()` is not available at that point. `?lng=` picks the language.
|
|
121
|
+
`window.__oauth.suspended()` / `.token()` read the real flow store and auth service back.
|
|
122
|
+
- **What is covered:** signed-out suspension (record, expiry, dispatcher, no request made); the full
|
|
123
|
+
sign-in round trip back to the same `ref`; device and code grants (client, code, device, redirect
|
|
124
|
+
host, the localhost warning, approve/deny each way, `location` follows the redirect); every failure as
|
|
125
|
+
one sentence; the framed refusal (an iframe of `tests/harness/frame.html`, the framed app carrying its
|
|
126
|
+
own `bearer`); use-another-account; the device screen bare and linked; the done screen; and the
|
|
127
|
+
consent screen in all seven languages.
|
|
128
|
+
- Also `package-boundary.spec.ts` (no consumer aliases in source) and `i18n.spec.ts` (7-language parity).
|
|
129
|
+
|
|
130
|
+
A test of a refusal that the screen would otherwise hide still asserts what is ABSENT (no approve or
|
|
131
|
+
deny button, no wire text) — the point of those cases is that nothing can be approved.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
3
|
+
declare const buttonVariants: (props?: ({
|
|
4
|
+
variant?: "default" | "destructive" | "ghost" | "link" | "outline" | "secondary" | null | undefined;
|
|
5
|
+
size?: "default" | "icon" | "lg" | "sm" | null | undefined;
|
|
6
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
+
declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
|
|
8
|
+
asChild?: boolean;
|
|
9
|
+
}): React.JSX.Element;
|
|
10
|
+
export { Button, buttonVariants };
|
|
11
|
+
//# sourceMappingURL=button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../../src/@/components/ui/button.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAIjE,QAAA,MAAM,cAAc;;;8EA6BnB,CAAA;AAED,iBAAS,MAAM,CAAC,EACd,SAAS,EACT,OAAO,EACP,IAAI,EACJ,OAAe,EACf,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,GAC/B,YAAY,CAAC,OAAO,cAAc,CAAC,GAAG;IACpC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,qBAUF;AAED,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAA"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
3
|
+
import { cva } from 'class-variance-authority';
|
|
4
|
+
import { cn } from '../../lib/utils.js';
|
|
5
|
+
const buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive cursor-pointer", {
|
|
6
|
+
variants: {
|
|
7
|
+
variant: {
|
|
8
|
+
default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
|
|
9
|
+
destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
10
|
+
outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
|
11
|
+
secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
|
12
|
+
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
13
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
14
|
+
},
|
|
15
|
+
size: {
|
|
16
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
17
|
+
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
18
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
19
|
+
icon: "size-9",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
defaultVariants: {
|
|
23
|
+
variant: "default",
|
|
24
|
+
size: "default",
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
function Button({ className, variant, size, asChild = false, ...props }) {
|
|
28
|
+
const Comp = asChild ? Slot : "button";
|
|
29
|
+
return (_jsx(Comp, { "data-slot": "button", className: cn(buttonVariants({ variant, size, className })), ...props }));
|
|
30
|
+
}
|
|
31
|
+
export { Button, buttonVariants };
|
|
32
|
+
//# sourceMappingURL=button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button.js","sourceRoot":"","sources":["../../../../src/@/components/ui/button.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAC3C,OAAO,EAAE,GAAG,EAAqB,MAAM,0BAA0B,CAAA;AAEjE,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC,MAAM,cAAc,GAAG,GAAG,CACxB,4cAA4c,EAC5c;IACE,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,OAAO,EACL,kEAAkE;YACpE,WAAW,EACT,6JAA6J;YAC/J,OAAO,EACL,uIAAuI;YACzI,SAAS,EACP,wEAAwE;YAC1E,KAAK,EACH,sEAAsE;YACxE,IAAI,EAAE,iDAAiD;SACxD;QACD,IAAI,EAAE;YACJ,OAAO,EAAE,+BAA+B;YACxC,EAAE,EAAE,+CAA+C;YACnD,EAAE,EAAE,sCAAsC;YAC1C,IAAI,EAAE,QAAQ;SACf;KACF;IACD,eAAe,EAAE;QACf,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,SAAS;KAChB;CACF,CACF,CAAA;AAED,SAAS,MAAM,CAAC,EACd,SAAS,EACT,OAAO,EACP,IAAI,EACJ,OAAO,GAAG,KAAK,EACf,GAAG,KAAK,EAIP;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAA;IAEtC,OAAO,CACL,KAAC,IAAI,iBACO,QAAQ,EAClB,SAAS,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,KACvD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
declare function Card({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
3
|
+
declare function CardHeader({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
4
|
+
declare function CardTitle({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
5
|
+
declare function CardDescription({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
6
|
+
declare function CardAction({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
7
|
+
declare function CardContent({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
8
|
+
declare function CardFooter({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
9
|
+
export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent, };
|
|
10
|
+
//# sourceMappingURL=card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../../../src/@/components/ui/card.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,iBAAS,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWjE;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWvE;AAED,iBAAS,SAAS,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQtE;AAED,iBAAS,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQ5E;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWvE;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQxE;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQvE;AAED,OAAO,EACL,IAAI,EACJ,UAAU,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,WAAW,GACZ,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from '../../lib/utils.js';
|
|
3
|
+
function Card({ className, ...props }) {
|
|
4
|
+
return (_jsx("div", { "data-slot": "card", className: cn("bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm", className), ...props }));
|
|
5
|
+
}
|
|
6
|
+
function CardHeader({ className, ...props }) {
|
|
7
|
+
return (_jsx("div", { "data-slot": "card-header", className: cn("@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6", className), ...props }));
|
|
8
|
+
}
|
|
9
|
+
function CardTitle({ className, ...props }) {
|
|
10
|
+
return (_jsx("div", { "data-slot": "card-title", className: cn("leading-none font-semibold", className), ...props }));
|
|
11
|
+
}
|
|
12
|
+
function CardDescription({ className, ...props }) {
|
|
13
|
+
return (_jsx("div", { "data-slot": "card-description", className: cn("text-muted-foreground text-sm", className), ...props }));
|
|
14
|
+
}
|
|
15
|
+
function CardAction({ className, ...props }) {
|
|
16
|
+
return (_jsx("div", { "data-slot": "card-action", className: cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className), ...props }));
|
|
17
|
+
}
|
|
18
|
+
function CardContent({ className, ...props }) {
|
|
19
|
+
return (_jsx("div", { "data-slot": "card-content", className: cn("px-6", className), ...props }));
|
|
20
|
+
}
|
|
21
|
+
function CardFooter({ className, ...props }) {
|
|
22
|
+
return (_jsx("div", { "data-slot": "card-footer", className: cn("flex items-center px-6 [.border-t]:pt-6", className), ...props }));
|
|
23
|
+
}
|
|
24
|
+
export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent, };
|
|
25
|
+
//# sourceMappingURL=card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card.js","sourceRoot":"","sources":["../../../../src/@/components/ui/card.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC,SAAS,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IAChE,OAAO,CACL,2BACY,MAAM,EAChB,SAAS,EAAE,EAAE,CACX,mFAAmF,EACnF,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,4JAA4J,EAC5J,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,SAAS,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACrE,OAAO,CACL,2BACY,YAAY,EACtB,SAAS,EAAE,EAAE,CAAC,4BAA4B,EAAE,SAAS,CAAC,KAClD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IAC3E,OAAO,CACL,2BACY,kBAAkB,EAC5B,SAAS,EAAE,EAAE,CAAC,+BAA+B,EAAE,SAAS,CAAC,KACrD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,gEAAgE,EAChE,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACvE,OAAO,CACL,2BACY,cAAc,EACxB,SAAS,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,KAC5B,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CAAC,yCAAyC,EAAE,SAAS,CAAC,KAC/D,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EACL,IAAI,EACJ,UAAU,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,WAAW,GACZ,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../../src/@/components/ui/input.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,iBAAS,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,qBAc1E;AAED,OAAO,EAAE,KAAK,EAAE,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from '../../lib/utils.js';
|
|
3
|
+
function Input({ className, type, ...props }) {
|
|
4
|
+
return (_jsx("input", { type: type, "data-slot": "input", className: cn("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", className), ...props }));
|
|
5
|
+
}
|
|
6
|
+
export { Input };
|
|
7
|
+
//# sourceMappingURL=input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.js","sourceRoot":"","sources":["../../../../src/@/components/ui/input.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC,SAAS,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,KAAK,EAAiC;IACzE,OAAO,CACL,gBACE,IAAI,EAAE,IAAI,eACA,OAAO,EACjB,SAAS,EAAE,EAAE,CACX,icAAic,EACjc,+EAA+E,EAC/E,wGAAwG,EACxG,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"label.d.ts","sourceRoot":"","sources":["../../../../src/@/components/ui/label.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,cAAc,MAAM,uBAAuB,CAAA;AAIvD,iBAAS,KAAK,CAAC,EACb,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,IAAI,CAAC,qBAWlD;AAED,OAAO,EAAE,KAAK,EAAE,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as LabelPrimitive from '@radix-ui/react-label';
|
|
3
|
+
import { cn } from '../../lib/utils.js';
|
|
4
|
+
function Label({ className, ...props }) {
|
|
5
|
+
return (_jsx(LabelPrimitive.Root, { "data-slot": "label", className: cn("flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", className), ...props }));
|
|
6
|
+
}
|
|
7
|
+
export { Label };
|
|
8
|
+
//# sourceMappingURL=label.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"label.js","sourceRoot":"","sources":["../../../../src/@/components/ui/label.tsx"],"names":[],"mappings":";AAEA,OAAO,KAAK,cAAc,MAAM,uBAAuB,CAAA;AAEvD,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC,SAAS,KAAK,CAAC,EACb,SAAS,EACT,GAAG,KAAK,EACyC;IACjD,OAAO,CACL,KAAC,cAAc,CAAC,IAAI,iBACR,OAAO,EACjB,SAAS,EAAE,EAAE,CACX,qNAAqN,EACrN,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/@/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,MAAM,CAAA;AAG5C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/@/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,MAAM,MAAM,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAExC,MAAM,UAAU,EAAE,CAAC,GAAG,MAAoB;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;AAC9B,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ClientContext } from '@owlmeans/client-context';
|
|
2
|
+
import type { ClientConfig } from '@owlmeans/client-context';
|
|
3
|
+
/**
|
|
4
|
+
* Fail fast when the one precondition these screens actually depend on is missing, rather than
|
|
5
|
+
* deep inside `suspendFlow` the first time somebody who is not signed in opens a consent screen.
|
|
6
|
+
*
|
|
7
|
+
* There is nothing else to register here: the three screens are bound through `oauthEntrypoints`
|
|
8
|
+
* (spread into the application's own entrypoint list, exactly like every other screen package in
|
|
9
|
+
* this framework), and the translations register themselves as a side effect of importing this
|
|
10
|
+
* package's barrel — `appendOAuthScreens` is the documented call an application makes, but the
|
|
11
|
+
* strings are already there whether it is called or not.
|
|
12
|
+
*/
|
|
13
|
+
export declare const appendOAuthScreens: <C extends ClientConfig, T extends ClientContext<C>>(context: T) => T;
|
|
14
|
+
//# sourceMappingURL=append.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"append.d.ts","sourceRoot":"","sources":["../src/append.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAE5D;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,GAAI,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,KAAG,CASnG,CAAA"}
|
package/build/append.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { FLOW_STATE } from '@owlmeans/client-flow';
|
|
2
|
+
/**
|
|
3
|
+
* Fail fast when the one precondition these screens actually depend on is missing, rather than
|
|
4
|
+
* deep inside `suspendFlow` the first time somebody who is not signed in opens a consent screen.
|
|
5
|
+
*
|
|
6
|
+
* There is nothing else to register here: the three screens are bound through `oauthEntrypoints`
|
|
7
|
+
* (spread into the application's own entrypoint list, exactly like every other screen package in
|
|
8
|
+
* this framework), and the translations register themselves as a side effect of importing this
|
|
9
|
+
* package's barrel — `appendOAuthScreens` is the documented call an application makes, but the
|
|
10
|
+
* strings are already there whether it is called or not.
|
|
11
|
+
*/
|
|
12
|
+
export const appendOAuthScreens = (context) => {
|
|
13
|
+
if (!context.hasResource(FLOW_STATE)) {
|
|
14
|
+
throw new SyntaxError('web-oauth: no FLOW_STATE resource registered. Call appendFlowService (@owlmeans/web-flow) — '
|
|
15
|
+
+ 'or whatever registers it in this app\'s makeContext — before appendOAuthScreens.');
|
|
16
|
+
}
|
|
17
|
+
return context;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=append.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"append.js","sourceRoot":"","sources":["../src/append.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAIlD;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAqD,OAAU,EAAK,EAAE;IACtG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,WAAW,CACnB,8FAA8F;cAC5F,kFAAkF,CACrF,CAAA;IACH,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { RoutedComponent } from '@owlmeans/client';
|
|
2
|
+
/**
|
|
3
|
+
* The device/authorization-code consent screen. Full-page, no application chrome — the same
|
|
4
|
+
* shape `/dispatcher` and `/iam/interact/:uid` already render in, because a sign-in round trip is
|
|
5
|
+
* never a panel inside the application's own navigation.
|
|
6
|
+
*
|
|
7
|
+
* The screen refuses to render when framed: a device or code approval is exactly the click a
|
|
8
|
+
* clickjacking overlay would want to steal, and nothing about this decision needs to happen
|
|
9
|
+
* inside a frame.
|
|
10
|
+
*/
|
|
11
|
+
export declare const OAuthConsentScreen: RoutedComponent;
|
|
12
|
+
//# sourceMappingURL=consent-screen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent-screen.d.ts","sourceRoot":"","sources":["../../src/components/consent-screen.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAOvD;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,EAAE,eA6EhC,CAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useContext } from '@owlmeans/client';
|
|
3
|
+
import { useI18nLib } from '@owlmeans/client-i18n';
|
|
4
|
+
import { OAUTH_I18N } from '../consts.js';
|
|
5
|
+
import { useOAuthConsent } from '../hooks/use-oauth-consent.js';
|
|
6
|
+
import { Button } from '../@/components/ui/button.js';
|
|
7
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../@/components/ui/card.js';
|
|
8
|
+
/**
|
|
9
|
+
* The device/authorization-code consent screen. Full-page, no application chrome — the same
|
|
10
|
+
* shape `/dispatcher` and `/iam/interact/:uid` already render in, because a sign-in round trip is
|
|
11
|
+
* never a panel inside the application's own navigation.
|
|
12
|
+
*
|
|
13
|
+
* The screen refuses to render when framed: a device or code approval is exactly the click a
|
|
14
|
+
* clickjacking overlay would want to steal, and nothing about this decision needs to happen
|
|
15
|
+
* inside a frame.
|
|
16
|
+
*/
|
|
17
|
+
export const OAuthConsentScreen = () => {
|
|
18
|
+
const context = useContext();
|
|
19
|
+
const [query] = context.router().useSearchParams();
|
|
20
|
+
const ref = query.get('ref');
|
|
21
|
+
const t = useI18nLib(OAUTH_I18N, 'consent');
|
|
22
|
+
const { stage, view, errorKind, approve, deny, switchAccount } = useOAuthConsent(ref);
|
|
23
|
+
const framed = typeof window !== 'undefined' && window.top !== window.self;
|
|
24
|
+
return (_jsx("div", { style: { minHeight: '100dvh', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16 }, children: _jsx(Card, { style: { width: '100%', maxWidth: 440 }, "data-testid": "oauth-consent-card", children: framed ? (_jsx(CardContent, { children: _jsx("p", { role: "alert", children: t('framed') }) })) : stage === 'checking' || stage === 'signing-in' ? (_jsx(CardContent, { children: _jsx("p", { children: t('checking') }) })) : stage === 'loading' ? (_jsx(CardContent, { children: _jsx("p", { children: t('loading') }) })) : stage === 'error' ? (_jsx(CardContent, { children: _jsx("p", { role: "alert", "data-testid": "oauth-consent-error", children: t(errorKind == null || errorKind === 'failed' ? 'error' : `error-${errorKind}`) }) })) : view != null ? (_jsxs(_Fragment, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { "data-testid": "oauth-consent-client", children: t('title', { client: view.client.name }) }), _jsx(CardDescription, { children: view.client.origin === 'cimd' && view.client.host != null
|
|
25
|
+
? t('known-by-host', { host: view.client.host })
|
|
26
|
+
: view.client.origin === 'dcr'
|
|
27
|
+
? t('unverified')
|
|
28
|
+
: t('known') })] }), _jsxs(CardContent, { style: { display: 'flex', flexDirection: 'column', gap: 12 }, children: [view.userCode != null && (_jsx("p", { "data-testid": "oauth-consent-code", children: t('device-code', { code: view.userCode }) })), view.deviceName != null && _jsx("p", { children: t('device-name', { name: view.deviceName }) }), view.redirectHost != null && _jsx("p", { children: t('redirect-host', { host: view.redirectHost }) }), view.localhostOnly === true && (_jsx("p", { role: "alert", children: t('localhost-warning') })), _jsx("p", { children: t('scope', { scopes: view.scopes.join(', ') }) }), _jsxs("div", { style: { display: 'flex', gap: 8, justifyContent: 'flex-end' }, children: [_jsx(Button, { type: "button", variant: "outline", disabled: stage === 'deciding', "data-testid": "oauth-consent-deny", onClick: () => void deny(), children: t('deny') }), _jsx(Button, { type: "button", disabled: stage === 'deciding', "data-testid": "oauth-consent-approve", onClick: () => void approve(), autoFocus: true, children: t('approve') })] }), _jsx(Button, { type: "button", variant: "link", size: "sm", disabled: stage === 'deciding', "data-testid": "oauth-consent-switch", onClick: () => void switchAccount(), children: t('switch-account') })] })] })) : null }) }));
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=consent-screen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent-screen.js","sourceRoot":"","sources":["../../src/components/consent-screen.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RoutedComponent } from '@owlmeans/client';
|
|
2
|
+
/**
|
|
3
|
+
* The device-verification screen (RFC 8628's `verification_uri`). Opened by the MCP, either bare
|
|
4
|
+
* (a person types the code they were shown) or complete (`?user_code=…`, already carrying it).
|
|
5
|
+
*
|
|
6
|
+
* Either way it goes through the SAME flow transition — `verify` → `next` → `consent` — so the
|
|
7
|
+
* two entry shapes converge onto one path before anything else runs.
|
|
8
|
+
*/
|
|
9
|
+
export declare const OAuthDeviceScreen: RoutedComponent;
|
|
10
|
+
//# sourceMappingURL=device-screen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-screen.d.ts","sourceRoot":"","sources":["../../src/components/device-screen.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAWvD;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,EAAE,eA2D/B,CAAA"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
3
|
+
import { useContext, useNavigate } from '@owlmeans/client';
|
|
4
|
+
import { useI18nLib } from '@owlmeans/client-i18n';
|
|
5
|
+
import { makeFlowModel } from '@owlmeans/flow';
|
|
6
|
+
import { normalizeUserCode, oauthFlow, OAuthFlowStep, OAUTH_PAYLOAD_REF } from '@owlmeans/oauth';
|
|
7
|
+
import { OAUTH_I18N } from '../consts.js';
|
|
8
|
+
import { Button } from '../@/components/ui/button.js';
|
|
9
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../@/components/ui/card.js';
|
|
10
|
+
import { Input } from '../@/components/ui/input.js';
|
|
11
|
+
import { Label } from '../@/components/ui/label.js';
|
|
12
|
+
/**
|
|
13
|
+
* The device-verification screen (RFC 8628's `verification_uri`). Opened by the MCP, either bare
|
|
14
|
+
* (a person types the code they were shown) or complete (`?user_code=…`, already carrying it).
|
|
15
|
+
*
|
|
16
|
+
* Either way it goes through the SAME flow transition — `verify` → `next` → `consent` — so the
|
|
17
|
+
* two entry shapes converge onto one path before anything else runs.
|
|
18
|
+
*/
|
|
19
|
+
export const OAuthDeviceScreen = () => {
|
|
20
|
+
const context = useContext();
|
|
21
|
+
const nav = useNavigate();
|
|
22
|
+
const [query] = context.router().useSearchParams();
|
|
23
|
+
const t = useI18nLib(OAUTH_I18N, 'device');
|
|
24
|
+
const [code, setCode] = useState(query.get('user_code') ?? '');
|
|
25
|
+
const proceed = useCallback(async (typed) => {
|
|
26
|
+
const model = await makeFlowModel(oauthFlow);
|
|
27
|
+
model.enter(OAuthFlowStep.Verify);
|
|
28
|
+
model.updatePayload({ [OAUTH_PAYLOAD_REF]: normalizeUserCode(typed) });
|
|
29
|
+
model.transit('next', true);
|
|
30
|
+
const destination = model.step();
|
|
31
|
+
await nav.navigate(context.entrypoint(destination.module), { query: model.payload() });
|
|
32
|
+
}, [nav]);
|
|
33
|
+
const initial = query.get('user_code');
|
|
34
|
+
const complete = initial != null && initial !== '';
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (complete)
|
|
37
|
+
void proceed(initial);
|
|
38
|
+
}, [complete, initial]);
|
|
39
|
+
const onSubmit = (event) => {
|
|
40
|
+
event.preventDefault();
|
|
41
|
+
void proceed(code);
|
|
42
|
+
};
|
|
43
|
+
if (complete) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
return (_jsx("div", { style: { minHeight: '100dvh', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16 }, children: _jsxs(Card, { style: { width: '100%', maxWidth: 380 }, "data-testid": "oauth-device-card", children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { children: t('title') }), _jsx(CardDescription, { children: t('description') })] }), _jsx(CardContent, { children: _jsxs("form", { onSubmit: onSubmit, style: { display: 'flex', flexDirection: 'column', gap: 12 }, children: [_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4 }, children: [_jsx(Label, { htmlFor: "oauth-device-code", children: t('code-label') }), _jsx(Input, { id: "oauth-device-code", "data-testid": "oauth-device-input", autoComplete: "off", placeholder: "XXXX-XXXX", value: code, onChange: event => setCode(event.target.value) })] }), _jsx(Button, { type: "submit", "data-testid": "oauth-device-submit", disabled: code.trim() === '', children: t('continue') })] }) })] }) }));
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=device-screen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-screen.js","sourceRoot":"","sources":["../../src/components/device-screen.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAExD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE1D,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAChG,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAA;AACrD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AACtG,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAA;AAEnD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAoB,GAAG,EAAE;IACrD,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;IAC5B,MAAM,GAAG,GAAG,WAAW,EAAE,CAAA;IACzB,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,eAAe,EAAE,CAAA;IAClD,MAAM,CAAC,GAAG,UAAU,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;IAC1C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAA;IAE9D,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,KAAa,EAAE,EAAE;QAClD,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,CAAA;QAC5C,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;QACjC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QACtE,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QAC3B,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;QAChC,MAAM,GAAG,CAAC,QAAQ,CAChB,OAAO,CAAC,UAAU,CAA2B,WAAW,CAAC,MAAO,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,CAC9F,CAAA;IACH,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;IAET,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACtC,MAAM,QAAQ,GAAG,OAAO,IAAI,IAAI,IAAI,OAAO,KAAK,EAAE,CAAA;IAElD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,QAAQ;YAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACrC,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAA;IAEvB,MAAM,QAAQ,GAAG,CAAC,KAAgB,EAAE,EAAE;QACpC,KAAK,CAAC,cAAc,EAAE,CAAA;QACtB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACpB,CAAC,CAAA;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,CACL,cAAK,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,YAC/G,MAAC,IAAI,IAAC,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,iBAAc,mBAAmB,aAC5E,MAAC,UAAU,eACT,KAAC,SAAS,cAAE,CAAC,CAAC,OAAO,CAAC,GAAa,EACnC,KAAC,eAAe,cAAE,CAAC,CAAC,aAAa,CAAC,GAAmB,IAC1C,EACb,KAAC,WAAW,cACV,gBAAM,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,EAAE,aACpF,eAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,aAC9D,KAAC,KAAK,IAAC,OAAO,EAAC,mBAAmB,YAAE,CAAC,CAAC,YAAY,CAAC,GAAS,EAC5D,KAAC,KAAK,IACJ,EAAE,EAAC,mBAAmB,iBAAa,oBAAoB,EAAC,YAAY,EAAC,KAAK,EAC1E,WAAW,EAAC,WAAW,EAAC,KAAK,EAAE,IAAI,EACnC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAC9C,IACE,EACN,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,iBAAa,qBAAqB,EAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,YACjF,CAAC,CAAC,UAAU,CAAC,GACP,IACJ,GACK,IACT,GACH,CACP,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RoutedComponent } from '@owlmeans/client';
|
|
2
|
+
/**
|
|
3
|
+
* The final screen of the device grant — the moment the person's part is finished and the MCP's
|
|
4
|
+
* poll is expected to catch up within the device-authorization's own poll interval. There is
|
|
5
|
+
* nothing here to click and nowhere further to go; the tab's only remaining job is to be closed.
|
|
6
|
+
*/
|
|
7
|
+
export declare const OAuthDoneScreen: RoutedComponent;
|
|
8
|
+
//# sourceMappingURL=done-screen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"done-screen.d.ts","sourceRoot":"","sources":["../../src/components/done-screen.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAKvD;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,eAkB7B,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useContext } from '@owlmeans/client';
|
|
3
|
+
import { useI18nLib } from '@owlmeans/client-i18n';
|
|
4
|
+
import { OAUTH_I18N } from '../consts.js';
|
|
5
|
+
import { Card, CardContent, CardHeader, CardTitle } from '../@/components/ui/card.js';
|
|
6
|
+
/**
|
|
7
|
+
* The final screen of the device grant — the moment the person's part is finished and the MCP's
|
|
8
|
+
* poll is expected to catch up within the device-authorization's own poll interval. There is
|
|
9
|
+
* nothing here to click and nowhere further to go; the tab's only remaining job is to be closed.
|
|
10
|
+
*/
|
|
11
|
+
export const OAuthDoneScreen = () => {
|
|
12
|
+
const context = useContext();
|
|
13
|
+
const [query] = context.router().useSearchParams();
|
|
14
|
+
const t = useI18nLib(OAUTH_I18N, 'done');
|
|
15
|
+
const kind = query.get('kind');
|
|
16
|
+
return (_jsx("div", { style: { minHeight: '100dvh', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16 }, children: _jsxs(Card, { style: { width: '100%', maxWidth: 380, textAlign: 'center' }, "data-testid": "oauth-done-card", children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: t('title') }) }), _jsx(CardContent, { children: _jsx("p", { children: kind === 'device' ? t('device-message') : t('message') }) })] }) }));
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=done-screen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"done-screen.js","sourceRoot":"","sources":["../../src/components/done-screen.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAErF;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAoB,GAAG,EAAE;IACnD,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;IAC5B,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,eAAe,EAAE,CAAA;IAClD,MAAM,CAAC,GAAG,UAAU,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;IACxC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAE9B,OAAO,CACL,cAAK,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,YAC/G,MAAC,IAAI,IAAC,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,iBAAc,iBAAiB,aAC/F,KAAC,UAAU,cACT,KAAC,SAAS,cAAE,CAAC,CAAC,OAAO,CAAC,GAAa,GACxB,EACb,KAAC,WAAW,cACV,sBAAI,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAK,GACnD,IACT,GACH,CACP,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** The lib-tier i18n resource this package registers its strings under. */
|
|
2
|
+
export declare const OAUTH_I18N = "oauth";
|
|
3
|
+
/** How long a consent screen's suspended sign-in stays valid — generous enough for a person to
|
|
4
|
+
* pick a provider and come back, short enough that a stale suspension is not a lingering hazard. */
|
|
5
|
+
export declare const OAUTH_SUSPEND_TTL_MS: number;
|
|
6
|
+
//# sourceMappingURL=consts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,eAAO,MAAM,UAAU,UAAU,CAAA;AAEjC;oGACoG;AACpG,eAAO,MAAM,oBAAoB,QAAiB,CAAA"}
|
package/build/consts.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** The lib-tier i18n resource this package registers its strings under. */
|
|
2
|
+
export const OAUTH_I18N = 'oauth';
|
|
3
|
+
/** How long a consent screen's suspended sign-in stays valid — generous enough for a person to
|
|
4
|
+
* pick a provider and come back, short enough that a stale suspension is not a lingering hazard. */
|
|
5
|
+
export const OAUTH_SUSPEND_TTL_MS = 10 * 60 * 1000;
|
|
6
|
+
//# sourceMappingURL=consts.js.map
|