DEV: Allow plugins to hook into user preferences update process on the server (#21737)
This commit introduces a new `within_user_updater_transaction` event that's triggered inside the transaction that saves user updates in `UserUpdater`. Plugins can hook into the transaction using the event to include custom changes in the transaction. Callbacks for this event receive 2 arguments: 1. the user being saved 2. the changed attributes that are passed to `UserUpdater`. There's also new modifier in this commit called `users_controller_update_user_params` to allow plugins to allowlist custom params in the `UsersController` which eventually end up getting passed as attributes to the `UserUpdater` and the new `within_user_updater_transaction` event where they can be used to perform additional updates using the custom params. ----- New API is used in https://github.com/discourse/discourse-mailinglist-integration/pull/1.
This commit is contained in:
parent
9268bb92bd
commit
bb3c05ba0e
|
@ -2015,7 +2015,13 @@ class UsersController < ApplicationController
|
|||
end
|
||||
|
||||
deprecate_modify_user_params_method
|
||||
modify_user_params(result)
|
||||
result = modify_user_params(result)
|
||||
DiscoursePluginRegistry.apply_modifier(
|
||||
:users_controller_update_user_params,
|
||||
result,
|
||||
current_user,
|
||||
params,
|
||||
)
|
||||
end
|
||||
|
||||
# Plugins can use this to modify user parameters
|
||||
|
|
|
@ -237,6 +237,7 @@ class UserUpdater
|
|||
attributes.fetch(:name) { "" },
|
||||
)
|
||||
end
|
||||
DiscourseEvent.trigger(:within_user_updater_transaction, user, attributes)
|
||||
rescue Addressable::URI::InvalidURIError => e
|
||||
# Prevent 500 for crazy url input
|
||||
return saved
|
||||
|
|
|
@ -2973,6 +2973,32 @@ RSpec.describe UsersController do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when a plugin introduces a users_controller_update_user_params modifier" do
|
||||
before { sign_in(user) }
|
||||
|
||||
after { DiscoursePluginRegistry.clear_modifiers! }
|
||||
|
||||
it "allows the plugin to modify the user params" do
|
||||
block_called = false
|
||||
|
||||
plugin = Plugin::Instance.new
|
||||
plugin.register_modifier(
|
||||
:users_controller_update_user_params,
|
||||
) do |result, current_user, params|
|
||||
block_called = true
|
||||
expect(current_user.id).to eq(user.id)
|
||||
result[:location] = params[:plugin_location_alias]
|
||||
result
|
||||
end
|
||||
|
||||
put "/u/#{user.username}.json", params: { location: "abc", plugin_location_alias: "xyz" }
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
expect(user.reload.user_profile.location).to eq("xyz")
|
||||
expect(block_called).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#badge_title" do
|
||||
|
|
|
@ -46,6 +46,42 @@ RSpec.describe UserUpdater do
|
|||
expect(user.reload.name).to eq "Jim Tom"
|
||||
end
|
||||
|
||||
describe "the within_user_updater_transaction event" do
|
||||
it "allows plugins to perform additional updates" do
|
||||
update_attributes = { name: "Jimmmy Johnny" }
|
||||
handler =
|
||||
Proc.new do |user, attrs|
|
||||
user.user_profile.update!(bio_raw: "hello world I'm Jimmmy")
|
||||
expect(attrs).to eq(update_attributes)
|
||||
end
|
||||
DiscourseEvent.on(:within_user_updater_transaction, &handler)
|
||||
|
||||
updater = UserUpdater.new(user, user)
|
||||
updater.update(update_attributes)
|
||||
|
||||
expect(user.reload.name).to eq("Jimmmy Johnny")
|
||||
expect(user.user_profile.bio_raw).to eq("hello world I'm Jimmmy")
|
||||
ensure
|
||||
DiscourseEvent.off(:within_user_updater_transaction, &handler)
|
||||
end
|
||||
|
||||
it "can cancel the whole update transaction if a handler raises" do
|
||||
error_class = Class.new(StandardError)
|
||||
handler = Proc.new { raise error_class.new }
|
||||
|
||||
DiscourseEvent.on(:within_user_updater_transaction, &handler)
|
||||
|
||||
old_name = user.name
|
||||
updater = UserUpdater.new(user, user)
|
||||
|
||||
expect { updater.update(name: "Failure McClario") }.to raise_error(error_class)
|
||||
|
||||
expect(user.reload.name).to eq(old_name)
|
||||
ensure
|
||||
DiscourseEvent.off(:within_user_updater_transaction, &handler)
|
||||
end
|
||||
end
|
||||
|
||||
it "can update categories and tags" do
|
||||
updater = UserUpdater.new(user, user)
|
||||
updater.update(watched_tags: "#{tag.name},#{tag2.name}", muted_category_ids: [category.id])
|
||||
|
|
Loading…
Reference in New Issue