Backend support for group pms
This commit is contained in:
parent
f1df1f5234
commit
4b2e8af711
|
@ -118,7 +118,7 @@ class DiscourseChat::ChatController < ApplicationController
|
||||||
|
|
||||||
def create_rule
|
def create_rule
|
||||||
begin
|
begin
|
||||||
hash = params.require(:rule).permit(:channel_id, :filter, :category_id, tags:[])
|
hash = params.require(:rule).permit(:channel_id, :filter, :group_id, :category_id, tags:[])
|
||||||
|
|
||||||
rule = DiscourseChat::Rule.new(hash)
|
rule = DiscourseChat::Rule.new(hash)
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ class DiscourseChat::ChatController < ApplicationController
|
||||||
def update_rule
|
def update_rule
|
||||||
begin
|
begin
|
||||||
rule = DiscourseChat::Rule.find(params[:id].to_i)
|
rule = DiscourseChat::Rule.find(params[:id].to_i)
|
||||||
hash = params.require(:rule).permit(:filter, :category_id, tags:[])
|
hash = params.require(:rule).permit(:filter, :group_id, :category_id, tags:[])
|
||||||
|
|
||||||
if not rule.update(hash)
|
if not rule.update(hash)
|
||||||
raise Discourse::InvalidParameters, 'Rule is not valid'
|
raise Discourse::InvalidParameters, 'Rule is not valid'
|
||||||
|
|
|
@ -2,7 +2,7 @@ class DiscourseChat::Rule < DiscourseChat::PluginModel
|
||||||
KEY_PREFIX = 'rule:'
|
KEY_PREFIX = 'rule:'
|
||||||
|
|
||||||
# Setup ActiveRecord::Store to use the JSON field to read/write these values
|
# Setup ActiveRecord::Store to use the JSON field to read/write these values
|
||||||
store :value, accessors: [ :channel_id, :category_id, :tags, :filter ], coder: JSON
|
store :value, accessors: [ :channel_id, :group_id, :category_id, :tags, :filter ], coder: JSON
|
||||||
|
|
||||||
after_initialize :init_filter
|
after_initialize :init_filter
|
||||||
|
|
||||||
|
@ -13,16 +13,29 @@ class DiscourseChat::Rule < DiscourseChat::PluginModel
|
||||||
validates :filter, :inclusion => { :in => %w(watch follow mute),
|
validates :filter, :inclusion => { :in => %w(watch follow mute),
|
||||||
:message => "%{value} is not a valid filter" }
|
:message => "%{value} is not a valid filter" }
|
||||||
|
|
||||||
validate :channel_valid?, :category_valid?, :tags_valid?
|
validate :channel_valid?, :category_and_group_valid?, :tags_valid?
|
||||||
|
|
||||||
def channel_valid?
|
def channel_valid?
|
||||||
# Validate category
|
# Validate channel
|
||||||
if not (DiscourseChat::Channel.where(id: channel_id).exists?)
|
if not (DiscourseChat::Channel.where(id: channel_id).exists?)
|
||||||
errors.add(:channel_id, "#{channel_id} is not a valid channel id")
|
errors.add(:channel_id, "#{channel_id} is not a valid channel id")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def category_valid?
|
def category_and_group_valid?
|
||||||
|
if category_id and group_id
|
||||||
|
errors.add(:category_id, "cannot be specified in addition to group_id")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if group_id
|
||||||
|
# Validate group
|
||||||
|
if not Group.where(id: group_id).exists?
|
||||||
|
errors.add(:group_id, "#{group_id} is not a valid group id")
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
# Validate category
|
# Validate category
|
||||||
if not (category_id.nil? or Category.where(id: category_id).exists?)
|
if not (category_id.nil? or Category.where(id: category_id).exists?)
|
||||||
errors.add(:category_id, "#{category_id} is not a valid category id")
|
errors.add(:category_id, "#{category_id} is not a valid category id")
|
||||||
|
@ -79,6 +92,7 @@ class DiscourseChat::Rule < DiscourseChat::PluginModel
|
||||||
scope :with_channel_id, ->(channel_id) { where("value::json->>'channel_id'=?", channel_id.to_s)}
|
scope :with_channel_id, ->(channel_id) { where("value::json->>'channel_id'=?", channel_id.to_s)}
|
||||||
|
|
||||||
scope :with_category_id, ->(category_id) { category_id.nil? ? where("(value::json->'category_id') IS NULL OR json_typeof(value::json->'category_id')='null'") : where("value::json->>'category_id'=?", category_id.to_s)}
|
scope :with_category_id, ->(category_id) { category_id.nil? ? where("(value::json->'category_id') IS NULL OR json_typeof(value::json->'category_id')='null'") : where("value::json->>'category_id'=?", category_id.to_s)}
|
||||||
|
scope :with_group_ids, ->(group_id) { where("value::json->>'group_id' IN (?)", group_id.map(&:to_s))}
|
||||||
|
|
||||||
scope :order_by_precedence, ->{ order("CASE
|
scope :order_by_precedence, ->{ order("CASE
|
||||||
WHEN value::json->>'filter' = 'mute' THEN 1
|
WHEN value::json->>'filter' = 'mute' THEN 1
|
||||||
|
|
|
@ -1,3 +1,14 @@
|
||||||
class DiscourseChat::RuleSerializer < ApplicationSerializer
|
class DiscourseChat::RuleSerializer < ApplicationSerializer
|
||||||
attributes :id, :channel_id, :category_id, :tags, :filter
|
attributes :id, :channel_id, :group_id, :group_name, :category_id, :tags, :filter
|
||||||
|
|
||||||
|
def group_name
|
||||||
|
if object.group_id
|
||||||
|
groups = Group.where(id:object.group_id)
|
||||||
|
if groups.exists?
|
||||||
|
return groups.first.name
|
||||||
|
else
|
||||||
|
return I18n.t("chat_integration.deleted_group")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
|
@ -18,14 +18,19 @@ module DiscourseChat
|
||||||
|
|
||||||
topic = post.topic
|
topic = post.topic
|
||||||
|
|
||||||
# Abort if a private message (possible TODO: Add support for notifying about group PMs)
|
# Abort if topic is blank... this should never be the case
|
||||||
return if topic.blank? || topic.archetype == Archetype.private_message
|
return if topic.blank?
|
||||||
|
|
||||||
# Load all the rules that apply to this topic's category
|
# If it's a private message, filter rules by groups, otherwise filter rules by category
|
||||||
matching_rules = DiscourseChat::Rule.with_category_id(topic.category_id)
|
if topic.archetype == Archetype.private_message
|
||||||
|
group_ids_with_access = topic.topic_allowed_groups.pluck(:group_id)
|
||||||
if topic.category # Also load the rules for the wildcard category
|
return if group_ids_with_access.empty?
|
||||||
matching_rules += DiscourseChat::Rule.with_category_id(nil)
|
matching_rules = DiscourseChat::Rule.with_group_ids(group_ids_with_access)
|
||||||
|
else
|
||||||
|
matching_rules = DiscourseChat::Rule.with_category_id(topic.category_id)
|
||||||
|
if topic.category # Also load the rules for the wildcard category
|
||||||
|
matching_rules += DiscourseChat::Rule.with_category_id(nil)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# If tagging is enabled, thow away rules that don't apply to this topic
|
# If tagging is enabled, thow away rules that don't apply to this topic
|
||||||
|
|
|
@ -60,6 +60,7 @@ en:
|
||||||
|
|
||||||
all_categories: "(all categories)"
|
all_categories: "(all categories)"
|
||||||
deleted_category: "(deleted category)"
|
deleted_category: "(deleted category)"
|
||||||
|
deleted_group: "(deleted group)"
|
||||||
|
|
||||||
provider:
|
provider:
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@ RSpec.describe DiscourseChat::Rule do
|
||||||
let(:tag2){Fabricate(:tag)}
|
let(:tag2){Fabricate(:tag)}
|
||||||
|
|
||||||
let(:channel){DiscourseChat::Channel.create(provider:'dummy')}
|
let(:channel){DiscourseChat::Channel.create(provider:'dummy')}
|
||||||
|
let(:category) {Fabricate(:category)}
|
||||||
|
let(:group) {Fabricate(:group)}
|
||||||
|
|
||||||
describe '.alloc_key' do
|
describe '.alloc_key' do
|
||||||
it 'should return sequential numbers' do
|
it 'should return sequential numbers' do
|
||||||
|
@ -28,7 +30,7 @@ RSpec.describe DiscourseChat::Rule do
|
||||||
|
|
||||||
rule = DiscourseChat::Rule.create({
|
rule = DiscourseChat::Rule.create({
|
||||||
channel: channel,
|
channel: channel,
|
||||||
category_id: 1,
|
category_id: category.id,
|
||||||
tags: [tag1.name, tag2.name],
|
tags: [tag1.name, tag2.name],
|
||||||
filter: 'watch'
|
filter: 'watch'
|
||||||
})
|
})
|
||||||
|
@ -38,7 +40,7 @@ RSpec.describe DiscourseChat::Rule do
|
||||||
loadedRule = DiscourseChat::Rule.find(rule.id)
|
loadedRule = DiscourseChat::Rule.find(rule.id)
|
||||||
|
|
||||||
expect(loadedRule.channel.id).to eq(channel.id)
|
expect(loadedRule.channel.id).to eq(channel.id)
|
||||||
expect(loadedRule.category_id).to eq(1)
|
expect(loadedRule.category_id).to eq(category.id)
|
||||||
expect(loadedRule.tags).to contain_exactly(tag1.name,tag2.name)
|
expect(loadedRule.tags).to contain_exactly(tag1.name,tag2.name)
|
||||||
expect(loadedRule.filter).to eq('watch')
|
expect(loadedRule.filter).to eq('watch')
|
||||||
|
|
||||||
|
@ -48,7 +50,7 @@ RSpec.describe DiscourseChat::Rule do
|
||||||
before do
|
before do
|
||||||
rule = DiscourseChat::Rule.create({
|
rule = DiscourseChat::Rule.create({
|
||||||
channel: channel,
|
channel: channel,
|
||||||
category_id: 1,
|
category_id: category.id,
|
||||||
tags: [tag1.name, tag2.name]
|
tags: [tag1.name, tag2.name]
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
@ -102,15 +104,29 @@ RSpec.describe DiscourseChat::Rule do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'can be filtered by category' do
|
it 'can be filtered by category' do
|
||||||
rule2 = DiscourseChat::Rule.create(channel:channel, category_id: 1)
|
rule2 = DiscourseChat::Rule.create(channel:channel, category_id: category.id)
|
||||||
rule3 = DiscourseChat::Rule.create(channel:channel, category_id: nil)
|
rule3 = DiscourseChat::Rule.create(channel:channel, category_id: nil)
|
||||||
|
|
||||||
expect(DiscourseChat::Rule.all.length).to eq(3)
|
expect(DiscourseChat::Rule.all.length).to eq(3)
|
||||||
|
|
||||||
expect(DiscourseChat::Rule.with_category_id(1).length).to eq(2)
|
expect(DiscourseChat::Rule.with_category_id(category.id).length).to eq(2)
|
||||||
expect(DiscourseChat::Rule.with_category_id(nil).length).to eq(1)
|
expect(DiscourseChat::Rule.with_category_id(nil).length).to eq(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'can be filtered by group' do
|
||||||
|
group1 = Fabricate(:group)
|
||||||
|
group2 = Fabricate(:group)
|
||||||
|
rule2 = DiscourseChat::Rule.create(channel:channel, group_id: group1.id)
|
||||||
|
rule3 = DiscourseChat::Rule.create(channel:channel, group_id: group2.id)
|
||||||
|
|
||||||
|
expect(DiscourseChat::Rule.all.length).to eq(3)
|
||||||
|
|
||||||
|
expect(DiscourseChat::Rule.with_category_id(category.id).length).to eq(1)
|
||||||
|
expect(DiscourseChat::Rule.with_group_ids([group1.id,group2.id]).length).to eq(2)
|
||||||
|
expect(DiscourseChat::Rule.with_group_ids([group1.id]).length).to eq(1)
|
||||||
|
expect(DiscourseChat::Rule.with_group_ids([group2.id]).length).to eq(1)
|
||||||
|
end
|
||||||
|
|
||||||
it 'can be sorted by precedence' do
|
it 'can be sorted by precedence' do
|
||||||
rule2 = DiscourseChat::Rule.create(channel:channel, filter:'mute')
|
rule2 = DiscourseChat::Rule.create(channel:channel, filter:'mute')
|
||||||
rule3 = DiscourseChat::Rule.create(channel:channel, filter:'follow')
|
rule3 = DiscourseChat::Rule.create(channel:channel, filter:'follow')
|
||||||
|
@ -128,7 +144,7 @@ RSpec.describe DiscourseChat::Rule do
|
||||||
DiscourseChat::Rule.create({
|
DiscourseChat::Rule.create({
|
||||||
filter: 'watch',
|
filter: 'watch',
|
||||||
channel: channel,
|
channel: channel,
|
||||||
category_id: 1,
|
category_id: category.id,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -140,9 +156,25 @@ RSpec.describe DiscourseChat::Rule do
|
||||||
expect(rule.valid?).to eq(false)
|
expect(rule.valid?).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "doesn't allow both category and group to be set" do
|
||||||
|
expect(rule.valid?).to eq(true)
|
||||||
|
rule.group_id = group.id
|
||||||
|
expect(rule.valid?).to eq(false)
|
||||||
|
rule.category_id = nil
|
||||||
|
expect(rule.valid?).to eq(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'validates group correctly' do
|
||||||
|
rule.category_id = nil
|
||||||
|
rule.group_id = group.id
|
||||||
|
expect(rule.valid?).to eq(true)
|
||||||
|
rule.group_id = -99
|
||||||
|
expect(rule.valid?).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
it 'validates category correctly' do
|
it 'validates category correctly' do
|
||||||
expect(rule.valid?).to eq(true)
|
expect(rule.valid?).to eq(true)
|
||||||
rule.category_id = 99
|
rule.category_id = -99
|
||||||
expect(rule.valid?).to eq(false)
|
expect(rule.valid?).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ RSpec.describe DiscourseChat::Manager do
|
||||||
|
|
||||||
let(:manager) {::DiscourseChat::Manager}
|
let(:manager) {::DiscourseChat::Manager}
|
||||||
let(:category) {Fabricate(:category)}
|
let(:category) {Fabricate(:category)}
|
||||||
|
let(:group) {Fabricate(:group)}
|
||||||
let(:topic){Fabricate(:topic, category_id: category.id )}
|
let(:topic){Fabricate(:topic, category_id: category.id )}
|
||||||
let(:first_post) {Fabricate(:post, topic: topic)}
|
let(:first_post) {Fabricate(:post, topic: topic)}
|
||||||
let(:second_post) {Fabricate(:post, topic: topic, post_number:2)}
|
let(:second_post) {Fabricate(:post, topic: topic, post_number:2)}
|
||||||
|
@ -107,6 +108,32 @@ RSpec.describe DiscourseChat::Manager do
|
||||||
expect(provider.sent_to_channel_ids).to contain_exactly()
|
expect(provider.sent_to_channel_ids).to contain_exactly()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "should work for group pms" do
|
||||||
|
DiscourseChat::Rule.create!(channel: chan1, filter: 'watch' ) # Wildcard watch
|
||||||
|
DiscourseChat::Rule.create!(channel: chan2, filter: 'watch', group_id: group.id ) # Group watch
|
||||||
|
|
||||||
|
private_post = Fabricate(:private_message_post)
|
||||||
|
private_post.topic.invite_group(Fabricate(:user), group)
|
||||||
|
|
||||||
|
manager.trigger_notifications(private_post.id)
|
||||||
|
|
||||||
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan2.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should work for pms with multiple groups" do
|
||||||
|
group2 = Fabricate(:group)
|
||||||
|
DiscourseChat::Rule.create!(channel: chan1, filter: 'watch', group_id: group.id )
|
||||||
|
DiscourseChat::Rule.create!(channel: chan2, filter: 'watch', group_id: group2.id )
|
||||||
|
|
||||||
|
private_post = Fabricate(:private_message_post)
|
||||||
|
private_post.topic.invite_group(Fabricate(:user), group)
|
||||||
|
private_post.topic.invite_group(Fabricate(:user), group2)
|
||||||
|
|
||||||
|
manager.trigger_notifications(private_post.id)
|
||||||
|
|
||||||
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id, chan2.id)
|
||||||
|
end
|
||||||
|
|
||||||
it "should not notify about posts the chat_user cannot see" do
|
it "should not notify about posts the chat_user cannot see" do
|
||||||
DiscourseChat::Rule.create!(channel: chan1, filter: 'follow', category_id: nil ) # Wildcard watch
|
DiscourseChat::Rule.create!(channel: chan1, filter: 'follow', category_id: nil ) # Wildcard watch
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue