diff --git a/app/assets/javascripts/discourse/templates/components/reviewable-score.hbs b/app/assets/javascripts/discourse/templates/components/reviewable-score.hbs
index e19c9ceb65e..6454ffb5a40 100644
--- a/app/assets/javascripts/discourse/templates/components/reviewable-score.hbs
+++ b/app/assets/javascripts/discourse/templates/components/reviewable-score.hbs
@@ -19,7 +19,7 @@
diff --git a/app/assets/stylesheets/common/base/reviewables.scss b/app/assets/stylesheets/common/base/reviewables.scss
index 88cf15bd888..0dbd1821576 100644
--- a/app/assets/stylesheets/common/base/reviewables.scss
+++ b/app/assets/stylesheets/common/base/reviewables.scss
@@ -296,6 +296,12 @@
}
}
+.reviewable-score-reason {
+ margin: 0.5em 0;
+ max-width: $topic-body-width;
+ margin-bottom: 0.5em;
+}
+
.reviewable-conversation {
margin: 0.5em 0;
diff --git a/app/jobs/regular/create_user_reviewable.rb b/app/jobs/regular/create_user_reviewable.rb
index 2546f7fe636..fb1824c8aa0 100644
--- a/app/jobs/regular/create_user_reviewable.rb
+++ b/app/jobs/regular/create_user_reviewable.rb
@@ -2,6 +2,12 @@ class Jobs::CreateUserReviewable < Jobs::Base
def execute(args)
raise Discourse::InvalidParameters unless args[:user_id].present?
+ reason = nil
+ reason ||= :must_approve_users if SiteSetting.must_approve_users?
+ reason ||= :invite_only if SiteSetting.invite_only?
+
+ return unless reason
+
if user = User.find_by(id: args[:user_id])
return if user.approved?
@@ -18,6 +24,7 @@ class Jobs::CreateUserReviewable < Jobs::Base
reviewable.add_score(
Discourse.system_user,
ReviewableScore.types[:needs_approval],
+ reason: reason,
force_review: true
)
end
diff --git a/app/models/reviewable.rb b/app/models/reviewable.rb
index dfd73b8d3f0..5debd5ba4cf 100644
--- a/app/models/reviewable.rb
+++ b/app/models/reviewable.rb
@@ -115,6 +115,7 @@ class Reviewable < ActiveRecord::Base
def add_score(
user,
reviewable_score_type,
+ reason: nil,
created_at: nil,
take_action: false,
meta_topic_id: nil,
@@ -130,7 +131,7 @@ class Reviewable < ActiveRecord::Base
sub_total = SiteSetting.min_score_default_visibility
end
- rs = reviewable_scores.create!(
+ rs = reviewable_scores.new(
user: user,
status: ReviewableScore.statuses[:pending],
reviewable_score_type: reviewable_score_type,
@@ -139,6 +140,8 @@ class Reviewable < ActiveRecord::Base
take_action_bonus: take_action_bonus,
created_at: created_at || Time.zone.now
)
+ rs.reason = reason.to_s if reason
+ rs.save!
update(score: self.score + rs.score, latest_score: rs.created_at)
topic.update(reviewable_score: topic.reviewable_score + rs.score) if topic
diff --git a/app/serializers/reviewable_score_serializer.rb b/app/serializers/reviewable_score_serializer.rb
index c58568944cd..f5180d8f766 100644
--- a/app/serializers/reviewable_score_serializer.rb
+++ b/app/serializers/reviewable_score_serializer.rb
@@ -2,7 +2,7 @@ require_dependency 'reviewable_score_type_serializer'
class ReviewableScoreSerializer < ApplicationSerializer
- attributes :id, :score, :agree_stats, :status, :created_at, :reviewed_at
+ attributes :id, :score, :agree_stats, :status, :reason, :created_at, :reviewed_at
has_one :user, serializer: BasicUserSerializer, root: 'users'
has_one :score_type, serializer: ReviewableScoreTypeSerializer
has_one :reviewable_conversation, serializer: ReviewableConversationSerializer
@@ -16,4 +16,28 @@ class ReviewableScoreSerializer < ApplicationSerializer
}
end
+ def reason
+ return unless object.reason
+
+ if text = I18n.t("reviewables.reasons.#{object.reason}", default: nil)
+ # Create a convenient link to any site settings if the user is staff
+ settings_url = "#{Discourse.base_uri}/admin/site_settings/category/all_results?filter="
+
+ text.gsub!(/`[a-z_]+`/) do |m|
+ if scope.is_staff?
+ setting = m[1..-2]
+ "#{setting.gsub('_', ' ')}"
+ else
+ m.gsub('_', ' ')
+ end
+ end
+ end
+
+ text
+ end
+
+ def include_reason?
+ reason.present?
+ end
+
end
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 4d2f668aa23..7d7aefd3b8a 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -429,6 +429,7 @@ en:
conversation:
view_full: "view full conversation"
scores:
+ score: "Score"
date: "Date"
type: "Type"
status: "Status"
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index f156782efbe..a859b85417a 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -4385,6 +4385,18 @@ en:
reviewables:
missing_version: "You must supply a version parameter"
conflict: "There was an update conflict preventing you from doing that."
+ reasons:
+ post_count: "The poster has not met the `approve_post_count` requirements."
+ trust_level: "The poster has not met the `approve_unless_trust_level` requirement."
+ new_topics_unless_trust_level: "The poster has not met the `approve_new_topics_unless_trust_level` requirement."
+ fast_typer: "The poster typed in their post suspiciously fast. See: `min_first_post_typing_time`."
+ auto_silence_regexp: "The post matched the `auto_silence_first_post_regex` setting."
+ watched_word: "The post included a Watched Word."
+ staged: "The poster was staged and `approve_unless_staged` was set."
+ category: "The category of the post requires approval."
+ must_approve_users: "The user must be approved because `must_approve_users` is enabled."
+ invite_only: "The user must be approved because `invite_only` is enabled."
+
actions:
agree:
title: "Agree..."
diff --git a/db/migrate/20190411144545_add_reason_to_reviewable_scores.rb b/db/migrate/20190411144545_add_reason_to_reviewable_scores.rb
new file mode 100644
index 00000000000..a6105c6b271
--- /dev/null
+++ b/db/migrate/20190411144545_add_reason_to_reviewable_scores.rb
@@ -0,0 +1,5 @@
+class AddReasonToReviewableScores < ActiveRecord::Migration[5.2]
+ def change
+ add_column :reviewable_scores, :reason, :string
+ end
+end
diff --git a/lib/new_post_manager.rb b/lib/new_post_manager.rb
index d0eca260147..6269d978c10 100644
--- a/lib/new_post_manager.rb
+++ b/lib/new_post_manager.rb
@@ -198,12 +198,9 @@ class NewPostManager
def enqueue(reason = nil)
result = NewPostResult.new(:enqueued)
- payload = { raw: @args[:raw], tags: @args[:tags] }
- payload[:reason] = reason.to_s if reason
-
reviewable = ReviewableQueuedPost.new(
created_by: @user,
- payload: payload,
+ payload: { raw: @args[:raw], tags: @args[:tags] },
topic_id: @args[:topic_id],
reviewable_by_moderator: true
)
@@ -225,6 +222,7 @@ class NewPostManager
reviewable.add_score(
Discourse.system_user,
ReviewableScore.types[:needs_approval],
+ reason: reason,
force_review: true
)
else
diff --git a/spec/jobs/create_user_reviewable_spec.rb b/spec/jobs/create_user_reviewable_spec.rb
index ffb2c3b8922..acab20ba9af 100644
--- a/spec/jobs/create_user_reviewable_spec.rb
+++ b/spec/jobs/create_user_reviewable_spec.rb
@@ -6,14 +6,40 @@ describe Jobs::CreateUserReviewable do
let(:user) { Fabricate(:user) }
it "creates the reviewable" do
+ SiteSetting.must_approve_users = true
described_class.new.execute(user_id: user.id)
reviewable = Reviewable.find_by(target: user)
expect(reviewable).to be_present
expect(reviewable.pending?).to eq(true)
- expect(reviewable.reviewable_scores).to be_present
expect(reviewable.payload['username']).to eq(user.username)
expect(reviewable.payload['name']).to eq(user.name)
expect(reviewable.payload['email']).to eq(user.email)
end
+
+ describe "reasons" do
+ it "does nothing if there's no reason" do
+ described_class.new.execute(user_id: user.id)
+ expect(Reviewable.find_by(target: user)).to be_blank
+ end
+
+ it "adds must_approve_users if enabled" do
+ SiteSetting.must_approve_users = true
+ described_class.new.execute(user_id: user.id)
+ reviewable = Reviewable.find_by(target: user)
+ score = reviewable.reviewable_scores.first
+ expect(score).to be_present
+ expect(score.reason).to eq('must_approve_users')
+ end
+
+ it "adds invite_only if enabled" do
+ SiteSetting.invite_only = true
+ described_class.new.execute(user_id: user.id)
+ reviewable = Reviewable.find_by(target: user)
+ score = reviewable.reviewable_scores.first
+ expect(score).to be_present
+ expect(score.reason).to eq('invite_only')
+ end
+ end
+
end
diff --git a/spec/models/reviewable_user_spec.rb b/spec/models/reviewable_user_spec.rb
index fed75f86d71..1b914d826d3 100644
--- a/spec/models/reviewable_user_spec.rb
+++ b/spec/models/reviewable_user_spec.rb
@@ -38,6 +38,7 @@ RSpec.describe ReviewableUser, type: :model do
context "when a user is deleted" do
it "should reject the reviewable" do
+ SiteSetting.must_approve_users = true
Jobs::CreateUserReviewable.new.execute(user_id: user.id)
reviewable = Reviewable.find_by(target: user)
expect(reviewable.pending?).to eq(true)
diff --git a/spec/requests/posts_controller_spec.rb b/spec/requests/posts_controller_spec.rb
index 17b2b71a317..7e5e65557c6 100644
--- a/spec/requests/posts_controller_spec.rb
+++ b/spec/requests/posts_controller_spec.rb
@@ -801,7 +801,7 @@ describe PostsController do
expect(user).to be_silenced
rp = ReviewableQueuedPost.find_by(created_by: user)
- expect(rp.payload['reason']).to eq('fast_typer')
+ expect(rp.reviewable_scores.first.reason).to eq('fast_typer')
mod = Fabricate(:moderator)
rp.perform(mod, :approve)
@@ -851,7 +851,8 @@ describe PostsController do
expect(parsed["action"]).to eq("enqueued")
reviewable = ReviewableQueuedPost.find_by(created_by: user)
- expect(reviewable.payload['reason']).to eq('auto_silence_regex')
+ score = reviewable.reviewable_scores.first
+ expect(score.reason).to eq('auto_silence_regex')
user.reload
expect(user).to be_silenced
diff --git a/spec/serializers/reviewable_user_serializer_spec.rb b/spec/serializers/reviewable_user_serializer_spec.rb
index 88991ea19ae..2fa506494fd 100644
--- a/spec/serializers/reviewable_user_serializer_spec.rb
+++ b/spec/serializers/reviewable_user_serializer_spec.rb
@@ -6,6 +6,7 @@ describe ReviewableUserSerializer do
let(:admin) { Fabricate(:admin) }
it "includes the user fields for review" do
+ SiteSetting.must_approve_users = true
Jobs::CreateUserReviewable.new.execute(user_id: user.id)
reviewable = Reviewable.find_by(target: user)
|