diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index 0eed27323..a6c763150 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -60,6 +60,7 @@ class CommentsController < ApplicationController @comment.user_id = current_user.id authorize @comment + permit_commentor if @comment.save checked_code_of_conduct = params[:checked_code_of_conduct].present? && !current_user.checked_code_of_conduct @@ -93,6 +94,8 @@ class CommentsController < ApplicationController end # See https://github.com/thepracticaldev/dev.to/pull/5485#discussion_r366056925 # for details as to why this is necessary + rescue ModerationUnauthorizedError => e + render json: { error: e.message }, status: :unprocessable_entity rescue Pundit::NotAuthorizedError, RateLimitChecker::LimitReached raise rescue StandardError => e @@ -113,6 +116,7 @@ class CommentsController < ApplicationController @comment.user_id = moderator.id @comment.body_markdown = response_template.content authorize @comment + permit_commentor if @comment.save Notification.send_new_comment_notifications_without_delay(@comment) @@ -126,6 +130,8 @@ class CommentsController < ApplicationController else render json: { status: @comment&.errors&.full_messages&.to_sentence }, status: :unprocessable_entity end + rescue ModerationUnauthorizedError => e + render json: { error: e.message }, status: :unprocessable_entity rescue StandardError => e skip_authorization @@ -290,4 +296,16 @@ class CommentsController < ApplicationController :comment_creation end end + + def permit_commentor + return unless user_blocked? + + raise ModerationUnauthorizedError, "Not allowed due to moderation action" + end + + def user_blocked? + return false if current_user.blocked_by_count.zero? + + UserBlock.blocking?(@comment.commentable.user_id, current_user.id) + end end diff --git a/app/errors/moderation_unauthorized_error.rb b/app/errors/moderation_unauthorized_error.rb new file mode 100644 index 000000000..e9cd8c26a --- /dev/null +++ b/app/errors/moderation_unauthorized_error.rb @@ -0,0 +1 @@ +class ModerationUnauthorizedError < StandardError; end diff --git a/app/policies/comment_policy.rb b/app/policies/comment_policy.rb index c5dfaa8d1..c5ac2623b 100644 --- a/app/policies/comment_policy.rb +++ b/app/policies/comment_policy.rb @@ -4,7 +4,7 @@ class CommentPolicy < ApplicationPolicy end def create? - !user_suspended? && !user.comment_suspended? && !user_blocked? + !user_suspended? && !user.comment_suspended? end def update? @@ -28,7 +28,7 @@ class CommentPolicy < ApplicationPolicy end def moderator_create? - !user_blocked? && (user_moderator? || minimal_admin?) + user_moderator? || minimal_admin? end def hide? @@ -69,12 +69,6 @@ class CommentPolicy < ApplicationPolicy record.user_id == user.id end - def user_blocked? - return false if user.blocked_by_count.zero? - - UserBlock.blocking?(record.commentable.user_id, user.id) - end - def user_commentable_author? record.commentable.present? && record.commentable.user_id == user.id end diff --git a/spec/requests/comments_create_spec.rb b/spec/requests/comments_create_spec.rb index 1cb0c2ff6..fef6ee247 100644 --- a/spec/requests/comments_create_spec.rb +++ b/spec/requests/comments_create_spec.rb @@ -67,9 +67,8 @@ RSpec.describe "CommentsCreate", type: :request do user.update(blocked_by_count: 1) blocker_article = create(:article, user: blocker) - expect do - post comments_path, params: comment_params(commentable_id: blocker_article.id) - end.to raise_error(Pundit::NotAuthorizedError) + post comments_path, params: comment_params(commentable_id: blocker_article.id) + expect(response).to have_http_status(:unprocessable_entity) end end