mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
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:
@@ -2015,7 +2015,13 @@ class UsersController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
deprecate_modify_user_params_method
|
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
|
end
|
||||||
|
|
||||||
# Plugins can use this to modify user parameters
|
# Plugins can use this to modify user parameters
|
||||||
|
|||||||
@@ -237,6 +237,7 @@ class UserUpdater
|
|||||||
attributes.fetch(:name) { "" },
|
attributes.fetch(:name) { "" },
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
DiscourseEvent.trigger(:within_user_updater_transaction, user, attributes)
|
||||||
rescue Addressable::URI::InvalidURIError => e
|
rescue Addressable::URI::InvalidURIError => e
|
||||||
# Prevent 500 for crazy url input
|
# Prevent 500 for crazy url input
|
||||||
return saved
|
return saved
|
||||||
|
|||||||
@@ -2973,6 +2973,32 @@ RSpec.describe UsersController do
|
|||||||
end
|
end
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
describe "#badge_title" do
|
describe "#badge_title" do
|
||||||
|
|||||||
@@ -46,6 +46,42 @@ RSpec.describe UserUpdater do
|
|||||||
expect(user.reload.name).to eq "Jim Tom"
|
expect(user.reload.name).to eq "Jim Tom"
|
||||||
end
|
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
|
it "can update categories and tags" do
|
||||||
updater = UserUpdater.new(user, user)
|
updater = UserUpdater.new(user, user)
|
||||||
updater.update(watched_tags: "#{tag.name},#{tag2.name}", muted_category_ids: [category.id])
|
updater.update(watched_tags: "#{tag.name},#{tag2.name}", muted_category_ids: [category.id])
|
||||||
|
|||||||
Reference in New Issue
Block a user