UNPKG

fumadocs-openapi

Version:

Generate MDX docs for your OpenAPI spec

273 lines (271 loc) 9.55 kB
import { cn } from "../../utils/cn.js"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../ui/components/select.js"; import { Input, labelVariants } from "../../ui/components/input.js"; import { useQuery } from "../../utils/use-query.js"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "../../ui/components/dialog.js"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime"; import { buttonVariants } from "fumadocs-ui/components/ui/button"; //#region src/playground/components/oauth-dialog.tsx const FlowTypes = { password: { name: "Resource Owner Password Flow", description: "Authenticate using username and password." }, clientCredentials: { name: "Client Credentials", description: "Intended for the server-to-server authentication." }, authorizationCode: { name: "Authorization code", description: "Authenticate with 3rd party services" }, implicit: { name: "Implicit", description: "Retrieve the access token directly." } }; function OauthDialog({ scheme, scopes, setToken, children, open, setOpen }) { const [type, setType] = useState(() => { return Object.keys(scheme.flows)[0]; }); const form = useForm({ defaultValues: { clientId: "", clientSecret: "", username: "", password: "" } }); const authCodeCallback = useQuery(async (code, state) => { const value = scheme.flows.authorizationCode; const res = await fetch(value.tokenUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ grant_type: "authorization_code", code, redirect_uri: state.redirect_uri, client_id: state.client_id, client_secret: state.client_secret }) }); if (!res.ok) throw new Error(await res.text()); const { access_token, token_type = "Bearer" } = await res.json(); setToken(`${token_type} ${access_token}`); setOpen(false); }); useEffect(() => { if (scheme.flows.authorizationCode) { const params = new URLSearchParams(window.location.search); const state = params.get("state"); const code = params.get("code"); if (state && code) { const parsedState = JSON.parse(state); setOpen(true); form.setValue("clientId", parsedState.client_id); form.setValue("clientSecret", parsedState.client_secret); authCodeCallback.start(code, parsedState); window.history.replaceState(null, "", window.location.pathname); return; } } if (scheme.flows.implicit && window.location.hash.length > 1) { const params = new URLSearchParams(window.location.hash.slice(1)); const state = params.get("state"); const token = params.get("access_token"); const type$1 = params.get("token_type") ?? "Bearer"; if (state && token) { const parsedState = JSON.parse(state); form.setValue("clientId", parsedState.client_id); setToken(`${type$1} ${token}`); window.history.replaceState(null, "", window.location.pathname); } } }, []); const authorize = useQuery(async (values) => { if (type === "implicit") { const value = scheme.flows[type]; const params = new URLSearchParams(); params.set("response_type", "token"); params.set("client_id", values.clientId); params.set("redirect_uri", window.location.href); params.set("scope", scopes.join("+")); params.set("state", JSON.stringify({ client_id: values.clientId, redirect_uri: window.location.href })); window.location.replace(`${value.authorizationUrl}?${params.toString()}`); return; } if (type === "authorizationCode") { const value = scheme.flows[type]; const params = new URLSearchParams(); params.set("response_type", "code"); params.set("client_id", values.clientId); params.set("redirect_uri", window.location.href); params.set("scope", scopes.join("+")); params.set("state", JSON.stringify({ client_id: values.clientId, client_secret: values.clientSecret, redirect_uri: window.location.href })); window.location.replace(`${value.authorizationUrl}?${params.toString()}`); return; } let res; if (type === "password") { const value = scheme.flows[type]; res = await fetch(value.tokenUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ grant_type: "password", username: values.username, password: values.password, scope: scopes.join("+") }) }); } if (type === "clientCredentials") { const value = scheme.flows[type]; res = await fetch(value.tokenUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ grant_type: "client_credentials", client_id: values.clientId, client_secret: values.clientSecret, scope: scopes.join("+") }) }); } if (res) { if (!res.ok) throw new Error(await res.text()); const { access_token, token_type = "Bearer" } = await res.json(); setToken(`${token_type} ${access_token}`); setOpen(false); } }); const onSubmit = form.handleSubmit((values) => { return authorize.start(values); }); const isLoading = authorize.isLoading || authCodeCallback.isLoading; const error = authCodeCallback.error ?? authorize.error; return /* @__PURE__ */ jsxs(Dialog, { open, onOpenChange: setOpen, children: [children, /* @__PURE__ */ jsxs(DialogContent, { children: [/* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: "Authorization" }), /* @__PURE__ */ jsx(DialogDescription, { children: "Obtain the access token for API." })] }), /* @__PURE__ */ jsxs("form", { className: "flex flex-col gap-6", onSubmit: (e) => { onSubmit(e); e.stopPropagation(); }, children: [ /* @__PURE__ */ jsxs(Select, { value: type, onValueChange: setType, children: [/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, {}) }), /* @__PURE__ */ jsx(SelectContent, { children: Object.keys(scheme.flows).map((key) => { const { name, description } = FlowTypes[key]; return /* @__PURE__ */ jsxs(SelectItem, { value: key, children: [/* @__PURE__ */ jsx("p", { className: "font-medium", children: name }), /* @__PURE__ */ jsx("p", { className: "text-fd-muted-foreground", children: description })] }, key); }) })] }), (type === "authorizationCode" || type === "clientCredentials" || type === "implicit") && /* @__PURE__ */ jsxs("fieldset", { className: "flex flex-col gap-1.5", children: [ /* @__PURE__ */ jsx("label", { htmlFor: "client_id", className: cn(labelVariants()), children: "Client ID" }), /* @__PURE__ */ jsx("p", { className: "text-fd-muted-foreground text-sm", children: "The client ID of your OAuth application." }), /* @__PURE__ */ jsx(Input, { id: "client_id", placeholder: "Enter value", type: "text", autoComplete: "off", disabled: isLoading, ...form.register("clientId", { required: true }) }) ] }), (type === "authorizationCode" || type === "clientCredentials") && /* @__PURE__ */ jsxs("fieldset", { className: "flex flex-col gap-1.5", children: [ /* @__PURE__ */ jsx("label", { htmlFor: "client_secret", className: cn(labelVariants()), children: "Client Secret" }), /* @__PURE__ */ jsx("p", { className: "text-fd-muted-foreground text-sm", children: "The client secret of your OAuth application." }), /* @__PURE__ */ jsx(Input, { id: "client_secret", placeholder: "Enter value", type: "password", autoComplete: "off", disabled: isLoading, ...form.register("clientSecret", { required: true }) }) ] }), type === "password" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("fieldset", { className: "flex flex-col gap-1.5", children: [/* @__PURE__ */ jsx("label", { htmlFor: "username", className: cn(labelVariants()), children: "Username" }), /* @__PURE__ */ jsx(Input, { id: "username", placeholder: "Enter value", type: "text", disabled: isLoading, autoComplete: "off", ...form.register("username", { required: true }) })] }), /* @__PURE__ */ jsxs("fieldset", { className: "flex flex-col gap-1.5", children: [/* @__PURE__ */ jsx("label", { htmlFor: "password", className: cn(labelVariants()), children: "Client Secret" }), /* @__PURE__ */ jsx(Input, { id: "password", placeholder: "Enter value", type: "password", autoComplete: "off", disabled: isLoading, ...form.register("password", { required: true }) })] })] }), error ? /* @__PURE__ */ jsx("p", { className: "text-red-400 font-medium text-sm", children: String(error) }) : null, /* @__PURE__ */ jsx("button", { type: "submit", disabled: isLoading, className: cn(buttonVariants({ color: "primary" })), children: authCodeCallback.isLoading ? "Fetching token..." : "Submit" }) ] })] })] }); } const OauthDialogTrigger = DialogTrigger; //#endregion export { OauthDialog, OauthDialogTrigger }; //# sourceMappingURL=oauth-dialog.js.map