fix(activities): allow assignees to attach files when commenting under creator-only edit

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-11-12 09:49:22 +03:30
co-authored by Cursor
parent 68fcece743
commit 453ff1a5f6
+14 -6
View File
@@ -99,7 +99,9 @@ function canCollaborateActivity(
/** فقط dueAt / description → تعویق و ثبت نظر */ /** فقط dueAt / description → تعویق و ثبت نظر */
function isCollaboratorPatch(dto: UpdateActivityRequest): boolean { function isCollaboratorPatch(dto: UpdateActivityRequest): boolean {
const keys = Object.keys(dto); const keys = Object.keys(dto).filter(
(key) => (dto as Record<string, unknown>)[key] !== undefined,
);
return keys.length > 0 && keys.every((key) => key === 'dueAt' || key === 'description'); return keys.length > 0 && keys.every((key) => key === 'dueAt' || key === 'description');
} }
@@ -1199,8 +1201,9 @@ export class ActivitiesService {
assignees: { select: { id: true } }, assignees: { select: { id: true } },
}, },
}); });
if (!gate || !canMutateActivity(actor, gate)) { // پیوست در مسیر ثبت نظر — مسئولان هم مجازند حتی با editPolicy=creator
throw new ForbiddenException('شما مجوز ویرایش این فعالیت را ندارید'); if (!gate || !canCollaborateActivity(actor, gate)) {
throw new ForbiddenException('شما مجوز ثبت نظر یا پیوست برای این فعالیت را ندارید');
} }
if (!file?.buffer?.length) { if (!file?.buffer?.length) {
throw new BadRequestException('فایلی ارسال نشده است'); throw new BadRequestException('فایلی ارسال نشده است');
@@ -1305,13 +1308,18 @@ export class ActivitiesService {
assignees: { select: { id: true } }, assignees: { select: { id: true } },
}, },
}); });
if (!gate || !canMutateActivity(actor, gate)) {
throw new ForbiddenException('شما مجوز ویرایش این فعالیت را ندارید');
}
const row = await this.prisma.activityImage.findFirst({ const row = await this.prisma.activityImage.findFirst({
where: { id: imageId, activityId, organizationId }, where: { id: imageId, activityId, organizationId },
}); });
if (!row) throw new NotFoundException('فایل پیدا نشد'); if (!row) throw new NotFoundException('فایل پیدا نشد');
const canMutate = !!gate && canMutateActivity(actor, gate);
const canRemoveOwn =
!!gate &&
canCollaborateActivity(actor, gate) &&
row.uploadedById === actor.userId;
if (!canMutate && !canRemoveOwn) {
throw new ForbiddenException('شما مجوز حذف این پیوست را ندارید');
}
await this.files.remove(row.storageKey); await this.files.remove(row.storageKey);
await this.prisma.activityImage.delete({ where: { id: row.id } }); await this.prisma.activityImage.delete({ where: { id: row.id } });
await this.storage.addLocal(organizationId, -row.sizeBytes); await this.storage.addLocal(organizationId, -row.sizeBytes);