From 426e057f12b99979bc02818c7f0b69ac87db8167 Mon Sep 17 00:00:00 2001 From: stringsplit <77242831+nbitzz@users.noreply.github.com> Date: Mon, 17 Jun 2024 16:43:19 -0700 Subject: [PATCH] barebones invite api --- src/server/lib/invites.ts | 35 +++++++++++++++++++ src/server/routes/api/v1/account/index.ts | 17 ++++++--- src/server/routes/api/v1/definition.ts | 4 +++ src/server/routes/api/v1/server/invites.ts | 40 ++++++++++++++++++++++ 4 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 src/server/lib/invites.ts create mode 100644 src/server/routes/api/v1/server/invites.ts diff --git a/src/server/lib/invites.ts b/src/server/lib/invites.ts new file mode 100644 index 0000000..8a6f06c --- /dev/null +++ b/src/server/lib/invites.ts @@ -0,0 +1,35 @@ +// The only reason we have this is to make +// life very, very slightly easier. +// And also we can change how the invite +// system works a little easily +// if need be, I guess? + +import DbFile from "./dbfile.js"; +import { generateFileId } from "./files.js"; + +export const Db = new DbFile("invites", []) + +export function has(id: string) { + return Db.data.includes(id) +} + +export function use(id: string) { + if (!has(id)) return false + + Db.data.splice( + Db.data.indexOf(id), + 1 + ) + + Db.save() + return true +} + +export function make() { + let invite = generateFileId(6) + Db.data.push(invite) + Db.save() + return invite +} + +Db.read() \ No newline at end of file diff --git a/src/server/routes/api/v1/account/index.ts b/src/server/routes/api/v1/account/index.ts index 9564da1..c255763 100644 --- a/src/server/routes/api/v1/account/index.ts +++ b/src/server/routes/api/v1/account/index.ts @@ -28,6 +28,7 @@ import * as CodeMgr from "../../../../lib/codes.js" import Configuration from "../../../../lib/config.js" import { AccountSchemas, FileSchemas } from "../../../../lib/schemas/index.js" import { z } from "zod" +import * as invites from "../../../../lib/invites.js" const router = new Hono<{ Variables: { @@ -260,12 +261,17 @@ const UserUpdateScheme = z.union([ export default function (files: Files) { router.post("/", scheme(z.object({ username: AccountSchemas.Username, - password: AccountSchemas.StringPassword - })), async (ctx) => { + password: AccountSchemas.StringPassword, + invite: z.string().max(6) + }).omit( + Configuration.accounts.requiredForUpload + ? { invite: true } + : {} + )), async (ctx) => { const body = await ctx.req.json() if (!ctx.get("account")?.admin) { - if (!Configuration.accounts.registrationEnabled) - return ServeError(ctx, 403, "account registration disabled") + if (body.invite && !invites.has(body.invite)) + return ServeError(ctx, 400, "invite invalid") if (ctx.get("account")) return ServeError(ctx, 400, "you are already logged in") @@ -279,6 +285,9 @@ export default function (files: Files) { ) } + if (body.invite) + invites.use(body.invite) + return Accounts.create(body.username, body.password) .then((account) => { if (!ctx.get("account")) diff --git a/src/server/routes/api/v1/definition.ts b/src/server/routes/api/v1/definition.ts index 62091d5..9adc151 100644 --- a/src/server/routes/api/v1/definition.ts +++ b/src/server/routes/api/v1/definition.ts @@ -29,6 +29,10 @@ export default { "file": "file/individual", "to": "/file" }, + { + "file": "/server/invites", + "to": "/server/invites" + }, { "file": "/server/run", "to": "/server/run" diff --git a/src/server/routes/api/v1/server/invites.ts b/src/server/routes/api/v1/server/invites.ts new file mode 100644 index 0000000..658580f --- /dev/null +++ b/src/server/routes/api/v1/server/invites.ts @@ -0,0 +1,40 @@ +import { Hono } from "hono" +import * as Accounts from "../../../../lib/accounts.js" +import * as auth from "../../../../lib/auth.js" +import { HttpBindings } from "@hono/node-server" +import config, { ClientConfiguration } from "../../../../lib/config.js" +import type Files from "../../../../lib/files.js" +import { getAccount, requiresAccount, requiresAdmin } from "../../../../lib/middleware.js" +import { Writable } from "node:stream" +import { Db, make, use } from "../../../../lib/invites.js" +import ServeError from "../../../../lib/errors.js" + +const router = new Hono<{ + Variables: { + account: Accounts.Account + }, + Bindings: HttpBindings +}>() + +router.use(getAccount, requiresAccount, requiresAdmin) + +export default function(files: Files) { + + // api is structured like this + // in case invites become more complicated + // in the future + // if and when the api does become more complex + // i'll probably add GET /server/invites/:invite etc + + router.post("/", async (ctx) => ctx.json({id: make()})) + router.get("/", async (ctx) => ctx.json(Db.data.map(e => ({id: e})))) + router.delete("/:invite", async (ctx) => { + if (use(ctx.req.param("invite"))) { + return ctx.json({id: ctx.req.param("invite")}) + } else { + return ServeError(ctx, 404, "invalid invite") + } + }) + + return router +}