matthutchinson / acts_as_textcaptcha

Text-based logic question captcha's for Rails 🚫🤖

Home Page:https://acts-as-textcaptcha.hiddenloop.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Spam Answer is always incorrect

jules27 opened this issue · comments

I'm trying to use this gem to stop spam comments, but for some reason I'm always getting "Spam answer is incorrect, try another question instead" when I try to make a new comment, either via the form or on the Rails console.

I've added the gem in my Gemfile.

Controller:

@comment = Comment.new
@comment.textcaptcha

Model:

class Comment < ActiveRecord::Base
  attr_accessible :text, :name

  validates_presence_of :text, :name

  acts_as_textcaptcha bcrypt_salt: Settings.text_captcha_salt,
                      questions: [{ 'question' => '1+1', 'answers' => '2,two' }]
end

Form view:

= simple_form_for @comment do |f|
  = f.input :name
  = f.input :text, as: :text

  = f.label :spam_answer, comment.spam_question
  = f.text_field :spam_answer, value: ''
  %br

  = f.submit "Post Comment"

acts_as_textcaptcha config file:

development: &common_settings
  bcrypt_salt: <salt omitted>
  bcrypt_cost: 10
  questions:
      - question: 'Is ice hot or cold?'
        answers: 'cold'
      - question: 'what color is an orange?'
        answers: 'orange'
      <rest of the questions omitted>

test:
  <<: *common_settings
  bcrypt_salt: <salt omitted>
  bcrypt_cost: 1

production:
  <<: *common_settings

Adding comment through Rails console:

> a = Comment.new("name"=>"Hi", "text"=>"asdf", "spam_answer"=>"2")
> a.valid?
 => false 
> a.errors.messages
 => {:spam_answer=>["is incorrect, try another question instead"]} 

Can you see if I'm missing something obvious? Thanks!

Yep, you are not sending the encrypted spam answers in the form. To fix that you need to use the textcaptcha_fields helper method to wrap the answer input like so;

<%= textcaptcha_fields(f) do %>
  <div class="field">
    <%= f.label :spam_answer, @comment.spam_question %><br/>
    <%= f.text_field :spam_answer, :value => '' %>
  </div>
<% end %>

After doing this, view the page source and you'll see it has added an encrypted spam_answers param to check against on saving.

In console, to save a valid comment, you will have to use the textcaptcha method (like you do in the controller) This assigns the spam question and encrypted spam answers like so;

a = Comment.new("name"=>"Hi", "text"=>"asdf", "spam_answer"=>"2")
a.spam_answers # will be nil until you call ...
a.textcaptcha # which picks a spam question and assigns it's valid spam answers (but also clears spam_answer you mass-assigned above)
a.spam_answer = 2
a.valid? # true    

Or you can skip the spam checking altogether in console like this;

a = Comment.new("name"=>"Hi", "text"=>"asdf", "spam_answer"=>"2")
a.textcaptcha
a.skip_textcaptcha = true
a.save

Ps.. I should also point out, that since in your code, you have assigned questions directly in the model the questions you have in the acts_as_textcaptcha yml file will never be used for Comments.