app/controllers/comment_controller.rb
# app/controllers/comment_controller.rb:
# Show annotations upon a request or other object.
#
# Copyright (c) 2008 UK Citizens Online Democracy. All rights reserved.
# Email: hello@mysociety.org; WWW: http://www.mysociety.org/
class CommentController < ApplicationController
before_action :build_comment, only: [:new]
before_action :check_read_only, only: [ :new ]
before_action :find_info_request, only: [ :new ]
before_action :create_track_thing, only: [ :new ]
before_action :reject_unless_comments_allowed, only: [ :new ]
before_action :reject_if_user_banned, only: [ :new ]
before_action :set_in_pro_area, only: [ :new ]
def new
if params[:comment]
# TODO: this check should theoretically be a validation rule in the model
@existing_comment = Comment.find_existing(@info_request.id, params[:comment][:body])
else
# Default to subscribing to request when first viewing form
params[:subscribe_to_request] = true
end
# See if values were valid or not
if !params[:comment] || !@existing_comment.nil? || !@comment.valid? || params[:reedit]
@comment ||= @info_request.comments.new
render action: 'new'
return
end
# Show preview page, if it is a preview
if params[:preview].to_i == 1
render action: 'preview'
return
end
if !authenticated?
ask_to_login(
web: _('To post your annotation'),
email: _('Then your annotation to {{info_request_title}} will be ' \
'posted.',
info_request_title: @info_request.title),
email_subject: _('Confirm your annotation to {{info_request_title}}',
info_request_title: @info_request.title)
)
else
if spam_comment?(params[:comment][:body], @user)
handle_spam_comment(@user) && return
end
# Also subscribe to track for this request, so they get updates
# (do this first, so definitely don't send alert)
flash[:notice] = _("Thank you for making an annotation!")
if params[:subscribe_to_request]
@track_thing = TrackThing.create_track_for_request(@info_request)
@existing_track = TrackThing.find_existing(@user, @track_thing)
if @user && @info_request.user == @user
# don't subscribe to own request!
elsif !@existing_track
@track_thing.track_medium = 'email_daily'
@track_thing.tracking_user_id = @user.id
@track_thing.save!
flash[:notice] += _(" You will also be emailed updates about the request.")
else
flash[:notice] += _(" You are already being emailed updates about the request.")
end
end
# This automatically saves dependent objects in the same transaction
@comment = @info_request.add_comment(params[:comment][:body], authenticated_user)
@info_request.save!
# we don't use comment_url here, as then you don't see the flash at top of page
redirect_to request_url(@info_request)
end
end
private
def build_comment
if params[:comment]
@comment = Comment.new(comment_params.merge(user: @user))
end
end
def comment_params
params.require(:comment).permit(:body)
end
def find_info_request
if params[:type] == 'request'
@info_request = InfoRequest.find_by_url_title!(params[:url_title])
if @info_request.embargo && cannot?(:read, @info_request)
raise ActiveRecord::RecordNotFound
end
else
raise "Unknown type #{ params[:type] }"
end
end
def create_track_thing
@track_thing = TrackThing.create_track_for_request(@info_request)
end
# Are comments disabled on this request, or globally?
#
# There is no “add comment” link when comments are disabled, so users should
# not usually hit this unless they are explicitly attempting to avoid the
# comment block.
def reject_unless_comments_allowed
unless feature_enabled?(:annotations) && @info_request.comments_allowed?
redirect_to request_url(@info_request), notice: "Comments are not allowed on this request"
end
end
# Banned from adding comments?
def reject_if_user_banned
return if !authenticated? || authenticated_user.can_make_comments?
if authenticated_user.banned?
@details = authenticated_user.can_fail_html
render template: 'user/banned'
else
render template: 'comment/rate_limited'
end
end
# An override of ApplicationController#set_in_pro_area to set the flag
# whenever the info_request has an embargo, because we might not have a :pro
# parameter to go on.
def set_in_pro_area
@in_pro_area = @info_request.embargo.present?
end
def spam_comment?(comment_body, user)
!user.confirmed_not_spam? &&
AlaveteliSpamTermChecker.new.spam?(comment_body)
end
def block_spam_comments?
AlaveteliConfiguration.block_spam_comments ||
AlaveteliConfiguration.enable_anti_spam
end
# Sends an exception and blocks the comment depending on configuration.
def handle_spam_comment(user)
if send_exception_notifications?
e = Exception.new("Possible spam annotation from user #{ user.id }")
ExceptionNotifier.notify_exception(e, env: request.env)
end
if block_spam_comments?
flash.now[:error] = _("Sorry, we're currently unable to add your " \
"annotation. Please try again later.")
render action: 'new'
true
end
end
end