sharetribe/sharetribe

View on GitHub
app/controllers/feedbacks_controller.rb

Summary

Maintainability
A
25 mins
Test Coverage
class FeedbacksController < ApplicationController
  include ConfigRecaptcha
  skip_before_action :cannot_access_if_banned
  skip_before_action :cannot_access_without_confirmation
  skip_before_action :ensure_consent_given
  skip_before_action :ensure_user_belongs_to_community
  skip_before_action :set_display_expiration_notice

  FeedbackForm = FormUtils.define_form("Feedback",
                                       :content,
                                       :title,
                                       :url, # referrer
                                       :email
  ).with_validations {
    validates_presence_of :content
  }

  def new
    render_form
  end

  def create
    feedback_form = FeedbackForm.new(params[:feedback])

    unless validate_recaptcha(params['g-recaptcha-response'])
      flash[:error] = t('layouts.notifications.recaptcha_verification_failure')
      return render_form(feedback_form)
    end

    unless feedback_form.valid?
      flash[:error] = t("layouts.notifications.feedback_not_saved")
      return render_form(feedback_form)
    end

    return if ensure_not_spam!(params[:feedback], feedback_form)

    author_id = Maybe(@current_user).id.or_else("Anonymous")
    email = current_user_email || feedback_form.email

    feedback = Feedback.create(
      feedback_form.to_hash.merge({
                                    community_id: @current_community.id,
                                    author_id: author_id,
                                    email: email
                                  }))

    MailCarrier.deliver_later(PersonMailer.new_feedback(feedback, @current_community))

    flash[:notice] = t("layouts.notifications.feedback_saved")
    redirect_to search_path
  end

  private

  def render_form(form = nil)
    render action: :new, locals: feedback_locals(form).merge({
      has_admin_rights: @current_user && @current_user.has_admin_rights?(@current_community)
    })
  end

  def feedback_locals(feedback_form)
    {
      email_present: current_user_email.present?,
      feedback_form: feedback_form || FeedbackForm.new(title: nil) # title is honeypot
    }
  end

  def current_user_email
    Maybe(@current_user).confirmed_notification_email_to.or_else(nil)
  end

  # Return truthy if is spam
  def ensure_not_spam!(params, feedback_form)
    if spam?(params[:content], params[:title])
      flash[:error] = t("layouts.notifications.feedback_considered_spam")
      return render_form(feedback_form)
    else
      false
    end
  end

  def link_tags?(str)
    str.include?("[url=") || str.include?("<a href=")
  end

  def too_many_urls?(str)
    str.scan("http://").count > 10
  end

  # Detect most usual spam messages
  def spam?(content, honeypot)
    honeypot.present? || link_tags?(content) || too_many_urls?(content)
  end
end