diff --git a/Gemfile b/Gemfile index ba97ea0..f25fe5c 100644 --- a/Gemfile +++ b/Gemfile @@ -25,6 +25,7 @@ gem 'env_rails' gem 'instedd_telemetry', git: 'https://github.com/instedd/telemetry_rails.git' gem 'intercom-rails' gem 'dalli' +gem 'recaptcha' group :doc do gem 'sdoc', require: false diff --git a/Gemfile.lock b/Gemfile.lock index 2a4bc9b..82fd788 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -254,6 +254,8 @@ GEM rake (12.3.2) rdoc (4.1.2) json (~> 1.4) + recaptcha (5.5.0) + json responders (2.4.0) actionpack (>= 4.2.0, < 5.3) railties (>= 4.2.0, < 5.3) @@ -350,6 +352,7 @@ DEPENDENCIES rack-oauth2! rails (~> 4.2.0) rails-dev-tweaks (~> 1.1) + recaptcha rspec-rails ruby-openid sass-rails (~> 4.0.0) diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb new file mode 100644 index 0000000..82492d3 --- /dev/null +++ b/app/controllers/confirmations_controller.rb @@ -0,0 +1,11 @@ +class ConfirmationsController < Devise::ConfirmationsController + prepend_before_action :check_captcha, only: [:create] if Guisso::Settings.recaptcha? + + private + def check_captcha + unless verify_recaptcha + self.resource = resource_class.new + respond_with_navigational(resource) { render :new } + end + end +end diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb index 65faee5..e3f1866 100644 --- a/app/controllers/passwords_controller.rb +++ b/app/controllers/passwords_controller.rb @@ -1,8 +1,16 @@ class PasswordsController < Devise::PasswordsController + prepend_before_action :check_captcha, only: [:create] if Guisso::Settings.recaptcha? def create super Telemetry::Auth.reset_password if successfully_sent?(resource) end + private + def check_captcha + unless verify_recaptcha + self.resource = resource_class.new + respond_with_navigational(resource) { render :new } + end + end end diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 60dd762..c711db0 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -1,4 +1,6 @@ class RegistrationsController < Devise::RegistrationsController + prepend_before_action :check_captcha, only: [:create] if Guisso::Settings.recaptcha? + def new if redirect_url = params[:redirect_url] session[:user_return_to] = redirect_url @@ -9,4 +11,13 @@ def new def after_inactive_sign_up_path_for(resource) new_user_session_path end + + private + def check_captcha + unless verify_recaptcha + self.resource = resource_class.new sign_up_params + resource.validate # Look for any other validation errors besides reCAPTCHA + respond_with_navigational(resource) { render :new } + end + end end diff --git a/app/views/devise/confirmations/new.haml b/app/views/devise/confirmations/new.haml index 331d173..d8ebe22 100644 --- a/app/views/devise/confirmations/new.haml +++ b/app/views/devise/confirmations/new.haml @@ -8,6 +8,8 @@ = f.input_field :email, placeholder: 'Email', class: 'block email', pattern: false = f.full_error :email + = render 'recaptcha/in_form' + .control-group .controls = f.submit "Resend confirmation instructions", class: 'btn' diff --git a/app/views/devise/passwords/new.haml b/app/views/devise/passwords/new.haml index e2591eb..2274b1c 100644 --- a/app/views/devise/passwords/new.haml +++ b/app/views/devise/passwords/new.haml @@ -8,6 +8,8 @@ = f.input_field :email, placeholder: 'Email', class: 'block email', pattern: false = f.full_error :email + = render 'recaptcha/in_form' + .control-group .controls = f.submit "Send me reset password instructions", class: 'btn' diff --git a/app/views/devise/registrations/new.haml b/app/views/devise/registrations/new.haml index 3475d95..9d621bc 100644 --- a/app/views/devise/registrations/new.haml +++ b/app/views/devise/registrations/new.haml @@ -18,6 +18,8 @@ = f.input_field :password_confirmation, placeholder: 'Password confirmation', class: 'block password' = f.full_error :password_confirmation + = render 'recaptcha/in_form' + .control-group .controls = f.submit "Sign up", class: 'btn' diff --git a/app/views/layouts/centred_form.haml b/app/views/layouts/centred_form.haml index c35f387..e3c31ea 100644 --- a/app/views/layouts/centred_form.haml +++ b/app/views/layouts/centred_form.haml @@ -3,7 +3,7 @@ = yield :form_title .row.centred - .span4 + .span5 .well-white = yield diff --git a/app/views/recaptcha/_in_form.haml b/app/views/recaptcha/_in_form.haml new file mode 100644 index 0000000..760b1b1 --- /dev/null +++ b/app/views/recaptcha/_in_form.haml @@ -0,0 +1,5 @@ +- if Guisso::Settings.recaptcha? + .control-group{ class: flash[:recaptcha_error].present? ? "error" : "" } + = recaptcha_tags + %span.help-inline + = flash[:recaptcha_error] diff --git a/config/initializers/_settings.rb b/config/initializers/_settings.rb index c1a7814..ccb201b 100644 --- a/config/initializers/_settings.rb +++ b/config/initializers/_settings.rb @@ -49,5 +49,17 @@ def self.cookie_domain def self.openid_store URI(ENV["OPENID_STORE"] || Config["openid_store"] || "file:db/openid-store") end + + def self.recaptcha_site_key + ENV['RECAPTCHA_SITE_KEY'] || Config['recaptcha']['site_key'] + end + + def self.recaptcha_secret_key + ENV['RECAPTCHA_SECRET_KEY'] || Config['recaptcha']['secret_key'] + end + + def self.recaptcha? + recaptcha_site_key.present? && recaptcha_secret_key.present? + end end end diff --git a/config/initializers/recaptcha.rb b/config/initializers/recaptcha.rb new file mode 100644 index 0000000..125a62e --- /dev/null +++ b/config/initializers/recaptcha.rb @@ -0,0 +1,10 @@ +recaptcha_enabled = Guisso::Settings.recaptcha? +recaptcha_site_key = Guisso::Settings.recaptcha_site_key +recaptcha_secret_key = Guisso::Settings.recaptcha_secret_key + +if recaptcha_enabled + Recaptcha.configure do |config| + config.site_key = recaptcha_site_key + config.secret_key = recaptcha_secret_key + end +end diff --git a/config/routes.rb b/config/routes.rb index 628c203..d6ef886 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,6 +4,7 @@ omniauth_callbacks: 'omniauth_callbacks', sessions: 'sessions', registrations: 'registrations', + confirmations: 'confirmations', passwords: 'passwords' } diff --git a/config/settings.yml b/config/settings.yml index 0d2686d..94b2eba 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -11,3 +11,6 @@ cookie: name: guisso domain: instedd.org openid_store: file:db/openid-store +recaptcha: + site_key: + secret_key: