168 lines
6.1 KiB
TypeScript
168 lines
6.1 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
import { Prisma } from '@prisma/client'
|
|
import { getServerSession } from 'next-auth'
|
|
import { authOptions } from '@/lib/auth'
|
|
import { prisma } from '@/lib/prisma'
|
|
import { isSuperAdmin } from '@/lib/department-permission'
|
|
import { BINDING_STATUS } from '@/lib/employee-directory'
|
|
import { findNearestGroupMemberships } from '@/lib/organization-material-permissions'
|
|
import { ensureDefaultPermissionPacks } from '@/lib/user-permission-inherit'
|
|
|
|
async function requireSuperAdmin() {
|
|
const session = await getServerSession(authOptions)
|
|
const userId = (session?.user as { id?: string } | undefined)?.id
|
|
if (!session || !(await isSuperAdmin(userId))) return null
|
|
return session
|
|
}
|
|
|
|
export async function GET(request: NextRequest) {
|
|
try {
|
|
if (!(await requireSuperAdmin())) {
|
|
return NextResponse.json({ error: '需要超级管理员权限' }, { status: 403 })
|
|
}
|
|
|
|
await ensureDefaultPermissionPacks()
|
|
|
|
const keyword = String(new URL(request.url).searchParams.get('q') || '').trim()
|
|
if (keyword.length < 1) {
|
|
return NextResponse.json({ people: [], groups: [] })
|
|
}
|
|
|
|
const [bindings, packs] = await Promise.all([
|
|
prisma.userEmployeeBinding.findMany({
|
|
where: {
|
|
status: BINDING_STATUS.ACTIVE,
|
|
user: { isActive: true, dingtalkUserId: { not: null } },
|
|
OR: [
|
|
{ user: { username: { contains: keyword, mode: 'insensitive' } } },
|
|
{ user: { realName: { contains: keyword, mode: 'insensitive' } } },
|
|
{ employeeProfile: { displayName: { contains: keyword, mode: 'insensitive' } } },
|
|
{ employeeProfile: { jobNumber: { contains: keyword, mode: 'insensitive' } } },
|
|
],
|
|
},
|
|
take: 20,
|
|
select: {
|
|
userId: true,
|
|
user: {
|
|
select: {
|
|
username: true,
|
|
realName: true,
|
|
permissionInherits: {
|
|
select: { pack: { select: { slug: true, name: true } } },
|
|
},
|
|
},
|
|
},
|
|
employeeProfile: {
|
|
select: { displayName: true, departmentPath: true, departmentName: true, jobNumber: true },
|
|
},
|
|
},
|
|
}),
|
|
prisma.materialPermissionPack.findMany({
|
|
orderBy: { name: 'asc' },
|
|
select: { id: true, slug: true, name: true },
|
|
}),
|
|
])
|
|
|
|
const departmentRows = await prisma.materialPermissionPackDepartment
|
|
.findMany({
|
|
select: { packId: true, departmentPath: true },
|
|
})
|
|
.catch((error) => {
|
|
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === 'P2021') {
|
|
return [] as Array<{ packId: string; departmentPath: string }>
|
|
}
|
|
throw error
|
|
})
|
|
|
|
const memberships = departmentRows.flatMap((row) => {
|
|
const pack = packs.find((item) => item.id === row.packId)
|
|
if (!pack) return []
|
|
return [{ departmentPath: row.departmentPath, slug: pack.slug, name: pack.name }]
|
|
})
|
|
|
|
return NextResponse.json({
|
|
groups: packs.map((pack) => ({ slug: pack.slug, name: pack.name })),
|
|
people: bindings.map((binding) => {
|
|
const path = binding.employeeProfile.departmentPath
|
|
const nearest = path ? findNearestGroupMemberships(path, memberships) : null
|
|
const personalGroups = binding.user.permissionInherits.map((row) => ({
|
|
slug: row.pack.slug,
|
|
name: row.pack.name,
|
|
}))
|
|
return {
|
|
userId: binding.userId,
|
|
username: binding.user.username,
|
|
displayName: binding.employeeProfile.displayName || binding.user.realName || binding.user.username,
|
|
jobNumber: binding.employeeProfile.jobNumber,
|
|
departmentPath: path,
|
|
departmentName: binding.employeeProfile.departmentName,
|
|
departmentGroups: nearest
|
|
? nearest.items.map((item) => ({
|
|
slug: item.slug,
|
|
name: item.name,
|
|
attachedPath: nearest.attachedPath,
|
|
source: nearest.attachedPath === path ? 'own' : 'inherit',
|
|
}))
|
|
: [],
|
|
personalGroups,
|
|
}
|
|
}),
|
|
})
|
|
} catch (error) {
|
|
console.error('[user-permissions] GET failed', error)
|
|
return NextResponse.json({ error: '搜索人员权限失败' }, { status: 500 })
|
|
}
|
|
}
|
|
|
|
export async function PUT(request: NextRequest) {
|
|
try {
|
|
if (!(await requireSuperAdmin())) {
|
|
return NextResponse.json({ error: '需要超级管理员权限' }, { status: 403 })
|
|
}
|
|
|
|
const body = await request.json()
|
|
const action = String(body?.action || '').trim()
|
|
const userId = String(body?.userId || '').trim()
|
|
const slug = String(body?.slug || '').trim()
|
|
if (!userId) return NextResponse.json({ error: '请选择人员' }, { status: 400 })
|
|
if (!slug) return NextResponse.json({ error: '缺少权限组' }, { status: 400 })
|
|
|
|
const [user, pack] = await Promise.all([
|
|
prisma.user.findUnique({
|
|
where: { id: userId },
|
|
select: { id: true, dingtalkUserId: true },
|
|
}),
|
|
prisma.materialPermissionPack.findUnique({
|
|
where: { slug },
|
|
select: { id: true },
|
|
}),
|
|
])
|
|
if (!user) return NextResponse.json({ error: '没有这个账号' }, { status: 400 })
|
|
if (!user.dingtalkUserId) {
|
|
return NextResponse.json({ error: '这个账号没有钉钉绑定,不能进权限组' }, { status: 400 })
|
|
}
|
|
if (!pack) return NextResponse.json({ error: '没有这个权限组' }, { status: 400 })
|
|
|
|
if (action === 'remove-member') {
|
|
await prisma.userPermissionInherit.deleteMany({
|
|
where: { userId, packId: pack.id },
|
|
})
|
|
return NextResponse.json({ ok: true })
|
|
}
|
|
|
|
if (action === 'add-member') {
|
|
await prisma.userPermissionInherit.upsert({
|
|
where: { userId_packId: { userId, packId: pack.id } },
|
|
update: {},
|
|
create: { userId, packId: pack.id },
|
|
})
|
|
return NextResponse.json({ ok: true })
|
|
}
|
|
|
|
return NextResponse.json({ error: '不认识这个操作' }, { status: 400 })
|
|
} catch (error) {
|
|
console.error('[user-permissions] PUT failed', error)
|
|
return NextResponse.json({ error: '保存人员权限失败' }, { status: 500 })
|
|
}
|
|
}
|