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.
Files changed (45) hide show
  1. checksums.yaml +5 -13
  2. data/.circleci/config.yml +105 -0
  3. data/.github/pull_request_template.md +12 -0
  4. data/.github/workflows/publishing_sift_ruby.yml +38 -0
  5. data/.gitignore +1 -0
  6. data/.jenkins/Jenkinsfile +103 -0
  7. data/HISTORY +104 -0
  8. data/README.md +351 -0
  9. data/examples/psp_merchant_management_apis.rb +105 -0
  10. data/examples/validation_apis.rb +47 -0
  11. data/lib/sift/client/decision/apply_to.rb +129 -0
  12. data/lib/sift/client/decision.rb +66 -0
  13. data/lib/sift/client.rb +845 -112
  14. data/lib/sift/error.rb +13 -0
  15. data/lib/sift/router.rb +41 -0
  16. data/lib/sift/utils/hash_getter.rb +15 -0
  17. data/lib/sift/validate/decision.rb +65 -0
  18. data/lib/sift/validate/primitive.rb +43 -0
  19. data/lib/sift/version.rb +2 -2
  20. data/lib/sift.rb +85 -11
  21. data/sift.gemspec +5 -3
  22. data/spec/fixtures/fake_responses.rb +16 -0
  23. data/spec/spec_helper.rb +1 -1
  24. data/spec/unit/client/decision/apply_to_spec.rb +262 -0
  25. data/spec/unit/client/decision_spec.rb +83 -0
  26. data/spec/unit/client_203_spec.rb +193 -0
  27. data/spec/unit/client_205_spec.rb +117 -0
  28. data/spec/unit/client_label_spec.rb +68 -11
  29. data/spec/unit/client_psp_merchant_spec.rb +133 -0
  30. data/spec/unit/client_spec.rb +556 -79
  31. data/spec/unit/client_validationapi_spec.rb +91 -0
  32. data/spec/unit/router_spec.rb +37 -0
  33. data/spec/unit/validate/decision_spec.rb +85 -0
  34. data/spec/unit/validate/primitive_spec.rb +73 -0
  35. data/test_integration_app/decisions_api/test_decisions_api.rb +31 -0
  36. data/test_integration_app/events_api/test_events_api.rb +843 -0
  37. data/test_integration_app/globals.rb +2 -0
  38. data/test_integration_app/main.rb +67 -0
  39. data/test_integration_app/psp_merchants_api/test_psp_merchant_api.rb +44 -0
  40. data/test_integration_app/score_api/test_score_api.rb +11 -0
  41. data/test_integration_app/verification_api/test_verification_api.rb +32 -0
  42. metadata +85 -28
  43. data/.travis.yml +0 -13
  44. data/README.rdoc +0 -85
  45. 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