ls-deno/routes/register.tsx

93 lines
2.6 KiB
TypeScript
Raw Normal View History

2022-09-30 15:14:57 -05:00
import { Handlers, PageProps } from "$fresh/server.ts";
2022-10-08 02:03:57 -05:00
import { createUser, PostgresError } from "@/db/mod.ts";
2022-09-30 15:14:57 -05:00
import { hash } from "https://deno.land/x/bcrypt@v0.4.1/mod.ts";
2022-10-21 03:06:37 -05:00
type UserId = string;
2022-09-30 15:14:57 -05:00
interface RegistrationError {
message: string;
}
2022-10-21 03:06:37 -05:00
export const handler: Handlers<UserId | RegistrationError | null> = {
2022-09-30 15:14:57 -05:00
async POST(request, context) {
const formData = (await request.formData());
const username = formData.get("username");
const password = formData.get("password");
2022-10-05 17:02:21 -05:00
// TODO: verify that username conforms to some regex? no spaces?
2022-10-01 14:03:15 -05:00
if (!username) {
return await context.render({ message: "no username provided" });
}
if (!password) {
return await context.render({ message: "no password provided" });
}
2022-10-08 02:03:57 -05:00
const passwordDigest = await hash(password.toString());
2022-09-30 15:14:57 -05:00
try {
2022-10-21 03:06:37 -05:00
const user = await createUser({
2022-10-08 02:03:57 -05:00
username: username.toString(),
passwordDigest,
});
2022-10-11 17:12:32 -05:00
return await context.render(user.id);
2022-09-30 15:14:57 -05:00
} catch (err) {
2022-10-01 14:03:15 -05:00
if (
err instanceof PostgresError && err.fields.code == "23505" &&
err.fields.constraint == "user_username_key"
) {
return await context.render({
message: `A user with username '${username}' already exists`,
});
2022-10-07 17:09:13 -05:00
} else if (
err instanceof PostgresError && err.fields.code == "23514" &&
err.fields.constraint == "valid_username"
) {
return await context.render({
message:
2022-10-08 00:00:45 -05:00
`Username must ONLY be comprised of letters, number, dashes, and underscores`,
2022-10-07 17:09:13 -05:00
});
2022-09-30 15:14:57 -05:00
}
2022-10-01 14:03:15 -05:00
throw err;
2022-09-30 15:14:57 -05:00
}
},
};
export default function Register(
2022-10-21 03:06:37 -05:00
{ data: userId }: PageProps<UserId | RegistrationError | null>,
2022-09-30 15:14:57 -05:00
) {
if (typeof userId == "string") {
return RegistrationSuccessful(userId);
} else {
return RegistrationForm(userId);
}
}
2022-10-21 03:06:37 -05:00
function RegistrationSuccessful(_userId: UserId) {
2022-09-30 15:14:57 -05:00
return (
2022-10-11 17:12:32 -05:00
<p>
You're all signed up! Let's go <a href="/login">log in</a>!
</p>
2022-09-30 15:14:57 -05:00
);
}
function RegistrationForm(props?: RegistrationError | null) {
console.log(props);
2022-09-29 20:22:30 -05:00
return (
2022-10-11 17:12:32 -05:00
<form class="flex flex-col max-w-lg" method="post">
2022-10-01 14:34:07 -05:00
<h1 class="text-4xl mb-4">Register your account</h1>
2022-09-30 15:14:57 -05:00
{props != null &&
2022-10-01 14:03:15 -05:00
(
<p class="text-red-500">
<strong>Error</strong>: {props.message}
</p>
)}
2022-10-11 17:12:32 -05:00
<label for="username">Username</label>
<input type="text" name="username" />
<label for="password">Password</label>
<input type="password" name="password" />
<input
class="bg-blue-800 px-4 p-2 mt-2"
type="submit"
value="Register"
/>
</form>
2022-09-29 20:22:30 -05:00
);
}