import type { DataVisibility, UserRole } from '@mento/shared'; import { canViewAllRecords } from '@mento/shared'; import type { Prisma } from '@prisma/client'; export type Actor = { userId: string; role: string; organizationId: string; /** own | team | org — از Membership */ dataVisibility?: DataVisibility; /** * شناسه کاربرانی که پرونده‌شان برای این Actor قابل‌مشاهده است. * اگر undefined باشد فقط خود کاربر؛ اگر null یعنی همه (elevated/org). */ visibleUserIds?: string[] | null; }; export function elevated(role: string | null | undefined): boolean { return canViewAllRecords(role); } export function seesAllRecords( actor: Pick, ): boolean { if (elevated(actor.role)) return true; if (actor.dataVisibility === 'org') return true; if (actor.visibleUserIds === null) return true; return false; } function scopedOwnerIds( actor: Pick, ): string[] | null { if (seesAllRecords(actor)) return null; const ids = actor.visibleUserIds?.length ? actor.visibleUserIds : [actor.userId]; return [...new Set(ids.filter(Boolean))]; } /** فیلتر مالکیت برای Deal / Quote / Invoice / Person / Company */ export function ownerWhere( actor: Pick, ): { ownerId: string } | { ownerId: { in: string[] } } | Record { const ids = scopedOwnerIds(actor); if (!ids) return {}; if (ids.length === 1) return { ownerId: ids[0]! }; return { ownerId: { in: ids } }; } /** فعالیت‌ها بر اساس مسئول */ export function assigneeWhere( actor: Pick, ): | { assigneeId: string } | { assigneeId: { in: string[] } } | Record { const ids = scopedOwnerIds(actor); if (!ids) return {}; if (ids.length === 1) return { assigneeId: ids[0]! }; return { assigneeId: { in: ids } }; } /** یادداشت: نویسنده یا پرونده‌های تحت مالکیت در محدوده دید */ export function noteAccessWhere( actor: Pick, ): Prisma.NoteWhereInput { const ids = scopedOwnerIds(actor); if (!ids) return {}; return { OR: [ { authorId: { in: ids } }, { deal: { ownerId: { in: ids } } }, { person: { ownerId: { in: ids } } }, { company: { ownerId: { in: ids } } }, ], }; } export function resolveOwnerId( actor: Pick, requested?: string | null, ): string { if (elevated(actor.role) && requested?.trim()) { return requested.trim(); } return actor.userId; } /** تیکت: مسئول یا ثبت‌کننده در محدوده دید */ export function ticketAccessWhere( actor: Pick, ): Prisma.TicketWhereInput { const ids = scopedOwnerIds(actor); if (!ids) return {}; return { OR: [{ assigneeId: { in: ids } }, { reporterId: { in: ids } }], }; } export function canReassignOwner(role: string | null | undefined): boolean { return elevated(role); } export type OrgRole = UserRole; export function normalizeDataVisibility( value: string | null | undefined, ): DataVisibility { if (value === 'team' || value === 'org' || value === 'own') return value; return 'own'; }