From d33d0317420dc93d1bdf4420f0916fad5aa8085a Mon Sep 17 00:00:00 2001 From: Vinoth Kannan Date: Wed, 5 Dec 2018 14:44:06 +0530 Subject: [PATCH] FEATURE: Filter topic and post web hook events by tags (#6726) * FEATURE: Filter topic and post web hook events by tags * Add a spec test with unmatched tags --- .../controllers/admin-web-hooks-show.js.es6 | 5 +++ .../javascripts/admin/models/web-hook.js.es6 | 2 ++ .../admin/routes/admin-web-hooks-show.js.es6 | 1 + .../admin/templates/web-hooks-show.hbs | 7 ++++ app/controllers/admin/web_hooks_controller.rb | 1 + app/jobs/regular/emit_web_hook_event.rb | 3 ++ app/models/web_hook.rb | 7 ++++ app/serializers/admin_web_hook_serializer.rb | 1 + config/locales/client.en.yml | 2 ++ ...193426_create_join_table_web_hooks_tags.rb | 7 ++++ spec/jobs/emit_web_hook_event_spec.rb | 36 +++++++++++++++++++ 11 files changed, 72 insertions(+) create mode 100644 db/migrate/20181204193426_create_join_table_web_hooks_tags.rb diff --git a/app/assets/javascripts/admin/controllers/admin-web-hooks-show.js.es6 b/app/assets/javascripts/admin/controllers/admin-web-hooks-show.js.es6 index 279fc535368..55e6b007fda 100644 --- a/app/assets/javascripts/admin/controllers/admin-web-hooks-show.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-web-hooks-show.js.es6 @@ -9,6 +9,11 @@ export default Ember.Controller.extend({ defaultEventTypes: Ember.computed.alias("adminWebHooks.defaultEventTypes"), contentTypes: Ember.computed.alias("adminWebHooks.contentTypes"), + @computed + showTagsFilter() { + return this.siteSettings.tagging_enabled; + }, + @computed("model.isSaving", "saved", "saveButtonDisabled") savingStatus(isSaving, saved, saveButtonDisabled) { if (isSaving) { diff --git a/app/assets/javascripts/admin/models/web-hook.js.es6 b/app/assets/javascripts/admin/models/web-hook.js.es6 index 142d22b7972..a2a7ae79fb7 100644 --- a/app/assets/javascripts/admin/models/web-hook.js.es6 +++ b/app/assets/javascripts/admin/models/web-hook.js.es6 @@ -63,6 +63,7 @@ export default RestModel.extend({ createProperties() { const types = this.get("web_hook_event_types"); const categoryIds = this.get("categories").map(c => c.id); + const tagNames = this.get("tag_names"); // Hack as {{group-selector}} accepts a comma-separated string as data source, but // we use an array to populate the datasource above. @@ -81,6 +82,7 @@ export default RestModel.extend({ ? [null] : types.map(type => type.id), category_ids: Ember.isEmpty(categoryIds) ? [null] : categoryIds, + tag_names: Ember.isEmpty(tagNames) ? [null] : tagNames, group_ids: Ember.isEmpty(groupNames) || Ember.isEmpty(groupNames[0]) ? [null] diff --git a/app/assets/javascripts/admin/routes/admin-web-hooks-show.js.es6 b/app/assets/javascripts/admin/routes/admin-web-hooks-show.js.es6 index f548a4e2022..611b015dcb0 100644 --- a/app/assets/javascripts/admin/routes/admin-web-hooks-show.js.es6 +++ b/app/assets/javascripts/admin/routes/admin-web-hooks-show.js.es6 @@ -19,6 +19,7 @@ export default Discourse.Route.extend({ } model.set("category_ids", model.get("category_ids")); + model.set("tag_names", model.get("tag_names")); model.set("group_ids", model.get("group_ids")); controller.setProperties({ model, saved: false }); }, diff --git a/app/assets/javascripts/admin/templates/web-hooks-show.hbs b/app/assets/javascripts/admin/templates/web-hooks-show.hbs index 294e6b3d413..bf408bf11c3 100644 --- a/app/assets/javascripts/admin/templates/web-hooks-show.hbs +++ b/app/assets/javascripts/admin/templates/web-hooks-show.hbs @@ -51,6 +51,13 @@ {{category-selector categories=model.categories}}
{{i18n 'admin.web_hooks.categories_filter_instructions'}}
+ {{#if showTagsFilter}} +
+ + {{tag-chooser tags=model.tag_names everyTag=true}} +
{{i18n 'admin.web_hooks.tags_filter_instructions'}}
+
+ {{/if}}
{{group-selector groupNames=model.groupsFilterInName groupFinder=model.groupFinder}} diff --git a/app/controllers/admin/web_hooks_controller.rb b/app/controllers/admin/web_hooks_controller.rb index 92ec8019c3d..1ba3b71a6c8 100644 --- a/app/controllers/admin/web_hooks_controller.rb +++ b/app/controllers/admin/web_hooks_controller.rb @@ -111,6 +111,7 @@ class Admin::WebHooksController < Admin::AdminController :wildcard_web_hook, :active, :verify_certificate, web_hook_event_type_ids: [], group_ids: [], + tag_names: [], category_ids: []) end diff --git a/app/jobs/regular/emit_web_hook_event.rb b/app/jobs/regular/emit_web_hook_event.rb index 5cd4010abcd..643d496a6c8 100644 --- a/app/jobs/regular/emit_web_hook_event.rb +++ b/app/jobs/regular/emit_web_hook_event.rb @@ -28,6 +28,9 @@ module Jobs return if web_hook.category_ids.present? && (!args[:category_id].present? || !web_hook.category_ids.include?(args[:category_id])) + return if web_hook.tag_ids.present? && (args[:tag_ids].blank? || + (web_hook.tag_ids & args[:tag_ids]).blank?) + raise Discourse::InvalidParameters.new(:payload) unless args[:payload].present? args[:payload] = JSON.parse(args[:payload]) end diff --git a/app/models/web_hook.rb b/app/models/web_hook.rb index 518b076abcf..b72a3b7a0dd 100644 --- a/app/models/web_hook.rb +++ b/app/models/web_hook.rb @@ -2,6 +2,7 @@ class WebHook < ActiveRecord::Base has_and_belongs_to_many :web_hook_event_types has_and_belongs_to_many :groups has_and_belongs_to_many :categories + has_and_belongs_to_many :tags has_many :web_hook_events, dependent: :destroy @@ -15,6 +16,10 @@ class WebHook < ActiveRecord::Base before_save :strip_url + def tag_names=(tag_names_arg) + DiscourseTagging.add_or_create_tags_by_name(self, tag_names_arg, unlimited: true) + end + def self.content_types @content_types ||= Enum.new('application/json' => 1, 'application/x-www-form-urlencoded' => 2) @@ -68,6 +73,7 @@ class WebHook < ActiveRecord::Base WebHook.enqueue_hooks(:topic, event, id: topic.id, category_id: topic&.category_id, + tag_ids: topic&.tags.pluck(:id), payload: payload ) end @@ -80,6 +86,7 @@ class WebHook < ActiveRecord::Base WebHook.enqueue_hooks(:post, event, id: post.id, category_id: post&.topic&.category_id, + tag_ids: post&.topic&.tags.pluck(:id), payload: payload ) end diff --git a/app/serializers/admin_web_hook_serializer.rb b/app/serializers/admin_web_hook_serializer.rb index ff74ae3f9d0..711674b7320 100644 --- a/app/serializers/admin_web_hook_serializer.rb +++ b/app/serializers/admin_web_hook_serializer.rb @@ -10,6 +10,7 @@ class AdminWebHookSerializer < ApplicationSerializer :web_hook_event_types has_many :categories, serializer: BasicCategorySerializer, embed: :ids, include: false + has_many :tags, key: :tag_names, serializer: TagSerializer, embed: :ids, embed_key: :name, include: false has_many :groups, serializer: BasicGroupSerializer, embed: :ids, include: false def web_hook_event_types diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index b06270555dc..de7874f10de 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -3082,6 +3082,8 @@ en: active_notice: "We will deliver event details when it happens." categories_filter_instructions: "Relevant webhooks will only be triggered if the event is related with specified categories. Leave blank to trigger webhooks for all categories." categories_filter: "Triggered Categories" + tags_filter_instructions: "Relevant webhooks will only be triggered if the event is related with specified tags. Leave blank to trigger webhooks for all tags." + tags_filter: "Triggered Tags" groups_filter_instructions: "Relevant webhooks will only be triggered if the event is related with specified groups. Leave blank to trigger webhooks for all groups." groups_filter: "Triggered Groups" delete_confirm: "Delete this webhook?" diff --git a/db/migrate/20181204193426_create_join_table_web_hooks_tags.rb b/db/migrate/20181204193426_create_join_table_web_hooks_tags.rb new file mode 100644 index 00000000000..9b74621b4a2 --- /dev/null +++ b/db/migrate/20181204193426_create_join_table_web_hooks_tags.rb @@ -0,0 +1,7 @@ +class CreateJoinTableWebHooksTags < ActiveRecord::Migration[5.2] + def change + create_join_table :web_hooks, :tags do |t| + t.index [:web_hook_id, :tag_id], name: 'web_hooks_tags', unique: true + end + end +end diff --git a/spec/jobs/emit_web_hook_event_spec.rb b/spec/jobs/emit_web_hook_event_spec.rb index acc5961f3f4..06aadf83de7 100644 --- a/spec/jobs/emit_web_hook_event_spec.rb +++ b/spec/jobs/emit_web_hook_event_spec.rb @@ -125,6 +125,42 @@ describe Jobs::EmitWebHookEvent do end end + context 'with tag filters' do + let(:tag) { Fabricate(:tag) } + let(:topic) { Fabricate(:topic, tags: [tag]) } + let(:topic_hook) { Fabricate(:topic_web_hook, tags: [tag]) } + + it "doesn't emit when event is not included any tags" do + subject.execute( + web_hook_id: topic_hook.id, + event_type: 'topic', + payload: { test: "some payload" }.to_json + ) + end + + it "doesn't emit when event is not related with defined tags" do + subject.execute( + web_hook_id: topic_hook.id, + event_type: 'topic', + tag_ids: [Fabricate(:tag).id], + payload: { test: "some payload" }.to_json + ) + end + + it 'emit when event is related with defined tags' do + stub_request(:post, "https://meta.discourse.org/webhook_listener") + .with(body: "{\"topic\":{\"test\":\"some payload\"}}") + .to_return(body: 'OK', status: 200) + + subject.execute( + web_hook_id: topic_hook.id, + event_type: 'topic', + tag_ids: topic.tags.pluck(:id), + payload: { test: "some payload" }.to_json + ) + end + end + describe '#web_hook_request' do it 'creates delivery event record' do stub_request(:post, "https://meta.discourse.org/webhook_listener")