Skip to content

Commit

Permalink
Communication: Fix mentioned users recieving notifications in convers…
Browse files Browse the repository at this point in the history
…ations they are not part of (#9814)
  • Loading branch information
PaRangger authored Nov 20, 2024
1 parent e3ed347 commit 8d596a9
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,15 @@ public class ConversationNotificationService {

private final SingleUserNotificationRepository singleUserNotificationRepository;

private final SingleUserNotificationService singleUserNotificationService;

public ConversationNotificationService(ConversationNotificationRepository conversationNotificationRepository,
GeneralInstantNotificationService generalInstantNotificationService, SingleUserNotificationRepository singleUserNotificationRepository) {
GeneralInstantNotificationService generalInstantNotificationService, SingleUserNotificationRepository singleUserNotificationRepository,
SingleUserNotificationService singleUserNotificationService) {
this.conversationNotificationRepository = conversationNotificationRepository;
this.generalInstantNotificationService = generalInstantNotificationService;
this.singleUserNotificationRepository = singleUserNotificationRepository;
this.singleUserNotificationService = singleUserNotificationService;
}

/**
Expand Down Expand Up @@ -83,7 +87,7 @@ public ConversationNotification createNotification(Post createdMessage, Conversa
String[] placeholders = createPlaceholdersNewMessageChannelText(course.getTitle(), createdMessage.getContent(), createdMessage.getCreationDate().toString(),
conversationName, createdMessage.getAuthor().getName(), conversationType);
ConversationNotification notification = createConversationMessageNotification(course.getId(), createdMessage, notificationType, notificationText, true, placeholders);
save(notification, mentionedUsers, placeholders);
save(notification, mentionedUsers, placeholders, createdMessage);
return notification;
}

Expand All @@ -93,11 +97,12 @@ public static String[] createPlaceholdersNewMessageChannelText(String courseTitl
return new String[] { courseTitle, messageContent, messageCreationDate, conversationName, authorName, conversationType };
}

private void save(ConversationNotification notification, Set<User> mentionedUsers, String[] placeHolders) {
private void save(ConversationNotification notification, Set<User> mentionedUsers, String[] placeHolders, Post createdMessage) {
conversationNotificationRepository.save(notification);

Set<SingleUserNotification> mentionedUserNotifications = mentionedUsers.stream().map(mentionedUser -> SingleUserNotificationFactory
.createNotification(notification.getMessage(), NotificationType.CONVERSATION_USER_MENTIONED, notification.getText(), placeHolders, mentionedUser))
Set<SingleUserNotification> mentionedUserNotifications = singleUserNotificationService
.filterAllowedRecipientsInMentionedUsers(mentionedUsers, createdMessage.getConversation()).map(mentionedUser -> SingleUserNotificationFactory
.createNotification(notification.getMessage(), NotificationType.CONVERSATION_USER_MENTIONED, notification.getText(), placeHolders, mentionedUser))
.collect(Collectors.toSet());
singleUserNotificationRepository.saveAll(mentionedUserNotifications);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,23 +443,34 @@ public void notifyInvolvedUsersAboutNewMessageReply(Post post, SingleUserNotific
usersInvolved.add(post.getAuthor());
}

mentionedUsers.stream().filter(user -> {
boolean isChannelAndCourseWide = post.getConversation() instanceof Channel channel && channel.getIsCourseWide();
boolean isChannelVisibleToStudents = !(post.getConversation() instanceof Channel channel) || conversationService.isChannelVisibleToStudents(channel);
boolean isChannelVisibleToMentionedUser = isChannelVisibleToStudents
|| authorizationCheckService.isAtLeastTeachingAssistantInCourse(post.getConversation().getCourse(), user);

// Only send a notification to the mentioned user if...
// (for course-wide channels) ...the course-wide channel is visible
// (for all other cases) ...the user is a member of the conversation
return (isChannelAndCourseWide && isChannelVisibleToMentionedUser) || conversationService.isMember(post.getConversation().getId(), user.getId());
}).forEach(mentionedUser -> notifyUserAboutNewMessageReply(savedAnswerMessage, notification, mentionedUser, author, CONVERSATION_USER_MENTIONED));
filterAllowedRecipientsInMentionedUsers(mentionedUsers, post.getConversation())
.forEach(mentionedUser -> notifyUserAboutNewMessageReply(savedAnswerMessage, notification, mentionedUser, author, CONVERSATION_USER_MENTIONED));

Conversation conv = conversationService.getConversationById(post.getConversation().getId());
usersInvolved.stream().filter(userInvolved -> !mentionedUsers.contains(userInvolved))
.forEach(userInvolved -> notifyUserAboutNewMessageReply(savedAnswerMessage, notification, userInvolved, author, getAnswerMessageNotificationType(conv)));
}

/**
* Filters which of the mentioned users are permitted to receive a notification
*
* @param mentionedUsers users mentioned in the answer message
* @param conversation the conversation of the created post/notification, used for filtering
* @return the stream of mentioned users which are permitted to receive the notification for the given conversation
*/
public Stream<User> filterAllowedRecipientsInMentionedUsers(Set<User> mentionedUsers, Conversation conversation) {
return mentionedUsers.stream().filter(user -> {
boolean isChannelAndCourseWide = conversation instanceof Channel channel && channel.getIsCourseWide();
boolean isChannelVisibleToStudents = !(conversation instanceof Channel channel) || conversationService.isChannelVisibleToStudents(channel);
boolean isChannelVisibleToMentionedUser = isChannelVisibleToStudents || authorizationCheckService.isAtLeastTeachingAssistantInCourse(conversation.getCourse(), user);

// Only send a notification to the mentioned user if...
// (for course-wide channels) ...the course-wide channel is visible
// (for all other cases) ...the user is a member of the conversation
return (isChannelAndCourseWide && isChannelVisibleToMentionedUser) || conversationService.isMember(conversation.getId(), user.getId());
});
}

/**
* Saves the given notification in database and sends it to the client via websocket.
* Also creates and sends an instant notification.
Expand Down

0 comments on commit 8d596a9

Please sign in to comment.