// 任务模块: 项目成员校验 (T-PM-01, B-13) // 所有 /api/projects/:id/* 与任务写操作都必须确认请求者是项目成员. import { prisma } from '../db.js' /** 取出当前用户可访问的项目 (不存在或非成员 -> null) */ export async function loadProjectForUser(projectId, userId) { const id = Number(projectId) if (!Number.isInteger(id) || id <= 0) return null const project = await prisma.project.findFirst({ where: { id, members: { some: { userId } } }, }) return project || null } /** 任务 -> 校验其项目可访问, 返回 { task, project } */ export async function loadTaskForUser(taskId, userId) { const id = Number(taskId) if (!Number.isInteger(id) || id <= 0) return null const task = await prisma.task.findFirst({ where: { id, project: { members: { some: { userId } } } }, include: { column: true, assignee: { select: { id: true, name: true } }, creator: { select: { id: true, name: true } }, members: { include: { user: { select: { id: true, name: true } } } }, tags: true, children: { include: { column: true, assignee: { select: { id: true, name: true } }, members: { include: { user: { select: { id: true, name: true } } } }, tags: true, }, orderBy: [{ sortOrder: 'asc' }, { id: 'asc' }], }, }, }) if (!task) return null const project = await prisma.project.findUnique({ where: { id: task.projectId } }) return { task, project } } /** 项目全部列 (按显示顺序) */ export async function loadColumns(projectId) { return prisma.boardColumn.findMany({ where: { projectId: Number(projectId) }, orderBy: [{ sortOrder: 'asc' }, { id: 'asc' }], }) } /** 项目成员 userId 集合 */ export async function loadMemberIds(projectId) { const rows = await prisma.projectMember.findMany({ where: { projectId: Number(projectId) }, select: { userId: true }, }) return rows.map((r) => r.userId) }