102 lines
2.9 KiB
TypeScript
102 lines
2.9 KiB
TypeScript
import { Handlers, PageProps } from "$fresh/server.ts";
|
|
import { Page } from "@/components/Page.tsx";
|
|
import { createUser, PostgresError } from "@/db/mod.ts";
|
|
import { hash } from "https://deno.land/x/bcrypt@v0.4.1/mod.ts";
|
|
|
|
type UserID = string;
|
|
|
|
interface RegistrationError {
|
|
message: string;
|
|
}
|
|
|
|
export const handler: Handlers<UserID | RegistrationError | null> = {
|
|
async POST(request, context) {
|
|
const formData = (await request.formData());
|
|
const username = formData.get("username");
|
|
const password = formData.get("password");
|
|
// TODO: verify that username conforms to some regex? no spaces?
|
|
if (!username) {
|
|
return await context.render({ message: "no username provided" });
|
|
}
|
|
if (!password) {
|
|
return await context.render({ message: "no password provided" });
|
|
}
|
|
const passwordDigest = await hash(password.toString());
|
|
try {
|
|
const result = await createUser({
|
|
username: username.toString(),
|
|
passwordDigest,
|
|
});
|
|
console.debug(result);
|
|
if (!result) throw "insert failed";
|
|
const [user, _team] = result;
|
|
if (!user) throw "insert failed";
|
|
return await context.render(id);
|
|
} catch (err) {
|
|
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`,
|
|
});
|
|
} else if (
|
|
err instanceof PostgresError && err.fields.code == "23514" &&
|
|
err.fields.constraint == "valid_username"
|
|
) {
|
|
return await context.render({
|
|
message:
|
|
`Username must ONLY be comprised of letters, number, dashes, and underscores`,
|
|
});
|
|
}
|
|
throw err;
|
|
}
|
|
},
|
|
};
|
|
|
|
export default function Register(
|
|
{ data: userId }: PageProps<UserID | RegistrationError | null>,
|
|
) {
|
|
if (typeof userId == "string") {
|
|
return RegistrationSuccessful(userId);
|
|
} else {
|
|
return RegistrationForm(userId);
|
|
}
|
|
}
|
|
|
|
function RegistrationSuccessful(_userId: UserID) {
|
|
return (
|
|
<Page>
|
|
<p>
|
|
You're all signed up! Let's go <a href="/login">log in</a>!
|
|
</p>
|
|
</Page>
|
|
);
|
|
}
|
|
|
|
function RegistrationForm(props?: RegistrationError | null) {
|
|
console.log(props);
|
|
return (
|
|
<Page>
|
|
<h1 class="text-4xl mb-4">Register your account</h1>
|
|
{props != null &&
|
|
(
|
|
<p class="text-red-500">
|
|
<strong>Error</strong>: {props.message}
|
|
</p>
|
|
)}
|
|
<form class="flex flex-col max-w-lg" method="post">
|
|
<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>
|
|
</Page>
|
|
);
|
|
}
|