FEATURE: use new clean pattern for preloading fields
FIX: work around concurrency bug FIX: add rate limits on accepting / unaccepting (20 an hour, 4 per 30 secs)
This commit is contained in:
parent
7ed0be0527
commit
f183671365
46
plugin.rb
46
plugin.rb
|
@ -19,6 +19,9 @@ after_initialize do
|
|||
require_dependency "application_controller"
|
||||
class DiscourseSolved::AnswerController < ::ApplicationController
|
||||
def accept
|
||||
|
||||
limit_accepts
|
||||
|
||||
post = Post.find(params[:id].to_i)
|
||||
|
||||
guardian.ensure_can_accept_answer!(post.topic)
|
||||
|
@ -54,6 +57,9 @@ after_initialize do
|
|||
end
|
||||
|
||||
def unaccept
|
||||
|
||||
limit_accepts
|
||||
|
||||
post = Post.find(params[:id].to_i)
|
||||
|
||||
guardian.ensure_can_accept_answer!(post.topic)
|
||||
|
@ -75,6 +81,13 @@ after_initialize do
|
|||
|
||||
render json: success_json
|
||||
end
|
||||
|
||||
def limit_accepts
|
||||
unless current_user.staff?
|
||||
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
|
||||
end
|
||||
|
||||
DiscourseSolved::Engine.routes.draw do
|
||||
|
@ -140,7 +153,8 @@ after_initialize do
|
|||
|
||||
def accepted_answer_post_id
|
||||
id = object.topic.custom_fields["accepted_answer_post_id"]
|
||||
id && id.to_i
|
||||
# a bit messy but race conditions can give us an array here, avoid
|
||||
id && id.to_i rescue nil
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -241,7 +255,7 @@ after_initialize do
|
|||
attributes :has_accepted_answer
|
||||
|
||||
def include_has_accepted_answer?
|
||||
object.has_accepted_answer
|
||||
object.custom_fields["accepted_answer_post_id"]
|
||||
end
|
||||
|
||||
def has_accepted_answer
|
||||
|
@ -249,32 +263,6 @@ after_initialize do
|
|||
end
|
||||
end
|
||||
|
||||
class ::Topic
|
||||
attr_accessor :has_accepted_answer
|
||||
end
|
||||
|
||||
module ::DiscourseSolved::ExtendTopics
|
||||
def load_topics
|
||||
topics = super
|
||||
if topics.present?
|
||||
# super efficient for front page
|
||||
with_accepted = Set.new(Topic.exec_sql(
|
||||
'SELECT topic_id FROM topic_custom_fields
|
||||
WHERE topic_id in (:topic_ids) AND
|
||||
value IS NOT NULL AND
|
||||
name = \'accepted_answer_post_id\'',
|
||||
topic_ids: topics.map(&:id)
|
||||
).values.flatten.map(&:to_i))
|
||||
topics.each do |topic|
|
||||
topic.has_accepted_answer = true if with_accepted.include? topic.id
|
||||
end
|
||||
end
|
||||
topics
|
||||
end
|
||||
end
|
||||
|
||||
class ::TopicList
|
||||
prepend ::DiscourseSolved::ExtendTopics
|
||||
end
|
||||
TopicList.preloaded_custom_fields << "accepted_answer_post_id" if TopicList.respond_to? :preloaded_custom_fields
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue