discourse/plugins/discourse-solved/app/controllers/discourse_solved/answer_controller.rb
David Battersby ce377f6949
DEV: add service objects for accept_answer and unaccept_answer (#37878)
Extracts `accept_answer!` and `unaccept_answer!` from plugin.rb and
moves the logic into separate service objects, along with adding more
detailed test coverage for each service.

---------

Co-authored-by: Loïc Guitaut <loic@discourse.org>
2026-03-04 12:34:37 +04:00

51 lines
1.9 KiB
Ruby
Vendored

# frozen_string_literal: true
class DiscourseSolved::AnswerController < ::ApplicationController
requires_plugin DiscourseSolved::PLUGIN_NAME
before_action :limit_accepts
def accept
DiscourseSolved::AcceptAnswer.call(params: { post_id: params[:id] }, guardian:) do
on_success { |topic:| render_json_dump(topic.accepted_answer_post_info) }
on_model_not_found(:post) { raise Discourse::NotFound }
on_model_not_found(:topic) { raise Discourse::NotFound }
on_failed_policy(:can_accept_answer) { raise Discourse::InvalidAccess }
on_model_errors(:solved) do |model|
render_json_error(model, type: :record_invalid, status: 422)
end
on_failed_contract do |contract|
render json: failed_json.merge(errors: contract.errors.full_messages), status: :bad_request
end
on_failure { render json: failed_json, status: :unprocessable_entity }
end
end
def unaccept
DiscourseSolved::UnacceptAnswer.call(params: { post_id: params[:id] }, guardian:) do
on_success { render json: success_json }
on_model_not_found(:post) { raise Discourse::NotFound }
on_model_not_found(:topic) { raise Discourse::NotFound }
on_failed_policy(:can_unaccept_answer) { raise Discourse::InvalidAccess }
on_failed_contract do |contract|
render json: failed_json.merge(errors: contract.errors.full_messages), status: :bad_request
end
on_failure { render json: failed_json, status: :unprocessable_entity }
end
end
private
def limit_accepts
return if current_user.staff?
run_rate_limiter =
DiscoursePluginRegistry.apply_modifier(
:solved_answers_controller_run_rate_limiter,
true,
current_user,
)
return if !run_rate_limiter
RateLimiter.new(nil, "accept-hr-#{current_user.id}", 20, 1.hour).performed!
RateLimiter.new(nil, "accept-min-#{current_user.id}", 4, 30.seconds).performed!
end
end