113 lines
3.4 KiB
Ruby
113 lines
3.4 KiB
Ruby
module RuCaptcha
|
|
module ControllerHelpers
|
|
extend ActiveSupport::Concern
|
|
|
|
included do
|
|
helper_method :verify_rucaptcha?
|
|
end
|
|
|
|
# session key of rucaptcha
|
|
def rucaptcha_sesion_key_key
|
|
|
|
session_id = session.respond_to?(:id) ? session.id : session[:session_id]
|
|
warning_when_session_invalid if session_id.blank?
|
|
|
|
# With https://github.com/rack/rack/commit/7fecaee81f59926b6e1913511c90650e76673b38
|
|
# to protected session_id into secret
|
|
session_id_digest = Digest::SHA256.hexdigest(session_id.inspect)
|
|
['rucaptcha-session', session_id_digest].join(':')
|
|
end
|
|
|
|
# Generate a new Captcha
|
|
def generate_rucaptcha
|
|
res = RuCaptcha.generate()
|
|
session_val = {
|
|
code: res[0],
|
|
time: Time.now.to_i
|
|
}
|
|
RuCaptcha.cache.write(rucaptcha_sesion_key_key, session_val, expires_in: RuCaptcha.config.expires_in)
|
|
res[1]
|
|
end
|
|
def generate_speech_rucaptcha
|
|
raise RuntimeError, "espeak disabled" unless RuCaptcha.espeak?
|
|
wav_file = Tempfile.new("#{current_captcha_code}.wav")
|
|
RuCaptcha.espeak.generate(current_captcha_code, wav_file.path)
|
|
File.read(wav_file.path)
|
|
end
|
|
def current_captcha_code
|
|
if @code
|
|
@code
|
|
else
|
|
store_info = RuCaptcha.cache.read(rucaptcha_sesion_key_key)
|
|
@code = store_info[:code]
|
|
end
|
|
end
|
|
|
|
# Verify captcha code
|
|
#
|
|
# params:
|
|
# resource - [optional] a ActiveModel object, if given will add validation error message to object.
|
|
# :keep_session - if true, RuCaptcha will not delete the captcha code session.
|
|
# :captcha - if given, the value of it will be used to verify the captcha,
|
|
# if do not give or blank, the value of params[:_rucaptcha] will be used to verify the captcha
|
|
#
|
|
# exmaples:
|
|
#
|
|
# verify_rucaptcha?
|
|
# verify_rucaptcha?(user, keep_session: true)
|
|
# verify_rucaptcha?(nil, keep_session: true)
|
|
# verify_rucaptcha?(nil, captcha: params[:user][:captcha])
|
|
#
|
|
def gotcha_valid?(resource = nil, opts = {})
|
|
verify_rucaptcha?(resource, opts)
|
|
end
|
|
def verify_rucaptcha?(resource = nil, opts = {})
|
|
opts ||= {}
|
|
|
|
store_info = RuCaptcha.cache.read(rucaptcha_sesion_key_key)
|
|
# make sure move used key
|
|
RuCaptcha.cache.delete(rucaptcha_sesion_key_key) unless opts[:keep_session]
|
|
|
|
# Make sure session exist
|
|
if store_info.blank?
|
|
return add_rucaptcha_validation_error
|
|
end
|
|
|
|
# Make sure not expire
|
|
if (Time.now.to_i - store_info[:time]) > RuCaptcha.config.expires_in
|
|
return add_rucaptcha_validation_error
|
|
end
|
|
|
|
# Make sure parama have captcha
|
|
captcha = (opts[:captcha] || params[:_rucaptcha] || '').downcase.strip
|
|
if captcha.blank?
|
|
return add_rucaptcha_validation_error
|
|
end
|
|
|
|
if captcha != store_info[:code]
|
|
return add_rucaptcha_validation_error
|
|
end
|
|
|
|
true
|
|
end
|
|
|
|
private
|
|
|
|
def add_rucaptcha_validation_error
|
|
if defined?(resource) && resource && resource.respond_to?(:errors)
|
|
resource.errors.add(:base, t('rucaptcha.invalid'))
|
|
end
|
|
false
|
|
end
|
|
|
|
def warning_when_session_invalid
|
|
return unless Rails.env.development?
|
|
|
|
Rails.logger.warn "
|
|
WARNING! The session.id is blank, RuCaptcha can't work properly, please keep session available.
|
|
More details about this: https://github.com/huacnlee/rucaptcha/pull/66
|
|
"
|
|
end
|
|
end
|
|
end
|