From 0fb907441c827cadc767641b29d5d2c0e554f7a4 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 25 Jan 2022 22:37:12 +0100 Subject: Add ability to set hCaptcha either on registration form or on e-mail validation Upshot of CAPTCHA on e-mail validation is it does not need to break the in-band registration API. --- app/controllers/auth/confirmations_controller.rb | 50 ++++++++++++++++++++++++ app/controllers/concerns/captcha_concern.rb | 12 +++++- 2 files changed, 60 insertions(+), 2 deletions(-) (limited to 'app/controllers') diff --git a/app/controllers/auth/confirmations_controller.rb b/app/controllers/auth/confirmations_controller.rb index 0b5a2f3c9..e9a646f91 100644 --- a/app/controllers/auth/confirmations_controller.rb +++ b/app/controllers/auth/confirmations_controller.rb @@ -1,12 +1,18 @@ # frozen_string_literal: true class Auth::ConfirmationsController < Devise::ConfirmationsController + include CaptchaConcern + layout 'auth' before_action :set_body_classes before_action :set_pack + before_action :set_confirmation_user!, only: [:show, :confirm_captcha] before_action :require_unconfirmed! + before_action :extend_csp_for_captcha!, only: [:show, :confirm_captcha] + before_action :require_captcha_if_needed!, only: [:show] + skip_before_action :require_functional! def new @@ -15,8 +21,52 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController resource.email = current_user.unconfirmed_email || current_user.email if user_signed_in? end + def show + clear_captcha! + + old_session_values = session.to_hash + reset_session + session.update old_session_values.except('session_id') + + super + end + + def confirm_captcha + check_captcha! do |message| + flash.now[:alert] = message + render :captcha + return + end + + show + end + private + def require_captcha_if_needed! + render :captcha if captcha_required? + end + + def set_confirmation_user! + # We need to reimplement looking up the user because + # Devise::ConfirmationsController#show looks up and confirms in one + # step. + confirmation_token = params[:confirmation_token] + return if confirmation_token.nil? + @confirmation_user = User.find_first_by_auth_conditions(confirmation_token: confirmation_token) + end + + def captcha_user_bypass? + return true if @confirmation_user.nil? || @confirmation_user.confirmed? + + invite = Invite.find(@confirmation_user.invite_id) if @confirmation_user.invite_id.present? + invite.present? && !invite.max_uses.nil? + end + + def captcha_context + 'email-confirmation' + end + def set_pack use_pack 'auth' end diff --git a/app/controllers/concerns/captcha_concern.rb b/app/controllers/concerns/captcha_concern.rb index 4a942c988..02069d205 100644 --- a/app/controllers/concerns/captcha_concern.rb +++ b/app/controllers/concerns/captcha_concern.rb @@ -15,17 +15,21 @@ module CaptchaConcern end def captcha_enabled? - captcha_available? && Setting.captcha_enabled + captcha_available? && Setting.captcha_mode == captcha_context end def captcha_recently_passed? session[:captcha_passed_at].present? && session[:captcha_passed_at] >= CAPTCHA_TIMEOUT.ago end + def captcha_user_bypass? + current_user.present? || (@invite.present? && @invite.valid_for_use? && !@invite.max_uses.nil?) + end + def captcha_required? return false if ENV['OMNIAUTH_ONLY'] == 'true' return false unless Setting.registrations_mode != 'none' || @invite&.valid_for_use? - captcha_enabled? && !current_user && !(@invite.present? && @invite.valid_for_use? && !@invite.max_uses.nil?) && !captcha_recently_passed? + captcha_enabled? && !captcha_user_bypass? && !captcha_recently_passed? end def clear_captcha! @@ -65,4 +69,8 @@ module CaptchaConcern hcaptcha_tags end + + def captcha_context + 'registration-form' + end end -- cgit