carehq 0.0.1 → 0.1.0

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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/carehq.rb +64 -23
  3. metadata +6 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3d40aabe2a58bfa22dfd36fd4e4ae83b49e9e89bdc4e7e3031fdd217b204718
4
- data.tar.gz: 5dc6072646b3caef0a22234634d3c8dc2c41474ad9fd5c4fa3146039077aaed3
3
+ metadata.gz: 3c5392d4a773b74353df2c87d0e01199673532e835874b7ecd7f73c132529279
4
+ data.tar.gz: 7f7cc0a7371f1aadfe7d28565dc7c4b840cb70cf87d0bdf891014db73b373741
5
5
  SHA512:
6
- metadata.gz: f81342e9a3f80254ea673b38de329fcff8611335756490a5a598b7b45f5f5ca50bec23f5cd583284ae79eec2cd0d9a97dfe5264667d79259511d33bc5e96bd46
7
- data.tar.gz: 906d32aa18a01523966b36ae8765b428d718a5479dbbc89f231b5d59cb30ab959616c53bc496888f6dbfabdc468b8f0b6ac30fb8537d9affa8f71e9c4a267e72
6
+ metadata.gz: c67df5095a77bdfdc495d29e74c7a6bd757434215257dbd90cfd28b2c065b91e457a5a7d9256f4d8dcf211f92e4192517772baf0be1b7f0e9f7cd70397ab56b2
7
+ data.tar.gz: 12580a56d519da1eedc9dd32d5bb977b87be6d116b56dddd032fee324424ff6c2ac57cb46774a8ee85ae8eef48e3dd1ea3663a2c180979424556f838603d1b3d
data/lib/carehq.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  require 'digest'
2
2
  require 'httparty'
3
+ require 'securerandom'
4
+ require 'openssl'
3
5
 
6
+ require 'carehq/exceptions'
4
7
 
5
8
  class HTTPartyWrapper
6
9
  include HTTParty
@@ -40,7 +43,8 @@ class APIClient
40
43
  @api_secret = api_secret
41
44
 
42
45
  # The base URL to use when calling the API
43
- @api_base_url = api_base_url
46
+ # Trailing slashes are removed.
47
+ @api_base_url = api_base_url.chomp('/')
44
48
 
45
49
  # The period of time before requests to the API should timeout
46
50
  @timeout = timeout
@@ -64,9 +68,7 @@ class APIClient
64
68
  def request(method, path, params: nil, data: nil)
65
69
  # Call the API
66
70
 
67
- # Filter out params/data set to `nil` and ensure all arguments are
68
- # converted to strings.
69
-
71
+ # Filter out params/data set to `nil`
70
72
  if params
71
73
  params.delete_if {|k, v| v.nil?}
72
74
  end
@@ -75,36 +77,44 @@ class APIClient
75
77
  data.delete_if {|k, v| v.nil?}
76
78
  end
77
79
 
78
- # Build the signature
79
- signature_data = method.downcase == 'get' ? params : data
80
+ # Ensure all params/data values are strings
81
+ if params
82
+ params.each do |k, v|
83
+ params[k] = _ensure_string(v)
84
+ end
85
+ end
80
86
 
81
- signature_values = []
82
- (signature_data or {}).each_pair do |key, value|
83
- signature_values.push(key)
84
- if value.kind_of?(Array)
85
- signature_values.concat(value)
86
- else
87
- signature_values.push(value)
87
+ if data
88
+ data.each do |k, v|
89
+ data[k] = _ensure_string(v)
88
90
  end
89
91
  end
90
92
 
91
- signature_body = signature_values.join ''
93
+ # Ensure path does not start with a slash
94
+ path = path.reverse.chomp('/').reverse
92
95
 
93
- timestamp = Time.now.to_f.to_s
96
+ # Build the signature (v2)
97
+ timestamp_str = Time.now.to_i.to_s
98
+ nonce = SecureRandom.urlsafe_base64(16)
99
+ string_to_sign = [
100
+ timestamp_str,
101
+ nonce,
102
+ method.upcase,
103
+ "/v1/#{path}",
104
+ _canonical_params_str(method.upcase == 'GET' ? params : data)
105
+ ].join("\n").encode('utf-8')
94
106
 
95
- signature_hash = Digest::SHA1.new
96
- signature_hash.update timestamp
97
- signature_hash.update signature_body
98
- signature_hash.update @api_secret
99
- signature = signature_hash.hexdigest
107
+ signature = _compute_signature(@api_secret, string_to_sign)
100
108
 
101
109
  # Build the headers
102
110
  headers = {
103
111
  'Accept' => 'application/json',
104
112
  'X-CareHQ-AccountId' => @account_id,
105
113
  'X-CareHQ-APIKey' => @api_key,
114
+ 'X-CareHQ-Nonce' => nonce,
106
115
  'X-CareHQ-Signature' => signature,
107
- 'X-CareHQ-Timestamp' => timestamp
116
+ 'X-CareHQ-Signature-Version' => '2.0',
117
+ 'X-CareHQ-Timestamp' => timestamp_str
108
118
  }
109
119
 
110
120
  # Make the request
@@ -135,6 +145,37 @@ class APIClient
135
145
 
136
146
  end
137
147
 
138
- end
148
+ private
139
149
 
140
- require 'carehq/exceptions'
150
+ def _ensure_string(val)
151
+ # Ensure values that will be converted to a form-encoded value are a
152
+ # string (or list of strings).
153
+
154
+ if val.is_a?(Array) || val.is_a?(Set)
155
+ return val.map {|v| v.to_s}
156
+ else
157
+ return val.to_s
158
+ end
159
+ end
160
+
161
+ def _canonical_params_str(params)
162
+ # Build a canonical string of params used for signing.
163
+ # Sort keys, sort values for each key, and join as "key=value" lines.
164
+ params ||= {}
165
+
166
+ parts = []
167
+ params.keys.sort.each do |key|
168
+ values = params[key]
169
+ values = [values] unless values.is_a?(Array) || values.is_a?(Set)
170
+ values.sort.each do |value|
171
+ parts << "#{key}=#{value}"
172
+ end
173
+ end
174
+
175
+ parts.join("\n")
176
+ end
177
+
178
+ def _compute_signature(secret, msg)
179
+ OpenSSL::HMAC.hexdigest('sha256', secret.to_s, msg.to_s)
180
+ end
181
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carehq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony Blackshaw
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-30 00:00:00.000000000 Z
11
+ date: 2026-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -36,7 +36,7 @@ homepage: https://github.com/CareHQ/carehq-ruby
36
36
  licenses:
37
37
  - MIT
38
38
  metadata: {}
39
- post_install_message:
39
+ post_install_message:
40
40
  rdoc_options: []
41
41
  require_paths:
42
42
  - lib
@@ -51,9 +51,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
51
51
  - !ruby/object:Gem::Version
52
52
  version: '0'
53
53
  requirements: []
54
- rubyforge_project:
55
- rubygems_version: 2.7.6
56
- signing_key:
54
+ rubygems_version: 3.4.20
55
+ signing_key:
57
56
  specification_version: 4
58
57
  summary: CareHQ API client
59
58
  test_files: []