diff --git a/app/components/ui/input.tsx b/app/components/ui/input.tsx new file mode 100644 index 0000000..f676e3f --- /dev/null +++ b/app/components/ui/input.tsx @@ -0,0 +1,25 @@ +import * as React from "react"; + +import { cn } from "~/lib/utils"; + +export interface InputProps + extends React.InputHTMLAttributes {} + +const Input = React.forwardRef( + ({ className, type, ...props }, ref) => { + return ( + + ); + }, +); +Input.displayName = "Input"; + +export { Input }; diff --git a/app/components/ui/label.tsx b/app/components/ui/label.tsx new file mode 100644 index 0000000..28a3034 --- /dev/null +++ b/app/components/ui/label.tsx @@ -0,0 +1,24 @@ +import * as React from "react"; +import * as LabelPrimitive from "@radix-ui/react-label"; +import { cva, type VariantProps } from "class-variance-authority"; + +import { cn } from "~/lib/utils"; + +const labelVariants = cva( + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", +); + +const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, ...props }, ref) => ( + +)); +Label.displayName = LabelPrimitive.Root.displayName; + +export { Label }; diff --git a/app/drizzle/meta/0001_snapshot.json b/app/drizzle/meta/0001_snapshot.json new file mode 100644 index 0000000..c8b7e06 --- /dev/null +++ b/app/drizzle/meta/0001_snapshot.json @@ -0,0 +1,198 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "7dee99c9-e3ff-4dc0-bbd8-060f5e974163", + "prevId": "79e43276-dcf0-4e97-81da-cd758f0cf38a", + "tables": { + "emails": { + "name": "emails", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "message_from": { + "name": "message_from", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "message_to": { + "name": "message_to", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "headers": { + "name": "headers", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "from": { + "name": "from", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sender": { + "name": "sender", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "reply_to": { + "name": "reply_to", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "delivered_to": { + "name": "delivered_to", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "return_path": { + "name": "return_path", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "to": { + "name": "to", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cc": { + "name": "cc", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "bcc": { + "name": "bcc", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "subject": { + "name": "subject", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "in_reply_to": { + "name": "in_reply_to", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "references": { + "name": "references", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "date": { + "name": "date", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "html": { + "name": "html", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "text": { + "name": "text", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "attachments": { + "name": "attachments", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "message_to_idx": { + "name": "message_to_idx", + "columns": ["message_to"], + "isUnique": false + }, + "created_at_idx": { + "name": "created_at_idx", + "columns": ["created_at"], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} diff --git a/app/routes/_h.$(lang).auth.tsx b/app/routes/_h.$(lang).auth.tsx new file mode 100644 index 0000000..e2fd36d --- /dev/null +++ b/app/routes/_h.$(lang).auth.tsx @@ -0,0 +1,72 @@ +import type { + ActionFunctionArgs, + LoaderFunctionArgs, +} from "@remix-run/cloudflare"; +import { + Form, + redirect, + useActionData, + useLoaderData, + useNavigation, +} from "@remix-run/react"; +import { LockKeyholeIcon } from "lucide-react"; +import { sessionWrapper } from "~/.server/session"; +import { Button } from "~/components/ui/button"; +import { Input } from "~/components/ui/input"; +import { Label } from "~/components/ui/label"; +import { getLocaleData } from "~/locales/locale"; + +export async function loader({ params }: LoaderFunctionArgs) { + const lang = params.lang || "en"; + const locale = await getLocaleData(lang); + return { + locale, + }; +} + +export async function action({ request, context }: ActionFunctionArgs) { + const password = (await request.formData()).get("password") as string; + if (password === context.cloudflare.env.PASSWORD) { + const { getSession, commitSession } = sessionWrapper( + context.cloudflare.env, + ); + const session = await getSession(request.headers.get("Cookie")); + session.set("password", password); + return redirect("/", { + headers: { + "Set-Cookie": await commitSession(session), + }, + }); + } + return { + error: true, + }; +} + +export default function Auth() { + const { locale } = useLoaderData(); + const actionData = useActionData(); + + const navigation = useNavigation(); + + return ( +
+
+ +
+ + + {actionData?.error && ( +
{locale.auth.msg}
+ )} +
+ + +
+ ); +}