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 +4 -4
- data/.circleci/config.yml +17 -0
- data/.jenkins/Jenkinsfile +103 -0
- data/HISTORY +3 -0
- data/README.md +33 -2
- data/lib/sift/client.rb +10 -2
- data/lib/sift/version.rb +1 -1
- data/spec/unit/client_spec.rb +30 -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 +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71be696ff04ffb1503d22a724241e5087809d2ffa2ab29f08666939ecd6bb98b
|
4
|
+
data.tar.gz: e2e841d8259fbea8c247b1b2bd3cdf208bd53ded613a765a75f595714a2e1e8d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
data/README.md
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# sift-ruby
|
2
|
-
[](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
|
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
|
-
|
239
|
-
|
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
data/spec/unit/client_spec.rb
CHANGED
@@ -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
|