moesif_rack 1.2.5 → 1.2.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9204370515cc07a90a131af8026d143f8fb666f45fc487b10b3bf21579cc20d9
4
- data.tar.gz: 2de61defa7298cd0c70e0a453e3b12242dd249f26334569d326f5e7ab257ea11
3
+ metadata.gz: 8c8bb62325d278fd7e988de98c2da89a2c70997f0b76a734e28adb817f176816
4
+ data.tar.gz: 364c201149ab8f9247f3964e3e78743fd6cb56a52de086c57cf1276df9ea51de
5
5
  SHA512:
6
- metadata.gz: b1f00c41d71b23c436aeab707803af8f8e6e39931560e3179ce7838aeeca121599048a46e936051b4a721499a876c1a5626cad72e78fe0ce034105aa53f15d5f
7
- data.tar.gz: b39d08f502436c211ad9851d927395e333a8ef4bd218ff4506aac9386d19fbe165ab15bd2f68d7f6b2df8e5b90353e6cd5c05d7b1e27dae8e22c6a05f57eaddc
6
+ metadata.gz: fcda4f70277329914b87572d137021b81e7b592810d5850f8a281fd410335faa0388e7f9ab1ec1e5a92422f34e47200b67ab33a01282e1903dc05a1ef672a468
7
+ data.tar.gz: 9222266c7fbfc1156ce0f91081d377ef0ccaa59ce71479b44c94e177772b7368aa14545a1a4185079d076dfc1a6311bc47e25bb86b538f71af3a147912d38d6d
data/README.md CHANGED
@@ -20,7 +20,7 @@ gem install moesif_rack
20
20
  and if you have a `Gemfile` in your project, please add this line to
21
21
 
22
22
  ```
23
- gem 'moesif_rack', '~> 1.2.5'
23
+ gem 'moesif_rack', '~> 1.2.6'
24
24
 
25
25
  ```
26
26
 
@@ -187,6 +187,59 @@ For details for the spec of event model, please see the [Moesif Ruby API Documen
187
187
 
188
188
  Optional. Boolean. Default false. If true, it will print out debug messages. In debug mode, the processing is not done in backend thread.
189
189
 
190
+ ## Update User
191
+
192
+ ### update_user method
193
+ A method is attached to the moesif middleware object to update the users profile or metadata.
194
+ The metadata field can be any custom data you want to set on the user. The `user_id` field is required.
195
+
196
+ ```ruby
197
+ metadata = JSON.parse('{'\
198
+ '"email": "testrubyapi@user.com",'\
199
+ '"name": "ruby api user",'\
200
+ '"custom": "testdata"'\
201
+ '}')
202
+
203
+ user_model = { "user_id" => "testrubyapiuser",
204
+ "modified_time" => Time.now.utc.iso8601,
205
+ "metadata" => metadata }
206
+
207
+ update_user = MoesifRack::MoesifMiddleware.new(@app, @options).update_user(user_model)
208
+ ```
209
+
210
+ ### update_users_batch method
211
+ A method is attached to the moesif middleware object to update the users profile or metadata in batch.
212
+ The metadata field can be any custom data you want to set on the user. The `user_id` field is required.
213
+
214
+ ```ruby
215
+ metadata = JSON.parse('{'\
216
+ '"email": "testrubyapi@user.com",'\
217
+ '"name": "ruby api user",'\
218
+ '"custom": "testdata"'\
219
+ '}')
220
+
221
+ user_models = []
222
+
223
+ user_model_A = { "user_id" => "testrubyapiuser",
224
+ "modified_time" => Time.now.utc.iso8601,
225
+ "metadata" => metadata }
226
+
227
+ user_model_B = { "user_id" => "testrubyapiuser1",
228
+ "modified_time" => Time.now.utc.iso8601,
229
+ "metadata" => metadata }
230
+
231
+ user_models << user_model_A << user_model_B
232
+ response = MoesifRack::MoesifMiddleware.new(@app, @options).update_users_batch(user_models)
233
+ ```
234
+
235
+ ## How to test
236
+
237
+ 1. Manually clone the git repo
238
+ 2. From terminal/cmd navigate to the root directory of the middleware.
239
+ 3. Invoke 'gem install moesif_rack'
240
+ 4. Add your own application id to 'test/moesif_rack_test.rb'. You can find your Application Id from [_Moesif Dashboard_](https://www.moesif.com/) -> _Top Right Menu_ -> _Installation_
241
+ 5. Invoke 'ruby test/moesif_rack_test.rb'
242
+
190
243
  ## Example Code
191
244
 
192
245
  [Moesif Rack Example](https://github.com/Moesif/moesif-rack-example) is an
@@ -195,7 +248,7 @@ for reference.
195
248
 
196
249
  ## Other integrations
197
250
 
198
- To view more more documentation on integration options, please visit __[the Integration Options Documentation](https://www.moesif.com/docs/getting-started/integration-options/).
251
+ To view more more documentation on integration options, please visit [the Integration Options Documentation](https://www.moesif.com/docs/getting-started/integration-options/).
199
252
 
200
253
  [ico-built-for]: https://img.shields.io/badge/built%20for-rack-blue.svg
201
254
  [ico-version]: https://img.shields.io/gem/v/moesif_rack.svg
@@ -0,0 +1,121 @@
1
+
2
+ def is_ip?(value)
3
+ if
4
+ ipv4 = /^(?:(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/
5
+ ipv6 = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/
6
+ # We use !! to convert the return value to a boolean
7
+ !!(value =~ ipv4 or value=~ ipv6)
8
+ end
9
+ end
10
+
11
+ def get_client_ip_from_x_forwarded_for(value)
12
+ begin
13
+ value = value.encode('utf-8')
14
+
15
+ if value.to_s.empty?
16
+ return nil
17
+ end
18
+
19
+ if !value.instance_of?(String)
20
+ puts ("Expected a string, got - " + value.class.to_s)
21
+ else
22
+ # x-forwarded-for may return multiple IP addresses in the format:
23
+ # "client IP, proxy 1 IP, proxy 2 IP"
24
+ # Therefore, the right-most IP address is the IP address of the most recent proxy
25
+ # and the left-most IP address is the IP address of the originating client.
26
+ # source: http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/x-forwarded-headers.html
27
+ # Azure Web App's also adds a port for some reason, so we'll only use the first part (the IP)
28
+ forwardedIps = []
29
+
30
+ value.gsub(/\s+/, "").split(',').each do |e|
31
+ if e.include?(':')
32
+ splitted = e.split(':')
33
+ if splitted.length == 2
34
+ forwardedIps << splitted.first
35
+ end
36
+ end
37
+ forwardedIps << e
38
+ end
39
+
40
+ # Sometimes IP addresses in this header can be 'unknown' (http://stackoverflow.com/a/11285650).
41
+ # Therefore taking the left-most IP address that is not unknown
42
+ # A Squid configuration directive can also set the value to "unknown" (http://www.squid-cache.org/Doc/config/forwarded_for/)
43
+ return forwardedIps.find {|e| is_ip?(e) }
44
+ end
45
+ rescue
46
+ return value.encode('utf-8')
47
+ end
48
+ end
49
+
50
+ def get_client_address(env)
51
+ begin
52
+ # Standard headers used by Amazon EC2, Heroku, and others.
53
+ if env.key?('HTTP_X_CLIENT_IP')
54
+ if is_ip?(env['HTTP_X_CLIENT_IP'])
55
+ return env['HTTP_X_CLIENT_IP']
56
+ end
57
+ end
58
+
59
+ # Load-balancers (AWS ELB) or proxies.
60
+ if env.key?('HTTP_X_FORWARDED_FOR')
61
+ xForwardedFor = get_client_ip_from_x_forwarded_for(env['HTTP_X_FORWARDED_FOR'])
62
+ if is_ip?(xForwardedFor)
63
+ return xForwardedFor
64
+ end
65
+ end
66
+
67
+ # Cloudflare.
68
+ # @see https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-
69
+ # CF-Connecting-IP - applied to every request to the origin.
70
+ if env.key?('HTTP_CF_CONNECTING_IP')
71
+ if is_ip?(env['HTTP_CF_CONNECTING_IP'])
72
+ return env['HTTP_CF_CONNECTING_IP']
73
+ end
74
+ end
75
+
76
+ # Akamai and Cloudflare: True-Client-IP.
77
+ if env.key?('HTTP_TRUE_CLIENT_IP')
78
+ if is_ip?(env['HTTP_TRUE_CLIENT_IP'])
79
+ return env['HTTP_TRUE_CLIENT_IP']
80
+ end
81
+ end
82
+
83
+ # Default nginx proxy/fcgi; alternative to x-forwarded-for, used by some proxies.
84
+ if env.key?('HTTP_X_REAL_IP')
85
+ if is_ip?(env['HTTP_X_REAL_IP'])
86
+ return env['HTTP_X_REAL_IP']
87
+ end
88
+ end
89
+
90
+ # (Rackspace LB and Riverbed's Stingray)
91
+ # http://www.rackspace.com/knowledge_center/article/controlling-access-to-linux-cloud-sites-based-on-the-client-ip-address
92
+ # https://splash.riverbed.com/docs/DOC-1926
93
+ if env.key?('HTTP_X_CLUSTER_CLIENT_IP')
94
+ if is_ip?(env['HTTP_X_CLUSTER_CLIENT_IP'])
95
+ return env['HTTP_X_CLUSTER_CLIENT_IP']
96
+ end
97
+ end
98
+
99
+ if env.key?('HTTP_X_FORWARDED')
100
+ if is_ip?(env['HTTP_X_FORWARDED'])
101
+ return env['HTTP_X_FORWARDED']
102
+ end
103
+ end
104
+
105
+ if env.key?('HTTP_FORWARDED_FOR')
106
+ if is_ip?(env['HTTP_FORWARDED_FOR'])
107
+ return env['HTTP_FORWARDED_FOR']
108
+ end
109
+ end
110
+
111
+ if env.key?('HTTP_FORWARDED')
112
+ if is_ip?(env['HTTP_FORWARDED'])
113
+ return env['HTTP_FORWARDED']
114
+ end
115
+ end
116
+
117
+ return env['REMOTE_ADDR']
118
+ rescue
119
+ return env['REMOTE_ADDR']
120
+ end
121
+ end
@@ -2,6 +2,7 @@ require 'moesif_api'
2
2
  require 'json'
3
3
  require 'time'
4
4
  require 'base64'
5
+ require_relative './client_ip.rb'
5
6
 
6
7
  module MoesifRack
7
8
 
@@ -58,6 +59,61 @@ module MoesifRack
58
59
  return sample_rate
59
60
  end
60
61
 
62
+ def update_user(user_profile)
63
+ if user_profile.any?
64
+ if user_profile.key?("user_id")
65
+ begin
66
+ @api_controller.update_user(MoesifApi::UserModel.from_hash(user_profile))
67
+ if @debug
68
+ puts "Update User Successfully"
69
+ end
70
+ rescue MoesifApi::APIException => e
71
+ if e.response_code.between?(401, 403)
72
+ puts "Unathorized accesss updating user to Moesif. Please verify your Application Id."
73
+ end
74
+ if @debug
75
+ puts "Error updating user to Moesif, with status code: "
76
+ puts e.response_code
77
+ end
78
+ end
79
+ else
80
+ puts "To update an user, an user_id field is required"
81
+ end
82
+ else
83
+ puts "Expecting the input to be of the type - dictionary while updating user"
84
+ end
85
+ end
86
+
87
+ def update_users_batch(user_profiles)
88
+ userModels = []
89
+ user_profiles.each { |user|
90
+ if user.key?("user_id")
91
+ userModels << MoesifApi::UserModel.from_hash(user)
92
+ else
93
+ puts "To update an user, an user_id field is required"
94
+ end
95
+ }
96
+
97
+ if userModels.any?
98
+ begin
99
+ @api_controller.update_users_batch(userModels)
100
+ if @debug
101
+ puts "Update Users Successfully"
102
+ end
103
+ rescue MoesifApi::APIException => e
104
+ if e.response_code.between?(401, 403)
105
+ puts "Unathorized accesss updating user to Moesif. Please verify your Application Id."
106
+ end
107
+ if @debug
108
+ puts "Error updating user to Moesif, with status code: "
109
+ puts e.response_code
110
+ end
111
+ end
112
+ else
113
+ puts "Expecting the input to be of the type - Array of hashes while updating users in batch"
114
+ end
115
+ end
116
+
61
117
  def call env
62
118
  start_time = Time.now.utc.iso8601
63
119
 
@@ -142,7 +198,7 @@ module MoesifRack
142
198
  headers["X-Moesif-Transaction-Id"] = transaction_id
143
199
  end
144
200
 
145
- event_req.ip_address = req.ip
201
+ event_req.ip_address = get_client_address(req.env)
146
202
  event_req.headers = req_headers
147
203
  event_req.body = req_body
148
204
  event_req.transfer_encoding = req_body_transfer_encoding
@@ -205,7 +261,7 @@ module MoesifRack
205
261
  end
206
262
  else
207
263
  if @debug
208
- puts("Skipped Event due to sampling percentage: " + @sampling_percentage.to_s + " and random percentage: " + @random_percentage.to_s);
264
+ puts("Skipped Event due to sampling percentage: " + @sampling_percentage.to_s + " and random percentage: " + @random_percentage.to_s)
209
265
  end
210
266
  end
211
267
  rescue MoesifApi::APIException => e
@@ -0,0 +1,64 @@
1
+ require 'test/unit'
2
+ require 'rack'
3
+ require_relative '../lib/moesif_rack'
4
+
5
+ class MoesifRackTest < Test::Unit::TestCase
6
+ def setup
7
+ @app = ->(env) { [200, { "Content-Type" => "application/json" }, ["{ \"key\": \"value\"}"]]}
8
+ @options = { 'application_id' => 'Your Application Id',
9
+ 'debug' => true,
10
+ 'disable_transaction_id' => true}
11
+ @moesif_rack_app = MoesifRack::MoesifMiddleware.new(@app, @options)
12
+ end
13
+
14
+ def test_new_calls_to_middleware
15
+ assert_instance_of MoesifRack::MoesifMiddleware, @moesif_rack_app
16
+ end
17
+
18
+ def test_update_user
19
+ metadata = JSON.parse('{'\
20
+ '"email": "testrubyapi@user.com",'\
21
+ '"name": "ruby api user",'\
22
+ '"custom": "testdata"'\
23
+ '}')
24
+
25
+ user_model = { "user_id" => "testrubyapiuser",
26
+ "modified_time" => Time.now.utc.iso8601,
27
+ "metadata" => metadata }
28
+
29
+ response = @moesif_rack_app.update_user(user_model)
30
+ assert_equal response, nil
31
+ end
32
+
33
+ def test_update_users_batch
34
+ metadata = JSON.parse('{'\
35
+ '"email": "testrubyapi@user.com",'\
36
+ '"name": "ruby api user",'\
37
+ '"custom": "testdata"'\
38
+ '}')
39
+
40
+ user_models = []
41
+
42
+ user_model_A = { "user_id" => "testrubyapiuser",
43
+ "modified_time" => Time.now.utc.iso8601,
44
+ "metadata" => metadata }
45
+
46
+ user_model_B = { "user_id" => "testrubyapiuser1",
47
+ "modified_time" => Time.now.utc.iso8601,
48
+ "metadata" => metadata }
49
+
50
+ user_models << user_model_A << user_model_B
51
+ response = @moesif_rack_app.update_users_batch(user_models)
52
+ assert_equal response, nil
53
+ end
54
+
55
+ def test_log_event
56
+ response = @moesif_rack_app.call(Rack::MockRequest.env_for("https://acmeinc.com/items/42752/reviews"))
57
+ assert_equal response, @app.call(nil)
58
+ end
59
+
60
+ def test_get_config
61
+ assert_operator 100, :>=, @moesif_rack_app.get_config(nil)
62
+ end
63
+
64
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moesif_rack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.5
4
+ version: 1.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Moesif, Inc
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-03-02 00:00:00.000000000 Z
12
+ date: 2019-03-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: test-unit
@@ -48,7 +48,9 @@ files:
48
48
  - LICENSE
49
49
  - README.md
50
50
  - lib/moesif_rack.rb
51
+ - lib/moesif_rack/client_ip.rb
51
52
  - lib/moesif_rack/moesif_middleware.rb
53
+ - test/moesif_rack_test.rb
52
54
  homepage: https://moesif.com
53
55
  licenses:
54
56
  - Apache-2.0