Files
ysj7705andCursor 3fa4ae2b66 Add everyone system user for anonymous registry pull.
Reserved PUBLIC ACLs can grant unauthenticated pull while blocking login, deletion, and anonymous push/delete.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-06 17:12:27 +09:00

66 lines
1.7 KiB
TypeScript

import { z } from 'zod'
const aclSchema = z.object({
repository: z.string().min(1),
canPull: z.boolean().default(true),
canPush: z.boolean().default(false),
canDelete: z.boolean().default(false),
})
const bodySchema = z.object({
username: z
.string()
.min(1)
.max(64)
.regex(/^[a-zA-Z0-9._-]+$/, 'Username may contain letters, numbers, . _ -'),
password: z.string().min(6),
role: z.enum(['ADMIN', 'USER']).default('USER'),
active: z.boolean().default(true),
acls: z.array(aclSchema).default([]),
})
export default defineEventHandler(async (event) => {
await requireAdmin(event)
await ensureBootstrap()
const body = bodySchema.parse(await readBody(event))
if (isEveryoneUsername(body.username)) {
throw createError({ statusCode: 409, statusMessage: 'Username "everyone" is reserved' })
}
const existing = await prisma.user.findUnique({ where: { username: body.username } })
if (existing) {
throw createError({ statusCode: 409, statusMessage: 'Username already exists' })
}
const user = await prisma.user.create({
data: {
username: body.username,
passwordHash: await hashPassword(body.password),
role: body.role,
active: body.active,
acls: {
create: body.acls.map((acl) => ({
repository: acl.repository,
canPull: acl.canPull,
canPush: acl.canPush,
canDelete: acl.canDelete,
})),
},
},
include: { acls: true },
})
return {
user: {
id: user.id,
username: user.username,
role: user.role,
active: user.active,
createdAt: user.createdAt,
updatedAt: user.updatedAt,
acls: user.acls,
},
}
})