diff --git a/dashboard/src/app/(inside)/client/create/page.tsx b/dashboard/src/app/(inside)/client/create/page.tsx index 8b67099..f42fda6 100644 --- a/dashboard/src/app/(inside)/client/create/page.tsx +++ b/dashboard/src/app/(inside)/client/create/page.tsx @@ -1,3 +1,6 @@ +import { CreateClientForm } from '@/components/forms/client-form'; +import { createClient } from '@/lib/action/client'; + export default async function CreateClientPage() { return (
@@ -7,6 +10,7 @@ export default async function CreateClientPage() { Configure your new OAuth2 Client.

+ ); } \ No newline at end of file diff --git a/dashboard/src/components/forms/client-form.tsx b/dashboard/src/components/forms/client-form.tsx new file mode 100644 index 0000000..afaca44 --- /dev/null +++ b/dashboard/src/components/forms/client-form.tsx @@ -0,0 +1,276 @@ +'use client'; + +import { z } from 'zod'; +import { clientFormSchema } from '@/lib/forms/client-form'; +import { useForm } from 'react-hook-form'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { kratos } from '@/ory'; +import { useEffect, useState } from 'react'; +import { Identity, OAuth2Client } from '@ory/client'; +import { AxiosResponse } from 'axios'; +import { AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle } from '@/components/ui/alert-dialog'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { useRouter } from 'next/navigation'; +import { Checkbox } from '@/components/ui/checkbox'; + +interface CreateClientFormProps { + action: (data: z.infer) => Promise>; +} + +export function CreateClientForm({ action }: CreateClientFormProps) { + + const router = useRouter(); + const [identity, setIdentity] = useState(); + + useEffect(() => { + kratos.toSession() + .then(response => response.data) + .then(session => setIdentity(session.identity)); + }, []); + + const form = useForm>({ + resolver: zodResolver(clientFormSchema), + defaultValues: { + client_name: '', + owner: '', + scope: '', + skip: false, + logo_uri: '', + policy_uri: '', + tos_uri: '', + }, + }); + + const [successDialogOpen, setSuccessDialogOpen] = useState(false); + const [createdClient, setCreatedClient] = useState(); + const handleSubmit = async (data: z.infer) => { + await action(data) + .then((response) => { + console.log(response); + return response.data; + }) + .then((client) => { + setCreatedClient(client); + setSuccessDialogOpen(true); + }) + .catch((error) => { + console.error(error); + }); + }; + + useEffect(() => { + form.setValue('owner', identity?.id ?? ''); + }, [identity]); + + return ( + <> + { + createdClient && ( + setSuccessDialogOpen(false)}> + + + Client created + + Your client was created successfully. Make sure to safe the client secret! + + + + ) + } +
+ + + + + + Essentials + + + + ( + + Client Name + + + + + The human-readable name of the client to be presented to the end-user + during + authorization. + + + + )} + /> + ( + + Scopes + + + + + Scope is a string containing a space-separated list of scope values (as + described in + Section 3.3 of OAuth 2.0 [RFC6749]) that the client can use when + requesting + access + tokens. + + + + )} + /> + ( + + Scopes + + + + + Scope is a string containing a space-separated list of scope values (as + described in + Section 3.3 of OAuth 2.0 [RFC6749]) that the client can use when + requesting + access + tokens. + + + + )} + /> + + + + + + + Consent Screen + + + + ( + +
+ + Skip consent + + + Whether or not the consent screen is skipped for this client + +
+ + + +
+ )}/> + { + !form.getValues('skip') && ( + <> + ( + + Logo URI + + + + + A URL string referencing the client's logo. + + + + )}/> + + ( + + Policy URI + + + + + A URL string pointing to a human-readable + privacy policy document for the client that describes how the + deployment organization collects, uses, retains, and discloses + personal data. + + + + )}/> + + ( + + Terms URI + + + + + A URL string pointing to a human-readable terms of service + document for the client that describes a contractual + relationship between the end-user and the client that the + end-user accepts when authorizing the client. + + + + )}/> + + ( + + Owner + + + + + Owner is a string identifying the owner of the OAuth 2.0 Client. + + + + )} + /> + + ) + } +
+
+ +
+ + +
+
+ + + ); +} diff --git a/dashboard/src/lib/forms/client-form.ts b/dashboard/src/lib/forms/client-form.ts new file mode 100644 index 0000000..b11378e --- /dev/null +++ b/dashboard/src/lib/forms/client-form.ts @@ -0,0 +1,12 @@ +import { z } from 'zod'; + +export const clientFormSchema = z.object({ + access_token_strategy: z.string().default('opaque').readonly(), + client_name: z.string().min(1, 'Client name is required'), + owner: z.string().min(1, 'Owner is required'), + scope: z.string(), + skip: z.boolean(), + logo_uri: z.string().url(), + tos_uri: z.string().url(), + policy_uri: z.string().url(), +});