FEATURE: allow plugins to extend Groups (#14216)

* add_permitted_group_param API for plugins
* add groups-interaction-custom-options outlet
* custom search can use custom group scope
This commit is contained in:
Krzysztof Kotlarek 2021-09-06 10:18:51 +10:00 committed by GitHub
parent 9873a942e3
commit f859fd6bde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 78 additions and 3 deletions

View File

@ -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,

View File

@ -104,3 +104,5 @@
onChange=(action (mut model.default_notification_level))
}}
</div>
{{plugin-outlet name="groups-interaction-custom-options" args=(hash model=model)}}

View File

@ -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,

View File

@ -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

View File

@ -736,6 +736,8 @@ class GroupsController < ApplicationController
end
end
permitted_params = permitted_params | DiscoursePluginRegistry.group_params
params.require(:group).permit(*permitted_params)
end

View File

@ -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|

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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