diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index c857838c22e..815266b0dd4 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -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 diff --git a/app/services/user_updater.rb b/app/services/user_updater.rb index 32481fb5933..8c740f4c0e7 100644 --- a/app/services/user_updater.rb +++ b/app/services/user_updater.rb @@ -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 diff --git a/spec/requests/users_controller_spec.rb b/spec/requests/users_controller_spec.rb index 6e4d17be872..56874e84f35 100644 --- a/spec/requests/users_controller_spec.rb +++ b/spec/requests/users_controller_spec.rb @@ -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 diff --git a/spec/services/user_updater_spec.rb b/spec/services/user_updater_spec.rb index abd6a44d24d..7573dd5f99e 100644 --- a/spec/services/user_updater_spec.rb +++ b/spec/services/user_updater_spec.rb @@ -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])