diff --git a/pages/admin/users/auth/simple/index.vue b/pages/admin/users/auth/simple/index.vue index 8d6a8ac..e58189f 100644 --- a/pages/admin/users/auth/simple/index.vue +++ b/pages/admin/users/auth/simple/index.vue @@ -360,6 +360,9 @@ :loading="loading" type="submit" class="w-full sm:w-fit" + :disabled=" + !(validUsername && validEmail && username && email) + " > {{ $t("users.admin.simple.inviteButton") }} diff --git a/server/api/v1/admin/auth/invitation/index.post.ts b/server/api/v1/admin/auth/invitation/index.post.ts index 90ad5e7..d1e97ff 100644 --- a/server/api/v1/admin/auth/invitation/index.post.ts +++ b/server/api/v1/admin/auth/invitation/index.post.ts @@ -1,18 +1,14 @@ -import { type } from "arktype"; import { readDropValidatedBody, throwingArktype } from "~/server/arktype"; import aclManager from "~/server/internal/acls"; import prisma from "~/server/internal/db/database"; +import { CreateUserValidator } from "../../../auth/signup/simple.post"; -const CreateInvite = type({ - isAdmin: "boolean?", - username: "string?", - email: "string.email?", - expires: "string.date.iso.parse", +const CreateInvite = CreateUserValidator.and({ + expires: "Date", + isAdmin: "boolean = false", }).configure(throwingArktype); -export default defineEventHandler<{ - body: typeof CreateInvite.infer; -}>(async (h3) => { +export default defineEventHandler(async (h3) => { const allowed = await aclManager.allowSystemACL(h3, [ "auth:simple:invitation:new", ]); @@ -20,6 +16,8 @@ export default defineEventHandler<{ const body = await readDropValidatedBody(h3, CreateInvite); + console.log(body); + const invitation = await prisma.invitation.create({ data: body, }); diff --git a/server/api/v1/auth/signup/simple.post.ts b/server/api/v1/auth/signup/simple.post.ts index 5541ec3..4ff2a16 100644 --- a/server/api/v1/auth/signup/simple.post.ts +++ b/server/api/v1/auth/signup/simple.post.ts @@ -5,21 +5,22 @@ import * as jdenticon from "jdenticon"; import objectHandler from "~/server/internal/objects"; import { type } from "arktype"; import { randomUUID } from "node:crypto"; +import { throwingArktype } from "~/server/arktype"; -const userValidator = type({ - invitation: "string", +export const CreateUserValidator = type({ + invitation: "string?", // Optional because we re-use this validator username: "string >= 5", email: "string.email", password: "string >= 14", "displayName?": "string | undefined", -}); +}).configure(throwingArktype); export default defineEventHandler<{ - body: typeof userValidator.infer; + body: typeof CreateUserValidator.infer; }>(async (h3) => { - const body = await readBody(h3); + const user = await readValidatedBody(h3, CreateUserValidator); - const invitationId = body.invitation; + const invitationId = user.invitation; if (!invitationId) throw createError({ statusCode: 401, @@ -35,17 +36,6 @@ export default defineEventHandler<{ statusMessage: "Invalid or expired invitation.", }); - const user = userValidator(body); - if (user instanceof type.errors) { - // hover out.summary to see validation errors - console.error(user.summary); - - throw createError({ - statusCode: 400, - statusMessage: user.summary, - }); - } - // reuse items from invite if (invitation.username !== null) user.username = invitation.username; if (invitation.email !== null) user.email = invitation.email;