Skip to content

Commit 6dc6067

Browse files
authored
Merge pull request #288 from bennett-sh/account-settings
2 parents 6e5d5d9 + 2eb9b8f commit 6dc6067

File tree

2 files changed

+170
-0
lines changed

2 files changed

+170
-0
lines changed

src/components/header.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@ export const Header = ({
3030
</a>
3131
</li>
3232
)}
33+
{!allowUnauthenticated ? (
34+
<li>
35+
<a
36+
class={`
37+
text-accent-600 transition-all
38+
hover:text-accent-500 hover:underline
39+
`}
40+
href={`${webroot}/account`}
41+
>
42+
Account
43+
</a>
44+
</li>
45+
) : null}
3346
{!allowUnauthenticated ? (
3447
<li>
3548
<a

src/index.tsx

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,163 @@ const app = new Elysia({
475475

476476
return redirect(`${WEBROOT}/login`, 302);
477477
})
478+
.get("/account", async ({ jwt, redirect, cookie: { auth } }) => {
479+
if (!auth?.value) {
480+
return redirect(`${WEBROOT}/`);
481+
}
482+
const user = await jwt.verify(auth.value);
483+
484+
if (!user) {
485+
return redirect(`${WEBROOT}/`, 302);
486+
}
487+
488+
const userData = db
489+
.query("SELECT * FROM users WHERE id = ?")
490+
.as(User)
491+
.get(user.id);
492+
493+
if (!userData) {
494+
return redirect(`${WEBROOT}/`, 302);
495+
}
496+
497+
return (
498+
<BaseHtml webroot={WEBROOT} title="ConvertX | Login">
499+
<>
500+
<Header
501+
webroot={WEBROOT}
502+
accountRegistration={ACCOUNT_REGISTRATION}
503+
allowUnauthenticated={ALLOW_UNAUTHENTICATED}
504+
hideHistory={HIDE_HISTORY}
505+
/>
506+
<main
507+
class={`
508+
w-full px-2
509+
sm:px-4
510+
`}
511+
>
512+
<article class="article">
513+
<form method="post" class="flex flex-col gap-4">
514+
<fieldset class="mb-4 flex flex-col gap-4">
515+
<label class="flex flex-col gap-1">
516+
Email
517+
<input
518+
type="email"
519+
name="email"
520+
class="rounded-sm bg-neutral-800 p-3"
521+
placeholder="Email"
522+
autocomplete="email"
523+
value={userData.email}
524+
required
525+
/>
526+
</label>
527+
<label class="flex flex-col gap-1">
528+
Password (leave blank for unchanged)
529+
<input
530+
type="password"
531+
name="newPassword"
532+
class="rounded-sm bg-neutral-800 p-3"
533+
placeholder="Password"
534+
autocomplete="new-password"
535+
/>
536+
</label>
537+
<label class="flex flex-col gap-1">
538+
Current Password
539+
<input
540+
type="password"
541+
name="password"
542+
class="rounded-sm bg-neutral-800 p-3"
543+
placeholder="Password"
544+
autocomplete="current-password"
545+
required
546+
/>
547+
</label>
548+
</fieldset>
549+
<div role="group">
550+
<input
551+
type="submit"
552+
value="Update"
553+
class="btn-primary w-full"
554+
/>
555+
</div>
556+
</form>
557+
</article>
558+
</main>
559+
</>
560+
</BaseHtml>
561+
);
562+
})
563+
.post(
564+
"/account",
565+
async function handler({ body, set, redirect, jwt, cookie: { auth } }) {
566+
if (!auth?.value) {
567+
return redirect(`${WEBROOT}/login`, 302);
568+
}
569+
570+
const user = await jwt.verify(auth.value);
571+
if (!user) {
572+
return redirect(`${WEBROOT}/login`, 302);
573+
}
574+
const existingUser = db
575+
.query("SELECT * FROM users WHERE id = ?")
576+
.as(User)
577+
.get(user.id);
578+
579+
if (!existingUser) {
580+
if (auth?.value) {
581+
auth.remove();
582+
}
583+
return redirect(`${WEBROOT}/login`, 302);
584+
}
585+
586+
const validPassword = await Bun.password.verify(
587+
body.password,
588+
existingUser.password,
589+
);
590+
591+
if (!validPassword) {
592+
set.status = 403;
593+
return {
594+
message: "Invalid credentials.",
595+
};
596+
}
597+
598+
const fields = [];
599+
const values = [];
600+
601+
if (body.email) {
602+
const existingUser = await db
603+
.query("SELECT id FROM users WHERE email = ?")
604+
.as(User)
605+
.get(body.email);
606+
if (existingUser && existingUser.id.toString() !== user.id) {
607+
set.status = 409;
608+
return { message: "Email already in use." };
609+
}
610+
fields.push("email");
611+
values.push(body.email);
612+
}
613+
if (body.newPassword) {
614+
fields.push("password");
615+
values.push(await Bun.password.hash(body.newPassword));
616+
}
617+
618+
if (fields.length > 0) {
619+
db.query(
620+
`UPDATE users SET ${fields.map((field) => `${field}=?`).join(", ")} WHERE id=?`,
621+
).run(...values, user.id);
622+
}
623+
624+
return redirect(`${WEBROOT}/`, 302);
625+
},
626+
{
627+
body: t.Object({
628+
email: t.MaybeEmpty(t.String()),
629+
newPassword: t.MaybeEmpty(t.String()),
630+
password: t.String(),
631+
}),
632+
},
633+
)
634+
478635
.get("/", async ({ jwt, redirect, cookie: { auth, jobId } }) => {
479636
if (!ALLOW_UNAUTHENTICATED) {
480637
if (FIRST_RUN) {

0 commit comments

Comments
 (0)