From 3f636b2d19647025f5646acc2087187b37d9870a Mon Sep 17 00:00:00 2001 From: Guo Xiang Tan <tgx_world@hotmail.com> Date: Thu, 22 Nov 2018 16:01:03 +0800 Subject: [PATCH] FIX: Check whether group is mentionable by user when cooking post. --- app/models/group.rb | 22 +++++++++++++------- lib/pretty_text.rb | 18 ++++++++++------ spec/components/pretty_text_spec.rb | 12 ++++++++++- spec/models/post_spec.rb | 32 +++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 14 deletions(-) diff --git a/app/models/group.rb b/app/models/group.rb index a3c467eb7bf..45615dd2bcd 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -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]] diff --git a/lib/pretty_text.rb b/lib/pretty_text.rb index e7682f9010a..a22d2699de7 100644 --- a/lib/pretty_text.rb +++ b/lib/pretty_text.rb @@ -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 = {} diff --git a/spec/components/pretty_text_spec.rb b/spec/components/pretty_text_spec.rb index 6655e085310..7b58eec64d5 100644 --- a/spec/components/pretty_text_spec.rb +++ b/spec/components/pretty_text_spec.rb @@ -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) diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index 6ac88dff443..532781d7313 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -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