locked-rb 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/locked.rb +3 -1
- data/lib/locked/client.rb +25 -1
- data/lib/locked/commands/authenticate.rb +2 -1
- data/lib/locked/commands/verify.rb +19 -0
- data/lib/locked/configuration.rb +19 -3
- data/lib/locked/configurations/merger.rb +15 -0
- data/lib/locked/failover_response.rb +42 -0
- data/lib/locked/version.rb +1 -1
- data/spec/lib/Locked/client_spec.rb +70 -4
- data/spec/lib/Locked/commands/verify_spec.rb +21 -0
- data/spec/lib/Locked/configuration_spec.rb +25 -1
- data/spec/lib/Locked/configurations/merger_spec.rb +34 -0
- data/spec/spec_helper.rb +2 -3
- metadata +9 -3
- data/lib/locked/failover_auth_response.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64951c658b06a83e358adbc3c642bea2436f1eb1bd3860571a211440b48a5077
|
4
|
+
data.tar.gz: e95b6a99564437a343ae196f408c9baa994044628eeb7570f9e9d8ca8df75c4e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0a4cf2b3ae6a0fab35bac7f61e84fae9115ee9e9804eddeb18e500b2a8df93d8257b14988356560fa4b8db7b34ccd41937ce2738a62eedd391937964425bc0e
|
7
|
+
data.tar.gz: 51a40bf5f9494e7948180042f820dfb0b311513b0d1c35b4026689f27697f67b461c402a05241aa37df95e51dcf56032d12947820bca1249a95089e77a8a1d8b
|
data/lib/locked.rb
CHANGED
@@ -23,8 +23,9 @@
|
|
23
23
|
locked/commands/identify
|
24
24
|
locked/commands/authenticate
|
25
25
|
locked/commands/review
|
26
|
+
locked/commands/verify
|
26
27
|
locked/configuration
|
27
|
-
locked/
|
28
|
+
locked/failover_response
|
28
29
|
locked/client
|
29
30
|
locked/header_formatter
|
30
31
|
locked/secure_mode
|
@@ -36,6 +37,7 @@
|
|
36
37
|
locked/api/request/build
|
37
38
|
locked/review
|
38
39
|
locked/api
|
40
|
+
locked/configurations/merger
|
39
41
|
].each(&method(:require))
|
40
42
|
|
41
43
|
# main sdk module
|
data/lib/locked/client.rb
CHANGED
@@ -43,7 +43,31 @@ module Locked
|
|
43
43
|
Locked::API.request(command).merge(failover: false, failover_reason: nil)
|
44
44
|
rescue Locked::RequestError, Locked::InternalServerError => error
|
45
45
|
self.class.failover_response_or_raise(
|
46
|
-
|
46
|
+
Locked::FailoverResponse::Auth.new(options[:user_id], reason: error.to_s), error
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def failed_in_verification(token = {})
|
52
|
+
command = Locked::Commands::Verify.new(@context).build('deny_verification', token)
|
53
|
+
begin
|
54
|
+
response = Locked::API.request(command)
|
55
|
+
response.merge(failover: false, failover_reason: nil)
|
56
|
+
rescue Locked::RequestError, Locked::InternalServerError => error
|
57
|
+
self.class.failover_response_or_raise(
|
58
|
+
Locked::FailoverResponse::Verification.new(reason: error.to_s), error
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def succeeded_in_verification(token = {})
|
64
|
+
command = Locked::Commands::Verify.new(@context).build('allow_verification', token)
|
65
|
+
begin
|
66
|
+
response = Locked::API.request(command)
|
67
|
+
response.merge(failover: false, failover_reason: nil)
|
68
|
+
rescue Locked::RequestError, Locked::InternalServerError => error
|
69
|
+
self.class.failover_response_or_raise(
|
70
|
+
Locked::FailoverResponse::Verification.new(reason: error.to_s), error
|
47
71
|
)
|
48
72
|
end
|
49
73
|
end
|
@@ -11,10 +11,11 @@ module Locked
|
|
11
11
|
Locked::Validators::Present.call(options, %i[event])
|
12
12
|
context = Locked::Context::Merger.call(@context, options[:context])
|
13
13
|
context = Locked::Context::Sanitizer.call(context)
|
14
|
+
options_with_config = Locked::Configurations::Merger.call(options)
|
14
15
|
|
15
16
|
Locked::Command.new(
|
16
17
|
'authenticate',
|
17
|
-
|
18
|
+
options_with_config.merge(context: context),
|
18
19
|
:post
|
19
20
|
)
|
20
21
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Locked
|
4
|
+
module Commands
|
5
|
+
class Verify
|
6
|
+
def initialize(context)
|
7
|
+
@context = context
|
8
|
+
end
|
9
|
+
|
10
|
+
def build(path, body, **options)
|
11
|
+
context = Locked::Context::Merger.call(@context, options[:context])
|
12
|
+
context = Locked::Context::Sanitizer.call(context)
|
13
|
+
body_with_context = body.merge(context: context)
|
14
|
+
|
15
|
+
Locked::Command.new(path, body_with_context, :post)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/locked/configuration.rb
CHANGED
@@ -3,8 +3,14 @@
|
|
3
3
|
module Locked
|
4
4
|
# manages configuration variables
|
5
5
|
class Configuration
|
6
|
-
HOST = '
|
7
|
-
|
6
|
+
HOST = if ENV['DOCKER_USE'].to_i == 1
|
7
|
+
'app'
|
8
|
+
elsif ENV['LOCKED_RUBY_DEV_MODE'].to_s == 'on'
|
9
|
+
'localhost'
|
10
|
+
else
|
11
|
+
'api.locked.jp'
|
12
|
+
end
|
13
|
+
PORT = ENV['LOCKED_RUBY_DEV_MODE'] == 'on' ? 3000 : 443
|
8
14
|
URL_PREFIX = 'api/v1/client'
|
9
15
|
FAILOVER_STRATEGY = :deny
|
10
16
|
REQUEST_TIMEOUT = 1000 # in milliseconds
|
@@ -25,9 +31,10 @@ module Locked
|
|
25
31
|
'CF_CONNECTING_IP'
|
26
32
|
].freeze
|
27
33
|
BLACKLISTED = ['HTTP_COOKIE'].freeze
|
34
|
+
CUSTOM_VERIFICATION = %i[email].freeze
|
28
35
|
|
29
36
|
attr_accessor :host, :port, :request_timeout, :url_prefix
|
30
|
-
attr_reader :api_key, :whitelisted, :blacklisted, :failover_strategy
|
37
|
+
attr_reader :api_key, :whitelisted, :blacklisted, :failover_strategy, :custom_verification
|
31
38
|
|
32
39
|
def initialize
|
33
40
|
@formatter = Locked::HeaderFormatter.new
|
@@ -39,6 +46,7 @@ module Locked
|
|
39
46
|
self.whitelisted = WHITELISTED
|
40
47
|
self.blacklisted = BLACKLISTED
|
41
48
|
self.api_key = ''
|
49
|
+
self.custom_verification = []
|
42
50
|
end
|
43
51
|
|
44
52
|
def api_key=(value)
|
@@ -62,6 +70,14 @@ module Locked
|
|
62
70
|
raise Locked::ConfigurationError, 'unrecognized failover strategy' if @failover_strategy.nil?
|
63
71
|
end
|
64
72
|
|
73
|
+
def custom_verification=(values)
|
74
|
+
return @custom_verification = [] if values.empty?
|
75
|
+
@custom_verification = values.each_with_object([]) do |value, array|
|
76
|
+
raise Locked::ConfigurationError, 'unrecognized custom verification' unless CUSTOM_VERIFICATION.include?(value)
|
77
|
+
array << value
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
65
81
|
private
|
66
82
|
|
67
83
|
def respond_to_missing?(method_name, _include_private)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Locked
|
4
|
+
module Configurations
|
5
|
+
class Merger
|
6
|
+
class << self
|
7
|
+
def call(options)
|
8
|
+
return options if Locked.config.custom_verification.empty?
|
9
|
+
|
10
|
+
options.merge(custom_verification: Locked.config.custom_verification)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Locked
|
4
|
+
module FailoverResponse
|
5
|
+
# generate failover authentication response
|
6
|
+
class Auth
|
7
|
+
def initialize(user_id, strategy: Locked.config.failover_strategy, reason:)
|
8
|
+
@strategy = strategy
|
9
|
+
@reason = reason
|
10
|
+
@user_id = user_id
|
11
|
+
end
|
12
|
+
|
13
|
+
def generate
|
14
|
+
{
|
15
|
+
data: {
|
16
|
+
action: @strategy.to_s,
|
17
|
+
user_id: @user_id,
|
18
|
+
},
|
19
|
+
failover: true,
|
20
|
+
failover_reason: @reason
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Verification
|
26
|
+
def initialize(strategy: Locked.config.failover_strategy, reason:)
|
27
|
+
@strategy = strategy
|
28
|
+
@reason = reason
|
29
|
+
end
|
30
|
+
|
31
|
+
def generate
|
32
|
+
{
|
33
|
+
data: {
|
34
|
+
action: @strategy.to_s,
|
35
|
+
},
|
36
|
+
failover: true,
|
37
|
+
failover_reason: @reason
|
38
|
+
}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/locked/version.rb
CHANGED
@@ -142,7 +142,7 @@ describe Locked::Client do
|
|
142
142
|
before { request_response }
|
143
143
|
|
144
144
|
it do
|
145
|
-
assert_requested :post, 'https://locked.jp/api/v1/client/authenticate', times: 1 do |req|
|
145
|
+
assert_requested :post, 'https://api.locked.jp/api/v1/client/authenticate', times: 1 do |req|
|
146
146
|
JSON.parse(req.body) == JSON.parse(request_body.to_json)
|
147
147
|
end
|
148
148
|
end
|
@@ -155,7 +155,7 @@ describe Locked::Client do
|
|
155
155
|
end
|
156
156
|
|
157
157
|
it do
|
158
|
-
assert_requested :post, 'https://locked.jp/api/v1/client/authenticate', times: 1 do |req|
|
158
|
+
assert_requested :post, 'https://api.locked.jp/api/v1/client/authenticate', times: 1 do |req|
|
159
159
|
JSON.parse(req.body) == JSON.parse(request_body.to_json)
|
160
160
|
end
|
161
161
|
end
|
@@ -168,7 +168,7 @@ describe Locked::Client do
|
|
168
168
|
end
|
169
169
|
|
170
170
|
it do
|
171
|
-
assert_requested :post, 'https://locked.jp/api/v1/client/authenticate', times: 1 do |req|
|
171
|
+
assert_requested :post, 'https://api.locked.jp/api/v1/client/authenticate', times: 1 do |req|
|
172
172
|
JSON.parse(req.body) == JSON.parse(request_body.to_json)
|
173
173
|
end
|
174
174
|
end
|
@@ -181,7 +181,7 @@ describe Locked::Client do
|
|
181
181
|
before { request_response }
|
182
182
|
|
183
183
|
it do
|
184
|
-
assert_requested :post, 'https://locked.jp/api/v1/client/authenticate', times: 1 do |req|
|
184
|
+
assert_requested :post, 'https://api.locked.jp/api/v1/client/authenticate', times: 1 do |req|
|
185
185
|
JSON.parse(req.body) == JSON.parse(request_body.to_json)
|
186
186
|
end
|
187
187
|
end
|
@@ -223,4 +223,70 @@ describe Locked::Client do
|
|
223
223
|
end
|
224
224
|
end
|
225
225
|
end
|
226
|
+
|
227
|
+
describe '#failed_in_verification' do
|
228
|
+
let(:request_body) { { token: 'sample25f90350c69f50acc968' } }
|
229
|
+
|
230
|
+
subject { client.failed_in_verification(request_body) }
|
231
|
+
|
232
|
+
context '正常系' do
|
233
|
+
it '期待したrequest bodyが生成されること' do
|
234
|
+
subject
|
235
|
+
|
236
|
+
assert_requested :post, 'https://api.locked.jp/api/v1/client/deny_verification', times: 1 do |req|
|
237
|
+
JSON.parse(req.body) == JSON.parse(request_body.to_json)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
context '異常系' do
|
243
|
+
before { allow(Locked::API).to receive(:request).and_raise(Locked::RequestError.new(Timeout::Error)) }
|
244
|
+
|
245
|
+
context 'with request error and throw strategy' do
|
246
|
+
before { allow(Locked.config).to receive(:failover_strategy).and_return(:throw) }
|
247
|
+
|
248
|
+
it { expect { subject }.to raise_error(Locked::RequestError) }
|
249
|
+
end
|
250
|
+
|
251
|
+
context 'with request error and not throw on eg deny strategy' do
|
252
|
+
it { assert_not_requested :post, 'https://locked.jp/api/v1/client/deny_verification' }
|
253
|
+
it { expect(subject[:data][:action]).to be_eql('deny') }
|
254
|
+
it { expect(subject[:failover]).to be true }
|
255
|
+
it { expect(subject[:failover_reason]).to be_eql('Locked::RequestError') }
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
describe '#succeeded_in_verification' do
|
261
|
+
let(:request_body) { { token: 'sample25f90350c69f50acc968' } }
|
262
|
+
|
263
|
+
subject { client.succeeded_in_verification(request_body) }
|
264
|
+
|
265
|
+
context '正常系' do
|
266
|
+
it '期待したrequest bodyが生成されること' do
|
267
|
+
subject
|
268
|
+
|
269
|
+
assert_requested :post, 'https://api.locked.jp/api/v1/client/allow_verification', times: 1 do |req|
|
270
|
+
JSON.parse(req.body) == JSON.parse(request_body.to_json)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
context '異常系' do
|
276
|
+
before { allow(Locked::API).to receive(:request).and_raise(Locked::RequestError.new(Timeout::Error)) }
|
277
|
+
|
278
|
+
context 'with request error and throw strategy' do
|
279
|
+
before { allow(Locked.config).to receive(:failover_strategy).and_return(:throw) }
|
280
|
+
|
281
|
+
it { expect { subject }.to raise_error(Locked::RequestError) }
|
282
|
+
end
|
283
|
+
|
284
|
+
context 'with request error and not throw on eg deny strategy' do
|
285
|
+
it { assert_not_requested :post, 'https://locked.jp/api/v1/client/allow_verification' }
|
286
|
+
it { expect(subject[:data][:action]).to be_eql('deny') }
|
287
|
+
it { expect(subject[:failover]).to be true }
|
288
|
+
it { expect(subject[:failover_reason]).to be_eql('Locked::RequestError') }
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
226
292
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe Locked::Commands::Verify do
|
4
|
+
let(:context) { { test: { test1: '1' } } }
|
5
|
+
|
6
|
+
describe '.build' do
|
7
|
+
subject { Locked::Commands::Verify.new(context).build('deny_verification', token: 'f68c5f338f2ba6b14e17') }
|
8
|
+
|
9
|
+
it '期待したpathが返ること' do
|
10
|
+
expect(subject.path).to eq 'deny_verification'
|
11
|
+
end
|
12
|
+
|
13
|
+
it '期待したbodyが返ること' do
|
14
|
+
expect(subject.data).to include token: 'f68c5f338f2ba6b14e17'
|
15
|
+
end
|
16
|
+
|
17
|
+
it '期待したhttpメソッドが返ること' do
|
18
|
+
expect(subject.method).to eq :post
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -7,7 +7,7 @@ describe Locked::Configuration do
|
|
7
7
|
|
8
8
|
describe 'host' do
|
9
9
|
context 'with default' do
|
10
|
-
it { expect(config.host).to be_eql('locked.jp') }
|
10
|
+
it { expect(config.host).to be_eql('api.locked.jp') }
|
11
11
|
end
|
12
12
|
|
13
13
|
context 'with setter' do
|
@@ -143,4 +143,28 @@ describe Locked::Configuration do
|
|
143
143
|
end
|
144
144
|
end
|
145
145
|
end
|
146
|
+
|
147
|
+
describe 'custom_verification' do
|
148
|
+
it do
|
149
|
+
expect(config.custom_verification).to be_eql([])
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'with setter' do
|
153
|
+
before do
|
154
|
+
config.custom_verification = [:email]
|
155
|
+
end
|
156
|
+
|
157
|
+
it do
|
158
|
+
expect(config.custom_verification).to be_eql([:email])
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context 'when broken' do
|
163
|
+
it do
|
164
|
+
expect do
|
165
|
+
config.custom_verification = [:unknown]
|
166
|
+
end.to raise_error(Locked::ConfigurationError)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
146
170
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe Locked::Configurations::Merger do
|
4
|
+
describe '.call' do
|
5
|
+
context '正常系' do
|
6
|
+
let(:options) do
|
7
|
+
{
|
8
|
+
event: '$login.success',
|
9
|
+
user_id: 1234,
|
10
|
+
user_ip: '1.1.1.1',
|
11
|
+
user_agent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063',
|
12
|
+
email: 'example@locked.jp',
|
13
|
+
callback_url: 'https://locked.jp/login/result'
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'configでcustom_verificationが設定されていない場合' do
|
18
|
+
it '引数で投げられたoptionsが返ること' do
|
19
|
+
expect(Locked::Configurations::Merger.call(options)).to eq options
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'configでcustom_verificationが設定されている場合' do
|
24
|
+
before do
|
25
|
+
Locked.config.custom_verification = [:email]
|
26
|
+
end
|
27
|
+
|
28
|
+
it '引数で投げられたoptionsにcustom verificationがマージされて返ること' do
|
29
|
+
expect(Locked::Configurations::Merger.call(options)).to include custom_verification: [:email]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: locked-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yoshiki Takeda
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: locked protects your users from account compromise
|
14
14
|
email: takeda@locked.jp
|
@@ -28,7 +28,9 @@ files:
|
|
28
28
|
- lib/locked/commands/authenticate.rb
|
29
29
|
- lib/locked/commands/identify.rb
|
30
30
|
- lib/locked/commands/review.rb
|
31
|
+
- lib/locked/commands/verify.rb
|
31
32
|
- lib/locked/configuration.rb
|
33
|
+
- lib/locked/configurations/merger.rb
|
32
34
|
- lib/locked/context/default.rb
|
33
35
|
- lib/locked/context/merger.rb
|
34
36
|
- lib/locked/context/sanitizer.rb
|
@@ -36,7 +38,7 @@ files:
|
|
36
38
|
- lib/locked/extractors/client_id.rb
|
37
39
|
- lib/locked/extractors/headers.rb
|
38
40
|
- lib/locked/extractors/ip.rb
|
39
|
-
- lib/locked/
|
41
|
+
- lib/locked/failover_response.rb
|
40
42
|
- lib/locked/header_formatter.rb
|
41
43
|
- lib/locked/review.rb
|
42
44
|
- lib/locked/secure_mode.rb
|
@@ -60,7 +62,9 @@ files:
|
|
60
62
|
- spec/lib/Locked/commands/authenticate_spec.rb
|
61
63
|
- spec/lib/Locked/commands/identify_spec.rb
|
62
64
|
- spec/lib/Locked/commands/review_spec.rb
|
65
|
+
- spec/lib/Locked/commands/verify_spec.rb
|
63
66
|
- spec/lib/Locked/configuration_spec.rb
|
67
|
+
- spec/lib/Locked/configurations/merger_spec.rb
|
64
68
|
- spec/lib/Locked/context/default_spec.rb
|
65
69
|
- spec/lib/Locked/context/merger_spec.rb
|
66
70
|
- spec/lib/Locked/context/sanitizer_spec.rb
|
@@ -104,6 +108,7 @@ specification_version: 4
|
|
104
108
|
summary: locked
|
105
109
|
test_files:
|
106
110
|
- spec/spec_helper.rb
|
111
|
+
- spec/lib/Locked/configurations/merger_spec.rb
|
107
112
|
- spec/lib/Locked/review_spec.rb
|
108
113
|
- spec/lib/Locked/client_spec.rb
|
109
114
|
- spec/lib/Locked/context/default_spec.rb
|
@@ -122,6 +127,7 @@ test_files:
|
|
122
127
|
- spec/lib/Locked/api/request/build_spec.rb
|
123
128
|
- spec/lib/Locked/commands/review_spec.rb
|
124
129
|
- spec/lib/Locked/commands/authenticate_spec.rb
|
130
|
+
- spec/lib/Locked/commands/verify_spec.rb
|
125
131
|
- spec/lib/Locked/commands/identify_spec.rb
|
126
132
|
- spec/lib/Locked/validators/not_supported_spec.rb
|
127
133
|
- spec/lib/Locked/validators/present_spec.rb
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Locked
|
4
|
-
# generate failover authentication response
|
5
|
-
class FailoverAuthResponse
|
6
|
-
def initialize(user_id, strategy: Locked.config.failover_strategy, reason:)
|
7
|
-
@strategy = strategy
|
8
|
-
@reason = reason
|
9
|
-
@user_id = user_id
|
10
|
-
end
|
11
|
-
|
12
|
-
def generate
|
13
|
-
{
|
14
|
-
data: {
|
15
|
-
action: @strategy.to_s,
|
16
|
-
user_id: @user_id,
|
17
|
-
},
|
18
|
-
failover: true,
|
19
|
-
failover_reason: @reason
|
20
|
-
}
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|