cm-graphql 0.0.12 → 0.0.14

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3adaf1303f53f1360bcb8497b025b1960958b8fc285c7abe2a6547a6be56a620
4
- data.tar.gz: 857f7282ed8dc874f1f886cba9d93b384cd2be4ee4d4ec84513bf989265f99d1
3
+ metadata.gz: f96a2b69bc022c0d1c34f17f3446eeb9e568675a3311085850673299f538dc5d
4
+ data.tar.gz: 1312ee2a215b9bf4a3f8506105c41dd9a05f66b70624bbaf5f9a74aab2366030
5
5
  SHA512:
6
- metadata.gz: 9f5d3aa1a49d5fc8922a72366a7ba05b2a821cea8c094994aad1bbd205d8a1cdb11dce7ceb7ad0755547629c140753da12b728a5d84f1c5db0b239fb1222d26e
7
- data.tar.gz: 70b4a6394d65a12ffd916c1e44f6d1654e40104c7c1ab348a7680c12a3726583bfb49da56d7a9bbe7a062e9542bd32f1a2e0ab200a9dfd442b92af6fe976d89d
6
+ metadata.gz: 3934404241a4ddb217799a54dee2da3c019941a1ee61c3313391e9cd768d836bd46d382cc01fa95b673ef12f5554a8e5cc37460f604f15e8eea52fad7c132035
7
+ data.tar.gz: 3e564a39769a51646162853f7ad72c7331ea86f5a079450480a1e168ceee4276c1d91aa68f1cb41cfe2dfb704af1a96f266c6ec20864ee2e25aba97ad4f6c1aa
data/Gemfile CHANGED
@@ -3,3 +3,7 @@
3
3
  source 'https://rubygems.org'
4
4
 
5
5
  gemspec
6
+
7
+ group :development, :test do
8
+ gem 'rspec', '~> 3.12'
9
+ end
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cm-graphql (0.0.12)
4
+ cm-graphql (0.0.14)
5
5
  graphiql-rails (>= 1.9)
6
6
  graphql (>= 2.2.5)
7
7
  graphql-rails_logger (>= 1.2.4)
@@ -53,6 +53,7 @@ GEM
53
53
  connection_pool (2.5.2)
54
54
  crass (1.0.6)
55
55
  date (3.4.1)
56
+ diff-lcs (1.6.2)
56
57
  drb (2.2.1)
57
58
  erubi (1.13.1)
58
59
  fiber-storage (1.0.1)
@@ -90,11 +91,7 @@ GEM
90
91
  loofah (2.24.0)
91
92
  crass (~> 1.0.2)
92
93
  nokogiri (>= 1.12.0)
93
- mini_portile2 (2.8.8)
94
94
  minitest (5.25.5)
95
- nokogiri (1.18.8)
96
- mini_portile2 (~> 2.8.2)
97
- racc (~> 1.4)
98
95
  nokogiri (1.18.8-arm64-darwin)
99
96
  racc (~> 1.4)
100
97
  pp (0.6.2)
@@ -133,6 +130,19 @@ GEM
133
130
  reline (0.6.1)
134
131
  io-console (~> 0.5)
135
132
  rouge (4.5.1)
133
+ rspec (3.13.2)
134
+ rspec-core (~> 3.13.0)
135
+ rspec-expectations (~> 3.13.0)
136
+ rspec-mocks (~> 3.13.0)
137
+ rspec-core (3.13.6)
138
+ rspec-support (~> 3.13.0)
139
+ rspec-expectations (3.13.5)
140
+ diff-lcs (>= 1.2.0, < 2.0)
141
+ rspec-support (~> 3.13.0)
142
+ rspec-mocks (3.13.7)
143
+ diff-lcs (>= 1.2.0, < 2.0)
144
+ rspec-support (~> 3.13.0)
145
+ rspec-support (3.13.7)
136
146
  securerandom (0.4.1)
137
147
  stringio (3.1.7)
138
148
  thor (1.3.2)
@@ -146,10 +156,12 @@ GEM
146
156
  PLATFORMS
147
157
  arm64-darwin-20
148
158
  arm64-darwin-22
149
- ruby
159
+ arm64-darwin-23
160
+ arm64-darwin-24
150
161
 
151
162
  DEPENDENCIES
152
163
  cm-graphql!
164
+ rspec (~> 3.12)
153
165
 
154
166
  BUNDLED WITH
155
167
  2.6.8
@@ -2,18 +2,15 @@ module CmGraphql
2
2
  module Extensions
3
3
  class RecaptchaExtension < GraphQL::Schema::FieldExtension
4
4
  def apply
5
- if field.resolver
6
- field.resolver.argument(:recaptcha_token, String, required: true)
7
- else
8
- field.argument(:recaptcha_token, String, required: true)
9
- end
5
+ input_arg = field.arguments["input"]
6
+ input_type = input_arg.type.unwrap
7
+ input_type.argument(:recaptcha_token, String, required: true)
10
8
  end
11
-
12
- def resolve(object:, arguments:, context:)
13
- args_hash = arguments.to_h
14
- input_hash = args_hash[:input].respond_to?(:to_h) ? args_hash[:input].to_h : nil
15
9
 
16
- recaptcha_token = input_hash ? input_hash[:recaptcha_token] : args_hash[:recaptcha_token]
10
+ def resolve(object:, arguments:, context:, **_rest)
11
+ args_hash = arguments.to_h
12
+ input_hash = args_hash[:input].to_h
13
+ recaptcha_token = input_hash[:recaptcha_token]
17
14
 
18
15
  RecaptchaVerifier.verify_v3!(
19
16
  token: recaptcha_token,
@@ -22,13 +19,8 @@ module CmGraphql
22
19
  minimum_score: options[:minimum_score] || RECAPTCHA_MINIMUM_SCORE
23
20
  )
24
21
 
25
- if input_hash
26
- next_input = input_hash.dup
27
- next_input.delete(:recaptcha_token)
28
- yield(object, args_hash.merge(input: next_input))
29
- else
30
- yield(object, arguments.except(:recaptcha_token))
31
- end
22
+ next_input = input_hash.except(:recaptcha_token)
23
+ yield(object, args_hash.except(:input).merge(input: next_input), nil)
32
24
  end
33
25
  end
34
26
  end
@@ -2,19 +2,39 @@ require 'net/http'
2
2
  require 'json'
3
3
 
4
4
  class RecaptchaVerifier
5
- VERIFY_URL = URI.parse('https://www.google.com/recaptcha/api/siteverify').freeze
5
+ API_HOST = 'recaptchaenterprise.googleapis.com'
6
6
 
7
7
  def self.verify_v3(token:, action:, remote_ip: nil, minimum_score: 0.5)
8
- secret = Rails.application.credentials.dig(:gcp, :recaptcha_secret_key)
9
- raise RecaptchaVerificationFailed, "Please cofigure recaptcha credentials, so it reads Rails.application.credentials.dig(:gcp, :recaptcha_secret_key)." if secret.blank? || token.blank?
8
+ project_id = Rails.application.credentials.dig(:gcp, :recaptcha_enterprise_project_id)
9
+ site_key = Rails.application.credentials.dig(:gcp, :recaptcha_site_key)
10
+ api_key = Rails.application.credentials.dig(:gcp, :recaptcha_api_key)
10
11
 
11
- response = post_verify(secret:, token:, remote_ip:)
12
- raise RecaptchaVerificationFailed, "Invalid response from recaptcha" unless response.is_a?(Hash)
12
+ if project_id.blank? || site_key.blank? || api_key.blank?
13
+ raise RecaptchaVerificationFailed,
14
+ 'Please configure recaptcha enterprise credentials at Rails.application.credentials.dig(:gcp, :recaptcha_enterprise_project_id), :recaptcha_site_key, :recaptcha_api_key.'
15
+ end
13
16
 
14
- raise RecaptchaVerificationFailed, "Recaptcha verification failed" unless response['success'] == true
15
- raise RecaptchaVerificationFailed, "Recaptcha action mismatch" if response['action'].present? && response['action'] != action
17
+ raise RecaptchaVerificationFailed, 'Recaptcha token missing' if token.blank?
16
18
 
17
- score = response['score']
19
+ response = create_assessment(project_id:, site_key:, api_key:, token:, action:, remote_ip:)
20
+ raise RecaptchaVerificationFailed, 'Invalid response from recaptcha' unless response.is_a?(Hash)
21
+
22
+ token_props = response['tokenProperties']
23
+ unless token_props.is_a?(Hash)
24
+ raise RecaptchaVerificationFailed, 'Invalid response from recaptcha'
25
+ end
26
+
27
+ unless token_props['valid'] == true
28
+ reason = token_props['invalidReason']
29
+ raise RecaptchaVerificationFailed, reason.present? ? "Recaptcha invalid token: #{reason}" : 'Recaptcha invalid token'
30
+ end
31
+
32
+ if token_props['action'].present? && token_props['action'] != action
33
+ raise RecaptchaVerificationFailed, 'Recaptcha action mismatch'
34
+ end
35
+
36
+ risk = response['riskAnalysis']
37
+ score = risk.is_a?(Hash) ? risk['score'] : nil
18
38
  return true if score.nil?
19
39
 
20
40
  score.to_f >= minimum_score.to_f
@@ -27,18 +47,44 @@ class RecaptchaVerifier
27
47
  true
28
48
  end
29
49
 
30
- def self.post_verify(secret:, token:, remote_ip: nil)
31
- request = Net::HTTP::Post.new(VERIFY_URL)
32
- request.set_form_data({ secret:, response: token }.tap { |h| h[:remoteip] = remote_ip if remote_ip.present? })
50
+ def self.create_assessment(project_id:, site_key:, api_key:, token:, action:, remote_ip: nil)
51
+ uri = URI::HTTPS.build(
52
+ host: API_HOST,
53
+ path: "/v1/projects/#{project_id}/assessments",
54
+ query: URI.encode_www_form(key: api_key)
55
+ )
56
+
57
+ event = {
58
+ token: token,
59
+ siteKey: site_key,
60
+ expectedAction: action
61
+ }
62
+ event[:userIpAddress] = remote_ip if remote_ip.present?
33
63
 
34
- http = Net::HTTP.new(VERIFY_URL.host, VERIFY_URL.port)
64
+ request = Net::HTTP::Post.new(uri)
65
+ request['Content-Type'] = 'application/json'
66
+ request.body = JSON.generate({ event: event })
67
+
68
+ http = Net::HTTP.new(uri.host, uri.port)
35
69
  http.use_ssl = true
36
70
 
37
71
  raw_response = http.request(request)
38
- JSON.parse(raw_response.body)
39
- rescue JSON::ParserError, SocketError, Timeout::Error, Errno::ECONNRESET, Errno::ECONNREFUSED
40
- false
72
+ body = raw_response.body.to_s
73
+
74
+ parsed_body = JSON.parse(body)
75
+
76
+ unless raw_response.is_a?(Net::HTTPSuccess)
77
+ error_message = parsed_body.dig('error', 'message')
78
+ raise RecaptchaVerificationFailed,
79
+ "Recaptcha enterprise HTTP #{raw_response.code}: #{error_message.presence || raw_response.message}"
80
+ end
81
+
82
+ parsed_body
83
+ rescue JSON::ParserError
84
+ raise RecaptchaVerificationFailed, "Recaptcha enterprise returned invalid JSON"
85
+ rescue SocketError, Timeout::Error, Errno::ECONNRESET, Errno::ECONNREFUSED
86
+ raise RecaptchaVerificationFailed, 'Recaptcha enterprise request failed'
41
87
  end
42
88
 
43
- private_class_method :post_verify
89
+ private_class_method :create_assessment
44
90
  end
data/cm-graphql.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'cm-graphql'
5
- spec.version = '0.0.12'
5
+ spec.version = '0.0.14'
6
6
  spec.date = '2022-09-14'
7
7
  spec.summary = 'A gem to setup grapqhl basics like pagination, file upload'
8
8
  spec.description = 'A gem to setup grapqhl basics like pagination, file upload'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cm-graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.12
4
+ version: 0.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anbazhagan Palani