feat(roles): let each section decide who may assign work to others
Section access now only creates a record for yourself. Assigning it to a colleague requires a separate permission on that section. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -30,6 +30,7 @@ import {
|
||||
dealAccessWhere,
|
||||
ownerWhere,
|
||||
} from '../common/record-scope';
|
||||
import { assertAssigneeSet } from '../common/assign-access';
|
||||
import { normalizeTags } from '../common/tags';
|
||||
import { GamificationService } from '../gamification/gamification.service';
|
||||
import { tehranDayKey } from '../routines/routine-dates';
|
||||
@@ -566,6 +567,12 @@ export class ActivitiesService {
|
||||
? [dto.assigneeId]
|
||||
: [userId],
|
||||
);
|
||||
await assertAssigneeSet(
|
||||
this.prisma,
|
||||
{ userId, role: linkActor.role, organizationId },
|
||||
'activities',
|
||||
assigneeIds,
|
||||
);
|
||||
const assigneeId = assigneeIds[0] ?? userId;
|
||||
const initialStageId = emptyToNull(dto.stageId ?? null);
|
||||
const initialStage = initialStageId
|
||||
@@ -587,6 +594,12 @@ export class ActivitiesService {
|
||||
resolved.fields,
|
||||
dto.fields,
|
||||
);
|
||||
await assertAssigneeSet(
|
||||
this.prisma,
|
||||
{ userId, role: linkActor.role, organizationId },
|
||||
'activities',
|
||||
participantIds,
|
||||
);
|
||||
|
||||
const row = await this.prisma.activity.create({
|
||||
data: {
|
||||
@@ -723,6 +736,13 @@ export class ActivitiesService {
|
||||
data.typeDefId = resolved.typeDefId;
|
||||
data.fields = fields as Prisma.InputJsonValue;
|
||||
data.participantIds = participantIds;
|
||||
await assertAssigneeSet(
|
||||
this.prisma,
|
||||
{ userId: actor.userId, role: actor.role, organizationId },
|
||||
'activities',
|
||||
participantIds,
|
||||
existing?.participantIds ?? [],
|
||||
);
|
||||
const before = new Set(existing?.participantIds ?? []);
|
||||
addedParticipants = participantIds.filter((uid) => !before.has(uid) && uid !== actor.userId);
|
||||
}
|
||||
@@ -748,22 +768,47 @@ export class ActivitiesService {
|
||||
if ('companyId' in dto) data.companyId = emptyToNull(dto.companyId ?? null);
|
||||
if ('dealId' in dto) data.dealId = emptyToNull(dto.dealId ?? null);
|
||||
let assigneeConnect: Array<{ id: string }> | undefined;
|
||||
if (dto.assigneeIds !== undefined) {
|
||||
const assigneeIds = await this.normalizeAssigneeIds(
|
||||
organizationId,
|
||||
dto.assigneeIds,
|
||||
);
|
||||
if (!assigneeIds.length) {
|
||||
throw new BadRequestException('حداقل یک مسئول لازم است');
|
||||
if (dto.assigneeIds !== undefined || 'assigneeId' in dto) {
|
||||
const current = await this.prisma.activity.findFirst({
|
||||
where: { id, organizationId },
|
||||
select: { assigneeId: true, assignees: { select: { id: true } } },
|
||||
});
|
||||
const previous = current?.assignees.length
|
||||
? current.assignees.map((item) => item.id)
|
||||
: current?.assigneeId
|
||||
? [current.assigneeId]
|
||||
: [];
|
||||
if (dto.assigneeIds !== undefined) {
|
||||
const assigneeIds = await this.normalizeAssigneeIds(
|
||||
organizationId,
|
||||
dto.assigneeIds,
|
||||
);
|
||||
if (!assigneeIds.length) {
|
||||
throw new BadRequestException('حداقل یک مسئول لازم است');
|
||||
}
|
||||
await assertAssigneeSet(
|
||||
this.prisma,
|
||||
{ userId: actor.userId, role: actor.role, organizationId },
|
||||
'activities',
|
||||
assigneeIds,
|
||||
previous,
|
||||
);
|
||||
data.assigneeId = assigneeIds[0]!;
|
||||
assigneeConnect = assigneeIds.map((uid) => ({ id: uid }));
|
||||
} else {
|
||||
const assigneeId = emptyToNull(dto.assigneeId ?? null);
|
||||
if (assigneeId) await this.assertUserInOrg(organizationId, assigneeId);
|
||||
await assertAssigneeSet(
|
||||
this.prisma,
|
||||
{ userId: actor.userId, role: actor.role, organizationId },
|
||||
'activities',
|
||||
[assigneeId],
|
||||
previous,
|
||||
);
|
||||
data.assigneeId = assigneeId;
|
||||
if (assigneeId) assigneeConnect = [{ id: assigneeId }];
|
||||
else assigneeConnect = [];
|
||||
}
|
||||
data.assigneeId = assigneeIds[0]!;
|
||||
assigneeConnect = assigneeIds.map((uid) => ({ id: uid }));
|
||||
} else if ('assigneeId' in dto) {
|
||||
const assigneeId = emptyToNull(dto.assigneeId ?? null);
|
||||
if (assigneeId) await this.assertUserInOrg(organizationId, assigneeId);
|
||||
data.assigneeId = assigneeId;
|
||||
if (assigneeId) assigneeConnect = [{ id: assigneeId }];
|
||||
else assigneeConnect = [];
|
||||
}
|
||||
if (dto.status !== undefined) {
|
||||
data.status = dto.status;
|
||||
|
||||
Reference in New Issue
Block a user