From b130e4e2cbd319ea1dfca9e28c700d8a092903fa Mon Sep 17 00:00:00 2001 From: stringsplit <77242831+nbitzz@users.noreply.github.com> Date: Fri, 24 May 2024 21:17:05 -0700 Subject: [PATCH] fix a few implementations --- src/server/lib/accounts.ts | 28 ++++++++++------------ src/server/lib/auth.ts | 2 +- src/server/lib/middleware.ts | 27 ++++++++++----------- src/server/routes/api/v1/account/access.ts | 2 +- src/server/routes/api/v1/account/index.ts | 9 +++++-- src/server/routes/api/v1/session.ts | 6 ++--- 6 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/server/lib/accounts.ts b/src/server/lib/accounts.ts index 55f371f..1d10592 100644 --- a/src/server/lib/accounts.ts +++ b/src/server/lib/accounts.ts @@ -21,23 +21,21 @@ export type Account = z.infer * @returns A Promise which returns the new account's ID */ -export async function create(username:string,pwd:string,admin:boolean=false):Promise { - let accId = crypto.randomBytes(12).toString("hex") - - Db.data.push( - { - id: accId, - username: username, - password: password.hash(pwd), - files: [], - admin: admin, - defaultFileVisibility: "public", - settings: AccountSchemas.Settings.User.parse({}) - } - ) +export async function create(username:string,pwd:string,admin:boolean=false):Promise { + let acc: Account = { + id: crypto.randomUUID(), + username: username, + password: password.hash(pwd), + files: [], + admin: admin, + defaultFileVisibility: "public", + settings: AccountSchemas.Settings.User.parse({}) + } + Db.data.push(acc) await Db.save() - return accId + + return acc } /** diff --git a/src/server/lib/auth.ts b/src/server/lib/auth.ts index f8f42cd..722d3d0 100644 --- a/src/server/lib/auth.ts +++ b/src/server/lib/auth.ts @@ -59,7 +59,7 @@ export function makeJwt(_token: TokenResolvable) { sub: token.account, jti: token.id, ...(token.type != "User" ? { scope: token.scopes } : {}) - }) + }).setProtectedHeader({ alg: "HS256" }) return jwt.sign(config.jwtSecret) } diff --git a/src/server/lib/middleware.ts b/src/server/lib/middleware.ts index 9fbb29d..596645e 100644 --- a/src/server/lib/middleware.ts +++ b/src/server/lib/middleware.ts @@ -10,19 +10,18 @@ import { codes } from "./codes.js" * @description Middleware which adds an account, if any, to ctx.get("account") */ export const getAccount: RequestHandler = async function (ctx, next) { - let account = Accounts.getFromToken((await auth.tokenFor(ctx))!) + let uToken = (await auth.tokenFor(ctx))! + let account = Accounts.getFromToken(uToken) if (account?.suspension) - setCookie(ctx, "auth", "") + auth.invalidate(uToken) ctx.set("account", account) return next() } -export function resolveTarget(actor: Accounts.Account, targetString: string) { - return targetString == "me" +export function resolveTarget(actor: Accounts.Account, target: Accounts.AccountResolvable) { + return target == "me" ? actor - : targetString.startsWith("@") - ? Accounts.getFromUsername(targetString.slice(1)) - : Accounts.getFromId(targetString) + : Accounts.resolve(target) } /** @@ -36,7 +35,6 @@ export const getTarget: RequestHandler = async (ctx, next) => { permissions = auth.getScopes(tok) let actor = ctx.get("account") - let target = resolveTarget(actor, ctx.req.param("user")) if (!target) return ServeError(ctx, 404, "account does not exist") @@ -44,11 +42,12 @@ export const getTarget: RequestHandler = async (ctx, next) => { if (actor && ( ( target != actor // target is not the current account - && !actor?.admin // account is not admin - ) - || ( - actor?.admin // account is admin - && permissions && !permissions.includes("manage_server") // permissions does not include manage_server + && ( + !actor?.admin // account is not admin + || ( + permissions && !permissions.includes("manage_server") // account is admin but permissions does not include manage_server + ) + ) ) )) return ServeError(ctx, 403, "you cannot manage this user") @@ -188,7 +187,7 @@ export function scheme(scheme: z.ZodTypeAny, transformer: (ctx: Context) => Prom // Not really middleware but a utility -export const login = async (ctx: Context, account: string) => { +export const login = async (ctx: Context, account: Accounts.AccountResolvable) => { let token = auth.create(account, 3 * 24 * 60 * 60 * 1000) setCookie(ctx, "auth", await auth.makeJwt(token), { path: "/", diff --git a/src/server/routes/api/v1/account/access.ts b/src/server/routes/api/v1/account/access.ts index 201be99..7f6614c 100644 --- a/src/server/routes/api/v1/account/access.ts +++ b/src/server/routes/api/v1/account/access.ts @@ -90,7 +90,7 @@ export default function (files: Files) { }) router.delete("/:token", async (ctx) => { - auth.invalidate(ctx.get("targetToken").id) + auth.invalidate(ctx.get("targetToken")) return ctx.text(`deleted token ${ctx.req.param("token")}`) }) diff --git a/src/server/routes/api/v1/account/index.ts b/src/server/routes/api/v1/account/index.ts index 3e77194..9564da1 100644 --- a/src/server/routes/api/v1/account/index.ts +++ b/src/server/routes/api/v1/account/index.ts @@ -217,7 +217,12 @@ router.use(getAccount) router.on( ["GET","PATCH","DELETE"], "/:user", - requiresAccount, getTarget, accountMgmtRoute + requiresAccount, getTarget +) +router.on( + ["PATCH","DELETE"], + "/:user", + accountMgmtRoute ) function isMessage(object: any): object is Message { @@ -278,7 +283,7 @@ export default function (files: Files) { .then((account) => { if (!ctx.get("account")) login(ctx, account) - return ctx.text(account) + return ctx.text(account.id) }) .catch((e) => { console.error(e) diff --git a/src/server/routes/api/v1/session.ts b/src/server/routes/api/v1/session.ts index c23206d..4aa368d 100644 --- a/src/server/routes/api/v1/session.ts +++ b/src/server/routes/api/v1/session.ts @@ -12,6 +12,7 @@ import * as auth from "../../../lib/auth.js" import { getAccount, login, + mirror, requiresAccount, scheme } from "../../../lib/middleware.js" @@ -27,7 +28,7 @@ const router = new Hono<{ router.use(getAccount) -export default function (files: Files) { +export default function (files: Files, apiRoot: Hono) { router.post("/",scheme(z.object({ username: AccountSchemas.Username, password: AccountSchemas.StringPassword @@ -59,8 +60,7 @@ export default function (files: Files) { }) router.get("/", requiresAccount, async ctx => { - let sessionToken = (await auth.tokenFor(ctx))! - return ctx.redirect(`/api/v1`) + return ctx.json(auth.resolve((await auth.tokenFor(ctx))!)!) }) router.delete("/", requiresAccount, async ctx => {