sift 4.4.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ba7bb7dc985a6f320db6c39717c90e349a16306ec2b85f7a2ba28945c5e2f64
4
- data.tar.gz: 8665633d78bb4c9502443f241943d4fb98015ede3060d233913169f5921d528b
3
+ metadata.gz: 71be696ff04ffb1503d22a724241e5087809d2ffa2ab29f08666939ecd6bb98b
4
+ data.tar.gz: e2e841d8259fbea8c247b1b2bd3cdf208bd53ded613a765a75f595714a2e1e8d
5
5
  SHA512:
6
- metadata.gz: 75ce0e5c6631fbd4aa22ad72cb2ad9cebc0cf5ee0ec7e7de1dc308d9d90d3c1ef288a75a699ac0ef04ae650700a4a7b63ad1ece30d1386da0c06ceefcea10420
7
- data.tar.gz: 3804c62aaf0795bfce7eadc4d048ae36d3a67a0d1dd9c81548d31926f950a5908a4fb158a8363182bb14ebb77545d3c671b37292802c093ea31719176683bb26
6
+ metadata.gz: 9b578f6bccf6323d4ef53947cea5a517678920d882439da1d1df262cf5eb39e45064aab3a1dee702da01f41f29a522df0c5e7b850c68e1ac302fa0f7d9830e29
7
+ data.tar.gz: 3c4565ffc5f98626ac67a07b378adfd80aaef787e47ffc50d84780da4b62788bdfb43e1b2e4ed90ca59cb4ee0fe23ec727dad8d1c0dd9413c137d7ec1de95510
data/.circleci/config.yml CHANGED
@@ -81,8 +81,25 @@ jobs:
81
81
  - slack/notify:
82
82
  <<: *slack_notify
83
83
 
84
+ run_integration_tests:
85
+ docker:
86
+ - image: circleci/ruby:2.4.2-jessie-node
87
+ steps:
88
+ - checkout
89
+ - run:
90
+ name: Install bundle and run the tests
91
+ command: |
92
+ bundle check || bundle install
93
+ bundle exec ruby test_integration_app/main.rb
94
+
84
95
  workflows:
85
96
  ruby-test:
86
97
  jobs:
87
98
  - build:
88
99
  context: *context
100
+ ruby-integration-tests:
101
+ jobs:
102
+ - run_integration_tests:
103
+ filters:
104
+ branches:
105
+ only: master
@@ -0,0 +1,103 @@
1
+ // Load Jenkins shared library
2
+ jenkinsBranch = 'v0.37.0'
3
+ sharedLib = library("shared-lib@${jenkinsBranch}")
4
+
5
+ def siftRubyWorkflow = sharedLib.com.sift.ci.SiftRubyWorkflow.new()
6
+ def ciUtil = sharedLib.com.sift.ci.CIUtil.new()
7
+ def stackdriver = sharedLib.com.sift.ci.StackDriverMetrics.new()
8
+
9
+ // Default GitHub status context for automatically triggered builds
10
+ def defaultStatusContext = 'Jenkins:auto'
11
+
12
+ // Pod template file for Jenkins agent pod
13
+ // Pod template yaml file is defined in https://github.com/SiftScience/jenkins/tree/master/resources/jenkins-k8s-pod-templates
14
+ def ruby2PodTemplateFile = 'ruby-2-4-2-pod-template.yaml'
15
+ def ruby2PodLabel = "ruby2-${BUILD_TAG}"
16
+
17
+
18
+ // GitHub repo name
19
+ def repoName = 'sift-ruby'
20
+
21
+ pipeline {
22
+ agent none
23
+ options {
24
+ timestamps()
25
+ skipDefaultCheckout()
26
+ disableConcurrentBuilds()
27
+ disableRestartFromStage()
28
+ parallelsAlwaysFailFast()
29
+ buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '30', numToKeepStr: '')
30
+ timeout(time: 1, unit: 'HOURS')
31
+ }
32
+ environment {
33
+ GIT_BRANCH = "${env.CHANGE_BRANCH != null? env.CHANGE_BRANCH : env.BRANCH_NAME}"
34
+ }
35
+ stages {
36
+ stage('Initialize') {
37
+ steps {
38
+ script {
39
+ statusContext = defaultStatusContext
40
+ // Get the commit sha for the build
41
+ commitSha = ciUtil.commitHashForBuild()
42
+ ciUtil.updateGithubCommitStatus(repoName, statusContext, 'Started', 'pending', commitSha)
43
+ }
44
+ }
45
+ }
46
+ stage ('Build and Test Workflows') {
47
+ steps {
48
+ script {
49
+ def workflows = [:]
50
+ def stage1 = 'Run Integration Tests - ruby'
51
+ workflows[stage1] = {
52
+ stage(stage1) {
53
+ if (env.GIT_BRANCH.equals('master')) {
54
+ ciUtil.updateGithubCommitStatus(repoName, stage1, 'Started', 'pending', commitSha)
55
+ try {
56
+ siftRubyWorkflow.runSiftRubyIntegration(ruby2PodTemplateFile, ruby2PodLabel)
57
+ ciUtil.updateGithubCommitStatus(repoName, stage1, 'SUCCESS', 'success', commitSha)
58
+ } catch (Exception e) {
59
+ ciUtil.updateGithubCommitStatus(repoName, stage1, 'FAILURE', 'failure', commitSha)
60
+ print("${stage1} failed")
61
+ throw e
62
+ }
63
+ }
64
+ }
65
+ }
66
+ def stage2 = 'Test - ruby'
67
+ workflows[stage2] = {
68
+ stage(stage2) {
69
+ ciUtil.updateGithubCommitStatus(repoName, stage2, 'Started', 'pending', commitSha)
70
+ try {
71
+ siftRubyWorkflow.runSiftRubyTest(ruby2PodTemplateFile, ruby2PodLabel)
72
+ ciUtil.updateGithubCommitStatus(repoName, stage2, 'SUCCESS', 'success', commitSha)
73
+ } catch (Exception e) {
74
+ ciUtil.updateGithubCommitStatus(repoName, stage2, 'FAILURE', 'failure', commitSha)
75
+ print("${stage2} failed")
76
+ throw e
77
+ }
78
+ }
79
+ }
80
+ parallel workflows
81
+ }
82
+ }
83
+ }
84
+ }
85
+ post {
86
+ success {
87
+ script {
88
+ ciUtil.updateGithubCommitStatus(repoName, statusContext, currentBuild.currentResult, 'success', commitSha)
89
+ }
90
+ }
91
+ unsuccessful {
92
+ script {
93
+ ciUtil.updateGithubCommitStatus(repoName, statusContext, currentBuild.currentResult, 'failure', commitSha)
94
+ ciUtil.notifySlack(repoName, commitSha)
95
+ }
96
+ }
97
+ always {
98
+ script {
99
+ stackdriver.updatePipelineStatistics(this)
100
+ }
101
+ }
102
+ }
103
+ }
data/HISTORY CHANGED
@@ -1,3 +1,6 @@
1
+ === 4.5.0 2024-05-16
2
+ - Support for warnings in Events API
3
+
1
4
  === 4.4.0 2023-10-05
2
5
  - Score percentiles in Score API
3
6
 
data/README.md CHANGED
@@ -1,5 +1,4 @@
1
1
  # sift-ruby
2
- [![CircleCI](https://circleci.com/gh/SiftScience/sift-ruby.svg?style=svg)](https://circleci.com/gh/SiftScience/sift-ruby)
3
2
 
4
3
  The official Ruby bindings for the latest version (v205) of the [Sift API](https://sift.com/developers/docs/java/apis-overview).
5
4
 
@@ -39,8 +38,22 @@ client = Sift::Client.new(api_key: '<your_api_key_here>', account_id: '<your_acc
39
38
 
40
39
  ```
41
40
 
42
- ### Sending a transaction event
41
+ ### Sending an event
42
+ Send event to Sift.
43
+ To learn more about the Events API visit our [developer docs](https://developers.sift.com/docs/ruby/events-api/overview).
43
44
 
45
+
46
+ **Optional Params**
47
+ - `return_score`: `:true` or `:false`
48
+ - `return_action`: `:true` or `:false`
49
+ - `return_workflow_status`: `:true` or `:false`
50
+ - `return_route_info`: `:true` or `:false`
51
+ - `force_workflow_run`: `:true` or `:false`
52
+ - `include_score_percentiles`: `:true` or `:false`
53
+ - `warnings`: `:true` or `:false`
54
+ - `abuse_types`: `["payment_abuse", "content_abuse", "content_abuse", "account_abuse", "legacy", "account_takeover"]`
55
+
56
+ **Example:**
44
57
  ```ruby
45
58
  event = "$transaction"
46
59
 
@@ -318,3 +331,21 @@ To run the various tests use the rake command as follows:
318
331
  ```ruby
319
332
  $ rake spec
320
333
  ```
334
+
335
+ ## Integration testing app
336
+
337
+ For testing the app with real calls it is possible to run the integration testing app,
338
+ it makes calls to almost all our public endpoints to make sure the library integrates
339
+ well. At the moment, the app is run on every merge to master
340
+
341
+ #### How to run it locally
342
+
343
+ 1. Add env variable `ACCOUNT_ID` with the valid account id
344
+ 2. Add env variable `API_KEY` with the valid Api Key associated from the account
345
+ 3. Run the following under the project root folder
346
+ ```
347
+ # Install the budle locally
348
+ bundle check || bundle install
349
+ # Run the app
350
+ bundle exec ruby test_integration_app/main.rb
351
+ ```
data/lib/sift/client.rb CHANGED
@@ -205,6 +205,9 @@ module Sift
205
205
  # :include_score_percentiles::
206
206
  # include_score_percentiles(optional) : Whether to add new parameter in the query parameter.
207
207
  #
208
+ # :warnings::
209
+ # warnings(optional) : Whether to add list of warnings (if any) to response.
210
+ #
208
211
  # ==== Returns:
209
212
  #
210
213
  # In the case of a network error (timeout, broken connection, etc.),
@@ -223,6 +226,7 @@ module Sift
223
226
  force_workflow_run = opts[:force_workflow_run]
224
227
  abuse_types = opts[:abuse_types]
225
228
  include_score_percentiles = opts[:include_score_percentiles]
229
+ warnings = opts[:warnings]
226
230
 
227
231
  raise("event must be a non-empty string") if (!event.is_a? String) || event.empty?
228
232
  raise("properties cannot be empty") if properties.empty?
@@ -235,8 +239,12 @@ module Sift
235
239
  query["return_route_info"] = "true" if return_route_info
236
240
  query["force_workflow_run"] = "true" if force_workflow_run
237
241
  query["abuse_types"] = abuse_types.join(",") if abuse_types
238
- if include_score_percentiles == "true"
239
- query["fields"] = "SCORE_PERCENTILES"
242
+
243
+ if include_score_percentiles == "true" || warnings == "true"
244
+ fields = []
245
+ fields << "SCORE_PERCENTILES" if include_score_percentiles == "true"
246
+ fields << "WARNINGS" if warnings == "true"
247
+ query["fields"] = fields.join(",")
240
248
  end
241
249
 
242
250
  options = {
data/lib/sift/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Sift
2
- VERSION = "4.4.0"
2
+ VERSION = "4.5.0"
3
3
  API_VERSION = "205"
4
4
  end
@@ -110,6 +110,15 @@ describe Sift::Client do
110
110
  }
111
111
  end
112
112
 
113
+ def warnings
114
+ {
115
+ :count => 1,
116
+ :items => [{
117
+ :message => 'Invalid currency'
118
+ }]
119
+ }
120
+ end
121
+
113
122
  def percentile_response_json
114
123
  {
115
124
  :user_id => 'billy_jones_301',
@@ -689,4 +698,25 @@ describe Sift::Client do
689
698
  expect(response.body["scores"]["payment_abuse"]["score"]).to eq(0.78)
690
699
  end
691
700
 
701
+ it "Successfully submits a v205 event with WARNINGS" do
702
+ response_json =
703
+ { :status => 0, :error_message => "OK", :warnings => warnings}
704
+ stub_request(:post, "https://api.siftscience.com/v205/events?fields=WARNINGS").
705
+ with { | request|
706
+ parsed_body = JSON.parse(request.body)
707
+ expect(parsed_body).to include("$api_key" => "overridden")
708
+ }.to_return(:status => 200, :body => MultiJson.dump(response_json), :headers => {})
709
+
710
+ api_key = "foobar"
711
+ event = "$transaction"
712
+ properties = valid_transaction_properties
713
+
714
+ response = Sift::Client.new(:api_key => api_key, :version => "205")
715
+ .track(event, properties, :api_key => "overridden",:warnings => "true")
716
+ expect(response.ok?).to eq(true)
717
+ expect(response.api_status).to eq(0)
718
+ expect(response.api_error_message).to eq("OK")
719
+ expect(response.body["warnings"]["count"]).to eq(1)
720
+ expect(response.body["warnings"]["items"][0]["message"]).to eq("Invalid currency")
721
+ end
692
722
  end
@@ -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