diff --git a/app/assets/javascripts/discourse/app/lib/user-search.js b/app/assets/javascripts/discourse/app/lib/user-search.js index 7cde342f3fb..c16e74bda4c 100644 --- a/app/assets/javascripts/discourse/app/lib/user-search.js +++ b/app/assets/javascripts/discourse/app/lib/user-search.js @@ -25,6 +25,7 @@ function performSearch( topicId, categoryId, includeGroups, + customGroupsScope, includeMentionableGroups, includeMessageableGroups, allowedUsers, @@ -56,6 +57,7 @@ function performSearch( topic_id: topicId, category_id: categoryId, include_groups: includeGroups, + custom_groups_scope: customGroupsScope, include_mentionable_groups: includeMentionableGroups, include_messageable_groups: includeMessageableGroups, groups: groupMembersOf, @@ -100,6 +102,7 @@ let debouncedSearch = function ( topicId, categoryId, includeGroups, + customGroupsScope, includeMentionableGroups, includeMessageableGroups, allowedUsers, @@ -116,6 +119,7 @@ let debouncedSearch = function ( topicId, categoryId, includeGroups, + customGroupsScope, includeMentionableGroups, includeMessageableGroups, allowedUsers, @@ -207,6 +211,7 @@ export default function userSearch(options) { let term = options.term || "", includeGroups = options.includeGroups, + customGroupsScope = options.customGroupsScope, includeMentionableGroups = options.includeMentionableGroups, includeMessageableGroups = options.includeMessageableGroups, allowedUsers = options.allowedUsers, @@ -248,6 +253,7 @@ export default function userSearch(options) { topicId, categoryId, includeGroups, + customGroupsScope, includeMentionableGroups, includeMessageableGroups, allowedUsers, diff --git a/app/assets/javascripts/discourse/app/templates/components/groups-form-interaction-fields.hbs b/app/assets/javascripts/discourse/app/templates/components/groups-form-interaction-fields.hbs index df6d0ac8e2a..7681b30a854 100644 --- a/app/assets/javascripts/discourse/app/templates/components/groups-form-interaction-fields.hbs +++ b/app/assets/javascripts/discourse/app/templates/components/groups-form-interaction-fields.hbs @@ -104,3 +104,5 @@ onChange=(action (mut model.default_notification_level)) }} + +{{plugin-outlet name="groups-interaction-custom-options" args=(hash model=model)}} diff --git a/app/assets/javascripts/select-kit/addon/components/user-chooser.js b/app/assets/javascripts/select-kit/addon/components/user-chooser.js index a6b1db09ba9..9d3f90c00ca 100644 --- a/app/assets/javascripts/select-kit/addon/components/user-chooser.js +++ b/app/assets/javascripts/select-kit/addon/components/user-chooser.js @@ -70,6 +70,7 @@ export default MultiSelectComponent.extend({ categoryId: options.categoryId, exclude: this.excludedUsers, includeGroups: options.includeGroups, + customGroupsScope: options.customGroupsScope, allowedUsers: options.allowedUsers, includeMentionableGroups: options.includeMentionableGroups, includeMessageableGroups: options.includeMessageableGroups, diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index 3c84ff92981..f80dfe27c5e 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -180,6 +180,8 @@ class Admin::GroupsController < Admin::AdminController custom_fields = DiscoursePluginRegistry.editable_group_custom_fields permitted << { custom_fields: custom_fields } unless custom_fields.blank? + permitted = permitted | DiscoursePluginRegistry.group_params + params.require(:group).permit(permitted) end end diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 828bb11a5f5..8bc89054b8c 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -736,6 +736,8 @@ class GroupsController < ApplicationController end end + permitted_params = permitted_params | DiscoursePluginRegistry.group_params + params.require(:group).permit(*permitted_params) end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 98b8d28e90b..0835db62eef 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1123,7 +1123,12 @@ class UsersController < ApplicationController end if groups - groups = Group.search_groups(term, groups: groups) + groups = Group.search_groups(term, + groups: groups, + custom_scope: { + name: params["custom_groups_scope"]&.to_sym, + arguments: [current_user] + }) groups = groups.order('groups.name asc') to_render[:groups] = groups.map do |m| diff --git a/app/models/group.rb b/app/models/group.rb index 41ca0a3e6e9..d863b43d86b 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -557,8 +557,14 @@ class Group < ActiveRecord::Base lookup_group(name) || refresh_automatic_group!(name) end - def self.search_groups(name, groups: nil) - (groups || Group).where( + def self.search_groups(name, groups: nil, custom_scope: {}) + groups ||= Group + + if custom_scope.present? && DiscoursePluginRegistry.group_scope_for_search.include?(custom_scope[:name]) + groups = groups.send(custom_scope[:name], *custom_scope[:arguments]) + end + + groups.where( "name ILIKE :term_like OR full_name ILIKE :term_like", term_like: "%#{name}%" ) end diff --git a/lib/discourse_plugin_registry.rb b/lib/discourse_plugin_registry.rb index de86a251bbc..625e7fe798b 100644 --- a/lib/discourse_plugin_registry.rb +++ b/lib/discourse_plugin_registry.rb @@ -76,6 +76,8 @@ class DiscoursePluginRegistry define_filtered_register :staff_editable_user_custom_fields define_filtered_register :editable_group_custom_fields + define_filtered_register :group_params + define_filtered_register :group_scope_for_search define_filtered_register :topic_thumbnail_sizes diff --git a/lib/plugin/instance.rb b/lib/plugin/instance.rb index 6e9f59c906b..28fac3753ff 100644 --- a/lib/plugin/instance.rb +++ b/lib/plugin/instance.rb @@ -369,6 +369,17 @@ class Plugin::Instance end end + # Add a permitted_param to Group, respecting if the plugin is enabled + # Used in GroupsController#update and Admin::GroupsController#create + def register_group_param(param) + DiscoursePluginRegistry.register_group_param(param, self) + end + + # Add a custom scopes for search to Group, respecting if the plugin is enabled + def register_group_scope_for_search(scope_name) + DiscoursePluginRegistry.register_group_scope_for_search(scope_name, self) + end + # Add validation method but check that the plugin is enabled def validate(klass, name, &block) klass = klass.to_s.classify.constantize diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index 4a839950e74..9e3dc1b869d 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -920,6 +920,7 @@ describe Group do describe '.search_groups' do fab!(:group) { Fabricate(:group, name: 'tEsT_more_things', full_name: 'Abc something awesome') } + let(:messageable_group) { Fabricate(:group, name: "MessageableGroup", messageable_level: Group::ALIAS_LEVELS[:everyone]) } it 'should return the right groups' do group @@ -934,6 +935,18 @@ describe Group do expect(Group.search_groups('sOmEthi')).to eq([group]) expect(Group.search_groups('test2')).to eq([]) end + + it 'allows to filter with additional scope' do + messageable_group + + expect(Group.search_groups('es', custom_scope: { name: :messageable, arguments: [user] }).sort).to eq([messageable_group, group].sort) + + plugin = Plugin::Instance.new + plugin.register_group_scope_for_search(:messageable) + expect(Group.search_groups('es', custom_scope: { name: :messageable, arguments: [user] }).sort).to eq([messageable_group].sort) + + DiscoursePluginRegistry.reset! + end end describe '#bulk_add' do diff --git a/spec/requests/admin/groups_controller_spec.rb b/spec/requests/admin/groups_controller_spec.rb index c0053113e47..29a5c5a566d 100644 --- a/spec/requests/admin/groups_controller_spec.rb +++ b/spec/requests/admin/groups_controller_spec.rb @@ -76,6 +76,31 @@ RSpec.describe Admin::GroupsController do expect(group.custom_fields['test2']).to be_blank end end + + context 'with Group.plugin_permitted_params' do + after do + DiscoursePluginRegistry.reset! + end + + it 'filter unpermitted params' do + params = group_params + params[:group].merge!(allow_unknown_sender_topic_replies: true) + + post "/admin/groups.json", params: params + expect(Group.last.allow_unknown_sender_topic_replies).to eq(false) + end + + it 'allows plugin to allow custom params' do + params = group_params + params[:group].merge!(allow_unknown_sender_topic_replies: true) + + plugin = Plugin::Instance.new + plugin.register_group_param :allow_unknown_sender_topic_replies + + post "/admin/groups.json", params: params + expect(Group.last.allow_unknown_sender_topic_replies).to eq(true) + end + end end describe '#add_owners' do