securenative 0.1.18 → 0.1.24

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 (117) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -2
  3. data/Gemfile.lock +80 -81
  4. data/README.md +46 -41
  5. data/lib/securenative/api_manager.rb +41 -0
  6. data/lib/securenative/config/configuration_builder.rb +29 -0
  7. data/lib/securenative/config/configuration_manager.rb +58 -0
  8. data/lib/securenative/config/securenative_options.rb +25 -0
  9. data/lib/securenative/context/hanami_context.rb +44 -0
  10. data/lib/securenative/context/rails_context.rb +46 -0
  11. data/lib/securenative/context/securenative_context.rb +69 -0
  12. data/lib/securenative/context/sinatra_context.rb +44 -0
  13. data/lib/securenative/enums/api_route.rb +8 -0
  14. data/lib/securenative/enums/event_types.rb +25 -0
  15. data/lib/securenative/enums/failover_strategy.rb +8 -0
  16. data/lib/securenative/enums/risk_level.rb +9 -0
  17. data/lib/securenative/errors/securenative_config_error.rb +6 -0
  18. data/lib/securenative/errors/securenative_http_error.rb +6 -0
  19. data/lib/securenative/errors/securenative_invalid_options_error.rb +6 -0
  20. data/lib/securenative/errors/securenative_invalid_uri_error.rb +6 -0
  21. data/lib/securenative/errors/securenative_parse_error.rb +6 -0
  22. data/lib/securenative/errors/securenative_sdk_Illegal_state_error.rb +6 -0
  23. data/lib/securenative/errors/securenative_sdk_error.rb +6 -0
  24. data/lib/securenative/event_manager.rb +159 -0
  25. data/lib/securenative/http/secure_native_http_response.rb +14 -0
  26. data/lib/securenative/http/securenative_http_client.rb +52 -0
  27. data/lib/securenative/models/client_token.rb +14 -0
  28. data/lib/securenative/models/device.rb +12 -0
  29. data/lib/securenative/models/event_options.rb +39 -0
  30. data/lib/securenative/models/request_context.rb +20 -0
  31. data/lib/securenative/models/request_options.rb +14 -0
  32. data/lib/securenative/models/sdk_event.rb +51 -0
  33. data/lib/securenative/models/user_traits.rb +15 -0
  34. data/lib/securenative/models/verify_result.rb +18 -0
  35. data/lib/securenative/sdk.rb +85 -0
  36. data/lib/securenative/utils/date_utils.rb +11 -0
  37. data/lib/securenative/utils/encryption_utils.rb +51 -0
  38. data/lib/securenative/utils/ip_utils.rb +25 -0
  39. data/lib/securenative/utils/request_utils.rb +71 -0
  40. data/lib/securenative/utils/secure_native_logger.rb +46 -0
  41. data/lib/securenative/utils/signature_utils.rb +18 -0
  42. data/lib/securenative/utils/utils.rb +11 -0
  43. data/lib/securenative/utils/version_utils.rb +13 -0
  44. data/out/production/securenative-ruby/api_manager.rb +13 -5
  45. data/out/production/securenative-ruby/config/configuration_builder.rb +6 -9
  46. data/out/production/securenative-ruby/config/configuration_manager.rb +24 -23
  47. data/out/production/securenative-ruby/config/securenative_options.rb +8 -5
  48. data/{lib → out/production/securenative-ruby}/context/hanami_context.rb +9 -2
  49. data/{lib → out/production/securenative-ruby}/context/rails_context.rb +4 -1
  50. data/out/production/securenative-ruby/context/securenative_context.rb +35 -8
  51. data/{lib → out/production/securenative-ruby}/context/sinatra_context.rb +11 -4
  52. data/out/production/securenative-ruby/event_manager.rb +15 -14
  53. data/{lib → out/production/securenative-ruby}/http/secure_native_http_response.rb +0 -0
  54. data/out/production/securenative-ruby/http/securenative_http_client.rb +23 -5
  55. data/out/production/securenative-ruby/models/event_options.rb +23 -1
  56. data/out/production/securenative-ruby/models/request_context.rb +2 -2
  57. data/out/production/securenative-ruby/models/sdk_event.rb +22 -6
  58. data/out/production/securenative-ruby/models/user_traits.rb +1 -1
  59. data/out/production/securenative-ruby/models/verify_result.rb +5 -1
  60. data/out/production/securenative-ruby/securenative.rb +2 -10
  61. data/out/production/securenative-ruby/utils/date_utils.rb +1 -1
  62. data/out/production/securenative-ruby/utils/encryption_utils.rb +38 -24
  63. data/out/production/securenative-ruby/utils/request_utils.rb +53 -7
  64. data/out/production/securenative-ruby/utils/secure_native_logger.rb +6 -6
  65. data/out/production/securenative-ruby/utils/version_utils.rb +5 -6
  66. data/out/test/securenative-ruby/spec_api_manager.rb +37 -31
  67. data/out/test/securenative-ruby/spec_context_builder.rb +52 -34
  68. data/out/test/securenative-ruby/spec_encryption_utils.rb +13 -13
  69. data/out/test/securenative-ruby/spec_event_manager.rb +49 -15
  70. data/out/test/securenative-ruby/spec_helper.rb +8 -0
  71. data/out/test/securenative-ruby/spec_request_utils.rb +25 -0
  72. data/out/test/securenative-ruby/spec_sdk_event.rb +24 -0
  73. data/out/test/securenative-ruby/spec_securenative.rb +35 -39
  74. data/out/test/securenative-ruby/spec_securenative_http_client.rb +13 -5
  75. data/out/test/securenative-ruby/spec_signature_utils.rb +1 -1
  76. data/out/test/securenative-ruby/spec_version_util.rb +10 -0
  77. data/securenative.gemspec +16 -14
  78. metadata +48 -45
  79. data/VERSION +0 -1
  80. data/lib/api_manager.rb +0 -35
  81. data/lib/config/configuration_builder.rb +0 -30
  82. data/lib/config/configuration_manager.rb +0 -55
  83. data/lib/config/securenative_options.rb +0 -22
  84. data/lib/context/securenative_context.rb +0 -67
  85. data/lib/enums/api_route.rb +0 -6
  86. data/lib/enums/event_types.rb +0 -23
  87. data/lib/enums/failover_strategy.rb +0 -6
  88. data/lib/enums/risk_level.rb +0 -7
  89. data/lib/errors/securenative_config_error.rb +0 -4
  90. data/lib/errors/securenative_http_error.rb +0 -4
  91. data/lib/errors/securenative_invalid_options_error.rb +0 -4
  92. data/lib/errors/securenative_invalid_uri_error.rb +0 -4
  93. data/lib/errors/securenative_parse_error.rb +0 -4
  94. data/lib/errors/securenative_sdk_Illegal_state_error.rb +0 -4
  95. data/lib/errors/securenative_sdk_error.rb +0 -4
  96. data/lib/event_manager.rb +0 -156
  97. data/lib/event_options.rb +0 -32
  98. data/lib/http/securenative_http_client.rb +0 -32
  99. data/lib/models/client_token.rb +0 -12
  100. data/lib/models/device.rb +0 -10
  101. data/lib/models/event_options.rb +0 -15
  102. data/lib/models/request_context.rb +0 -18
  103. data/lib/models/request_options.rb +0 -12
  104. data/lib/models/sdk_event.rb +0 -35
  105. data/lib/models/user_traits.rb +0 -13
  106. data/lib/models/verify_result.rb +0 -12
  107. data/lib/securenative.rb +0 -95
  108. data/lib/utils/date_utils.rb +0 -9
  109. data/lib/utils/encryption_utils.rb +0 -35
  110. data/lib/utils/ip_utils.rb +0 -23
  111. data/lib/utils/request_utils.rb +0 -54
  112. data/lib/utils/secure_native_logger.rb +0 -44
  113. data/lib/utils/signature_utils.rb +0 -16
  114. data/lib/utils/utils.rb +0 -9
  115. data/lib/utils/version_utils.rb +0 -12
  116. data/out/production/securenative-ruby/event_options.rb +0 -32
  117. data/out/production/securenative-ruby/http/http_response.rb +0 -12
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SecureNative
4
+ class SecureNativeHttpResponse
5
+ attr_reader :ok, :status_code, :body
6
+ attr_writer :ok, :status_code, :body
7
+
8
+ def initialize(ok, status_code, body)
9
+ @ok = ok
10
+ @status_code = status_code
11
+ @body = body
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'uri'
5
+ require 'json'
6
+ require 'securenative/utils/version_utils'
7
+ require 'securenative/utils/secure_native_logger'
8
+
9
+ module SecureNative
10
+ class SecureNativeHttpClient
11
+ AUTHORIZATION_HEADER = 'Authorization'
12
+ VERSION_HEADER = 'SN-Version'
13
+ USER_AGENT_HEADER = 'User-Agent'
14
+ USER_AGENT_HEADER_VALUE = 'SecureNative-ruby'
15
+ CONTENT_TYPE_HEADER = 'Content-Type'
16
+ CONTENT_TYPE_HEADER_VALUE = 'application/json'
17
+
18
+ def initialize(securenative_options)
19
+ @options = securenative_options
20
+ end
21
+
22
+ def _headers
23
+ {
24
+ CONTENT_TYPE_HEADER => CONTENT_TYPE_HEADER_VALUE,
25
+ USER_AGENT_HEADER => USER_AGENT_HEADER_VALUE,
26
+ VERSION_HEADER => VersionUtils.version,
27
+ AUTHORIZATION_HEADER => @options.api_key
28
+ }
29
+ end
30
+
31
+ def post(path, body)
32
+ uri = URI.parse("#{@options.api_url}/#{path}")
33
+ headers = _headers
34
+
35
+ client = Net::HTTP.new(uri.host, uri.port)
36
+ client.use_ssl = true
37
+ client.verify_mode = OpenSSL::SSL::VERIFY_NONE
38
+
39
+ request = Net::HTTP::Post.new(uri.request_uri, headers)
40
+ request.body = body
41
+
42
+ res = nil
43
+ begin
44
+ res = client.request(request)
45
+ rescue StandardError => e
46
+ SecureNativeLogger.error("Failed to send request; #{e}")
47
+ return res
48
+ end
49
+ res
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SecureNative
4
+ class ClientToken
5
+ attr_reader :cid, :vid, :fp
6
+ attr_writer :cid, :vid, :fp
7
+
8
+ def initialize(cid, vid, fp)
9
+ @cid = cid
10
+ @vid = vid
11
+ @fp = fp
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SecureNative
4
+ class Device
5
+ attr_reader :device_id
6
+ attr_writer :device_id
7
+
8
+ def initialize(device_id)
9
+ @device_id = device_id
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securenative/models/event_options'
4
+ require 'securenative/models/user_traits'
5
+ require 'securenative/errors/securenative_invalid_options_error'
6
+
7
+ module SecureNative
8
+ class EventOptions
9
+ attr_reader :event, :user_id, :user_traits, :context, :properties, :timestamp
10
+ attr_writer :event, :user_id, :user_traits, :context, :properties, :timestamp
11
+
12
+ MAX_PROPERTIES_SIZE = 10
13
+
14
+ def initialize(event: nil, user_id: nil, user_traits: nil, user_name: nil, email: nil, phone: nil, created_at: nil, context: nil, properties: nil, timestamp: nil)
15
+ if !properties.nil? && properties.length > MAX_PROPERTIES_SIZE
16
+ raise SecureNativeInvalidOptionsError, "You can have only up to #{MAX_PROPERTIES_SIZE} custom properties"
17
+ end
18
+
19
+ if user_traits.nil?
20
+ if user_name && email && phone && created_at
21
+ user_traits = UserTraits(user_name, email, phone, created_at)
22
+ elsif user_name && email && phone
23
+ user_traits = UserTraits(user_name, email, phone)
24
+ elsif user_name && email
25
+ user_traits = UserTraits(user_name, email)
26
+ else
27
+ user_traits = UserTraits.new
28
+ end
29
+ end
30
+
31
+ @event = event
32
+ @user_id = user_id
33
+ @user_traits = user_traits
34
+ @context = context
35
+ @properties = properties
36
+ @timestamp = timestamp
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SecureNative
4
+ class RequestContext
5
+ attr_reader :cid, :vid, :fp, :ip, :remote_ip, :headers, :url, :http_method
6
+ attr_writer :cid, :vid, :fp, :ip, :remote_ip, :headers, :url, :http_method
7
+
8
+ def initialize(cid: nil, vid: nil, fp: nil, ip: nil, remote_ip: nil, headers: nil, url: nil, http_method: nil)
9
+ @cid = cid
10
+ @vid = vid
11
+ @fp = fp
12
+ @ip = ip
13
+ @remote_ip = remote_ip
14
+ @headers = headers
15
+ @url = url
16
+ @method = http_method
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SecureNative
4
+ class RequestOptions
5
+ attr_reader :url, :body, :retry_sending
6
+ attr_writer :url, :body, :retry_sending
7
+
8
+ def initialize(url, body, retry_sending)
9
+ @url = url
10
+ @body = body
11
+ @retry_sending = retry_sending
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securenative/context/securenative_context'
4
+ require 'securenative/errors/securenative_invalid_options_error'
5
+ require 'securenative/utils/encryption_utils'
6
+ require 'securenative/utils/date_utils'
7
+ require 'securenative/models/request_context'
8
+ require 'securerandom'
9
+
10
+ module SecureNative
11
+ class SDKEvent
12
+ attr_reader :context, :rid, :event_type, :user_id, :user_traits, :request, :timestamp, :properties
13
+ attr_writer :context, :rid, :event_type, :user_id, :user_traits, :request, :timestamp, :properties
14
+
15
+ def initialize(event_options, securenative_options)
16
+ if event_options.user_id.nil? || event_options.user_id.length <= 0 || event_options.user_id == ''
17
+ raise SecureNativeInvalidOptionsError.new, 'Invalid event structure; User Id is missing'
18
+ end
19
+
20
+ if event_options.event.nil? || event_options.event.length <= 0 || event_options.event == ''
21
+ raise SecureNativeInvalidOptionsError.new, 'Invalid event structure; Event Type is missing'
22
+ end
23
+
24
+ @context = if !event_options.context.nil?
25
+ event_options.context
26
+ else
27
+ SecureNativeContext.default_context_builder
28
+ end
29
+
30
+ client_token = EncryptionUtils.decrypt(@context.client_token, securenative_options.api_key)
31
+
32
+ @rid = SecureRandom.uuid.to_str
33
+ @event_type = event_options.event
34
+ @user_id = event_options.user_id
35
+ @user_traits = event_options.user_traits
36
+ @request = RequestContext.new(cid: client_token ? client_token.cid : '', vid: client_token ? client_token.vid : '',
37
+ fp: client_token ? client_token.fp : '', ip: @context.ip,
38
+ remote_ip: @context.remote_ip, headers: @context.headers,
39
+ url: @context.url, http_method: @context.http_method)
40
+
41
+
42
+ @timestamp = DateUtils.to_timestamp(event_options.timestamp)
43
+ @properties = event_options.properties
44
+ end
45
+
46
+ def to_s
47
+ "securenative.context: #{@context}, rid: #{@rid}, event_type: #{@event_type}, user_id: #{@user_id},
48
+ user_traits: #{@user_traits}, request: #{@request}, timestamp: #{@timestamp}, properties: #{@properties}"
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SecureNative
4
+ class UserTraits
5
+ attr_reader :name, :email, :phone, :created_at
6
+ attr_writer :name, :email, :phone, :created_at
7
+
8
+ def initialize(name: nil, email: nil, phone: nil, created_at: nil)
9
+ @name = name
10
+ @email = email
11
+ @created_at = created_at
12
+ @phone = phone
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SecureNative
4
+ class VerifyResult
5
+ attr_reader :risk_level, :score, :triggers
6
+ attr_writer :risk_level, :score, :triggers
7
+
8
+ def initialize(risk_level: nil, score: nil, triggers: nil)
9
+ @risk_level = risk_level
10
+ @score = score
11
+ @triggers = triggers
12
+ end
13
+
14
+ def to_s
15
+ "risk_level: #{@risk_level}, score: #{@score}, triggers: #{@triggers}"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securenative/utils/secure_native_logger'
4
+ require 'securenative/utils/signature_utils'
5
+ require 'securenative/utils/utils'
6
+ require 'securenative/errors/securenative_sdk_error'
7
+ require 'securenative/errors/securenative_sdk_Illegal_state_error'
8
+ require 'securenative/errors/securenative_config_error'
9
+ require 'securenative/enums/failover_strategy'
10
+ require 'securenative/config/configuration_builder'
11
+ require 'securenative/config/configuration_manager'
12
+ require 'securenative/event_manager'
13
+ require 'securenative/api_manager'
14
+
15
+ module SecureNative
16
+ class SecureNative
17
+ attr_reader :options
18
+
19
+ def initialize(options)
20
+ @securenative = nil
21
+ raise SecureNativeSDKError, 'You must pass your SecureNative api key' if Utils.null_or_empty?(options.api_key)
22
+
23
+ @options = options
24
+ @event_manager = EventManager.new(@options)
25
+
26
+ @event_manager.start_event_persist unless @options.api_url.nil?
27
+
28
+ @api_manager = ApiManager.new(@event_manager, @options)
29
+ SecureNativeLogger.init_logger(@options.log_level)
30
+ end
31
+
32
+ def self.init_with_options(options)
33
+ if @securenative.nil?
34
+ @securenative = SecureNative.new(options)
35
+ @securenative
36
+ else
37
+ SecureNativeLogger.debug('This SDK was already initialized.')
38
+ raise SecureNativeSDKError, 'This SDK was already initialized.'
39
+ end
40
+ end
41
+
42
+ def self.init_with_api_key(api_key)
43
+ raise SecureNativeConfigError, 'You must pass your SecureNative api key' if Utils.null_or_empty?(api_key)
44
+
45
+ if @securenative.nil?
46
+ options = ConfigurationBuilder.new(api_key: api_key)
47
+ @securenative = SecureNative.new(options)
48
+ @securenative
49
+ else
50
+ SecureNativeLogger.debug('This SDK was already initialized.')
51
+ raise SecureNativeSDKError, 'This SDK was already initialized.'
52
+ end
53
+ end
54
+
55
+ def self.init
56
+ options = ConfigurationManager.load_config
57
+ init_with_options(options)
58
+ end
59
+
60
+ def self.instance
61
+ raise SecureNativeSDKIllegalStateError if @securenative.nil?
62
+
63
+ @securenative
64
+ end
65
+
66
+ def track(event_options)
67
+ @api_manager.track(event_options)
68
+ end
69
+
70
+ def verify(event_options)
71
+ @api_manager.verify(event_options)
72
+ end
73
+
74
+ def self._flush
75
+ @securenative = nil
76
+ end
77
+
78
+ def verify_request_payload(request)
79
+ request_signature = request.header[SignatureUtils.SIGNATURE_HEADER]
80
+ body = request.body
81
+
82
+ SignatureUtils.valid_signature?(@options.api_key, body, request_signature)
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SecureNative
4
+ class DateUtils
5
+ def self.to_timestamp(date)
6
+ return Time.now.utc.iso8601 if date.nil?
7
+
8
+ Time.parse(date).iso8601
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openssl'
4
+ require 'digest'
5
+ require 'base64'
6
+ require 'securenative/models/client_token'
7
+
8
+ module SecureNative
9
+ class EncryptionUtils
10
+ def self.padding_key(key, length)
11
+ if key.length == length
12
+ key
13
+ else
14
+ if key.length > length
15
+ key.slice(0, length)
16
+ else
17
+ (length - key.length).times { key << '0' }
18
+ key
19
+ end
20
+ end
21
+ end
22
+
23
+ def self.encrypt(plain_text, secret_key)
24
+ begin
25
+ cipher = OpenSSL::Cipher.new('aes-256-cbc')
26
+ cipher.encrypt
27
+ iv = cipher.random_iv
28
+ cipher.key = padding_key(secret_key, 32)
29
+ encrypted = cipher.update(plain_text) + cipher.final
30
+ (iv + encrypted).unpack1('H*')
31
+ rescue StandardError
32
+ ''
33
+ end
34
+ end
35
+
36
+ def self.decrypt(cipher_text, secret_key)
37
+ begin
38
+ cipher = OpenSSL::Cipher.new('aes-256-cbc')
39
+ cipher.decrypt
40
+ raw_data = [cipher_text].pack('H*')
41
+ cipher.iv = raw_data.slice(0, 16)
42
+ cipher.key = padding_key(secret_key, 32)
43
+ decrypted = JSON.parse(cipher.update(raw_data.slice(16, raw_data.length)) + cipher.final)
44
+
45
+ return ClientToken.new(decrypted['cid'], decrypted['vid'], decrypted['fp'])
46
+ rescue StandardError
47
+ ClientToken.new('', '', '')
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "resolv"
4
+
5
+ module SecureNative
6
+ class IpUtils
7
+ def self.ip_address?(ip_address)
8
+ return true if ip_address =~ Resolv::IPv4::Regex
9
+ return true if ip_address =~ Resolv::IPv6::Regex
10
+
11
+ false
12
+ end
13
+
14
+ def self.valid_public_ip?(ip_address)
15
+ ip = IPAddr.new(ip_address)
16
+ return false if ip.loopback? || ip.private? || ip.link_local? || ip.untrusted? || ip.tainted?
17
+
18
+ true
19
+ end
20
+
21
+ def self.loop_back?(ip_address)
22
+ IPAddr.new(ip_address).loopback?
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SecureNative
4
+ class RequestUtils
5
+ SECURENATIVE_COOKIE = '_sn'
6
+ SECURENATIVE_HEADER = 'x-securenative'
7
+
8
+ def self.get_secure_header_from_request(headers)
9
+ begin
10
+ return headers[SECURENATIVE_HEADER] unless headers.nil?
11
+ rescue StandardError
12
+ []
13
+ end
14
+ []
15
+ end
16
+
17
+ def self.get_client_ip_from_request(request, options = nil)
18
+ begin
19
+ return request.ip unless request.ip.nil?
20
+ rescue NoMethodError
21
+ end
22
+
23
+ begin
24
+ x_forwarded_for = request.env['HTTP_X_FORWARDED_FOR']
25
+ return x_forwarded_for.scan(/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/)[0] unless x_forwarded_for.nil?
26
+ rescue NoMethodError
27
+ begin
28
+ x_forwarded_for = request['HTTP_X_FORWARDED_FOR']
29
+ return x_forwarded_for.scan(/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/)[0] unless x_forwarded_for.nil?
30
+ rescue NoMethodError
31
+ end
32
+ end
33
+
34
+ begin
35
+ x_forwarded_for = request.env['REMOTE_ADDR']
36
+ return x_forwarded_for.scan(/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/)[0] unless x_forwarded_for.nil?
37
+ rescue NoMethodError
38
+ begin
39
+ x_forwarded_for = request['REMOTE_ADDR']
40
+ return x_forwarded_for.scan(/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/)[0] unless x_forwarded_for.nil?
41
+ rescue NoMethodError
42
+ end
43
+ end
44
+
45
+ unless options.nil?
46
+ for header in options.proxy_headers do
47
+ begin
48
+ h = request.env[header]
49
+ return h.scan(/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/)[0] unless h.nil?
50
+ rescue NoMethodError
51
+ begin
52
+ h = request[header]
53
+ return h.scan(/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/)[0] unless h.nil?
54
+ rescue NoMethodError
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ ''
61
+ end
62
+
63
+ def self.get_remote_ip_from_request(request)
64
+ begin
65
+ request.remote_ip
66
+ rescue NoMethodError
67
+ ''
68
+ end
69
+ end
70
+ end
71
+ end