feat: routines module; super admin subscription badge, 7-day trial and lifetime plan
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
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<RoutineScope> {
|
||||
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 } };
|
||||
}
|
||||
Reference in New Issue
Block a user