WuYongJie ba98bf22cc feat: 添加许可证系统、Agent部署模块和Harbor镜像管理
- 新增许可证服务器 (license-server/)
- 新增 Agent 部署模块 (flnxi-agent/)
- 添加许可证验证和激活页面
- 添加 Harbor 镜像同步脚本
- 更新素材系统支持许可证验证
2025-12-15 21:19:46 +08:00

167 lines
4.6 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/lib/prisma'
import bcrypt from 'bcryptjs'
import { canCreateUser } from '@/lib/license'
export async function POST(req: NextRequest) {
try {
// 检查许可证用户数量限制
const userLimit = await canCreateUser();
if (!userLimit.allowed) {
return NextResponse.json(
{ error: userLimit.message || '已达到用户数量上限' },
{ status: 403 }
)
}
// 检查注册功能是否开启
const settings = await prisma.systemSettings.findFirst()
if (settings && !settings.enableRegistration) {
return NextResponse.json(
{ error: '注册功能已关闭,请联系管理员' },
{ status: 403 }
)
}
const { email, username, department, password, inviteCode } = await req.json()
// Validation
if (!email || !username || !password) {
return NextResponse.json(
{ error: '所有字段都是必填的' },
{ status: 400 }
)
}
// 如果注册功能关闭,检查是否有有效的邀请码
if (settings && !settings.enableRegistration) {
if (!inviteCode) {
return NextResponse.json(
{ error: '注册功能已关闭,请使用邀请链接注册' },
{ status: 403 }
)
}
// 验证邀请码
const invitation = await prisma.invitation.findUnique({
where: { code: inviteCode },
})
if (!invitation || !invitation.isActive) {
return NextResponse.json(
{ error: '邀请码无效或已失效' },
{ status: 403 }
)
}
if (invitation.currentUses >= invitation.maxUses) {
return NextResponse.json(
{ error: '邀请码使用次数已用完' },
{ status: 403 }
)
}
if (invitation.expiresAt && new Date() > invitation.expiresAt) {
return NextResponse.json(
{ error: '邀请码已过期' },
{ status: 403 }
)
}
}
// Check if user exists
const existingUser = await prisma.user.findFirst({
where: {
OR: [{ email }, { username }],
},
})
if (existingUser) {
return NextResponse.json(
{ error: '邮箱或用户名已存在' },
{ status: 400 }
)
}
// Hash password
const hashedPassword = await bcrypt.hash(password, 10)
// 如果启用了用户激活功能,新用户默认未激活
const isActive = settings?.enableUserActivation ? false : true
// 使用事务确保首位用户判断的原子性,避免并发问题
const user = await prisma.$transaction(async (tx) => {
// 在事务中判断是否为首个注册用户(赋予最高权限)
const totalUsers = await tx.user.count()
const isFirstUser = totalUsers === 0
if (isFirstUser) {
console.log('🎉 首位用户注册,自动授予超级管理员权限:', { email, username })
}
// 如果指定了部门,查找该部门的管理员作为直属上级
let parentId: string | null = null
if (department && !isFirstUser) {
const departmentManager = await tx.user.findFirst({
where: {
managedDepartment: department,
role: 'ADMIN',
},
select: { id: true },
})
if (departmentManager) {
parentId = departmentManager.id
}
}
// Create user
const newUser = await tx.user.create({
data: {
email,
username,
department: department || '',
password: hashedPassword,
isActive,
parentId,
// 首位用户自动设为超级管理员,拥有最高权限
isSuperAdmin: isFirstUser,
role: isFirstUser ? 'ADMIN' : 'USER', // 首位用户同时设置为 ADMIN 角色
} as any,
})
// 如果使用了邀请码,更新邀请码使用记录
if (inviteCode) {
await tx.invitation.update({
where: { code: inviteCode },
data: {
currentUses: { increment: 1 },
usedBy: newUser.id,
usedAt: new Date(),
},
})
}
return newUser
})
return NextResponse.json(
{ message: '注册成功', user: {
id: user.id,
email: user.email,
username: user.username,
department: user.department,
role: user.role,
createdAt: user.createdAt,
}},
{ status: 201 }
)
} catch (error) {
console.error('Registration error:', error)
return NextResponse.json(
{ error: '注册失败,请稍后再试' },
{ status: 500 }
)
}
}