sift 4.1.0 → 4.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b20b0230176dc6340e5ea4939e51b6e1ed2642e788c25fa2f7f4e829b5c61ff
4
- data.tar.gz: 28932a0fddd658fe868c6c6b6b408ab1d8529060cfbe0766ffeef76e2398e43e
3
+ metadata.gz: cf4d6cd2e8ea54d5ea80fdca8b5668a1f86aa2639eaa1b69a105e8e81dd31222
4
+ data.tar.gz: cd087556fba6bbfd8269366fb8a7ae1c4727841a184056f09406a9c6d78658f5
5
5
  SHA512:
6
- metadata.gz: b905f6002c28777a4cf82cc6b0e59b2c79c300fdf1f4b4b3bf8b0bff8691946325d83794da812d5abc4b344b5e35d24f72b720aae1ddc0783b7e935117f35588
7
- data.tar.gz: e161d32f1c210f3fc4562b985537ceb6e2f304330a3fb14ddbce142cd105b0a0c567f6e177dd3c29c99e6c50133e3a7eb40c5ba922071914d9cf56b540c8f427
6
+ metadata.gz: 66a74c28328b082be3b0f492f0f001c998a7bc99bd95ede179a4c950974b332b4b55158cf418677ce4b904307464912f3248a56b200b88bb76038fd38cdff281
7
+ data.tar.gz: e6bb108cbcbf692266ff6d87a0a426476e8ad0a4523a2436a9f3d6f201ceeab63baad1121466e6a1ef7ec16df7135a577e59e532fe3d463ea47c6c7f47955576
data/.circleci/config.yml CHANGED
@@ -1,4 +1,40 @@
1
- version: 2
1
+ version: 2.1
2
+
3
+ orbs:
4
+ slack: circleci/slack@4.4.2
5
+
6
+ commands:
7
+ export_slack_id:
8
+ steps:
9
+ - run:
10
+ name : Exporting circleci username as slack id.
11
+ command: echo 'export SLACK_PARAM_MENTIONS="$CIRCLE_USERNAME"' >> "$BASH_ENV"
12
+ - run:
13
+ name : CircleCi To Slack user mapping.
14
+ command: |
15
+ echo $GITHUB_SLACK_USERMAPPING | base64 --decode > github_slack
16
+ while read -r line || [[ -n $line ]];
17
+ do
18
+ [[ ${line//[[:space:]]/} =~ ^#.* || -z "$line" ]] && continue
19
+ echo "$line" | tr "=" "\n" | while read -r key; do
20
+ read -r value
21
+ if [ "$CIRCLE_USERNAME" = "${key}" ]; then
22
+ echo "export SLACK_PARAM_MENTIONS='<@${value}>'" >> $BASH_ENV
23
+ fi
24
+ done
25
+ done < github_slack
26
+ rm github_slack
27
+
28
+ slack/notify: &slack_notify
29
+ branch_pattern: master
30
+ event: fail
31
+ channel: ci-build-status
32
+ template: SLACK_TAG_CI_FAILURE_TEMPLATE
33
+
34
+ context: &context
35
+ - slack-templates
36
+ - slack_Oauth
37
+ - Github_Slack_UserMapping
2
38
 
3
39
  jobs:
4
40
  build:
@@ -11,6 +47,7 @@ jobs:
11
47
  BUNDLE_PATH: vendor/bundle
12
48
  steps:
13
49
  - checkout
50
+ - export_slack_id
14
51
 
15
52
  - run:
16
53
  name: Which bundler?
@@ -41,3 +78,11 @@ jobs:
41
78
 
42
79
  - store_test_results:
43
80
  path: test_results
81
+ - slack/notify:
82
+ <<: *slack_notify
83
+
84
+ workflows:
85
+ ruby-test:
86
+ jobs:
87
+ - build:
88
+ context: *context
@@ -0,0 +1,12 @@
1
+ ## Purpose
2
+
3
+ ## Summary
4
+
5
+ ## Testing
6
+
7
+ ## Checklist
8
+ - [ ] The change was thoroughly tested manually
9
+ - [ ] The change was covered with unit tests
10
+ - [ ] The change was tested with real API calls (if applicable)
11
+ - [ ] Necessary changes were made in the integration tests (if applicable)
12
+ - [ ] New functionality is reflected in README
data/HISTORY CHANGED
@@ -1,3 +1,7 @@
1
+ === 4.2.0 2023-06-20
2
+ - Verification API support [Verification API](https://sift.com/developers/docs/curl/verification-api/overview)
3
+ - Support for score percentiles (only applicable for the accounts with the feature enabled)
4
+
1
5
  === 4.1.0 2022-06-22
2
6
  - Add return_route_info query param
3
7
 
@@ -0,0 +1,47 @@
1
+ require "sift"
2
+ require 'multi_json'
3
+
4
+ #$api_key = "put-a-valid-apikey"
5
+ #$user_id = "put-a-valid-userid"
6
+
7
+ def valid_send_properties
8
+ {
9
+ :$user_id => $user_id,
10
+ :$send_to => $user_id,
11
+ :$verification_type => '$email',
12
+ :$brand_name => 'all',
13
+ :$language => 'en',
14
+ :$event => {
15
+ :$session_id => 'gigtleqddo84l8cm15qe4il',
16
+ :$verified_event => '$login',
17
+ :$reason => '$automated_rule',
18
+ :$ip => '192.168.1.1',
19
+ :$browser => {
20
+ :$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'
21
+ }
22
+ }
23
+ }
24
+ end
25
+
26
+ def valid_resend_properties
27
+ {
28
+ :$user_id => $user_id,
29
+ :$verified_event => '$login'
30
+ }
31
+ end
32
+
33
+ def valid_check_properties
34
+ {
35
+ :$user_id => $user_id,
36
+ :$code => '668316'
37
+ }
38
+ end
39
+
40
+ #response = Sift::Client.new(:api_key => $api_key,:user_id => $user_id,:version=>1.1).verification_send(valid_send_properties)
41
+
42
+ #response = Sift::Client.new(:api_key => $api_key,:user_id => $user_id,:version=>1.1).verification_resend(valid_resend_properties)
43
+ response = Sift::Client.new(:api_key => $api_key,:user_id => $user_id,:version=>1.1).verification_check(valid_check_properties)
44
+
45
+ p response
46
+
47
+ puts "completed"
data/lib/sift/client.rb CHANGED
@@ -219,6 +219,7 @@ module Sift
219
219
  return_route_info = opts[:return_route_info]
220
220
  force_workflow_run = opts[:force_workflow_run]
221
221
  abuse_types = opts[:abuse_types]
222
+ include_score_percentiles = opts[:include_score_percentiles]
222
223
 
223
224
  raise("event must be a non-empty string") if (!event.is_a? String) || event.empty?
224
225
  raise("properties cannot be empty") if properties.empty?
@@ -231,6 +232,9 @@ module Sift
231
232
  query["return_route_info"] = "true" if return_route_info
232
233
  query["force_workflow_run"] = "true" if force_workflow_run
233
234
  query["abuse_types"] = abuse_types.join(",") if abuse_types
235
+ if include_score_percentiles == "true"
236
+ query["fields"] = "SCORE_PERCENTILES"
237
+ end
234
238
 
235
239
  options = {
236
240
  :body => MultiJson.dump(delete_nils(properties).merge({"$type" => event,
@@ -716,6 +720,71 @@ module Sift
716
720
  handle_response(apply_decision(configs))
717
721
  end
718
722
 
723
+ def build_default_headers_post(api_key)
724
+ {
725
+ "Authorization" => "Basic #{Base64.encode64(api_key+":")}",
726
+ "User-Agent" => "SiftScience/v#{@version} sift-ruby/#{VERSION}",
727
+ "Content-Type" => "application/json"
728
+ }
729
+ end
730
+
731
+ def verification_send(properties = {}, opts = {})
732
+ api_key = opts[:api_key] || @api_key
733
+ version = opts[:version] || @version
734
+ timeout = opts[:timeout] || @timeout
735
+
736
+ raise("properties cannot be empty") if properties.empty?
737
+ raise("api_key cannot be empty") if api_key.empty?
738
+
739
+
740
+ options = {
741
+ :body => MultiJson.dump(delete_nils(properties)),
742
+ :headers => build_default_headers_post(api_key)
743
+ }
744
+ options.merge!(:timeout => timeout) unless timeout.nil?
745
+
746
+ response = self.class.post(Sift.verification_api_send_path(@version), options)
747
+ Response.new(response.body, response.code, response.response)
748
+ end
749
+
750
+ def verification_resend(properties = {}, opts = {})
751
+ api_key = opts[:api_key] || @api_key
752
+ version = opts[:version] || @version
753
+ timeout = opts[:timeout] || @timeout
754
+
755
+ raise("properties cannot be empty") if properties.empty?
756
+ raise("api_key cannot be empty") if api_key.empty?
757
+
758
+
759
+ options = {
760
+ :body => MultiJson.dump(delete_nils(properties)),
761
+ :headers => build_default_headers_post(api_key)
762
+ }
763
+ options.merge!(:timeout => timeout) unless timeout.nil?
764
+
765
+ response = self.class.post(Sift.verification_api_resend_path(@version), options)
766
+ Response.new(response.body, response.code, response.response)
767
+ end
768
+
769
+ def verification_check(properties = {}, opts = {})
770
+ api_key = opts[:api_key] || @api_key
771
+ version = opts[:version] || @version
772
+ timeout = opts[:timeout] || @timeout
773
+
774
+ raise("properties cannot be empty") if properties.empty?
775
+ raise("api_key cannot be empty") if api_key.empty?
776
+
777
+
778
+ options = {
779
+ :body => MultiJson.dump(delete_nils(properties)),
780
+ :headers => build_default_headers_post(api_key)
781
+ }
782
+ options.merge!(:timeout => timeout) unless timeout.nil?
783
+
784
+ response = self.class.post(Sift.verification_api_check_path(@version), options)
785
+ Response.new(response.body, response.code, response.response)
786
+ end
787
+
719
788
  private
720
789
 
721
790
  def handle_response(response)
data/lib/sift/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Sift
2
- VERSION = "4.1.0"
2
+ VERSION = "4.2.0"
3
3
  API_VERSION = "205"
4
4
  end
data/lib/sift.rb CHANGED
@@ -9,6 +9,21 @@ module Sift
9
9
  "/v#{version}/events"
10
10
  end
11
11
 
12
+ # Returns the path for the specified API version
13
+ def self.verification_api_send_path(version=API_VERSION)
14
+ "/v#{version}/verification/send"
15
+ end
16
+
17
+ # Returns the path for the specified API version
18
+ def self.verification_api_resend_path(version=API_VERSION)
19
+ "/v#{version}/verification/resend"
20
+ end
21
+
22
+ # Returns the path for the specified API version
23
+ def self.verification_api_check_path(version=API_VERSION)
24
+ "/v#{version}/verification/check"
25
+ end
26
+
12
27
  # Returns the Score API path for the specified user ID and API version
13
28
  def self.score_api_path(user_id, version=API_VERSION)
14
29
  "/v#{version}/score/#{ERB::Util.url_encode(user_id)}/"
@@ -0,0 +1,117 @@
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_transaction_properties
11
+ {
12
+ :$type => "$add_item_to_cart",
13
+ :$user_id => "haneeshv@exalture.com",
14
+ :$session_id => "gigtleqddo84l8cm15qe4il",
15
+ :$item => {
16
+ :$item_id => "B004834GQO",
17
+ :$product_title => "The Slanket Blanket-Texas Tea",
18
+ :$price => 39990000,
19
+ :$currency_code => "USD",
20
+ :$upc => "6786211451001",
21
+ :$sku => "004834GQ",
22
+ :$brand => "Slanket",
23
+ :$manufacturer => "Slanket",
24
+ :$category => "Blankets & Throws",
25
+ :$tags => [
26
+ "Awesome",
27
+ "Wintertime specials"
28
+ ],
29
+ :$color => "Texas Tea",
30
+ :$quantity => 16
31
+ },
32
+ :$brand_name => "sift",
33
+ :$site_domain => "sift.com",
34
+ :$site_country => "US",
35
+ :$browser => {
36
+ :$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",
37
+ :$accept_language => "en-US",
38
+ :$content_language => "en-GB"
39
+ }
40
+ }
41
+ end
42
+
43
+ def percentile_response_json
44
+ {
45
+ :user_id => 'haneeshv@exalture.com',
46
+ :latest_labels => {},
47
+ :workflow_statuses => [],
48
+ :scores => {
49
+ :account_abuse => {
50
+ :score => 0.32787917675535705,
51
+ :reasons => [{
52
+ :name => 'Latest item product title',
53
+ :value => 'The Slanket Blanket-Texas Tea'
54
+ }],
55
+ :percentiles => {
56
+ :last_7_days => -1.0, :last_1_days => -1.0, :last_10_days => -1.0, :last_5_days => -1.0
57
+ }
58
+ },
59
+ :acontent_abuse => {
60
+ :score => 0.28056292905897995,
61
+ :reasons => [{
62
+ :name => 'timeSinceFirstEvent',
63
+ :value => '13.15 minutes'
64
+ }],
65
+ :percentiles => {
66
+ :last_7_days => -1.0, :last_1_days => -1.0, :last_10_days => -1.0, :last_5_days => -1.0
67
+ }
68
+ },
69
+ :payment_abuse => {
70
+ :score => 0.28610507028376797,
71
+ :reasons => [{
72
+ :name => 'Latest item currency code',
73
+ :value => 'USD'
74
+ }, {
75
+ :name => 'Latest item item ID',
76
+ :value => 'B004834GQO'
77
+ }, {
78
+ :name => 'Latest item product title',
79
+ :value => 'The Slanket Blanket-Texas Tea'
80
+ }],
81
+ :percentiles => {
82
+ :last_7_days => -1.0, :last_1_days => -1.0, :last_10_days => -1.0, :last_5_days => -1.0
83
+ }
84
+ },
85
+ :promotion_abuse => {
86
+ :score => 0.05731508921450917,
87
+ :percentiles => {
88
+ :last_7_days => -1.0, :last_1_days => -1.0, :last_10_days => -1.0, :last_5_days => -1.0
89
+ }
90
+ }
91
+ },
92
+ :status => 0,
93
+ :error_message => 'OK'
94
+ }
95
+ end
96
+
97
+ it "Successfully submits a v205 event with SCORE_PERCENTILES" do
98
+ response_json =
99
+ { :status => 0, :error_message => "OK", :score_response => percentile_response_json}
100
+ stub_request(:post, "https://api.siftscience.com/v205/events?fields=SCORE_PERCENTILES&return_score=true").
101
+ with { | request|
102
+ parsed_body = JSON.parse(request.body)
103
+ expect(parsed_body).to include("$api_key" => "overridden")
104
+ }.to_return(:status => 200, :body => MultiJson.dump(response_json), :headers => {})
105
+
106
+ api_key = "foobar"
107
+ event = "$transaction"
108
+ properties = valid_transaction_properties
109
+
110
+ response = Sift::Client.new(:api_key => api_key, :version => "205")
111
+ .track(event, properties, :api_key => "overridden", :include_score_percentiles => "true", :return_score => "true")
112
+ expect(response.ok?).to eq(true)
113
+ expect(response.api_status).to eq(0)
114
+ expect(response.api_error_message).to eq("OK")
115
+ expect(response.body["score_response"]["scores"]["account_abuse"]["percentiles"]["last_7_days"]).to eq(-1.0)
116
+ end
117
+ end
@@ -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
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sift
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0
4
+ version: 4.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Sadaghiani
8
8
  - Yoav Schatzberg
9
9
  - Jacob Burnim
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-07-11 00:00:00.000000000 Z
13
+ date: 2023-07-07 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -124,6 +124,7 @@ extensions: []
124
124
  extra_rdoc_files: []
125
125
  files:
126
126
  - ".circleci/config.yml"
127
+ - ".github/pull_request_template.md"
127
128
  - ".gitignore"
128
129
  - Gemfile
129
130
  - HISTORY
@@ -131,6 +132,7 @@ files:
131
132
  - README.md
132
133
  - Rakefile
133
134
  - examples/simple.rb
135
+ - examples/validation_apis.rb
134
136
  - lib/sift.rb
135
137
  - lib/sift/client.rb
136
138
  - lib/sift/client/decision.rb
@@ -148,15 +150,17 @@ files:
148
150
  - spec/unit/client/decision/apply_to_spec.rb
149
151
  - spec/unit/client/decision_spec.rb
150
152
  - spec/unit/client_203_spec.rb
153
+ - spec/unit/client_205_spec.rb
151
154
  - spec/unit/client_label_spec.rb
152
155
  - spec/unit/client_spec.rb
156
+ - spec/unit/client_validationapi_spec.rb
153
157
  - spec/unit/router_spec.rb
154
158
  - spec/unit/validate/decision_spec.rb
155
159
  - spec/unit/validate/primitive_spec.rb
156
160
  homepage: http://siftscience.com
157
161
  licenses: []
158
162
  metadata: {}
159
- post_install_message:
163
+ post_install_message:
160
164
  rdoc_options: []
161
165
  require_paths:
162
166
  - lib
@@ -171,8 +175,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
175
  - !ruby/object:Gem::Version
172
176
  version: '0'
173
177
  requirements: []
174
- rubygems_version: 3.1.4
175
- signing_key:
178
+ rubygems_version: 3.0.3.1
179
+ signing_key:
176
180
  specification_version: 4
177
181
  summary: Sift Science Ruby API Gem
178
182
  test_files:
@@ -182,8 +186,10 @@ test_files:
182
186
  - spec/unit/client/decision/apply_to_spec.rb
183
187
  - spec/unit/client/decision_spec.rb
184
188
  - spec/unit/client_203_spec.rb
189
+ - spec/unit/client_205_spec.rb
185
190
  - spec/unit/client_label_spec.rb
186
191
  - spec/unit/client_spec.rb
192
+ - spec/unit/client_validationapi_spec.rb
187
193
  - spec/unit/router_spec.rb
188
194
  - spec/unit/validate/decision_spec.rb
189
195
  - spec/unit/validate/primitive_spec.rb