securenative 0.1.16 → 0.1.22

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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +7 -15
  3. data/.github/workflows/publish.yml +1 -1
  4. data/.github/workflows/test.yml +5 -2
  5. data/.gitignore +3 -1
  6. data/Gemfile +6 -4
  7. data/Gemfile.lock +234 -23
  8. data/README.md +38 -33
  9. data/lib/api_manager.rb +39 -0
  10. data/lib/config/configuration_builder.rb +26 -0
  11. data/lib/config/configuration_manager.rb +55 -0
  12. data/lib/config/securenative_options.rb +22 -0
  13. data/lib/context/hanami_context.rb +42 -0
  14. data/lib/context/rails_context.rb +44 -0
  15. data/lib/context/securenative_context.rb +67 -0
  16. data/lib/context/sinatra_context.rb +42 -0
  17. data/lib/enums/api_route.rb +6 -0
  18. data/lib/enums/event_types.rb +23 -0
  19. data/lib/enums/failover_strategy.rb +6 -0
  20. data/lib/enums/risk_level.rb +7 -0
  21. data/lib/errors/securenative_config_error.rb +4 -0
  22. data/lib/errors/securenative_http_error.rb +4 -0
  23. data/lib/errors/securenative_invalid_options_error.rb +4 -0
  24. data/lib/errors/securenative_invalid_uri_error.rb +4 -0
  25. data/lib/errors/securenative_parse_error.rb +4 -0
  26. data/lib/errors/securenative_sdk_Illegal_state_error.rb +4 -0
  27. data/lib/errors/securenative_sdk_error.rb +4 -0
  28. data/lib/event_manager.rb +157 -0
  29. data/lib/http/secure_native_http_response.rb +12 -0
  30. data/lib/http/securenative_http_client.rb +50 -0
  31. data/lib/{securenative/models → models}/client_token.rb +2 -0
  32. data/lib/{securenative/models → models}/device.rb +3 -1
  33. data/lib/models/event_options.rb +37 -0
  34. data/lib/models/request_context.rb +18 -0
  35. data/lib/models/request_options.rb +12 -0
  36. data/lib/models/sdk_event.rb +49 -0
  37. data/lib/models/user_traits.rb +13 -0
  38. data/lib/models/verify_result.rb +16 -0
  39. data/lib/securenative.rb +83 -0
  40. data/lib/utils/date_utils.rb +9 -0
  41. data/lib/utils/encryption_utils.rb +49 -0
  42. data/lib/{securenative/utils → utils}/ip_utils.rb +7 -6
  43. data/lib/utils/request_utils.rb +54 -0
  44. data/lib/{securenative/logger.rb → utils/secure_native_logger.rb} +5 -3
  45. data/lib/{securenative/utils → utils}/signature_utils.rb +4 -2
  46. data/lib/utils/utils.rb +9 -0
  47. data/lib/utils/version_utils.rb +11 -0
  48. data/{lib/securenative → out/production/securenative-ruby}/api_manager.rb +6 -5
  49. data/{lib/securenative → out/production/securenative-ruby}/config/configuration_builder.rb +7 -3
  50. data/{lib/securenative → out/production/securenative-ruby}/config/configuration_manager.rb +5 -3
  51. data/{lib/securenative → out/production/securenative-ruby}/config/securenative_options.rb +3 -1
  52. data/out/production/securenative-ruby/context/securenative_context.rb +40 -0
  53. data/out/production/securenative-ruby/enums/api_route.rb +6 -0
  54. data/out/production/securenative-ruby/enums/event_types.rb +23 -0
  55. data/out/production/securenative-ruby/enums/failover_strategy.rb +6 -0
  56. data/out/production/securenative-ruby/enums/risk_level.rb +7 -0
  57. data/out/production/securenative-ruby/errors/securenative_config_error.rb +4 -0
  58. data/out/production/securenative-ruby/errors/securenative_http_error.rb +4 -0
  59. data/out/production/securenative-ruby/errors/securenative_invalid_options_error.rb +4 -0
  60. data/out/production/securenative-ruby/errors/securenative_invalid_uri_error.rb +4 -0
  61. data/out/production/securenative-ruby/errors/securenative_parse_error.rb +4 -0
  62. data/out/production/securenative-ruby/errors/securenative_sdk_Illegal_state_error.rb +4 -0
  63. data/out/production/securenative-ruby/errors/securenative_sdk_error.rb +4 -0
  64. data/out/production/securenative-ruby/event_manager.rb +156 -0
  65. data/out/production/securenative-ruby/event_options.rb +32 -0
  66. data/{lib/securenative → out/production/securenative-ruby}/http/http_response.rb +3 -1
  67. data/out/production/securenative-ruby/http/securenative_http_client.rb +32 -0
  68. data/out/production/securenative-ruby/models/client_token.rb +12 -0
  69. data/out/production/securenative-ruby/models/device.rb +10 -0
  70. data/{lib/securenative → out/production/securenative-ruby}/models/event_options.rb +3 -1
  71. data/{lib/securenative → out/production/securenative-ruby}/models/request_context.rb +5 -2
  72. data/out/production/securenative-ruby/models/request_options.rb +12 -0
  73. data/{lib/securenative → out/production/securenative-ruby}/models/sdk_event.rb +11 -3
  74. data/out/production/securenative-ruby/models/user_traits.rb +13 -0
  75. data/{lib/securenative → out/production/securenative-ruby}/models/verify_result.rb +3 -1
  76. data/{lib/securenative → out/production/securenative-ruby}/securenative.rb +24 -15
  77. data/out/production/securenative-ruby/utils/date_utils.rb +9 -0
  78. data/{lib/securenative → out/production/securenative-ruby}/utils/encryption_utils.rb +1 -4
  79. data/out/production/securenative-ruby/utils/ip_utils.rb +23 -0
  80. data/{lib/securenative → out/production/securenative-ruby}/utils/request_utils.rb +5 -3
  81. data/out/production/securenative-ruby/utils/secure_native_logger.rb +44 -0
  82. data/out/production/securenative-ruby/utils/signature_utils.rb +16 -0
  83. data/out/production/securenative-ruby/utils/utils.rb +9 -0
  84. data/{lib/securenative → out/production/securenative-ruby}/utils/version_utils.rb +3 -1
  85. data/out/test/securenative-ruby/spec_api_manager.rb +81 -0
  86. data/out/test/securenative-ruby/spec_context_builder.rb +69 -0
  87. data/out/test/securenative-ruby/spec_date_utils.rb +13 -0
  88. data/out/test/securenative-ruby/spec_encryption_utils.rb +26 -0
  89. data/out/test/securenative-ruby/spec_event_manager.rb +59 -0
  90. data/out/test/securenative-ruby/spec_helper.rb +20 -0
  91. data/out/test/securenative-ruby/spec_ip_utils.rb +41 -0
  92. data/out/test/securenative-ruby/spec_securenative.rb +65 -0
  93. data/out/test/securenative-ruby/spec_securenative_http_client.rb +23 -0
  94. data/out/test/securenative-ruby/spec_signature_utils.rb +18 -0
  95. data/securenative.gemspec +2 -2
  96. metadata +88 -43
  97. data/.travis.yml +0 -6
  98. data/VERSION +0 -1
  99. data/lib/securenative/context/context_builder.rb +0 -59
  100. data/lib/securenative/context/securenative_context.rb +0 -14
  101. data/lib/securenative/enums/api_route.rb +0 -4
  102. data/lib/securenative/enums/event_types.rb +0 -21
  103. data/lib/securenative/enums/failover_strategy.rb +0 -4
  104. data/lib/securenative/enums/risk_level.rb +0 -5
  105. data/lib/securenative/event_manager.rb +0 -149
  106. data/lib/securenative/event_options_builder.rb +0 -21
  107. data/lib/securenative/exceptions/securenative_config_exception.rb +0 -2
  108. data/lib/securenative/exceptions/securenative_http_exception.rb +0 -2
  109. data/lib/securenative/exceptions/securenative_invalid_options_exception.rb +0 -2
  110. data/lib/securenative/exceptions/securenative_invalid_uri_exception.rb +0 -2
  111. data/lib/securenative/exceptions/securenative_parse_exception.rb +0 -2
  112. data/lib/securenative/exceptions/securenative_sdk_Illegal_state_exception.rb +0 -2
  113. data/lib/securenative/exceptions/securenative_sdk_exception.rb +0 -2
  114. data/lib/securenative/http/securenative_http_client.rb +0 -30
  115. data/lib/securenative/models/request_options.rb +0 -10
  116. data/lib/securenative/models/user_traits.rb +0 -10
  117. data/lib/securenative/securenative.iml +0 -9
  118. data/lib/securenative/utils/date_utils.rb +0 -7
  119. data/lib/securenative/utils/utils.rb +0 -9
@@ -1,6 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.7.1
6
- before_install: gem install bundler -v 2.1.2
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.1.16
@@ -1,59 +0,0 @@
1
- class ContextBuilder
2
- attr_reader :context
3
-
4
- def initialize(client_token = nil, ip = nil, remote_ip = nil, headers = nil, url = nil, method = nil, body = nil)
5
- @context = SecureNativeContext(client_token, ip, remote_ip, headers, url, method, body)
6
- end
7
-
8
- def client_token(client_token)
9
- @context.client_token = client_token
10
- end
11
-
12
- def ip(ip)
13
- @context.ip = ip
14
- end
15
-
16
- def remote_ip(remote_ip)
17
- @context.remote_ip = remote_ip
18
- end
19
-
20
- def headers(headers)
21
- @context.headers = headers
22
- end
23
-
24
- def url(url)
25
- @context.url = url
26
- end
27
-
28
- def method(method)
29
- @context.method = method
30
- end
31
-
32
- def body(body)
33
- @context.body = body
34
- end
35
-
36
- def self.default_context_builder
37
- ContextBuilder()
38
- end
39
-
40
- def self.from_http_request(request)
41
- begin
42
- client_token = request.cookies[RequestUtils.SECURENATIVE_COOKIE]
43
- rescue StandardError
44
- client_token = nil
45
- end
46
-
47
- begin
48
- headers = request.headers
49
- rescue StandardError
50
- headers = nil
51
- end
52
-
53
- client_token = RequestUtils.get_secure_header_from_request(headers) if Utils.null_or_empty?(client_token)
54
-
55
- ContextBuilder(url = request.url, method = request.method, header = headers, client_token = client_token,
56
- client_ip = RequestUtils.get_client_ip_from_request(request),
57
- remote_ip = RequestUtils.get_remote_ip_from_request(request), nil)
58
- end
59
- end
@@ -1,14 +0,0 @@
1
- class SecureNativeContext
2
- attr_reader :client_token, :ip, :remote_ip, :headers, :url, :method, :body
3
- attr_writer :client_token, :ip, :remote_ip, :headers, :url, :method, :body
4
-
5
- def initialize(client_token = nil, ip = nil, remote_ip = nil, headers = nil, url = nil, method = nil, body = nil)
6
- @client_token = client_token
7
- @ip = ip
8
- @remote_ip = remote_ip
9
- @headers = headers
10
- @url = url
11
- @method = method
12
- @body = body
13
- end
14
- end
@@ -1,4 +0,0 @@
1
- module ApiRoute
2
- TRACK = 'track'.freeze
3
- VERIFY = 'verify'.freeze
4
- end
@@ -1,21 +0,0 @@
1
- module EventTypes
2
- LOG_IN = 'sn.user.login'.freeze
3
- LOG_IN_CHALLENGE = 'sn.user.login.challenge'.freeze
4
- LOG_IN_FAILURE = 'sn.user.login.failure'.freeze
5
- LOG_OUT = 'sn.user.logout'.freeze
6
- SIGN_UP = 'sn.user.signup'.freeze
7
- AUTH_CHALLENGE = 'sn.user.auth.challenge'.freeze
8
- AUTH_CHALLENGE_SUCCESS = 'sn.user.auth.challenge.success'.freeze
9
- AUTH_CHALLENGE_FAILURE = 'sn.user.auth.challenge.failure'.freeze
10
- TWO_FACTOR_DISABLE = 'sn.user.2fa.disable'.freeze
11
- EMAIL_UPDATE = 'sn.user.email.update'.freeze
12
- PASSWORD_REST = 'sn.user.password.reset'.freeze
13
- PASSWORD_REST_SUCCESS = 'sn.user.password.reset.success'.freeze
14
- PASSWORD_UPDATE = 'sn.user.password.update'.freeze
15
- PASSWORD_REST_FAILURE = 'sn.user.password.reset.failure'.freeze
16
- USER_INVITE = 'sn.user.invite'.freeze
17
- ROLE_UPDATE = 'sn.user.role.update'.freeze
18
- PROFILE_UPDATE = 'sn.user.profile.update'.freeze
19
- PAGE_VIEW = 'sn.user.page.view'.freeze
20
- VERIFY = 'sn.verify'.freeze
21
- end
@@ -1,4 +0,0 @@
1
- module FailOverStrategy
2
- FAIL_OPEN = 'fail-open'.freeze
3
- FAIL_CLOSED = 'fail-closed'.freeze
4
- end
@@ -1,5 +0,0 @@
1
- module RiskLevel
2
- LOW = 'low'.freeze
3
- MEDIUM = 'medium'.freeze
4
- HIGH = 'high'.freeze
5
- end
@@ -1,149 +0,0 @@
1
- require_relative 'logger'
2
-
3
- class QueueItem
4
- attr_reader :url, :body, :retry
5
- attr_writer :url, :body, :retry
6
-
7
- def initialize(url, body, _retry)
8
- @url = url
9
- @body = body
10
- @retry = _retry
11
- end
12
- end
13
-
14
- class EventManager
15
- def initialize(options = SecureNativeOptions(), http_client = nil)
16
- if options.api_key.nil?
17
- raise SecureNativeSDKException('API key cannot be None, please get your API key from SecureNative console.')
18
- end
19
-
20
- @http_client = if http_client.nil?
21
- SecureNativeHttpClient(options)
22
- else
23
- http_client
24
- end
25
-
26
- @queue = []
27
- @thread = Thread.new(run)
28
- @thread.start
29
-
30
- @options = options
31
- @send_enabled = false
32
- @attempt = 0
33
- @coefficients = [1, 1, 2, 3, 5, 8, 13]
34
- @thread = nil
35
- @interval = options.interval
36
- end
37
-
38
- def send_async(event, resource_path)
39
- if @options.disable
40
- Logger.warning('SDK is disabled. no operation will be performed')
41
- return
42
- end
43
-
44
- item = QueueItem(resource_path, JSON.parse(EventManager.serialize(event)), false)
45
- @queue.append(item)
46
- end
47
-
48
- def flush
49
- @queue.each do |item|
50
- @http_client.post(item.url, item.body)
51
- end
52
- end
53
-
54
- def send_sync(event, resource_path, _retry)
55
- if @options.disable
56
- Logger.warning('SDK is disabled. no operation will be performed')
57
- return
58
- end
59
-
60
- Logger.debug('Attempting to send event {}'.format(event))
61
- res = @http_client.post(resource_path, JSON.parse(EventManager.serialize(event)))
62
-
63
- if res.status_code != 200
64
- Logger.info('SecureNative failed to call endpoint {} with event {}. adding back to queue'.format(resource_path, event))
65
- item = QueueItem(resource_path, JSON.parse(EventManager.serialize(event)), _retry)
66
- @queue.append(item)
67
- end
68
-
69
- res
70
- end
71
-
72
- def run
73
- loop do
74
- next unless !@queue.empty? && @send_enabled
75
-
76
- @queue.each do |item|
77
- begin
78
- res = @http_client.post(item.url, item.body)
79
- if res.status_code == 401
80
- item.retry = false
81
- elsif res.status_code != 200
82
- raise SecureNativeHttpException(res.status_code)
83
- end
84
- Logger.debug('Event successfully sent; {}'.format(item.body))
85
- return res
86
- rescue StandardError => e
87
- Logger.error('Failed to send event; {}'.format(e))
88
- if item.retry
89
- @attempt = 0 if @coefficients.length == @attempt + 1
90
-
91
- back_off = @coefficients[@attempt] * @options.interval
92
- Logger.debug('Automatic back-off of {}'.format(back_off))
93
- @send_enabled = false
94
- sleep back_off
95
- @send_enabled = true
96
- end
97
- end
98
- end
99
- sleep @interval / 1000
100
- end
101
- end
102
-
103
- def start_event_persist
104
- Logger.debug('Starting automatic event persistence')
105
- if @options.auto_send || @send_enabled
106
- @send_enabled = true
107
- else
108
- Logger.debug('Automatic event persistence is disabled, you should persist events manually')
109
- end
110
- end
111
-
112
- def stop_event_persist
113
- if @send_enabled
114
- Logger.debug('Attempting to stop automatic event persistence')
115
- begin
116
- flush
117
- @thread&.stop
118
- Logger.debug('Stopped event persistence')
119
- rescue StandardError => e
120
- Logger.error('Could not stop event scheduler; {}'.format(e))
121
- end
122
- end
123
- end
124
-
125
- def self.serialize(obj)
126
- {
127
- rid: obj.rid,
128
- eventType: obj.event_type,
129
- userId: obj.user_id,
130
- userTraits: {
131
- name: obj.user_traits.name,
132
- email: obj.user_traits.email,
133
- createdAt: obj.user_traits.created_at
134
- },
135
- request: {
136
- cid: obj.request.cid,
137
- vid: obj.request.vid,
138
- fp: obj.request.fp,
139
- ip: obj.request.ip,
140
- remoteIp: obj.request.remote_ip,
141
- method: obj.request.method,
142
- url: obj.request.url,
143
- headers: obj.request.headers
144
- },
145
- timestamp: obj.timestamp,
146
- properties: obj.properties
147
- }
148
- end
149
- end
@@ -1,21 +0,0 @@
1
- class EventOptionsBuilder
2
- MAX_PROPERTIES_SIZE = 10
3
-
4
- def initialize(event_type, user_id, user_traits, user_name, email, created_at, context, properties, timestamp)
5
- @event_options = EventOptions(event_type)
6
- @event_options.user_id = user_id
7
- @event_options.user_traits = user_traits if user_traits
8
- @event_options.user_traits = UserTraits(name, email, created_at) if user_name && email && created_at
9
- @event_options.context = context
10
- @event_options.properties = properties
11
- @event_options.timestamp = timestamp
12
- end
13
-
14
- def build
15
- if !@event_options.properties.nil? && @event_options.properties.length > MAX_PROPERTIES_SIZE
16
- raise SecureNativeInvalidOptionsException('You can have only up to {} custom properties', MAX_PROPERTIES_SIZE)
17
- end
18
-
19
- @event_options
20
- end
21
- end
@@ -1,2 +0,0 @@
1
- class SecureNativeConfigException < StandardError
2
- end
@@ -1,2 +0,0 @@
1
- class SecureNativeHttpException < StandardError
2
- end
@@ -1,2 +0,0 @@
1
- class SecureNativeInvalidOptionsException < StandardError
2
- end
@@ -1,2 +0,0 @@
1
- class SecureNativeInvalidUriException < StandardError
2
- end
@@ -1,2 +0,0 @@
1
- class SecureNativeParseException < StandardError
2
- end
@@ -1,2 +0,0 @@
1
- class SecureNativeSDKIllegalStateException < StandardError
2
- end
@@ -1,2 +0,0 @@
1
- class SecureNativeSDKException < StandardError
2
- end
@@ -1,30 +0,0 @@
1
- require 'httpclient'
2
-
3
- class SecureNativeHttpClient
4
- AUTHORIZATION_HEADER = 'Authorization'.freeze
5
- VERSION_HEADER = 'SN-Version'.freeze
6
- USER_AGENT_HEADER = 'User-Agent'.freeze
7
- USER_AGENT_HEADER_VALUE = 'SecureNative-python'.freeze
8
- CONTENT_TYPE_HEADER = 'Content-Type'.freeze
9
- CONTENT_TYPE_HEADER_VALUE = 'application/json'.freeze
10
-
11
- def __init__(securenative_options)
12
- @options = securenative_options
13
- @client = HTTPClient.new
14
- end
15
-
16
- def _headers
17
- {
18
- CONTENT_TYPE_HEADER => CONTENT_TYPE_HEADER_VALUE,
19
- USER_AGENT_HEADER => USER_AGENT_HEADER_VALUE,
20
- VERSION_HEADER => VersionUtils.version,
21
- AUTHORIZATION_HEADER => options.api_key
22
- }
23
- end
24
-
25
- def post(path, body)
26
- url = '{}/{}'.format(@options.api_url, path)
27
- headers = _headers
28
- @client.post(url, body, headers)
29
- end
30
- end
@@ -1,10 +0,0 @@
1
- class RequestOptions
2
- attr_reader :url, :body, :retry
3
- attr_writer :url, :body, :retry
4
-
5
- def initialize(url, body, _retry)
6
- @url = url
7
- @body = body
8
- @retry = _retry
9
- end
10
- end
@@ -1,10 +0,0 @@
1
- class UserTraits
2
- attr_reader :name, :email, :created_at
3
- attr_writer :name, :email, :created_at
4
-
5
- def initialize(name = nil, email = nil, created_at = nil)
6
- @name = name
7
- @email = email
8
- @created_at = created_at
9
- end
10
- end
@@ -1,9 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <module type="RUBY_MODULE" version="4">
3
- <component name="NewModuleRootManager" inherit-compiler-output="true">
4
- <exclude-output />
5
- <content url="file://$MODULE_DIR$" />
6
- <orderEntry type="jdk" jdkName="ruby-2.7.1-p83" jdkType="RUBY_SDK" />
7
- <orderEntry type="sourceFolder" forTests="false" />
8
- </component>
9
- </module>
@@ -1,7 +0,0 @@
1
- class DateUtils
2
- def self.to_timestamp(date)
3
- return Time.now.strftime('%Y-%m-%dT%H:%M:%S.%L%Z') if date.nil?
4
-
5
- Time.strptime(date, '%Y-%m-%dT%H:%M:%S.%L%Z')
6
- end
7
- end
@@ -1,9 +0,0 @@
1
- class Utils
2
- def self.null_or_empty?(string)
3
- return true if !string.nil? && !string.empty?
4
-
5
- return true unless string.nil?
6
-
7
- false
8
- end
9
- end