castle-rb 8.0.0 → 9.0.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 (133) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +317 -0
  3. data/LICENSE +21 -0
  4. data/README.md +290 -112
  5. data/lib/castle/api/filter.rb +3 -1
  6. data/lib/castle/api/list_items/archive.rb +23 -0
  7. data/lib/castle/api/list_items/count.rb +22 -0
  8. data/lib/castle/api/list_items/create.rb +22 -0
  9. data/lib/castle/api/list_items/create_batch.rb +22 -0
  10. data/lib/castle/api/list_items/get.rb +22 -0
  11. data/lib/castle/api/list_items/query.rb +22 -0
  12. data/lib/castle/api/list_items/unarchive.rb +22 -0
  13. data/lib/castle/api/list_items/update.rb +22 -0
  14. data/lib/castle/api/lists/create.rb +23 -0
  15. data/lib/castle/api/lists/delete.rb +22 -0
  16. data/lib/castle/api/lists/get.rb +22 -0
  17. data/lib/castle/api/lists/get_all.rb +22 -0
  18. data/lib/castle/api/lists/query.rb +22 -0
  19. data/lib/castle/api/lists/update.rb +22 -0
  20. data/lib/castle/api/log.rb +2 -1
  21. data/lib/castle/api/privacy/delete_data.rb +23 -0
  22. data/lib/castle/api/privacy/request_data.rb +23 -0
  23. data/lib/castle/api/risk.rb +2 -1
  24. data/lib/castle/client.rb +15 -52
  25. data/lib/castle/client_actions/list_items.rb +49 -0
  26. data/lib/castle/client_actions/lists.rb +39 -0
  27. data/lib/castle/client_actions/privacy.rb +20 -0
  28. data/lib/castle/commands/list_items/archive.rb +24 -0
  29. data/lib/castle/commands/list_items/count.rb +23 -0
  30. data/lib/castle/commands/list_items/create.rb +22 -0
  31. data/lib/castle/commands/list_items/create_batch.rb +22 -0
  32. data/lib/castle/commands/list_items/get.rb +23 -0
  33. data/lib/castle/commands/list_items/query.rb +24 -0
  34. data/lib/castle/commands/list_items/unarchive.rb +23 -0
  35. data/lib/castle/commands/list_items/update.rb +22 -0
  36. data/lib/castle/commands/lists/create.rb +21 -0
  37. data/lib/castle/commands/lists/delete.rb +20 -0
  38. data/lib/castle/commands/lists/get.rb +20 -0
  39. data/lib/castle/commands/lists/get_all.rb +17 -0
  40. data/lib/castle/commands/lists/query.rb +21 -0
  41. data/lib/castle/commands/lists/update.rb +22 -0
  42. data/lib/castle/commands/privacy/delete_data.rb +20 -0
  43. data/lib/castle/commands/privacy/request_data.rb +20 -0
  44. data/lib/castle/core/get_connection.rb +5 -1
  45. data/lib/castle/core/process_response.rb +1 -0
  46. data/lib/castle/core/process_webhook.rb +1 -1
  47. data/lib/castle/core/send_request.rb +2 -1
  48. data/lib/castle/errors.rb +1 -5
  49. data/lib/castle/headers/filter.rb +1 -1
  50. data/lib/castle/version.rb +1 -1
  51. data/lib/castle.rb +36 -17
  52. metadata +62 -162
  53. data/lib/castle/api/approve_device.rb +0 -20
  54. data/lib/castle/api/authenticate.rb +0 -28
  55. data/lib/castle/api/end_impersonation.rb +0 -22
  56. data/lib/castle/api/get_device.rb +0 -20
  57. data/lib/castle/api/get_devices_for_user.rb +0 -20
  58. data/lib/castle/api/report_device.rb +0 -20
  59. data/lib/castle/api/start_impersonation.rb +0 -22
  60. data/lib/castle/api/track.rb +0 -19
  61. data/lib/castle/commands/approve_device.rb +0 -17
  62. data/lib/castle/commands/authenticate.rb +0 -23
  63. data/lib/castle/commands/end_impersonation.rb +0 -25
  64. data/lib/castle/commands/get_device.rb +0 -17
  65. data/lib/castle/commands/get_devices_for_user.rb +0 -17
  66. data/lib/castle/commands/report_device.rb +0 -17
  67. data/lib/castle/commands/start_impersonation.rb +0 -25
  68. data/lib/castle/commands/track.rb +0 -22
  69. data/lib/castle/support/hanami.rb +0 -15
  70. data/lib/castle/support/padrino.rb +0 -19
  71. data/spec/integration/rails/rails_spec.rb +0 -95
  72. data/spec/integration/rails/support/all.rb +0 -6
  73. data/spec/integration/rails/support/application.rb +0 -17
  74. data/spec/integration/rails/support/home_controller.rb +0 -39
  75. data/spec/lib/castle/api/approve_device_spec.rb +0 -17
  76. data/spec/lib/castle/api/authenticate_spec.rb +0 -133
  77. data/spec/lib/castle/api/end_impersonation_spec.rb +0 -59
  78. data/spec/lib/castle/api/filter_spec.rb +0 -5
  79. data/spec/lib/castle/api/get_device_spec.rb +0 -17
  80. data/spec/lib/castle/api/get_devices_for_user_spec.rb +0 -17
  81. data/spec/lib/castle/api/log_spec.rb +0 -5
  82. data/spec/lib/castle/api/report_device_spec.rb +0 -17
  83. data/spec/lib/castle/api/risk_spec.rb +0 -5
  84. data/spec/lib/castle/api/start_impersonation_spec.rb +0 -59
  85. data/spec/lib/castle/api/track_spec.rb +0 -65
  86. data/spec/lib/castle/api_spec.rb +0 -36
  87. data/spec/lib/castle/client_id/extract_spec.rb +0 -47
  88. data/spec/lib/castle/client_spec.rb +0 -337
  89. data/spec/lib/castle/command_spec.rb +0 -9
  90. data/spec/lib/castle/commands/approve_device_spec.rb +0 -24
  91. data/spec/lib/castle/commands/authenticate_spec.rb +0 -86
  92. data/spec/lib/castle/commands/end_impersonation_spec.rb +0 -72
  93. data/spec/lib/castle/commands/filter_spec.rb +0 -72
  94. data/spec/lib/castle/commands/get_device_spec.rb +0 -24
  95. data/spec/lib/castle/commands/get_devices_for_user_spec.rb +0 -24
  96. data/spec/lib/castle/commands/log_spec.rb +0 -73
  97. data/spec/lib/castle/commands/report_device_spec.rb +0 -24
  98. data/spec/lib/castle/commands/risk_spec.rb +0 -73
  99. data/spec/lib/castle/commands/start_impersonation_spec.rb +0 -72
  100. data/spec/lib/castle/commands/track_spec.rb +0 -89
  101. data/spec/lib/castle/configuration_spec.rb +0 -14
  102. data/spec/lib/castle/context/get_default_spec.rb +0 -41
  103. data/spec/lib/castle/context/merge_spec.rb +0 -23
  104. data/spec/lib/castle/context/prepare_spec.rb +0 -42
  105. data/spec/lib/castle/context/sanitize_spec.rb +0 -27
  106. data/spec/lib/castle/core/get_connection_spec.rb +0 -43
  107. data/spec/lib/castle/core/process_response_spec.rb +0 -103
  108. data/spec/lib/castle/core/process_webhook_spec.rb +0 -52
  109. data/spec/lib/castle/core/send_request_spec.rb +0 -97
  110. data/spec/lib/castle/failover/strategy_spec.rb +0 -12
  111. data/spec/lib/castle/headers/extract_spec.rb +0 -103
  112. data/spec/lib/castle/headers/filter_spec.rb +0 -42
  113. data/spec/lib/castle/headers/format_spec.rb +0 -25
  114. data/spec/lib/castle/ips/extract_spec.rb +0 -91
  115. data/spec/lib/castle/logger_spec.rb +0 -39
  116. data/spec/lib/castle/payload/prepare_spec.rb +0 -52
  117. data/spec/lib/castle/secure_mode_spec.rb +0 -7
  118. data/spec/lib/castle/session_spec.rb +0 -61
  119. data/spec/lib/castle/singleton_configuration_spec.rb +0 -14
  120. data/spec/lib/castle/utils/clean_invalid_chars_spec.rb +0 -69
  121. data/spec/lib/castle/utils/clone_spec.rb +0 -19
  122. data/spec/lib/castle/utils/deep_symbolize_keys_spec.rb +0 -50
  123. data/spec/lib/castle/utils/get_timestamp_spec.rb +0 -16
  124. data/spec/lib/castle/utils/merge_spec.rb +0 -13
  125. data/spec/lib/castle/validators/not_supported_spec.rb +0 -19
  126. data/spec/lib/castle/validators/present_spec.rb +0 -25
  127. data/spec/lib/castle/verdict_spec.rb +0 -9
  128. data/spec/lib/castle/version_spec.rb +0 -5
  129. data/spec/lib/castle/webhooks/verify_spec.rb +0 -59
  130. data/spec/lib/castle_spec.rb +0 -58
  131. data/spec/spec_helper.rb +0 -24
  132. data/spec/support/shared_examples/action_request.rb +0 -167
  133. data/spec/support/shared_examples/configuration.rb +0 -99
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Castle
4
- module API
5
- # Sends GET users/#{user_id}/devices request
6
- module GetDevicesForUser
7
- class << self
8
- # @param options [Hash]
9
- # return [Hash]
10
- def call(options = {})
11
- options = Castle::Utils::DeepSymbolizeKeys.call(options || {})
12
- http = options.delete(:http)
13
- config = options.delete(:config) || Castle.config
14
-
15
- Castle::API.call(Castle::Commands::GetDevicesForUser.build(options), {}, http, config)
16
- end
17
- end
18
- end
19
- end
20
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Castle
4
- module API
5
- # Sends PUT devices/#{device_token}/report request
6
- module ReportDevice
7
- class << self
8
- # @param options [Hash]
9
- # return [Hash]
10
- def call(options = {})
11
- options = Castle::Utils::DeepSymbolizeKeys.call(options || {})
12
- http = options.delete(:http)
13
- config = options.delete(:config) || Castle.config
14
-
15
- Castle::API.call(Castle::Commands::ReportDevice.build(options), {}, http, config)
16
- end
17
- end
18
- end
19
- end
20
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Castle
4
- module API
5
- # Sends POST impersonate request
6
- module StartImpersonation
7
- class << self
8
- # @param options [Hash]
9
- def call(options = {})
10
- options = Castle::Utils::DeepSymbolizeKeys.call(options || {}) unless options[:no_symbolize]
11
- options.delete(:no_symbolize)
12
- http = options.delete(:http)
13
- config = options.delete(:config) || Castle.config
14
-
15
- Castle::API
16
- .call(Castle::Commands::StartImpersonation.build(options), {}, http, config)
17
- .tap { |response| raise Castle::ImpersonationFailed unless response[:success] }
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Castle
4
- module API
5
- module Track
6
- class << self
7
- # @param options [Hash]
8
- def call(options = {})
9
- options = Castle::Utils::DeepSymbolizeKeys.call(options || {}) unless options[:no_symbolize]
10
- options.delete(:no_symbolize)
11
- http = options.delete(:http)
12
- config = options.delete(:config) || Castle.config
13
-
14
- Castle::API.call(Castle::Commands::Track.build(options), {}, http, config)
15
- end
16
- end
17
- end
18
- end
19
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Castle
4
- module Commands
5
- # Generates the payload for the PUT devices/#{device_token}/approve request
6
- class ApproveDevice
7
- class << self
8
- # @param options [Hash]
9
- # @return [Castle::Command]
10
- def build(options = {})
11
- Castle::Validators::Present.call(options, %i[device_token])
12
- Castle::Command.new("devices/#{options[:device_token]}/approve", nil, :put)
13
- end
14
- end
15
- end
16
- end
17
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Castle
4
- module Commands
5
- # Generates the payload for the authenticate request
6
- class Authenticate
7
- class << self
8
- # @param options [Hash]
9
- # @return [Castle::Command]
10
- def build(options = {})
11
- Castle::Validators::Present.call(options, %i[event])
12
- context = Castle::Context::Sanitize.call(options[:context])
13
-
14
- Castle::Command.new(
15
- 'authenticate',
16
- options.merge(context: context, sent_at: Castle::Utils::GetTimestamp.call),
17
- :post
18
- )
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Castle
4
- module Commands
5
- # builder for impersonate command
6
- class EndImpersonation
7
- class << self
8
- # @param options [Hash]
9
- # @return [Castle::Command]
10
- def build(options = {})
11
- Castle::Validators::Present.call(options, %i[user_id])
12
- context = Castle::Context::Sanitize.call(options[:context])
13
-
14
- Castle::Validators::Present.call(context, %i[user_agent ip])
15
-
16
- Castle::Command.new(
17
- 'impersonate',
18
- options.merge(context: context, sent_at: Castle::Utils::GetTimestamp.call),
19
- :delete
20
- )
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Castle
4
- module Commands
5
- # Generates the payload for the GET devices/#{device_token} request
6
- class GetDevice
7
- class << self
8
- # @param options [Hash]
9
- # @return [Castle::Command]
10
- def build(options = {})
11
- Castle::Validators::Present.call(options, %i[device_token])
12
- Castle::Command.new("devices/#{options[:device_token]}", nil, :get)
13
- end
14
- end
15
- end
16
- end
17
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Castle
4
- module Commands
5
- # Generates the payload for the GET users/#{user_id}/devices request
6
- class GetDevicesForUser
7
- class << self
8
- # @param options [Hash]
9
- # @return [Castle::Command]
10
- def build(options = {})
11
- Castle::Validators::Present.call(options, %i[user_id])
12
- Castle::Command.new("users/#{options[:user_id]}/devices", nil, :get)
13
- end
14
- end
15
- end
16
- end
17
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Castle
4
- module Commands
5
- # Generates the payload for the PUT devices/#{device_token}/report request
6
- class ReportDevice
7
- class << self
8
- # @param options [Hash]
9
- # @return [Castle::Command]
10
- def build(options = {})
11
- Castle::Validators::Present.call(options, %i[device_token])
12
- Castle::Command.new("devices/#{options[:device_token]}/report", nil, :put)
13
- end
14
- end
15
- end
16
- end
17
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Castle
4
- module Commands
5
- # builder for impersonate command
6
- class StartImpersonation
7
- class << self
8
- # @param options [Hash]
9
- # @return [Castle::Command]
10
- def build(options = {})
11
- Castle::Validators::Present.call(options, %i[user_id])
12
- context = Castle::Context::Sanitize.call(options[:context])
13
-
14
- Castle::Validators::Present.call(context, %i[user_agent ip])
15
-
16
- Castle::Command.new(
17
- 'impersonate',
18
- options.merge(context: context, sent_at: Castle::Utils::GetTimestamp.call),
19
- :post
20
- )
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Castle
4
- module Commands
5
- class Track
6
- class << self
7
- # @param options [Hash]
8
- # @return [Castle::Command]
9
- def build(options = {})
10
- Castle::Validators::Present.call(options, %i[event])
11
- context = Castle::Context::Sanitize.call(options[:context])
12
-
13
- Castle::Command.new(
14
- 'track',
15
- options.merge(context: context, sent_at: Castle::Utils::GetTimestamp.call),
16
- :post
17
- )
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Castle
4
- module Hanami
5
- module Action
6
- def castle
7
- @castle ||= ::Castle::Client.from_request(request, cookies: (cookies if defined?(cookies)))
8
- end
9
- end
10
-
11
- def self.included(base)
12
- base.configure { controller.prepare { include Castle::Hanami::Action } }
13
- end
14
- end
15
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Padrino
4
- class Application
5
- module Castle
6
- module Helpers
7
- def castle
8
- @castle ||= ::Castle::Client.from_request(request)
9
- end
10
- end
11
-
12
- def self.registered(app)
13
- app.helpers Helpers
14
- end
15
- end
16
-
17
- register Castle
18
- end
19
- end
@@ -1,95 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
- require_relative 'support/all'
5
-
6
- RSpec.describe HomeController, type: :request do
7
- context 'with index pages' do
8
- let(:request) do
9
- {
10
- 'event' => '$login.succeeded',
11
- 'user_id' => '123',
12
- 'properties' => {
13
- 'key' => 'value'
14
- },
15
- 'user_traits' => {
16
- 'key' => 'value'
17
- },
18
- 'timestamp' => now.utc.iso8601(3),
19
- 'sent_at' => now.utc.iso8601(3),
20
- 'context' => {
21
- 'client_id' => '',
22
- 'active' => true,
23
- 'headers' => {
24
- 'Accept' =>
25
- 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
26
- 'Authorization' => true,
27
- 'Cookie' => true,
28
- 'Content-Length' => '0',
29
- 'Host' => 'www.example.com',
30
- 'X-Forwarded-For' => '5.5.5.5, 1.2.3.4',
31
- 'Remote-Addr' => '127.0.0.1',
32
- 'Version' => 'HTTP/1.0'
33
- },
34
- 'ip' => '1.2.3.4',
35
- 'library' => {
36
- 'name' => 'castle-rb',
37
- 'version' => Castle::VERSION
38
- }
39
- }
40
- }
41
- end
42
- let(:now) { Time.now }
43
- let(:headers) do
44
- {
45
- 'HTTP_AUTHORIZATION' => 'Basic 123',
46
- 'HTTP_X_FORWARDED_FOR' => '5.5.5.5, 1.2.3.4',
47
- 'HTTP_VERSION' => 'HTTP/1.0',
48
- 'HTTP_CONTENT_LENGTH' => '0'
49
- }
50
- end
51
-
52
- before do
53
- Timecop.freeze(now)
54
- stub_request(:post, 'https://api.castle.io/v1/track')
55
- end
56
-
57
- after { Timecop.return }
58
-
59
- describe '#index1' do
60
- before { get '/index1', headers: headers }
61
-
62
- it do
63
- assert_requested :post, 'https://api.castle.io/v1/track', times: 1 do |req|
64
- JSON.parse(req.body) == request
65
- end
66
- end
67
-
68
- it { expect(response).to be_successful }
69
- end
70
-
71
- describe '#index2' do
72
- before { get '/index2', headers: headers }
73
-
74
- it do
75
- assert_requested :post, 'https://api.castle.io/v1/track', times: 1 do |req|
76
- JSON.parse(req.body) == request
77
- end
78
- end
79
-
80
- it { expect(response).to be_successful }
81
- end
82
-
83
- describe '#index3' do
84
- before { get '/index3', headers: headers }
85
-
86
- it do
87
- assert_requested :post, 'https://api.castle.io/v1/track', times: 1 do |req|
88
- JSON.parse(req.body) == request
89
- end
90
- end
91
-
92
- it { expect(response).to be_successful }
93
- end
94
- end
95
- end
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- ENV['RAILS_ENV'] = 'test'
4
- require_relative 'application'
5
- require_relative 'home_controller'
6
- require 'rspec/rails'
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'action_controller/railtie'
4
-
5
- class TestApp < Rails::Application
6
- credentials.secret_token = 'secret_token'
7
- credentials.secret_key_base = 'secret_key_base'
8
-
9
- config.logger = Logger.new($stdout)
10
- Rails.logger = config.logger
11
-
12
- routes.draw do
13
- get '/index1' => 'home#index1'
14
- get '/index2' => 'home#index2'
15
- get '/index3' => 'home#index3'
16
- end
17
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class HomeController < ActionController::Base
4
- # prepare context and calling track with client example
5
- def index1
6
- request_context = ::Castle::Context::Prepare.call(request)
7
- payload = { event: '$login.succeeded', user_id: '123', properties: { key: 'value' }, user_traits: { key: 'value' } }
8
- client = ::Castle::Client.new(context: request_context)
9
- client.track(payload)
10
-
11
- render inline: 'hello'
12
- end
13
-
14
- # prepare payload and calling track with client example
15
- def index2
16
- payload =
17
- ::Castle::Payload::Prepare.call(
18
- { event: '$login.succeeded', user_id: '123', properties: { key: 'value' }, user_traits: { key: 'value' } },
19
- request
20
- )
21
- client = ::Castle::Client.new
22
- client.track(payload)
23
-
24
- render inline: 'hello'
25
- end
26
-
27
- # prepare payload and calling track with direct API::Track service
28
- def index3
29
- payload =
30
- ::Castle::Payload::Prepare.call(
31
- { event: '$login.succeeded', user_id: '123', properties: { key: 'value' }, user_traits: { key: 'value' } },
32
- request
33
- )
34
-
35
- Castle::API::Track.call(payload)
36
-
37
- render inline: 'hello'
38
- end
39
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- describe Castle::API::ApproveDevice do
4
- before do
5
- stub_request(:any, /api.castle.io/).with(basic_auth: ['', 'secret']).to_return(status: 200, body: '{}', headers: {})
6
- end
7
-
8
- describe '.call' do
9
- subject(:retrieve) { described_class.call(device_token: device_token) }
10
-
11
- let(:device_token) { '1234' }
12
-
13
- before { retrieve }
14
-
15
- it { assert_requested :put, "https://api.castle.io/v1/devices/#{device_token}/approve", times: 1 }
16
- end
17
- end
@@ -1,133 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- describe Castle::API::Authenticate do
4
- subject(:call_subject) { described_class.call(options) }
5
-
6
- let(:ip) { '1.2.3.4' }
7
- let(:cookie_id) { 'abcd' }
8
- let(:ua) { 'Chrome' }
9
- let(:env) do
10
- Rack::MockRequest.env_for(
11
- '/',
12
- 'HTTP_USER_AGENT' => ua,
13
- 'HTTP_X_FORWARDED_FOR' => ip,
14
- 'HTTP_COOKIE' => "__cid=#{cookie_id};other=efgh"
15
- )
16
- end
17
- let(:request) { Rack::Request.new(env) }
18
- let(:context) { Castle::Context::Prepare.call(request) }
19
- let(:time_now) { Time.now }
20
- let(:time_auto) { time_now.utc.iso8601(3) }
21
- let(:time_user) { (Time.now - 10_000).utc.iso8601(3) }
22
- let(:response_body) { {}.to_json }
23
-
24
- before do
25
- Timecop.freeze(time_now)
26
- stub_const('Castle::VERSION', '2.2.0')
27
- end
28
-
29
- after { Timecop.return }
30
-
31
- describe '.call' do
32
- let(:request_body) { { event: '$login.succeeded', context: context, user_id: '1234', sent_at: time_auto } }
33
-
34
- context 'when used with symbol keys' do
35
- before do
36
- stub_request(:any, /api.castle.io/).with(basic_auth: ['', 'secret']).to_return(
37
- status: 200,
38
- body: response_body,
39
- headers: {
40
- }
41
- )
42
- call_subject
43
- end
44
-
45
- let(:options) { { event: '$login.succeeded', user_id: '1234', context: context } }
46
-
47
- it do
48
- assert_requested :post, 'https://api.castle.io/v1/authenticate', times: 1 do |req|
49
- JSON.parse(req.body) == JSON.parse(request_body.to_json)
50
- end
51
- end
52
-
53
- context 'when passed timestamp in options and no defined timestamp' do
54
- let(:options) { { event: '$login.succeeded', user_id: '1234', timestamp: time_user, context: context } }
55
- let(:request_body) do
56
- { event: '$login.succeeded', user_id: '1234', context: context, timestamp: time_user, sent_at: time_auto }
57
- end
58
-
59
- it do
60
- assert_requested :post, 'https://api.castle.io/v1/authenticate', times: 1 do |req|
61
- JSON.parse(req.body) == JSON.parse(request_body.to_json)
62
- end
63
- end
64
- end
65
- end
66
-
67
- context 'when denied' do
68
- let(:failover_appendix) { { failover: false, failover_reason: nil } }
69
-
70
- let(:options) { { event: '$login.succeeded', user_id: '1234', context: context } }
71
-
72
- context 'when denied without any risk policy' do
73
- let(:response_body) { deny_response_without_rp.to_json }
74
- let(:deny_response_without_rp) { { action: 'deny', user_id: '12345', device_token: 'abcdefg1234' } }
75
- let(:deny_without_rp_failover_result) { deny_response_without_rp.merge(failover_appendix) }
76
-
77
- before do
78
- stub_request(:any, /api.castle.io/).with(basic_auth: ['', 'secret']).to_return(
79
- status: 200,
80
- body: deny_response_without_rp.to_json,
81
- headers: {
82
- }
83
- )
84
- call_subject
85
- end
86
-
87
- it do
88
- assert_requested :post, 'https://api.castle.io/v1/authenticate', times: 1 do |req|
89
- JSON.parse(req.body) == JSON.parse(request_body.to_json)
90
- end
91
- end
92
-
93
- it { expect(call_subject).to eql(deny_without_rp_failover_result) }
94
- end
95
-
96
- context 'when denied with risk policy' do
97
- let(:deny_response_with_rp) do
98
- {
99
- action: 'deny',
100
- user_id: '12345',
101
- device_token: 'abcdefg1234',
102
- risk_policy: {
103
- id: 'q-rbeMzBTdW2Fd09sbz55A',
104
- revision_id: 'pke4zqO2TnqVr-NHJOAHEg',
105
- name: 'Block Users from X',
106
- type: 'bot'
107
- }
108
- }
109
- end
110
- let(:response_body) { deny_response_with_rp.to_json }
111
- let(:deny_with_rp_failover_result) { deny_response_with_rp.merge(failover_appendix) }
112
-
113
- before do
114
- stub_request(:any, /api.castle.io/).with(basic_auth: ['', 'secret']).to_return(
115
- status: 200,
116
- body: deny_response_with_rp.to_json,
117
- headers: {
118
- }
119
- )
120
- call_subject
121
- end
122
-
123
- it do
124
- assert_requested :post, 'https://api.castle.io/v1/authenticate', times: 1 do |req|
125
- JSON.parse(req.body) == JSON.parse(request_body.to_json)
126
- end
127
- end
128
-
129
- it { expect(call_subject).to eql(deny_with_rp_failover_result) }
130
- end
131
- end
132
- end
133
- end
@@ -1,59 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- describe Castle::API::EndImpersonation do
4
- subject(:call) { described_class.call(options) }
5
-
6
- let(:ip) { '1.2.3.4' }
7
- let(:cookie_id) { 'abcd' }
8
- let(:ua) { 'Chrome' }
9
- let(:env) do
10
- Rack::MockRequest.env_for(
11
- '/',
12
- 'HTTP_USER_AGENT' => ua,
13
- 'HTTP_X_FORWARDED_FOR' => ip,
14
- 'HTTP_COOKIE' => "__cid=#{cookie_id};other=efgh"
15
- )
16
- end
17
- let(:request) { Rack::Request.new(env) }
18
- let(:context) { Castle::Context::Prepare.call(request) }
19
- let(:time_now) { Time.now }
20
- let(:time_auto) { time_now.utc.iso8601(3) }
21
-
22
- before do
23
- Timecop.freeze(time_now)
24
- stub_const('Castle::VERSION', '2.2.0')
25
- stub_request(:any, /api.castle.io/).with(basic_auth: ['', 'secret']).to_return(
26
- status: 200,
27
- body: response_body,
28
- headers: {
29
- }
30
- )
31
- end
32
-
33
- after { Timecop.return }
34
-
35
- describe 'call' do
36
- let(:impersonator) { 'test@castle.io' }
37
- let(:request_body) do
38
- { user_id: '1234', sent_at: time_auto, properties: { impersonator: impersonator }, context: context }
39
- end
40
- let(:response_body) { { success: true }.to_json }
41
- let(:options) { { user_id: '1234', properties: { impersonator: impersonator }, context: context } }
42
-
43
- context 'when used with symbol keys' do
44
- before { call }
45
-
46
- it do
47
- assert_requested :delete, 'https://api.castle.io/v1/impersonate', times: 1 do |req|
48
- JSON.parse(req.body) == JSON.parse(request_body.to_json)
49
- end
50
- end
51
- end
52
-
53
- context 'when request is not successful' do
54
- let(:response_body) { {}.to_json }
55
-
56
- it { expect { call }.to raise_error(Castle::ImpersonationFailed) }
57
- end
58
- end
59
- end
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- describe Castle::API::Filter do
4
- pending
5
- end