import { ForbiddenException } from '@nestjs/common'; import { type Actor, elevated, scopedOwnerIds } from '../common/record-scope'; import type { PrismaService } from '../prisma/prisma.service'; export type RoutineScope = { userId: string; organizationId: string; /** مالک/مدیر سازمان یا مدیر حداقل یک تیم */ isManager: boolean; /** کاربرانی که می‌تواند برایشان روتین/Task تعریف کند؛ null = همه */ manageableUserIds: string[] | null; /** کاربرانی که Taskهایشان را می‌بیند؛ null = همه */ viewableUserIds: string[] | null; }; export async function resolveRoutineScope( prisma: PrismaService, actor: Actor, ): Promise { const base = { userId: actor.userId, organizationId: actor.organizationId, }; if (elevated(actor.role)) { return { ...base, isManager: true, manageableUserIds: null, viewableUserIds: null }; } const managed = await prisma.teamMember.findMany({ where: { userId: actor.userId, role: 'manager', team: { organizationId: actor.organizationId } }, select: { teamId: true }, }); let manageable: string[] = [actor.userId]; if (managed.length) { const members = await prisma.teamMember.findMany({ where: { teamId: { in: managed.map((m) => m.teamId) } }, select: { userId: true }, }); manageable = [...new Set([actor.userId, ...members.map((m) => m.userId)])]; } const visible = scopedOwnerIds(actor, 'routines'); const viewable = visible === null ? null : [...new Set([...visible, ...manageable])]; return { ...base, isManager: managed.length > 0, manageableUserIds: manageable, viewableUserIds: viewable, }; } export function canView(scope: RoutineScope, userId: string): boolean { return scope.viewableUserIds === null || scope.viewableUserIds.includes(userId); } export function canManage(scope: RoutineScope, userId: string): boolean { return scope.manageableUserIds === null || scope.manageableUserIds.includes(userId); } export function assertManager(scope: RoutineScope): void { if (!scope.isManager) { throw new ForbiddenException('فقط مدیران به این بخش دسترسی دارند'); } } /** فیلتر Prisma روی assigneeId بر اساس دید کاربر و فیلتر کاربر درخواستی */ export function assigneeFilter( scope: RoutineScope, requestedUserId?: string | null, ): { assigneeId?: string | { in: string[] } } { if (requestedUserId) { if (!canView(scope, requestedUserId)) { throw new ForbiddenException('دسترسی به کارهای این کاربر ندارید'); } return { assigneeId: requestedUserId }; } if (scope.viewableUserIds === null) return {}; return { assigneeId: { in: scope.viewableUserIds } }; }