diff --git a/src/components/header.tsx b/src/components/header.tsx
index af3bd37..70fbdf9 100644
--- a/src/components/header.tsx
+++ b/src/components/header.tsx
@@ -30,6 +30,19 @@ export const Header = ({
)}
+ {!allowUnauthenticated ? (
+
+
+ Account
+
+
+ ) : null}
{!allowUnauthenticated ? (
{
+ if (!auth?.value) {
+ return redirect(`${WEBROOT}/`);
+ }
+ const user = await jwt.verify(auth.value);
+
+ if (!user) {
+ return redirect(`${WEBROOT}/`, 302);
+ }
+
+ const userData = db
+ .query("SELECT * FROM users WHERE id = ?")
+ .as(User)
+ .get(user.id);
+
+ if (!userData) {
+ return redirect(`${WEBROOT}/`, 302);
+ }
+
+ return (
+
+ <>
+
+
+
+
+
+
+ >
+
+ );
+ })
+ .post(
+ "/account",
+ async function handler({ body, set, redirect, jwt, cookie: { auth } }) {
+ if (!auth?.value) {
+ return redirect(`${WEBROOT}/login`, 302);
+ }
+
+ const user = await jwt.verify(auth.value);
+ if (!user) {
+ return redirect(`${WEBROOT}/login`, 302);
+ }
+ const existingUser = db
+ .query("SELECT * FROM users WHERE id = ?")
+ .as(User)
+ .get(user.id);
+
+ if (!existingUser) {
+ if (auth?.value) {
+ auth.remove();
+ }
+ return redirect(`${WEBROOT}/login`, 302);
+ }
+
+ const validPassword = await Bun.password.verify(
+ body.password,
+ existingUser.password,
+ );
+
+ if (!validPassword) {
+ set.status = 403;
+ return {
+ message: "Invalid credentials.",
+ };
+ }
+
+ const fields = [];
+ const values = [];
+
+ if (body.email) {
+ fields.push("email");
+ values.push(body.email);
+ }
+ if (body.newPassword) {
+ fields.push("password");
+ values.push(await Bun.password.hash(body.newPassword));
+ }
+
+ db.query(
+ `UPDATE users SET ${fields.map((field) => `${field}=?`).join(", ")} WHERE id=?`,
+ ).run(...values, user.id);
+
+ return redirect(`${WEBROOT}/`, 302);
+ },
+ {
+ body: t.Object({
+ email: t.MaybeEmpty(t.String()),
+ newPassword: t.MaybeEmpty(t.String()),
+ password: t.String(),
+ }),
+ },
+ )
+
.get("/", async ({ jwt, redirect, cookie: { auth, jobId } }) => {
if (!ALLOW_UNAUTHENTICATED) {
if (FIRST_RUN) {