smartcaptcha 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 14c706d26bfe6f1532c4fcb320ef0c60cd7fb6b75f8dd3d4c532bde584e9dceb
4
+ data.tar.gz: cabb6a4c6a308b2d6948f4c7d11b196e5bd0a1ccaa434017f3682107f6709b82
5
+ SHA512:
6
+ metadata.gz: 9db6a96f28593565d67f42a6a6ba8477f6e4396ddaaa1eeee11a620130d90edbaf2d06ec0a12d23d178826830ded44d35df19ad15b533dcddc1f209fbd043279
7
+ data.tar.gz: fa0947803486dcf4721b3cb43942ef1be48dfcd47a8837822dd9ca9dee208518fea305ae09164c4e84f1414fa1d3236eb234c0a59041d60cb3bbc331233ef10f
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Smartcaptcha
4
+ module Adapters
5
+ module ControllerMethods
6
+
7
+ private
8
+
9
+ def verify_smartcaptcha(options = {})
10
+ return true if Smartcaptcha.skip_env?
11
+
12
+ model = options[:model]
13
+ attribute = options.fetch(:attribute, :base)
14
+ options[:host] = request.host unless options.key?(:host)
15
+ options[:ip] = request.remote_ip
16
+ smartcaptcha_response = options[:response] || smartcaptcha_response_token(options[:action])
17
+ verified = Smartcaptcha.verify_via_api_call(smartcaptcha_response, options)
18
+ unless verified
19
+ smartcaptcha_error(
20
+ model,
21
+ attribute,
22
+ options.fetch(:message) { Smartcaptcha.error_message(:verification_failed) }
23
+ )
24
+ end
25
+ verified
26
+ end
27
+
28
+ def smartcaptcha_response_token(action = nil)
29
+ response_param = params['smart-token']
30
+ if response_param&.respond_to?(:to_h)
31
+ response_param[action].to_s
32
+ else
33
+ response_param.to_s
34
+ end
35
+ end
36
+
37
+ def smartcaptcha_error(model, attribute, message)
38
+ if model
39
+ model.errors.add(attribute, message)
40
+ elsif smartcaptcha_flash_supported?
41
+ flash[:smartcaptcha_error] = message
42
+ end
43
+ end
44
+
45
+ def smartcaptcha_flash_supported?
46
+ request.respond_to?(:format) && request.format == :html && respond_to?(:flash)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Smartcaptcha
4
+ module Adapters
5
+ module ViewMethods
6
+ def smartcaptcha_tags(options = {})
7
+ server_url = Smartcaptcha.configuration.server_url
8
+ attributes = {
9
+ sitekey: options.delete(:client_key) || Smartcaptcha.configuration.client_key!
10
+ }
11
+ tag_attributes = attributes.merge(options).map { |k, v| %(data-#{k}="#{v}") }.join(" ")
12
+ html = <<-HTML
13
+ <script src="#{server_url}" defer></script>
14
+ <div class="smart-captcha" #{tag_attributes}></div>
15
+ HTML
16
+ html.respond_to?(:html_safe) ? html.html_safe : html
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Smartcaptcha
4
+ class Configuration
5
+ DEFAULTS = {
6
+ 'server_url' => 'https://smartcaptcha.yandexcloud.net/captcha.js',
7
+ 'verify_url' => 'https://smartcaptcha.yandexcloud.net/validate'
8
+ }.freeze
9
+
10
+ attr_accessor :default_env, :skip_verify_env, :server_key, :client_key, :hostname
11
+ attr_writer :server_url, :verify_url
12
+
13
+ def initialize
14
+ @default_env = ENV['RAILS_ENV'] || ENV['RACK_ENV'] || (Rails.env if defined? Rails.env)
15
+ @skip_verify_env = %w[test cucumber]
16
+
17
+ @server_key = ENV['SMARTCAPTCHA_SERVER_KEY']
18
+ @client_key = ENV['SMARTCAPTCHA_CLIENT_KEY']
19
+ end
20
+
21
+ def server_key!
22
+ server_key || raise(SmartcaptchaError, "No server key specified.")
23
+ end
24
+
25
+ def client_key!
26
+ client_key || raise(SmartcaptchaError, "No client key specified.")
27
+ end
28
+
29
+ def server_url
30
+ @server_url || DEFAULTS.fetch('server_url')
31
+ end
32
+
33
+ def verify_url
34
+ @verify_url || DEFAULTS.fetch('verify_url')
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Smartcaptcha
4
+ class Railtie < Rails::Railtie
5
+ ActiveSupport.on_load(:action_view) do
6
+ include Smartcaptcha::Adapters::ViewMethods
7
+ end
8
+
9
+ ActiveSupport.on_load(:action_controller) do
10
+ include Smartcaptcha::Adapters::ControllerMethods
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Smartcaptcha
4
+ VERSION = '0.0.2'
5
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'net/http'
5
+ require 'uri'
6
+
7
+ require 'smartcaptcha/configuration'
8
+ require 'smartcaptcha/adapters/view_methods'
9
+ require 'smartcaptcha/adapters/controller_methods'
10
+ if defined?(Rails)
11
+ require 'smartcaptcha/railtie'
12
+ end
13
+
14
+ module Smartcaptcha
15
+ class SmartcaptchaError < StandardError
16
+ end
17
+
18
+ DEFAULT_ERRORS = {
19
+ verification_failed: 'SmartCaptcha verification failed, please try again'
20
+ }
21
+
22
+ def self.configuration
23
+ @configuration ||= Configuration.new
24
+ end
25
+
26
+ def self.configure
27
+ config = configuration
28
+ yield(config)
29
+ end
30
+
31
+ def self.verify_via_api_call(response, options)
32
+ server_key = options.fetch(:server_key) { configuration.server_key! }
33
+ verify_hash = { 'secret' => server_key, 'token' => response }
34
+ verify_hash['ip'] = options[:ip] if options.key?(:ip)
35
+ reply = api_verification(verify_hash)
36
+ success = reply['status'] == 'ok' &&
37
+ host_valid?(reply['host'], options[:host])
38
+ success
39
+ end
40
+
41
+ def self.host_valid?(hostname, validation)
42
+ hostname.sub!(/:\d+$/, '')
43
+ case validation
44
+ when nil, FalseClass then true
45
+ when String then validation == hostname
46
+ end
47
+ end
48
+
49
+ def self.api_verification(verify_hash)
50
+ query = URI.encode_www_form(verify_hash)
51
+ uri = URI.parse("#{configuration.verify_url}?#{query}")
52
+ request = Net::HTTP::Get.new(uri.request_uri)
53
+ http_client = Net::HTTP.new(uri.host, uri.port)
54
+ http_client.use_ssl = true if uri.port == 443
55
+ JSON.parse(http_client.request(request).body)
56
+ end
57
+
58
+ def self.error_message(key)
59
+ default = DEFAULT_ERRORS.fetch(key)
60
+ return default unless defined?(I18n)
61
+
62
+ I18n.translate("smartcaptcha.errors.#{key}", default: default)
63
+ end
64
+
65
+ def self.skip_env?
66
+ configuration.skip_verify_env.include?(configuration.default_env)
67
+ end
68
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smartcaptcha
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Alexey Yanchenko
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-03-31 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Ruby helpers for Yandex smartcaptcha
14
+ email:
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/smartcaptcha.rb
20
+ - lib/smartcaptcha/adapters/controller_methods.rb
21
+ - lib/smartcaptcha/adapters/view_methods.rb
22
+ - lib/smartcaptcha/configuration.rb
23
+ - lib/smartcaptcha/railtie.rb
24
+ - lib/smartcaptcha/version.rb
25
+ homepage: https://github.com/maildealer/smartcaptcha
26
+ licenses:
27
+ - MIT
28
+ metadata:
29
+ source_code_uri: https://github.com/maildealer/smartcaptcha
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubygems_version: 3.4.10
46
+ signing_key:
47
+ specification_version: 4
48
+ summary: Ruby helpers for Yandex smartcaptcha
49
+ test_files: []