FIX: Check whether group is mentionable by user when cooking post.

This commit is contained in:
Guo Xiang Tan 2018-11-22 16:01:03 +08:00
parent 0739c3b1d1
commit 3f636b2d19
4 changed files with 70 additions and 14 deletions

View File

@ -132,16 +132,13 @@ class Group < ActiveRecord::Base
}
scope :mentionable, lambda { |user|
where("mentionable_level in (:levels) OR
(
mentionable_level = #{ALIAS_LEVELS[:members_mods_and_admins]} AND id in (
SELECT group_id FROM group_users WHERE user_id = :user_id)
)", levels: alias_levels(user), user_id: user && user.id)
where(self.mentionable_sql_clause,
levels: alias_levels(user),
user_id: user&.id
)
}
scope :messageable, lambda { |user|
where("messageable_level in (:levels) OR
(
messageable_level = #{ALIAS_LEVELS[:members_mods_and_admins]} AND id in (
@ -149,6 +146,17 @@ class Group < ActiveRecord::Base
)", levels: alias_levels(user), user_id: user && user.id)
}
def self.mentionable_sql_clause
<<~SQL
mentionable_level in (:levels)
OR (
mentionable_level = #{ALIAS_LEVELS[:members_mods_and_admins]}
AND id in (
SELECT group_id FROM group_users WHERE user_id = :user_id)
)
SQL
end
def self.alias_levels(user)
levels = [ALIAS_LEVELS[:everyone]]

View File

@ -264,7 +264,9 @@ module PrettyText
add_s3_cdn(doc)
end
add_mentions(doc) if SiteSetting.enable_mentions
if SiteSetting.enable_mentions
add_mentions(doc, user_id: opts[:user_id])
end
doc.to_html
end
@ -425,11 +427,11 @@ module PrettyText
USER_TYPE ||= 'user'
GROUP_TYPE ||= 'group'
def self.add_mentions(doc)
def self.add_mentions(doc, user_id: nil)
elements = doc.css("span.mention")
names = elements.map { |element| element.text[1..-1] }
mentions = lookup_mentions(names)
mentions = lookup_mentions(names, user_id: user_id)
doc.css("span.mention").each do |element|
name = element.text[1..-1]
@ -453,7 +455,7 @@ module PrettyText
end
end
def self.lookup_mentions(names)
def self.lookup_mentions(names, user_id: nil)
sql = <<~SQL
(
SELECT
@ -468,14 +470,18 @@ module PrettyText
:group_type AS type,
name
FROM groups
WHERE name IN (:names)
WHERE name IN (:names) AND (#{Group.mentionable_sql_clause})
)
SQL
user = User.find_by(id: user_id)
results = DB.query(sql,
names: names,
user_type: USER_TYPE,
group_type: GROUP_TYPE
group_type: GROUP_TYPE,
levels: Group.alias_levels(user),
user_id: user_id
)
mentions = {}

View File

@ -225,7 +225,9 @@ describe PrettyText do
Fabricate(:user, username: username)
end
group = Fabricate(:group)
group = Fabricate(:group,
mentionable_level: Group::ALIAS_LEVELS[:everyone]
)
[
[
@ -241,6 +243,14 @@ describe PrettyText do
end
end
it "does not create mention for a non mentionable group" do
group = Fabricate(:group, mentionable_level: Group::ALIAS_LEVELS[:nobody])
expect(PrettyText.cook("test @#{group.name} test")).to eq(
%Q|<p>test <span class="mention">@#{group.name}</span> test</p>|
)
end
it 'does not mention staged users' do
user = Fabricate(:user, staged: true)

View File

@ -969,6 +969,38 @@ describe Post do
post.save
expect(post.cooked).to match(/nofollow noopener/)
end
describe 'mentions' do
let(:group) do
Fabricate(:group,
mentionable_level: Group::ALIAS_LEVELS[:members_mods_and_admins]
)
end
describe 'when user can not mention a group' do
it "should not create the mention" do
post = Fabricate(:post, raw: "hello @#{group.name}")
expect(post.cooked).to eq(
%Q|<p>hello <span class="mention">@#{group.name}</span></p>|
)
end
end
describe 'when user can mention a group' do
before do
group.add(post.user)
end
it 'should create the mention' do
post.update!(raw: "hello @#{group.name}")
expect(post.cooked).to eq(
%Q|<p>hello <a class="mention-group" href="/groups/#{group.name}">@#{group.name}</a></p>|
)
end
end
end
end
describe "calculate_avg_time" do