Skip to content

Commit 57593a6

Browse files
fix(api): send task-assignee email to only new assignee, not to all admins (#2107)
Co-authored-by: chasprowebdev <chasgarciaprowebdev@gmail.com>
1 parent c547f28 commit 57593a6

1 file changed

Lines changed: 73 additions & 198 deletions

File tree

apps/api/src/tasks/task-notifier.service.ts

Lines changed: 73 additions & 198 deletions
Original file line numberDiff line numberDiff line change
@@ -239,74 +239,41 @@ export class TaskNotifierService {
239239
const { organizationId, taskIds, newAssigneeId, changedByUserId } = params;
240240

241241
try {
242-
const [
243-
organization,
244-
changedByUser,
245-
tasks,
246-
allMembers,
247-
newAssigneeMember,
248-
] = await Promise.all([
249-
db.organization.findUnique({
250-
where: { id: organizationId },
251-
select: { name: true },
252-
}),
253-
db.user.findUnique({
254-
where: { id: changedByUserId },
255-
select: { name: true, email: true },
256-
}),
257-
db.task.findMany({
258-
where: {
259-
id: { in: taskIds },
260-
organizationId,
261-
},
262-
select: {
263-
id: true,
264-
title: true,
265-
},
266-
}),
267-
db.member.findMany({
268-
where: {
269-
organizationId,
270-
deactivated: false,
271-
},
272-
select: {
273-
id: true,
274-
role: true,
275-
user: {
276-
select: {
277-
id: true,
278-
name: true,
279-
email: true,
280-
},
242+
const [organization, changedByUser, tasks, newAssigneeMember] =
243+
await Promise.all([
244+
db.organization.findUnique({
245+
where: { id: organizationId },
246+
select: { name: true },
247+
}),
248+
db.user.findUnique({
249+
where: { id: changedByUserId },
250+
select: { name: true, email: true },
251+
}),
252+
db.task.findMany({
253+
where: {
254+
id: { in: taskIds },
255+
organizationId,
281256
},
282-
},
283-
}),
284-
newAssigneeId
285-
? db.member.findUnique({
286-
where: { id: newAssigneeId },
287-
select: {
288-
user: {
289-
select: {
290-
id: true,
291-
name: true,
292-
email: true,
257+
select: {
258+
id: true,
259+
title: true,
260+
},
261+
}),
262+
newAssigneeId
263+
? db.member.findUnique({
264+
where: { id: newAssigneeId },
265+
select: {
266+
user: {
267+
select: {
268+
id: true,
269+
name: true,
270+
email: true,
271+
},
293272
},
294273
},
295-
},
296-
})
297-
: Promise.resolve(null),
298-
]);
299-
300-
// Filter for admins/owners (roles can be comma-separated, e.g., "admin,auditor")
301-
const adminMembers = allMembers.filter(
302-
(member) =>
303-
member.role &&
304-
(member.role.includes('admin') || member.role.includes('owner')),
305-
);
306-
307-
this.logger.debug(
308-
`[notifyBulkAssigneeChange] Found ${allMembers.length} total members, ${adminMembers.length} admins/owners for organization ${organizationId}`,
309-
);
274+
})
275+
: Promise.resolve(null),
276+
]);
310277

311278
const organizationName = organization?.name ?? 'your organization';
312279
const changedByName =
@@ -319,17 +286,12 @@ export class TaskNotifierService {
319286
'Unassigned'
320287
: 'Unassigned';
321288

322-
// Build recipient list: new assignee + admins, excluding actor
323-
const recipientMap = new Map<
324-
string,
325-
{ id: string; name: string; email: string }
326-
>();
327-
328-
// Add new assignee if exists
289+
// Notify only the new assignee (the person who was assigned the tasks), excluding the actor
290+
const recipients: { id: string; name: string; email: string }[] = [];
329291
if (newAssigneeMember?.user?.id && newAssigneeMember.user.email) {
330292
const userId = newAssigneeMember.user.id;
331293
if (userId !== changedByUserId) {
332-
recipientMap.set(userId, {
294+
recipients.push({
333295
id: userId,
334296
name:
335297
newAssigneeMember.user.name?.trim() ||
@@ -339,23 +301,6 @@ export class TaskNotifierService {
339301
});
340302
}
341303
}
342-
343-
// Add admin members
344-
for (const member of adminMembers) {
345-
if (member.user?.id && member.user.email) {
346-
const userId = member.user.id;
347-
if (userId !== changedByUserId) {
348-
recipientMap.set(userId, {
349-
id: userId,
350-
name:
351-
member.user.name?.trim() || member.user.email?.trim() || 'User',
352-
email: member.user.email,
353-
});
354-
}
355-
}
356-
}
357-
358-
const recipients = Array.from(recipientMap.values());
359304
const taskCount = tasks.length;
360305

361306
const appUrl =
@@ -677,78 +622,45 @@ export class TaskNotifierService {
677622
} = params;
678623

679624
try {
680-
const [
681-
organization,
682-
changedByUser,
683-
oldAssigneeMember,
684-
newAssigneeMember,
685-
allMembers,
686-
] = await Promise.all([
687-
db.organization.findUnique({
688-
where: { id: organizationId },
689-
select: { name: true },
690-
}),
691-
db.user.findUnique({
692-
where: { id: changedByUserId },
693-
select: { name: true, email: true },
694-
}),
695-
oldAssigneeId
696-
? db.member.findUnique({
697-
where: { id: oldAssigneeId },
698-
select: {
699-
user: {
700-
select: {
701-
id: true,
702-
name: true,
703-
email: true,
625+
const [organization, changedByUser, oldAssigneeMember, newAssigneeMember] =
626+
await Promise.all([
627+
db.organization.findUnique({
628+
where: { id: organizationId },
629+
select: { name: true },
630+
}),
631+
db.user.findUnique({
632+
where: { id: changedByUserId },
633+
select: { name: true, email: true },
634+
}),
635+
oldAssigneeId
636+
? db.member.findUnique({
637+
where: { id: oldAssigneeId },
638+
select: {
639+
user: {
640+
select: {
641+
id: true,
642+
name: true,
643+
email: true,
644+
},
704645
},
705646
},
706-
},
707-
})
708-
: Promise.resolve(null),
709-
newAssigneeId
710-
? db.member.findUnique({
711-
where: { id: newAssigneeId },
712-
select: {
713-
user: {
714-
select: {
715-
id: true,
716-
name: true,
717-
email: true,
647+
})
648+
: Promise.resolve(null),
649+
newAssigneeId
650+
? db.member.findUnique({
651+
where: { id: newAssigneeId },
652+
select: {
653+
user: {
654+
select: {
655+
id: true,
656+
name: true,
657+
email: true,
658+
},
718659
},
719660
},
720-
},
721-
})
722-
: Promise.resolve(null),
723-
db.member.findMany({
724-
where: {
725-
organizationId,
726-
deactivated: false,
727-
},
728-
select: {
729-
id: true,
730-
role: true,
731-
user: {
732-
select: {
733-
id: true,
734-
name: true,
735-
email: true,
736-
},
737-
},
738-
},
739-
}),
740-
]);
741-
742-
// Filter for admins/owners (roles can be comma-separated, e.g., "admin,auditor")
743-
const adminMembers = allMembers.filter(
744-
(member) =>
745-
member.role &&
746-
(member.role.includes('admin') || member.role.includes('owner')),
747-
);
748-
749-
this.logger.debug(
750-
`[notifyAssigneeChange] Found ${allMembers.length} total members, ${adminMembers.length} admins/owners for organization ${organizationId}`,
751-
);
661+
})
662+
: Promise.resolve(null),
663+
]);
752664

753665
const organizationName = organization?.name ?? 'your organization';
754666
const changedByName =
@@ -766,32 +678,12 @@ export class TaskNotifierService {
766678
'Unassigned'
767679
: 'Unassigned';
768680

769-
// Build recipient list: old assignee + new assignee + admins, excluding actor
770-
const recipientMap = new Map<
771-
string,
772-
{ id: string; name: string; email: string }
773-
>();
774-
775-
// Add old assignee if exists
776-
if (oldAssigneeMember?.user?.id && oldAssigneeMember.user.email) {
777-
const userId = oldAssigneeMember.user.id;
778-
if (userId !== changedByUserId) {
779-
recipientMap.set(userId, {
780-
id: userId,
781-
name:
782-
oldAssigneeMember.user.name?.trim() ||
783-
oldAssigneeMember.user.email?.trim() ||
784-
'User',
785-
email: oldAssigneeMember.user.email,
786-
});
787-
}
788-
}
789-
790-
// Add new assignee if exists
681+
// Notify only the new assignee (the person who was assigned to the task), excluding the actor
682+
const recipients: { id: string; name: string; email: string }[] = [];
791683
if (newAssigneeMember?.user?.id && newAssigneeMember.user.email) {
792684
const userId = newAssigneeMember.user.id;
793685
if (userId !== changedByUserId) {
794-
recipientMap.set(userId, {
686+
recipients.push({
795687
id: userId,
796688
name:
797689
newAssigneeMember.user.name?.trim() ||
@@ -802,23 +694,6 @@ export class TaskNotifierService {
802694
}
803695
}
804696

805-
// Add admin members
806-
for (const member of adminMembers) {
807-
if (member.user?.id && member.user.email) {
808-
const userId = member.user.id;
809-
if (userId !== changedByUserId) {
810-
recipientMap.set(userId, {
811-
id: userId,
812-
name:
813-
member.user.name?.trim() || member.user.email?.trim() || 'User',
814-
email: member.user.email,
815-
});
816-
}
817-
}
818-
}
819-
820-
const recipients = Array.from(recipientMap.values());
821-
822697
const appUrl =
823698
process.env.NEXT_PUBLIC_APP_URL ??
824699
process.env.BETTER_AUTH_URL ??

0 commit comments

Comments
 (0)