diff options
author | Claire <claire.github-309c@sitedethib.com> | 2022-01-26 00:13:24 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-26 00:13:24 +0100 |
commit | 129bc429797452f984551b87f753222e824ec3ca (patch) | |
tree | 3b4b0bcfff51232ec9dd0d05a9a053194877ffa7 /app/controllers | |
parent | e58e0eb9aa375b1107b207e8229a2142c4edc0b8 (diff) | |
parent | b7cf3941b3783220e6b3bc9a6d3975ceecdc64cb (diff) |
Merge pull request #1665 from ClearlyClaire/glitch-soc/features/hcaptcha
Add optional hCaptcha support
Diffstat (limited to 'app/controllers')
-rw-r--r-- | app/controllers/auth/confirmations_controller.rb | 44 | ||||
-rw-r--r-- | app/controllers/concerns/captcha_concern.rb | 59 |
2 files changed, 103 insertions, 0 deletions
diff --git a/app/controllers/auth/confirmations_controller.rb b/app/controllers/auth/confirmations_controller.rb index 0b5a2f3c9..17ad56fa8 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,46 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController resource.email = current_user.unconfirmed_email || current_user.email if user_signed_in? end + def show + 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 set_pack use_pack 'auth' end diff --git a/app/controllers/concerns/captcha_concern.rb b/app/controllers/concerns/captcha_concern.rb new file mode 100644 index 000000000..538c1ffb1 --- /dev/null +++ b/app/controllers/concerns/captcha_concern.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +module CaptchaConcern + extend ActiveSupport::Concern + include Hcaptcha::Adapters::ViewMethods + + included do + helper_method :render_captcha + end + + def captcha_available? + ENV['HCAPTCHA_SECRET_KEY'].present? && ENV['HCAPTCHA_SITE_KEY'].present? + end + + def captcha_enabled? + captcha_available? && Setting.captcha_enabled + end + + def captcha_user_bypass? + false + end + + def captcha_required? + captcha_enabled? && !captcha_user_bypass? + end + + def check_captcha! + return true unless captcha_required? + + if verify_hcaptcha + true + else + if block_given? + message = flash[:hcaptcha_error] + flash.delete(:hcaptcha_error) + yield message + end + false + end + end + + def extend_csp_for_captcha! + policy = request.content_security_policy + return unless captcha_required? && policy.present? + + %w(script_src frame_src style_src connect_src).each do |directive| + values = policy.send(directive) + values << 'https://hcaptcha.com' unless values.include?('https://hcaptcha.com') || values.include?('https:') + values << 'https://*.hcaptcha.com' unless values.include?('https://*.hcaptcha.com') || values.include?('https:') + policy.send(directive, *values) + end + end + + def render_captcha + return unless captcha_required? + + hcaptcha_tags + end +end |