diff --git a/app/controllers/messages/by_bots_controller.rb b/app/controllers/messages/by_bots_controller.rb index f225e51..36a5069 100644 --- a/app/controllers/messages/by_bots_controller.rb +++ b/app/controllers/messages/by_bots_controller.rb @@ -1,9 +1,11 @@ class Messages::ByBotsController < MessagesController include RawRequestBody - allow_bot_access only: %i[ index create ] + allow_bot_access only: %i[ index create update destroy ] before_action :set_room + before_action :set_message, only: %i[ update destroy ] + before_action :ensure_can_administer, only: %i[ update destroy ] before_action :ensure_body_or_attachment_present, only: :create def index @@ -16,6 +18,11 @@ class Messages::ByBotsController < MessagesController head :created, location: message_url(@message) end + def destroy + super + head :no_content + end + private def set_room @room = Current.user.rooms.find_by(id: params[:room_id]) diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 959b652..4cbc771 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -37,7 +37,11 @@ class MessagesController < ApplicationController @message.update!(message_params) @message.broadcast_replace_to @room, :messages, target: [ @message, :presentation ], partial: "messages/presentation", attributes: { maintain_scroll: true } - redirect_to room_message_url(@room, @message) + + respond_to do |format| + format.html { redirect_to room_message_url(@room, @message) } + format.json { render :show } + end end def destroy diff --git a/app/views/messages/by_bots/show.json.jbuilder b/app/views/messages/by_bots/show.json.jbuilder new file mode 100644 index 0000000..a500e40 --- /dev/null +++ b/app/views/messages/by_bots/show.json.jbuilder @@ -0,0 +1 @@ +json.partial! "messages/message", message: @message diff --git a/config/routes.rb b/config/routes.rb index 03466a1..da01b4f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -64,7 +64,7 @@ Rails.application.routes.draw do nested do scope path: ":bot_key", as: :bot, defaults: { format: :json } do - resources :messages, controller: "messages/by_bots", only: %i[ index create ] do + resources :messages, controller: "messages/by_bots", only: %i[ index create update destroy ] do resources :boosts, controller: "messages/boosts/by_bots", only: :create end end diff --git a/test/controllers/messages/by_bots_controller_test.rb b/test/controllers/messages/by_bots_controller_test.rb index 0c145e7..da6f5cc 100644 --- a/test/controllers/messages/by_bots_controller_test.rb +++ b/test/controllers/messages/by_bots_controller_test.rb @@ -148,4 +148,88 @@ class Messages::ByBotsControllerTest < ActionDispatch::IntegrationTest get room_messages_url(@room, bot_key: users(:bender).bot_key) assert_response :forbidden end + + test "update" do + message = post_bot_message "Deploying..." + + assert_no_difference -> { Message.count } do + patch room_bot_message_url(@room, users(:bender).bot_key, message), params: +"Deployed." + end + + assert_response :ok + assert_equal "Deployed.", message.reload.plain_text_body + + json = JSON.parse(response.body) + assert_equal message.id, json["id"] + assert_equal "Deployed.", json["body"]["plain_text"] + assert_equal users(:bender).id, json["creator"]["id"] + assert_equal room_message_url(@room, message), json["url"] + end + + test "update with UTF-8 content" do + message = post_bot_message "Deploying..." + + patch room_bot_message_url(@room, users(:bender).bot_key, message), params: +"Deployed 🚀!" + + assert_response :ok + assert_equal "Deployed 🚀!", message.reload.plain_text_body + assert_equal "Deployed 🚀!", JSON.parse(response.body)["body"]["plain_text"] + end + + test "update can't touch a message the bot did not create" do + message = messages(:fourth) + original = message.plain_text_body + + patch room_bot_message_url(@room, users(:bender).bot_key, message), params: +"Hijacked!" + + assert_response :forbidden + assert_equal original, message.reload.plain_text_body + end + + test "update is not found for a room the bot is not a member of" do + message = messages(:first) + original = message.plain_text_body + + patch room_bot_message_url(rooms(:designers), users(:bender).bot_key, message), params: +"Hijacked!" + + assert_response :not_found + assert_equal original, message.reload.plain_text_body + end + + test "update can't be abused to edit messages as any user" do + message = messages(:fourth) + bot_key = "#{users(:jz).id}-" + original = message.plain_text_body + + patch room_bot_message_url(@room, bot_key, message), params: +"Hijacked!" + + assert_response :redirect + assert_equal original, message.reload.plain_text_body + end + + test "destroy" do + message = post_bot_message "Deploying..." + + assert_difference -> { Message.count }, -1 do + delete room_bot_message_url(@room, users(:bender).bot_key, message) + end + + assert_response :no_content + end + + test "destroy can't touch a message the bot did not create" do + message = messages(:fourth) + + assert_no_difference -> { Message.count } do + delete room_bot_message_url(@room, users(:bender).bot_key, message) + end + + assert_response :forbidden + end + + private + def post_bot_message(body) + post room_bot_messages_url(@room, users(:bender).bot_key), params: +body + Message.last + end end