1. add indexes to optimise query performance

2. add password protected
This commit is contained in:
akazwz
2024-10-01 10:33:53 +08:00
parent bc08ad1f6b
commit 9b0e408a5f
4 changed files with 319 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
import * as React from "react";
import { cn } from "~/lib/utils";
export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
ref={ref}
{...props}
/>
);
},
);
Input.displayName = "Input";
export { Input };

View File

@@ -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<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => (
<LabelPrimitive.Root
ref={ref}
className={cn(labelVariants(), className)}
{...props}
/>
));
Label.displayName = LabelPrimitive.Root.displayName;
export { Label };

View File

@@ -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": {}
}
}

View File

@@ -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<typeof loader>();
const actionData = useActionData<typeof action>();
const navigation = useNavigation();
return (
<div className="p-2">
<Form
method="POST"
className="flex flex-col w-full max-w-md mx-auto gap-4"
>
<LockKeyholeIcon strokeWidth="1.5px" className="size-8" />
<div className="flex flex-col gap-2">
<Label htmlFor="password">{locale.auth.title}</Label>
<Input id="password" name="password" type="password" required />
{actionData?.error && (
<div className="text-destructive text-xs">{locale.auth.msg}</div>
)}
</div>
<Button disabled={navigation.state === "submitting"}>
{locale.auth.submit}
</Button>
</Form>
</div>
);
}