From cdcc1f0312683d0dc1a03c5a28dd4e899334db3f Mon Sep 17 00:00:00 2001 From: stringsplit <77242831+nbitzz@users.noreply.github.com> Date: Thu, 7 Mar 2024 06:51:33 -0800 Subject: [PATCH] Graaahhh --- src/server/routes/api/v1/account.ts | 128 +++++++++++++++++++--------- 1 file changed, 88 insertions(+), 40 deletions(-) diff --git a/src/server/routes/api/v1/account.ts b/src/server/routes/api/v1/account.ts index eccd94e..d7ec366 100644 --- a/src/server/routes/api/v1/account.ts +++ b/src/server/routes/api/v1/account.ts @@ -8,7 +8,7 @@ import { getCookie, setCookie } from "hono/cookie" import Files, { id_check_regex } from "../../../lib/files.js" import * as Accounts from "../../../lib/accounts.js" -import * as Authentication from "../../../lib/auth.js" +import * as auth from "../../../lib/auth.js" import { assertAPI, getAccount, @@ -40,28 +40,23 @@ export default function (files: Files) { return } - if (Authentication.validate(getCookie(ctx, "auth")!)) { + if (auth.validate(getCookie(ctx, "auth")!)) { ServeError(ctx, 400, "you are already logged in") return } - const Account = Accounts.getFromUsername(body.username) + const account = Accounts.getFromUsername(body.username) - if (!Account || !Accounts.password.check(Account.id, body.password)) { + if (!account || !Accounts.password.check(account.id, body.password)) { ServeError(ctx, 400, "username or password incorrect") return } - setCookie( - ctx, - "auth", - Authentication.create( - Account.id, // account id - 3 * 24 * 60 * 60 * 1000 // expiration time - ), - { - // expires: - } - ) + setCookie(ctx, "auth", auth.create(account.id, 3 * 24 * 60 * 60 * 1000), { + path: "/", + sameSite: "Strict", + secure: true, + httpOnly: true + }) ctx.status(200) }) @@ -71,7 +66,7 @@ export default function (files: Files) { return ServeError(ctx, 403, "account registration disabled") } - if (Authentication.validate(getCookie(ctx, "auth")!)) { + if (auth.validate(getCookie(ctx, "auth")!)) { return ServeError(ctx, 400, "you are already logged in") } @@ -106,18 +101,13 @@ export default function (files: Files) { } return Accounts.create(body.username, body.password) - .then((Account) => { - setCookie( - ctx, - "auth", - Authentication.create( - Account, // account id - 3 * 24 * 60 * 60 * 1000 // expiration time - ), - { - // expires: - } - ) + .then((account) => { + setCookie(ctx, "auth", auth.create(account, 3 * 24 * 60 * 60 * 1000), { + path: "/", + sameSite: "Strict", + secure: true, + httpOnly: true + }) return ctx.status(200) }) .catch(() => { @@ -126,15 +116,15 @@ export default function (files: Files) { }) router.post("/logout", (ctx) => { - if (!Authentication.validate(getCookie(ctx, "auth")!)) { + if (!auth.validate(getCookie(ctx, "auth")!)) { return ServeError(ctx, 401, "not logged in") } - Authentication.invalidate(getCookie(ctx, "auth")!) + auth.invalidate(getCookie(ctx, "auth")!) return ctx.text("logged out") }) - router.patch( + router.put( "/dfv", requiresAccount, requiresPermissions("manage"), @@ -160,22 +150,80 @@ export default function (files: Files) { } ) - router.delete("/me", requiresAccount, noAPIAccess, async (ctx) => { + router.delete("/:user", requiresAccount, noAPIAccess, async (ctx) => { + let acc = ctx.req.param("user") == "me" ? ctx.get("account") : Accounts.getFromId(ctx.req.param("user")) + if (acc != ctx.get("account") && !ctx.get("account")?.admin) return ServeError(ctx, 403, "you are not an administrator") + if (!acc) return ServeError(ctx, 404, "account does not exist") const Account = ctx.get("account") as Accounts.Account const accountId = Account.id - Authentication.AuthTokens.filter((e) => e.account == accountId).forEach( + auth.AuthTokens.filter((e) => e.account == accountId).forEach( (token) => { - Authentication.invalidate(token.token) + auth.invalidate(token.token) } ) + if (acc.email) { + await sendMail( + acc.email, + "Notice of account deletion", + `Your account, ${ + acc.username + }, has been removed. Thank you for using monofile.` + ).catch() + return ctx.text("OK") + } + await Accounts.deleteAccount(accountId) return ctx.text("account deleted") }) - router.patch("/me/name", requiresAccount, noAPIAccess, async (ctx) => { - const Account = ctx.get("account") as Accounts.Account + router.put("/:user/password", requiresAccount, noAPIAccess, async (ctx) => { + let acc = ctx.req.param("user") == "me" ? ctx.get("account") : Accounts.getFromId(ctx.req.param("user")) + if (acc != ctx.get("account") && !ctx.get("account")?.admin) return ServeError(ctx, 403, "you are not an administrator") + if (!acc) return ServeError(ctx, 404, "account does not exist") + const body = await ctx.req.json() + const newPassword = body.newPassword + + if ( + typeof body.password != "string" || + !Accounts.password.check(acc.id, body.password) + ) { + return ServeError( + ctx, + 403, + "previous password not supplied" + ) + } + + if ( + typeof newPassword != "string" || + newPassword.length < 8 + ) { + return ServeError( + ctx, + 400, + "password must be 8 characters or longer" + ) + } + + Accounts.password.set(acc.id, newPassword) + Accounts.save() + + if (acc.email) { + await sendMail( + acc.email, + `Your login details have been updated`, + `Hello there! Your password has been updated. Please update your saved login details accordingly.` + ).catch() + return ctx.text("OK") + } + }) + + router.put("/:user/username", requiresAccount, noAPIAccess, async (ctx) => { + let acc = ctx.req.param("user") == "me" ? ctx.get("account") : Accounts.getFromId(ctx.req.param("user")) + if (acc != ctx.get("account") && !ctx.get("account")?.admin) return ServeError(ctx, 403, "you are not an administrator") + if (!acc) return ServeError(ctx, 404, "account does not exist") const body = await ctx.req.json() const newUsername = body.username @@ -206,14 +254,14 @@ export default function (files: Files) { return } - Account.username = newUsername + acc.username = newUsername Accounts.save() - if (Account.email) { + if (acc.email) { await sendMail( - Account.email, + acc.email, `Your login details have been updated`, - `Hello there! Your username has been updated to ${newUsername}. Please update your devices accordingly. Thank you for using monofile.` + `Hello there! Your username has been updated to ${newUsername}. Please update your saved login details accordingly.` ).catch() return ctx.text("OK") }