diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index c8b265f6186..14e2d55a19c 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -803,8 +803,16 @@ class TopicsController < ApplicationController end def set_notifications + user = + if is_api? && @guardian.is_admin? && + (params[:username].present? || params[:external_id].present?) + fetch_user_from_params + else + current_user + end + topic = Topic.find(params[:topic_id].to_i) - TopicUser.change(current_user, topic.id, notification_level: params[:notification_level].to_i) + TopicUser.change(user, topic.id, notification_level: params[:notification_level].to_i) render json: success_json end diff --git a/spec/requests/topics_controller_spec.rb b/spec/requests/topics_controller_spec.rb index 4ad4830079b..72c8a8b8ed6 100644 --- a/spec/requests/topics_controller_spec.rb +++ b/spec/requests/topics_controller_spec.rb @@ -4841,4 +4841,76 @@ RSpec.describe TopicsController do expect(body["group_name"]).to eq(group.name) end end + + describe "#set_notifications" do + describe "initiated by admin" do + it "can update another user's notification level via API" do + api_key = Fabricate(:api_key, user: admin) + post "/t/#{topic.id}/notifications", + params: { + username: user.username, + notification_level: NotificationLevels.topic_levels[:watching], + }, + headers: { + HTTP_API_KEY: api_key.key, + HTTP_API_USERNAME: admin.username, + } + expect(TopicUser.find_by(user: user, topic: topic).notification_level).to eq( + NotificationLevels.topic_levels[:watching], + ) + end + + it "can update own notification level via API" do + api_key = Fabricate(:api_key, user: admin) + post "/t/#{topic.id}/notifications", + params: { + notification_level: NotificationLevels.topic_levels[:watching], + }, + headers: { + HTTP_API_KEY: api_key.key, + HTTP_API_USERNAME: admin.username, + } + expect(TopicUser.find_by(user: admin, topic: topic).notification_level).to eq( + NotificationLevels.topic_levels[:watching], + ) + end + end + + describe "initiated by non-admin" do + it "only acts on current_user and ignores `username` param" do + sign_in(user) + TopicUser.create!( + user: user, + topic: topic, + notification_level: NotificationLevels.topic_levels[:tracking], + ) + post "/t/#{topic.id}/notifications.json", + params: { + username: user_2.username, + notification_level: NotificationLevels.topic_levels[:watching], + } + + expect(TopicUser.find_by(user: user, topic: topic).notification_level).to eq( + NotificationLevels.topic_levels[:watching], + ) + expect(TopicUser.find_by(user: user_2, topic: topic)).to be_blank + end + + it "can update own notification level via API" do + api_key = Fabricate(:api_key, user: user) + post "/t/#{topic.id}/notifications", + params: { + notification_level: NotificationLevels.topic_levels[:watching], + }, + headers: { + HTTP_API_KEY: api_key.key, + HTTP_API_USERNAME: user.username, + } + + expect(TopicUser.find_by(user: user, topic: topic).notification_level).to eq( + NotificationLevels.topic_levels[:watching], + ) + end + end + end end