barebones invite api

This commit is contained in:
split / May 2024-06-17 16:43:19 -07:00
parent 1703320b84
commit 426e057f12
4 changed files with 92 additions and 4 deletions

35
src/server/lib/invites.ts Normal file
View file

@ -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<string[]>("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()

View file

@ -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"))

View file

@ -29,6 +29,10 @@ export default {
"file": "file/individual",
"to": "/file"
},
{
"file": "/server/invites",
"to": "/server/invites"
},
{
"file": "/server/run",
"to": "/server/run"

View file

@ -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
}