Problem/Motivation

If you have a single page load (or in my case, hook_cron() invocation) that's triggering multiple group_notify events, users can get duplicate notifications for the same group content.

This is because of how the protected NotifyGroupNode::$recipients array is handled.

  1. group_notify_notify() gets the content plugin: $plugin = $entity->getContentPlugin();
  2. group_notify_notify() calls $plugin->addRecipient($member); once for each group member.
  3. group_notify_notify() calls $plugin->sendNotification($params);, which inspects $this->recipients for the list of users to notify.

If this only happens once in a given request, all's well. But when a 2nd node is updated in the same request, we get into trouble. Step #1 above returns a link to the same plugin object. It's already got all the recipients from the initial notification. But step #2 happily adds them again, and step #3 means we get multiple emails for the 2nd node.

If there was a 3rd node being updated in the same request, everyone would get 3 emails.

If the nodes are in different groups, it's even worse, since it means that notification emails leak content to users who aren't members of the group. E.g. node 1 from group A goes out to everyone in group A. Then node 2 is updated in group B, all users of groups A and B see the emails for node 2. Folks in both groups see it as duplicates. But folks only in group A see it as access bypass.

Steps to reproduce

  1. Install group + group_notify (8.x-1.5 or 8.x-1.x-dev).
  2. Create a group type configured to use group_notify for a specific node type.
  3. Create two groups.
  4. Subscribe a user to both groups.
  5. Either programmatically create a node for each group in a single page load, or in my case, update both nodes in the same page load to set them to be published and use #3164688: Forced notification when a node is created or updated via API (not via UI forms) to get group_notify to send notifications.

The user should get 2 emails (one from each group). In reality, they'll get 3.

Proposed resolution

Clear out the recipients before computing who gets notified for a given message.

Remaining tasks

  1. Do it.
  2. Tests?
  3. Reviews / refinements.
  4. Commit.

User interface changes

Nope.

API changes

Maybe we should add NotifyGroupNode::clearRecipients() so group_notify_notify() has a way to clear recipients for each distinct message?

Or we could always clear $this->recipients inside NotifyGroupNode::sendNotifications(). Probably that's better (and no API change).

Data model changes

CommentFileSizeAuthor
#3 3170625-2.patch685 bytesdww

Comments

dww created an issue. See original summary.

dww’s picture

Assigned: dww » Unassigned
Issue summary: View changes
Status: Active » Needs review

Here's the approach where we just clear $this->recipients at the end of GroupNotifyNode::sendNotification(). This seems simpler then exposing a clearRecipients() method and making it the caller's responsibility to get this right.

Thoughts?

Thanks!
-Derek

dww’s picture

StatusFileSize
new685 bytes

Attaching the patch would help. ;) Sorry for the noise.

gregcube’s picture

Wow. Good catch! Yes, lets not rely on the caller to clear the recipients array. I'm fine with your approach. Will commit shortly. Thanks again.

  • gregcube committed a937a50 on 8.x-1.x authored by dww
    Issue #3170625 by dww: Duplicate notifications sent if multiple messages...
gregcube’s picture

Status: Needs review » Fixed
dww’s picture

Great, thanks!

Cheers,
-Derek

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.