95 lines
2.6 KiB
TypeScript
95 lines
2.6 KiB
TypeScript
import { Head } from "$fresh/runtime.ts";
|
|
import { HandlerContext, PageProps } from "$fresh/server.ts";
|
|
import { setCookie } from "http/cookie.ts";
|
|
import { Status } from "http/http_status.ts";
|
|
import { connectDB } from "../src/user/db.ts";
|
|
import { getUser, verifyUser } from "../src/user/user.ts";
|
|
import { create as createJWT } from "djwt";
|
|
import { prepareSecretKey } from "../util/secret.ts";
|
|
import LoginForm from "../islands/Login.tsx";
|
|
|
|
async function GET(_req: Request, ctx: HandlerContext) {
|
|
return await ctx.render();
|
|
}
|
|
|
|
async function POST(req: Request, _ctx: HandlerContext): Promise<Response> {
|
|
const url = new URL(req.url);
|
|
const form = await req.formData();
|
|
const username = form.get("username");
|
|
const password = form.get("password");
|
|
if (username && password) {
|
|
const DB = await connectDB();
|
|
const user = await getUser(DB, username.toString());
|
|
if (user) {
|
|
const SECRET_KEY = await prepareSecretKey();
|
|
if (await verifyUser(user, password.toString())) {
|
|
const headers = new Headers();
|
|
const jwt = await createJWT({ alg: "HS512", typ: "JWT" }, {
|
|
username: user.name,
|
|
}, SECRET_KEY);
|
|
setCookie(headers, {
|
|
name: "auth",
|
|
value: jwt,
|
|
httpOnly: true,
|
|
sameSite: "Strict",
|
|
maxAge: 60 * 60 * 24 * 7,
|
|
domain: url.hostname,
|
|
path: "/",
|
|
secure: url.protocol === "https:",
|
|
});
|
|
|
|
let redirect = "/";
|
|
if (url.searchParams.has("redirect")) {
|
|
redirect = url.searchParams.get("redirect")!;
|
|
}
|
|
headers.set("Location", redirect);
|
|
return new Response(null, {
|
|
status: Status.SeeOther, // See Other
|
|
headers: headers,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
return new Response(
|
|
`<!DOCTYPE html><html>
|
|
<head> <title> Login Failed </title> </head>
|
|
<body>
|
|
<h1> Login Failed </h1>
|
|
<p> <a href="/"> Back to Home </a> </p>
|
|
<script>
|
|
document.location.href = "/login?failed=true&redirect=${
|
|
url.searchParams.get("redirect")
|
|
}";
|
|
</script>
|
|
</body>
|
|
</html>`,
|
|
{
|
|
headers: {
|
|
"Content-Type": "text/html",
|
|
},
|
|
status: Status.Unauthorized,
|
|
},
|
|
);
|
|
}
|
|
|
|
export const handler = {
|
|
GET,
|
|
POST,
|
|
};
|
|
|
|
export default function Login(props: PageProps) {
|
|
const redirect = props.url.searchParams.get("redirect");
|
|
const failed = props.url.searchParams.get("failed") === "true";
|
|
return (
|
|
<>
|
|
<Head>
|
|
<title>Simple file server - Login</title>
|
|
</Head>
|
|
<div class="">
|
|
<LoginForm redirect={redirect ?? "/"} failed={failed} />
|
|
</div>
|
|
</>
|
|
);
|
|
}
|