diff --git a/id.saladeaula.digital/app/routes/session.py b/id.saladeaula.digital/app/routes/session.py index 4d0626c..f2015e0 100644 --- a/id.saladeaula.digital/app/routes/session.py +++ b/id.saladeaula.digital/app/routes/session.py @@ -32,7 +32,7 @@ def session( raise ForbiddenError('Invalid credentials') return Response( - status_code=HTTPStatus.FOUND, + status_code=HTTPStatus.OK, cookies=[ Cookie( name='session_id', diff --git a/id.saladeaula.digital/client/app/components/ui/checkbox.tsx b/id.saladeaula.digital/client/app/components/ui/checkbox.tsx new file mode 100644 index 0000000..defeb01 --- /dev/null +++ b/id.saladeaula.digital/client/app/components/ui/checkbox.tsx @@ -0,0 +1,30 @@ +import * as React from "react" +import * as CheckboxPrimitive from "@radix-ui/react-checkbox" +import { CheckIcon } from "lucide-react" + +import { cn } from "@/lib/utils" + +function Checkbox({ + className, + ...props +}: React.ComponentProps) { + return ( + + + + + + ) +} + +export { Checkbox } diff --git a/id.saladeaula.digital/client/app/lib/session.ts b/id.saladeaula.digital/client/app/lib/session.ts new file mode 100644 index 0000000..76ee5b2 --- /dev/null +++ b/id.saladeaula.digital/client/app/lib/session.ts @@ -0,0 +1,12 @@ +import { createCookieSessionStorage } from 'react-router' + +const { getSession, commitSession, destroySession } = + createCookieSessionStorage({ + cookie: { + name: 'session_id', + httpOnly: true, + secure: true + } + }) + +export { getSession, commitSession, destroySession } diff --git a/id.saladeaula.digital/client/app/routes.ts b/id.saladeaula.digital/client/app/routes.ts index c7d4de9..ea0988c 100644 --- a/id.saladeaula.digital/client/app/routes.ts +++ b/id.saladeaula.digital/client/app/routes.ts @@ -1,5 +1,11 @@ -import { type RouteConfig, index, layout } from '@react-router/dev/routes' +import { + type RouteConfig, + index, + layout, + route +} from '@react-router/dev/routes' export default [ - layout('routes/layout.tsx', [index('routes/home.tsx')]) + layout('routes/layout.tsx', [index('routes/index.tsx')]), + route('/authorize', 'routes/authorize.tsx') ] satisfies RouteConfig diff --git a/id.saladeaula.digital/client/app/routes/authorize.tsx b/id.saladeaula.digital/client/app/routes/authorize.tsx new file mode 100644 index 0000000..a151e9c --- /dev/null +++ b/id.saladeaula.digital/client/app/routes/authorize.tsx @@ -0,0 +1,32 @@ +// import { parse } from 'cookie' + +import type { Route } from './+types/authorize' + +export async function loader({ request, context }: Route.LoaderArgs) { + const url = new URL(request.url) + const issuerUrl = new URL('/authorize', context.cloudflare.env.ISSUER_URL) + issuerUrl.search = url.search + + console.log(request.headers.get('Cookie')) + + console.log(issuerUrl.toString()) + + try { + const r = await fetch(issuerUrl.toString(), { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Cookie: request.headers.get('Cookie') + } + }) + + console.log(r) + + // return new Response(await r.text(), { + // status: r.status, + // headers: r.headers + // }) + } catch { + return new Response(null, { status: 500 }) + } +} diff --git a/id.saladeaula.digital/client/app/routes/home.tsx b/id.saladeaula.digital/client/app/routes/index.tsx similarity index 55% rename from id.saladeaula.digital/client/app/routes/home.tsx rename to id.saladeaula.digital/client/app/routes/index.tsx index 8f26125..c0bfe4a 100644 --- a/id.saladeaula.digital/client/app/routes/home.tsx +++ b/id.saladeaula.digital/client/app/routes/index.tsx @@ -1,14 +1,18 @@ -import type { Route } from './+types/home' +import type { Route } from './+types/index' import { isValidCPF } from '@brazilian-utils/brazilian-utils' import { zodResolver } from '@hookform/resolvers/zod' +import { Loader2Icon } from 'lucide-react' import { useForm } from 'react-hook-form' +import { useFetcher } from 'react-router' import { z } from 'zod' import { Button } from '@/components/ui/button' +import { Checkbox } from '@/components/ui/checkbox' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' +import { useState } from 'react' import logo from './logo.svg' const cpf = z.string().refine(isValidCPF, { message: 'CPF inválido' }) @@ -16,7 +20,7 @@ const email = z.string().email({ message: 'Email inválido' }) const schema = z.object({ username: z.union([cpf, email]), - password: z.string() + password: z.string().nonempty() }) type Schema = z.infer @@ -25,17 +29,44 @@ export function meta({}: Route.MetaArgs) { return [{ title: 'EDUSEG®' }] } -export function loader({ context }: Route.LoaderArgs) { - return { message: context.cloudflare.env.ISSUER_URL } +export async function action({ request, context }: Route.ActionArgs) { + const issuerUrl = context.cloudflare.env.ISSUER_URL + const formData = Object.fromEntries(await request.formData()) + const url = new URL(request.url) + url.pathname = '/authorize' + + try { + const r = await fetch(`${issuerUrl}/session`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(formData) + }) + + const headers = new Headers(r.headers) + headers.set('Location', url.toString()) + + return new Response(await r.text(), { + status: 302, + headers + }) + } catch { + return new Response(null, { status: 500 }) + } } -export default function Home({ loaderData }: Route.ComponentProps) { - const { register, handleSubmit } = useForm({ +export default function Index({}: Route.ComponentProps) { + const [show, setShow] = useState(false) + const fetcher = useFetcher() + + const { register, handleSubmit, formState } = useForm({ resolver: zodResolver(schema) }) - const onSubmit = (data: Schema) => { - console.log(data) + const onSubmit = async (data: Schema) => { + await fetcher.submit(data, { method: 'post' }) + console.log(fetcher.data) } return ( @@ -72,14 +103,36 @@ export default function Home({ loaderData }: Route.ComponentProps) { Esqueceu sua senha? - + + + +
+ setShow((x) => !x)} + /> + +
- diff --git a/id.saladeaula.digital/client/app/routes/layout.tsx b/id.saladeaula.digital/client/app/routes/layout.tsx index bbb490d..714ff9f 100644 --- a/id.saladeaula.digital/client/app/routes/layout.tsx +++ b/id.saladeaula.digital/client/app/routes/layout.tsx @@ -10,6 +10,7 @@ export default function Layout() { > Página inicial +
diff --git a/id.saladeaula.digital/client/app/routes/logo.svg b/id.saladeaula.digital/client/app/routes/logo.svg index cc7eb71..bbe178c 100644 --- a/id.saladeaula.digital/client/app/routes/logo.svg +++ b/id.saladeaula.digital/client/app/routes/logo.svg @@ -1 +1,7 @@ - \ No newline at end of file + + + + + + + \ No newline at end of file diff --git a/id.saladeaula.digital/client/package-lock.json b/id.saladeaula.digital/client/package-lock.json index f259cfd..35826aa 100644 --- a/id.saladeaula.digital/client/package-lock.json +++ b/id.saladeaula.digital/client/package-lock.json @@ -9,10 +9,12 @@ "dependencies": { "@brazilian-utils/brazilian-utils": "^1.0.0-rc.12", "@hookform/resolvers": "^5.2.1", + "@radix-ui/react-checkbox": "^1.3.3", "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-slot": "^1.2.3", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "cookie": "^1.0.2", "isbot": "^5.1.27", "lucide-react": "^0.539.0", "react": "^19.1.0", @@ -1736,6 +1738,42 @@ "dev": true, "license": "MIT" }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", + "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz", + "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-compose-refs": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", @@ -1751,6 +1789,21 @@ } } }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-label": { "version": "2.1.7", "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", @@ -1774,6 +1827,30 @@ } } }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", + "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-primitive": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", @@ -1815,6 +1892,91 @@ } } }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@react-router/dev": { "version": "7.8.0", "resolved": "https://registry.npmjs.org/@react-router/dev/-/dev-7.8.0.tgz", diff --git a/id.saladeaula.digital/client/package.json b/id.saladeaula.digital/client/package.json index 6981707..00a8420 100644 --- a/id.saladeaula.digital/client/package.json +++ b/id.saladeaula.digital/client/package.json @@ -14,10 +14,12 @@ "dependencies": { "@brazilian-utils/brazilian-utils": "^1.0.0-rc.12", "@hookform/resolvers": "^5.2.1", + "@radix-ui/react-checkbox": "^1.3.3", "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-slot": "^1.2.3", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "cookie": "^1.0.2", "isbot": "^5.1.27", "lucide-react": "^0.539.0", "react": "^19.1.0", diff --git a/id.saladeaula.digital/client/worker-configuration.d.ts b/id.saladeaula.digital/client/worker-configuration.d.ts index 096c974..f8b735e 100644 --- a/id.saladeaula.digital/client/worker-configuration.d.ts +++ b/id.saladeaula.digital/client/worker-configuration.d.ts @@ -1,9 +1,9 @@ /* eslint-disable */ -// Generated by Wrangler by running `wrangler types` (hash: 73d4543a7970c4847bf72b396e1b08ae) +// Generated by Wrangler by running `wrangler types` (hash: 64058b5920d46226ca8f7a7b04a89641) // Runtime types generated with workerd@1.20250803.0 2025-04-04 declare namespace Cloudflare { interface Env { - VALUE_FROM_CLOUDFLARE: "Hello from Cloudflare"; + ISSUER_URL: "https://58tkjsb308.execute-api.sa-east-1.amazonaws.com"; } } interface Env extends Cloudflare.Env {}