sift 1.1.6.2 → 4.5.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.
- checksums.yaml +5 -13
- data/.circleci/config.yml +105 -0
- data/.github/pull_request_template.md +12 -0
- data/.github/workflows/publishing_sift_ruby.yml +38 -0
- data/.gitignore +1 -0
- data/.jenkins/Jenkinsfile +103 -0
- data/HISTORY +104 -0
- data/README.md +351 -0
- data/examples/psp_merchant_management_apis.rb +105 -0
- data/examples/validation_apis.rb +47 -0
- data/lib/sift/client/decision/apply_to.rb +129 -0
- data/lib/sift/client/decision.rb +66 -0
- data/lib/sift/client.rb +845 -112
- data/lib/sift/error.rb +13 -0
- data/lib/sift/router.rb +41 -0
- data/lib/sift/utils/hash_getter.rb +15 -0
- data/lib/sift/validate/decision.rb +65 -0
- data/lib/sift/validate/primitive.rb +43 -0
- data/lib/sift/version.rb +2 -2
- data/lib/sift.rb +85 -11
- data/sift.gemspec +5 -3
- data/spec/fixtures/fake_responses.rb +16 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/client/decision/apply_to_spec.rb +262 -0
- data/spec/unit/client/decision_spec.rb +83 -0
- data/spec/unit/client_203_spec.rb +193 -0
- data/spec/unit/client_205_spec.rb +117 -0
- data/spec/unit/client_label_spec.rb +68 -11
- data/spec/unit/client_psp_merchant_spec.rb +133 -0
- data/spec/unit/client_spec.rb +556 -79
- data/spec/unit/client_validationapi_spec.rb +91 -0
- data/spec/unit/router_spec.rb +37 -0
- data/spec/unit/validate/decision_spec.rb +85 -0
- data/spec/unit/validate/primitive_spec.rb +73 -0
- data/test_integration_app/decisions_api/test_decisions_api.rb +31 -0
- data/test_integration_app/events_api/test_events_api.rb +843 -0
- data/test_integration_app/globals.rb +2 -0
- data/test_integration_app/main.rb +67 -0
- data/test_integration_app/psp_merchants_api/test_psp_merchant_api.rb +44 -0
- data/test_integration_app/score_api/test_score_api.rb +11 -0
- data/test_integration_app/verification_api/test_verification_api.rb +32 -0
- metadata +85 -28
- data/.travis.yml +0 -13
- data/README.rdoc +0 -85
- data/spec/unit/sift_spec.rb +0 -6
@@ -0,0 +1,91 @@
|
|
1
|
+
require_relative "../spec_helper"
|
2
|
+
require "sift"
|
3
|
+
|
4
|
+
describe Sift::Client do
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
Sift.api_key = nil
|
8
|
+
end
|
9
|
+
|
10
|
+
def valid_send_properties
|
11
|
+
{
|
12
|
+
:$user_id => 'billy_jones_301',
|
13
|
+
:$send_to => 'billy_jones_301@gmail.com',
|
14
|
+
:$verification_type => '$email',
|
15
|
+
:$brand_name => 'MyTopBrand',
|
16
|
+
:$language => 'en',
|
17
|
+
:$event => {
|
18
|
+
:$session_id => '09f7f361575d11ff',
|
19
|
+
:$verified_event => '$login',
|
20
|
+
:$reason => '$automated_rule',
|
21
|
+
:$ip => '192.168.1.1',
|
22
|
+
:$browser => {
|
23
|
+
:$user_agent => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def valid_resend_properties
|
30
|
+
{
|
31
|
+
:$user_id => 'billy_jones_301',
|
32
|
+
:$verified_event => '$login'
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def valid_check_properties
|
37
|
+
{
|
38
|
+
:$user_id => 'billy_jones_301',
|
39
|
+
:$code => '123456'
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
it "Successfully calls send" do
|
44
|
+
api_key = "foobar1"
|
45
|
+
user_id = "foobar2"
|
46
|
+
|
47
|
+
response_json = { :status => 0, :error_message => "OK"}
|
48
|
+
|
49
|
+
stub_request(:post, "https://foobar1:@api.siftscience.com/v1.1/verification/send")
|
50
|
+
.to_return(:status => 200, :body => MultiJson.dump(response_json))
|
51
|
+
|
52
|
+
response = Sift::Client.new(:api_key => api_key,:user_id => user_id,:version=>1.1).verification_send(valid_send_properties,:version => 205)
|
53
|
+
expect(response.ok?).to eq(true)
|
54
|
+
expect(response.api_status).to eq(0)
|
55
|
+
expect(response.api_error_message).to eq("OK")
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
it "Successfully calls resend" do
|
60
|
+
api_key = "foobar1"
|
61
|
+
user_id = "foobar2"
|
62
|
+
|
63
|
+
response_json = { :status => 0, :error_message => "OK"}
|
64
|
+
|
65
|
+
stub_request(:post, "https://foobar1:@api.siftscience.com/v1.1/verification/resend")
|
66
|
+
.to_return(:status => 200, :body => MultiJson.dump(response_json))
|
67
|
+
|
68
|
+
response = Sift::Client.new(:api_key => api_key,:user_id => user_id,:version=>1.1).verification_resend(valid_resend_properties,:version => 205)
|
69
|
+
expect(response.ok?).to eq(true)
|
70
|
+
expect(response.api_status).to eq(0)
|
71
|
+
expect(response.api_error_message).to eq("OK")
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
it "Successfully calls check" do
|
76
|
+
api_key = "foobar1"
|
77
|
+
user_id = "foobar2"
|
78
|
+
|
79
|
+
response_json = { :status => 0, :error_message => "OK"}
|
80
|
+
|
81
|
+
stub_request(:post, "https://foobar1:@api.siftscience.com/v1.1/verification/check")
|
82
|
+
.to_return(:status => 200, :body => MultiJson.dump(response_json))
|
83
|
+
|
84
|
+
response = Sift::Client.new(:api_key => api_key,:user_id => user_id,:version=>1.1).verification_check(valid_check_properties,:version => 205)
|
85
|
+
expect(response.ok?).to eq(true)
|
86
|
+
expect(response.api_status).to eq(0)
|
87
|
+
expect(response.api_error_message).to eq("OK")
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative "../spec_helper"
|
2
|
+
|
3
|
+
require "sift/router"
|
4
|
+
|
5
|
+
module Sift
|
6
|
+
describe Router do
|
7
|
+
let(:path) { "https://example.com" }
|
8
|
+
let(:body) { { question: "Do you wanna go ball?" } }
|
9
|
+
|
10
|
+
describe ".get" do
|
11
|
+
it "with a successful request will return a response object" do
|
12
|
+
stub_request(:get, path)
|
13
|
+
.with(body: MultiJson.dump(body))
|
14
|
+
.to_return(body: MultiJson.dump({ cool: true }))
|
15
|
+
|
16
|
+
response = Router.get(path, { body: body })
|
17
|
+
|
18
|
+
expect(response.ok?).to be(true)
|
19
|
+
expect(response.body["cool"]).to be(true)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "with an unsuccessful request will return a response object" do
|
23
|
+
stub_request(:get, path)
|
24
|
+
.with(body: MultiJson.dump(body))
|
25
|
+
.to_return(body: MultiJson.dump({ cool: false}), status: 403)
|
26
|
+
|
27
|
+
response = Router.get(path, { body: body })
|
28
|
+
|
29
|
+
expect(response.ok?).to be(false)
|
30
|
+
expect(response.body["cool"]).to be(false)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require_relative "../../spec_helper"
|
2
|
+
|
3
|
+
require "sift/validate/decision"
|
4
|
+
|
5
|
+
module Sift
|
6
|
+
module Validate
|
7
|
+
describe Decision do
|
8
|
+
describe "#valid_user?" do
|
9
|
+
it "will return true" do
|
10
|
+
validator = Decision.new(
|
11
|
+
user_id: "hello world",
|
12
|
+
source: :hello_world,
|
13
|
+
analyst: "asdfsadf@heyo.com"
|
14
|
+
)
|
15
|
+
|
16
|
+
expect(validator.valid_user?).to be(true)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "with invalid user_id, will return false" do
|
20
|
+
validator = Decision.new(order_id: "asfasdf")
|
21
|
+
expect(validator.valid_user?).to be(false), "nil user is valid"
|
22
|
+
|
23
|
+
validator = Decision.new(order_id: "asfasdf", user_id: {})
|
24
|
+
expect(validator.valid_user?).to be(false), "user hash is valid"
|
25
|
+
|
26
|
+
validator = Decision.new(order_id: "asfasdf", user_id: /werwer/)
|
27
|
+
expect(validator.valid_user?).to be(false), "regex user is valid"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#valid_order?" do
|
32
|
+
it "will return true with valid configs" do
|
33
|
+
validator = Decision.new(
|
34
|
+
order_id: "order_foo_bar_12354",
|
35
|
+
user_id: "hello world",
|
36
|
+
source: :hello_world,
|
37
|
+
analyst: "asdfsadf@heyo.com"
|
38
|
+
)
|
39
|
+
|
40
|
+
expect(validator.valid_order?).to be(true)
|
41
|
+
end
|
42
|
+
|
43
|
+
context "with invalid params:" do
|
44
|
+
it "user_id, will return false" do
|
45
|
+
validator = Decision.new(order_id: "asfasdf")
|
46
|
+
expect(validator.valid_order?).to be(false), "nil user is valid"
|
47
|
+
|
48
|
+
validator = Decision.new(order_id: "asfasdf", user_id: {})
|
49
|
+
expect(validator.valid_order?).to be(false), "user hash is valid"
|
50
|
+
|
51
|
+
validator = Decision.new(order_id: "asfasdf", user_id: /werwer/)
|
52
|
+
expect(validator.valid_order?).to be(false), "regex user is valid"
|
53
|
+
end
|
54
|
+
|
55
|
+
it "order_id, will return false" do
|
56
|
+
validator = Decision.new(user_id: 1235)
|
57
|
+
expect(validator.valid_order?).to be(false)
|
58
|
+
|
59
|
+
validator = Decision.new(user_id: 1235, order_id: {})
|
60
|
+
expect(validator.valid_order?).to be(false)
|
61
|
+
|
62
|
+
validator = Decision.new(user_id: 1235, order_id: /23424/)
|
63
|
+
expect(validator.valid_order?).to be(false)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#error_messages" do
|
69
|
+
it "will return an array of error messages" do
|
70
|
+
validator = Decision.new
|
71
|
+
|
72
|
+
error_message =
|
73
|
+
"#{Primitive::ERROR_MESSAGES[:non_empty_string]}, got NilClass"
|
74
|
+
|
75
|
+
validator.valid_order?
|
76
|
+
|
77
|
+
expect(validator.error_messages).to contain_exactly(
|
78
|
+
"order_id #{error_message}",
|
79
|
+
"user_id #{error_message}"
|
80
|
+
)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require_relative "../../spec_helper"
|
2
|
+
|
3
|
+
require "sift/validate/primitive"
|
4
|
+
|
5
|
+
module Sift
|
6
|
+
module Validate
|
7
|
+
describe Primitive do
|
8
|
+
describe ".non_empty_string" do
|
9
|
+
it "will return nil for valid values" do
|
10
|
+
expect(Primitive.non_empty_string("foobar")).to be_nil
|
11
|
+
end
|
12
|
+
|
13
|
+
it "will return an error message" do
|
14
|
+
[nil, 1, /asdfasdf/].each do |value|
|
15
|
+
error_message = "#{Primitive::ERROR_MESSAGES[:non_empty_string]}" \
|
16
|
+
", got #{value.class}"
|
17
|
+
|
18
|
+
expect(Primitive.non_empty_string(value)).to eq(error_message)
|
19
|
+
end
|
20
|
+
|
21
|
+
expect(Primitive.non_empty_string("")).to(
|
22
|
+
eq(Primitive.send(:empty_string_message, :non_empty_string))
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe ".is_numeric" do
|
28
|
+
it "will return nil for numeric values" do
|
29
|
+
[1, 29.01, 29 ** 1992848499198, -2].each do |value|
|
30
|
+
expect(Primitive.numeric(value)).to(
|
31
|
+
be_nil,
|
32
|
+
"#{value} is a non numeric value"
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "will return an error message for non numeric values" do
|
38
|
+
["foobar", nil, :hello_world, {}].each do |value|
|
39
|
+
expect(Primitive.numeric(value)).to(
|
40
|
+
be(Primitive::ERROR_MESSAGES[:numeric]),
|
41
|
+
"#{value} is a numeric value"
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe ".is_string_or_number?" do
|
48
|
+
it "will return nil for numeric or strings" do
|
49
|
+
[1234, "asdfasdf", "1234_asdfsdf"].each do |value|
|
50
|
+
expect(Primitive.string_or_number(value)).to(
|
51
|
+
be_nil,
|
52
|
+
"#{value} is a non numeric value"
|
53
|
+
)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it "will return an error message for any other type" do
|
58
|
+
[{}, [], :hello_world, nil].each do |value|
|
59
|
+
error_message = "#{Primitive::ERROR_MESSAGES[:string_or_number]}," \
|
60
|
+
" got #{value.class}"
|
61
|
+
|
62
|
+
expect(Primitive.string_or_number(value)).to eq(error_message)
|
63
|
+
end
|
64
|
+
|
65
|
+
error_message = "#{Primitive::ERROR_MESSAGES[:string_or_number]}, " \
|
66
|
+
"got an empty string"
|
67
|
+
expect(Primitive.string_or_number("")).to eq(error_message)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "sift"
|
2
|
+
|
3
|
+
class DecisionAPI
|
4
|
+
|
5
|
+
@@client = Sift::Client.new(:api_key => ENV["API_KEY"], :account_id => ENV["ACCOUNT_ID"])
|
6
|
+
|
7
|
+
def apply_user_decision()
|
8
|
+
properties = {
|
9
|
+
"decision_id": "integration_app_watch_account_abuse",
|
10
|
+
"description": "User linked to three other payment abusers and ordering high value items",
|
11
|
+
"source": "manual_review",
|
12
|
+
"analyst": "analyst@example.com",
|
13
|
+
"user_id": "userId"
|
14
|
+
}
|
15
|
+
|
16
|
+
return @@client.apply_decision(properties)
|
17
|
+
end
|
18
|
+
|
19
|
+
def apply_order_decision()
|
20
|
+
properties = {
|
21
|
+
"decision_id": "block_order_payment_abuse",
|
22
|
+
"description": "applied via the high priority queue, queued user because their risk score exceeded 85",
|
23
|
+
"source": "AUTOMATED_RULE",
|
24
|
+
"user_id": "userId",
|
25
|
+
"order_id": "orderId"
|
26
|
+
}
|
27
|
+
|
28
|
+
return @@client.apply_decision(properties)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|