diff --git a/app/page.tsx b/app/page.tsx index 1283536..7efde3b 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -4,6 +4,9 @@ import ClientOnly from "@/components/ClientOnly"; export default function Home() { return (
+

+ M-OAuth +

diff --git a/components/InputForm.tsx b/components/InputForm.tsx index cc402c2..d11be49 100644 --- a/components/InputForm.tsx +++ b/components/InputForm.tsx @@ -1,10 +1,10 @@ -'use client' +"use client"; -import * as z from "zod" -import { zodResolver } from "@hookform/resolvers/zod" -import { useForm } from "react-hook-form" +import * as z from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; -import { Button } from "@/components/ui/button" +import { Button } from "@/components/ui/button"; import { Form, FormControl, @@ -13,36 +13,84 @@ import { FormItem, FormLabel, FormMessage, -} from "@/components/ui/form" -import { Input } from "@/components/ui/input" -import { readScopes, writeScopes, adminScopes } from "@/lib/utils" -import ScopeSection from "./ScopeSection" +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { + READ_SCOPES, + WRITE_SCOPES, + ADMIN_READ_SCOPES, + ADMIN_WRITE_SCOPES, +} from "@/lib/utils"; +import ScopeSection from "./ScopeSection"; + +export type MethodType = + | "read" + | "write" + | "follow" + | "crypto" + | "follow" + | "admin" + | "push"; +export interface ScopeInfo { + method: MethodType; + scopes?: string[] | string[][]; + description: string; +} + +const scopesInfo: ScopeInfo[] = [ + { + method: "read", + scopes: READ_SCOPES, + description: "read account's data", + }, + { + method: "write", + scopes: WRITE_SCOPES, + description: "modify account's data", + }, + { + method: "follow", + description: "modify account relationships,deprecated in 3.5.0 and newer.", + }, + { + method: "push", + description: "receive push notifications", + }, + { + method: "admin", + scopes: [ADMIN_READ_SCOPES, ADMIN_WRITE_SCOPES], + description: "read all data on the server", + }, + { + method: "crypto", + description: "use end-to-end encryption", + }, +]; const formSchema = z.object({ instance: z.string().trim(), clientName: z.string().trim(), redirectUris: z.string().url().trim(), scopes: z.string().array().nonempty().optional(), - website: z.string().trim().optional() -}) + website: z.string().trim().optional(), +}); const InputForm = () => { const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { - instance:'https://', - clientName: '', - redirectUris: 'urn:ietf:wg:oauth:2.0:oob', + instance: "https://", + clientName: "", + redirectUris: "", }, - }) + }); function onSubmit(values: z.infer) { - console.log(values) + console.log(values); } return (
-

M-OAuth

{ Instance - + @@ -92,7 +140,13 @@ const InputForm = () => { - Use urn:ietf:wg:oauth:2.0:oob for local tests + + Use{" "} + + urn:ietf:wg:oauth:2.0:oob + {" "} + for local tests + )} @@ -100,18 +154,27 @@ const InputForm = () => { ( + render={() => ( Scopes -
- - - - - - -
+ ( + +
+ {scopesInfo.map((info) => ( + + ))} +
+
+ )} + >
@@ -120,7 +183,6 @@ const InputForm = () => { - ); }; export default InputForm; diff --git a/components/ScopeCheckbox.tsx b/components/ScopeCheckbox.tsx new file mode 100644 index 0000000..a01ad2c --- /dev/null +++ b/components/ScopeCheckbox.tsx @@ -0,0 +1,28 @@ +import { Checkbox } from "@radix-ui/react-checkbox"; +import { MethodType } from "./InputForm"; + +interface ScopeCheckboxProps { + scope: string; + method: MethodType; +} + +const ScopeCheckbox: React.FC = ({ scope, method }) => { + return ( +
+ +
+ +
+
+ ); +}; + +export default ScopeCheckbox; \ No newline at end of file diff --git a/components/ScopeSection.tsx b/components/ScopeSection.tsx index 0f987d3..c0f4cd0 100644 --- a/components/ScopeSection.tsx +++ b/components/ScopeSection.tsx @@ -9,22 +9,21 @@ import { import { Button } from "@/components/ui/button"; import { ChevronsUpDown } from "lucide-react"; -import { ReadScope, AdminScope, WriteScope } from "@/lib/types"; -import { MethodType } from "@/lib/types"; -import { ControllerRenderProps } from "react-hook-form"; - +import { ScopeInfo } from "./InputForm"; +import ScopeCheckbox from "./ScopeCheckbox"; interface ScopeSectionProps { - method: MethodType; - scopes?: ReadScope[] | WriteScope[] | AdminScope[]; + info: ScopeInfo; + field: any; } -const ScopeSection: React.FC = ({ method, scopes}) => { +const ScopeSection: React.FC = ({ info, field }) => { + const { method, description, scopes } = info; return (
- +
-

- {method === "read" && "read your account's data"} - {method === "write" && "modify your account's data"} - {method === "admin" && "read data on the server"} - {method === "follow" && "modify account relationships"} - {method === "push" && "receive your push notifications"} - {method === "crypto" && "use end-to-end encryption"} -

+

{description}

{scopes && ( @@ -51,28 +43,30 @@ const ScopeSection: React.FC = ({ method, scopes}) => { )}
- - {scopes && ( -
- {scopes.map((scope) => ( -
- -
-
+ )) + : (scopes as string[]).map((scope) => ( + + ))}
- )} - + + )} ); }; diff --git a/lib/types.ts b/lib/types.ts deleted file mode 100644 index 504558b..0000000 --- a/lib/types.ts +++ /dev/null @@ -1,28 +0,0 @@ -export type MethodType = "read" | "write" | "follow" | "push" | 'crypto' | 'admin' - -export type ReadScope = - |"account" - | "blocks" - | "bookmarks" - | "favourites" - | "filters" - | "filters" - | "lists" - | "mutes" - | "notifications" - | "search" - | "statuses"; - -export type WriteScope = Omit - | 'conversations' - | 'media' - | "reports" - -export type AdminScope = - "account" - | "reports" - | "domain_allows" - | "domain_blocks" - | "ip_blocks" - | "email_domain_blocks" - | "canonical_email_blocks"; diff --git a/lib/utils.ts b/lib/utils.ts index 2a756e2..b95e62c 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,45 +1,55 @@ import { clsx, type ClassValue } from "clsx"; import { twMerge } from "tailwind-merge"; -import { ReadScope, WriteScope, AdminScope } from "@/lib/types"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } -export const readScopes: ReadScope[] = [ - "account", - "blocks", - "bookmarks", - "favourites", - "filters", - "lists", - "mutes", - "notifications", - "search", - "statuses", +export const READ_SCOPES = [ + "read:accounts", + "read:blocks", + "read:bookmarks", + "read:favourites", + "read:filters", + "read:follows", + "read:lists", + "read:mutes", + "read:notifications", + "read:search", + "read:statuses", ]; -export const writeScopes: WriteScope[] = [ - "account", - "blocks", - "bookmarks", - "favourites", - "filters", - "lists", - "mutes", - "notifications", - "statuses", - "conversations", - "media", - "reports", +export const WRITE_SCOPES = [ + "write:account", + "write:blocks", + "write:bookmarks", + "write:favourites", + "write:filters", + "write:lists", + "write:mutes", + "write:notifications", + "write:statuses", + "write:conversations", + "write:media", + "write:reports", ]; -export const adminScopes: AdminScope[] = [ - "account", - "reports", - "domain_allows", - "domain_blocks", - "ip_blocks", - "email_domain_blocks", - "canonical_email_blocks", +export const ADMIN_READ_SCOPES = [ + "admin:read:account", + "admin:read:reports", + "admin:read:domain_allows", + "admin:read:domain_blocks", + "admin:read:ip_blocks", + "admin:read:email_domain_blocks", + "admin:read:canonical_email_blocks", +]; + +export const ADMIN_WRITE_SCOPES = [ + "admin:write:account", + "admin:write:reports", + "admin:write:domain_allows", + "admin:write:domain_blocks", + "admin:write:ip_blocks", + "admin:write:email_domain_blocks", + "admin:write:canonical_email_blocks", ];