FEATURE: Improve composer warnings for mentions (#18796)

* FEATURE: Show warning if group cannot be mentioned

A similar warning is displayed when the user cannot be mentioned because
they have not been invited to the topic.

* FEATURE: Resolve mentions for new topic

This commit improves several improvements and refactors
/u/is_local_username route to a better /composer/mentions route that
can handle new topics too.

* FEATURE: Show warning if only some are notified

Sometimes users are still notified even if the group that was mentioned
was not invited to the message. This happens because its members were
invited directly or are members of other groups that were invited.

* DEV: Refactor _warnCannotSeeMention
This commit is contained in:
Bianca Nenciu
2022-12-05 20:22:05 +02:00
committed by GitHub
parent b46a7b51f7
commit 93859037ef
16 changed files with 718 additions and 400 deletions

View File

@ -497,93 +497,6 @@ class UsersController < ApplicationController
end
end
def is_local_username
usernames = params[:usernames] if params[:usernames].present?
usernames = [params[:username]] if params[:username].present?
raise Discourse::InvalidParameters.new(:usernames) if !usernames.kind_of?(Array) || usernames.size > 20
groups = Group.where(name: usernames).pluck(:name)
mentionable_groups =
if current_user
Group.mentionable(current_user, include_public: false)
.where(name: usernames)
.pluck(:name, :user_count)
.map do |name, user_count|
{
name: name,
user_count: user_count
}
end
end
usernames -= groups
usernames.each(&:downcase!)
users = User
.where(staged: false, username_lower: usernames)
.index_by(&:username_lower)
cannot_see = {}
here_count = nil
topic_id = params[:topic_id]
if topic_id.present? && topic = Topic.find_by(id: topic_id)
topic_muted_by = TopicUser
.where(topic: topic)
.where(user_id: users.values.map(&:id))
.where(notification_level: TopicUser.notification_levels[:muted])
.pluck(:user_id)
.to_set
if topic.private_message?
topic_allowed_user_ids = TopicAllowedUser
.where(topic: topic)
.where(user_id: users.values.map(&:id))
.pluck(:user_id)
.to_set
topic_allowed_group_ids = TopicAllowedGroup
.where(topic: topic)
.pluck(:group_id)
.to_set
end
usernames.each do |username|
user = users[username]
next if user.blank?
cannot_see_reason = nil
if !user.guardian.can_see?(topic)
cannot_see_reason = topic.private_message? ? :private : :category
elsif topic_muted_by.include?(user.id)
cannot_see_reason = :muted_topic
elsif topic.private_message? && !topic_allowed_user_ids.include?(user.id) && !user.group_ids.any? { |group_id| topic_allowed_group_ids.include?(group_id) }
cannot_see_reason = :not_allowed
end
if !guardian.is_staff? && cannot_see_reason.present? && cannot_see_reason != :private && cannot_see_reason != :category
cannot_see_reason = nil # do not leak private information
end
cannot_see[username] = cannot_see_reason if cannot_see_reason.present?
end
if usernames.include?(SiteSetting.here_mention) && guardian.can_mention_here?
here_count = PostAlerter.new.expand_here_mention(topic.first_post, exclude_ids: [current_user.id]).size
end
end
render json: {
valid: users.keys,
valid_groups: groups,
mentionable_groups: mentionable_groups,
cannot_see: cannot_see,
here_count: here_count,
max_users_notified_per_group_mention: SiteSetting.max_users_notified_per_group_mention
}
end
def render_available_true
render(json: { available: true })
end