basic suspension implementation

!! NOT READY WAIT FOR CLIENT-V2 SO WE CAN NUKE V0
This commit is contained in:
May 2024-05-01 18:39:38 +00:00 committed by GitHub
parent 60b0308e31
commit 459c40bece
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 35 additions and 18 deletions

View file

@ -9,7 +9,10 @@ import { z } from "zod"
* @description Middleware which adds an account, if any, to ctx.get("account")
*/
export const getAccount: RequestHandler = function (ctx, next) {
ctx.set("account", Accounts.getFromToken(auth.tokenFor(ctx)!))
let account = Accounts.getFromToken(auth.tokenFor(ctx)!)
if (account?.suspension)
setCookie(ctx, "auth", "")
ctx.set("account", account)
return next()
}

View file

@ -53,7 +53,11 @@ export namespace Settings {
interface: Interface.default({}), links: Links.default({})
})
}
export const Suspension =
z.object({
reason: z.string(),
until: z.number().nullable()
})
export const Account =
z.object({
id: z.string(),
@ -64,5 +68,6 @@ export const Account =
admin: z.boolean(),
defaultFileVisibility: FileVisibility,
settings: Settings.User
settings: Settings.User,
suspension: Suspension.optional()
})

View file

@ -101,9 +101,7 @@ const validators: {
return undefined
}
if (!z.string().email().safeParse(typeof params.email).success)
return [400, "bad email"]
if (actor.admin) return params.email
if (actor.admin) return params.email || undefined
// send verification email
@ -191,6 +189,13 @@ const validators: {
else return [400, "cannot demote an admin"]
}
},
suspension: {
schema: AccountSchemas.Suspension.nullable(),
validator: (actor, target, params) => {
if (!actor.admin) return [400, "only admins can modify suspensions"]
return params.suspension || undefined
}
},
settings: {
schema: AccountSchemas.Settings.User.partial(),
validator: (actor, target, params) => {

View file

@ -34,16 +34,24 @@ export default function (files: Files) {
})), async (ctx) => {
const body = await ctx.req.json()
if (auth.validate(getCookie(ctx, "auth")!)) {
ServeError(ctx, 400, "you are already logged in")
return
}
if (ctx.get("account"))
return ServeError(ctx, 400, "you are already logged in")
const account = Accounts.getFromUsername(body.username)
if (!account || !Accounts.password.check(account.id, body.password)) {
ServeError(ctx, 400, "username or password incorrect")
return
return ServeError(ctx, 400, "username or password incorrect")
}
if (account.suspension) {
if (account.suspension.until && Date.now() > account.suspension.until) delete account.suspension;
else return ServeError(
ctx,
403,
`account ${account.suspension.until
? `suspended until ${new Date(account.suspension.until).toUTCString()}`
: "suspended indefinitely"
}: ${account.suspension.reason}`)
}
login(ctx, account.id)
@ -59,12 +67,8 @@ export default function (files: Files) {
})
})
router.delete("/", (ctx) => {
if (!auth.validate(getCookie(ctx, "auth")!)) {
return ServeError(ctx, 401, "not logged in")
}
auth.invalidate(getCookie(ctx, "auth")!)
router.delete("/", requiresAccount, (ctx) => {
auth.invalidate(auth.tokenFor(ctx)!)
return ctx.text("logged out")
})