sift 2.2.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HISTORY +6 -0
- data/README.md +15 -2
- data/lib/sift.rb +5 -0
- data/lib/sift/client.rb +43 -2
- data/lib/sift/client/decision/apply_to.rb +7 -0
- data/lib/sift/validate/decision.rb +6 -0
- data/lib/sift/version.rb +2 -2
- data/spec/unit/client_label_spec.rb +2 -2
- data/spec/unit/client_spec.rb +22 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cbaf2000cc0d9083f104b38c5e04ca271cc2cd9c
|
4
|
+
data.tar.gz: c90f468af4bdfdf91a04b22faaa0ec7eb637fd29
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb51191b838c93928607ef420f8ffd5588bf1de49f3e2f5e6ade15b9ce3e9d4a8d4b043b62605716cd452f261f4d39a48aacc33938d8a97c0c41a18ebc243482
|
7
|
+
data.tar.gz: 57fcde0d67394bacc175815dc12c60edf25782f75baad7174acc8bcded6d1d63a277aad4df2c1d7bceab2bcadbb7f520c772cad3c7be5c57c267dcff049ca059
|
data/HISTORY
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
=== 3.0.0.0 2018-03-05
|
2
|
+
* adds support for v205 of Sift Science's APIs
|
3
|
+
* v205 APIs are now called by default -- this is an incompatible change
|
4
|
+
(use :version => 204 to call the previous API version)
|
5
|
+
* Add content level decisions in Apply Decisions APIs.
|
6
|
+
|
1
7
|
=== 2.2.1.0 2018-02-12
|
2
8
|
* Add session level decisions in Apply Decisions APIs.
|
3
9
|
|
data/README.md
CHANGED
@@ -140,7 +140,7 @@ response = client.apply_decision({
|
|
140
140
|
user_id: "john@example.com"
|
141
141
|
})
|
142
142
|
|
143
|
-
# apply decision to "
|
143
|
+
# apply decision to "john@example.com"'s order
|
144
144
|
response = client.apply_decision({
|
145
145
|
decision_id: "block_bad_order",
|
146
146
|
source: "manual_review",
|
@@ -149,7 +149,7 @@ response = client.apply_decision({
|
|
149
149
|
order_id: "ORDER_1234"
|
150
150
|
})
|
151
151
|
|
152
|
-
# apply decision to "
|
152
|
+
# apply decision to "john@example.com"'s session
|
153
153
|
response = client.apply_decision({
|
154
154
|
decision_id: "block_bad_session",
|
155
155
|
source: "manual_review",
|
@@ -158,6 +158,16 @@ response = client.apply_decision({
|
|
158
158
|
session_id: "SESSION_ID_1234"
|
159
159
|
})
|
160
160
|
|
161
|
+
# apply decision to "john@example.com"'s content
|
162
|
+
response = client.apply_decision({
|
163
|
+
decision_id: "block_bad_session",
|
164
|
+
source: "manual_review",
|
165
|
+
analyst: "bob@your_company.com",
|
166
|
+
user_id: "john@example.com",
|
167
|
+
content_id: "CONTENT_ID_1234"
|
168
|
+
})
|
169
|
+
|
170
|
+
|
161
171
|
# Make sure you handle the response after applying a decision:
|
162
172
|
|
163
173
|
if response.ok?
|
@@ -196,6 +206,9 @@ response = client.get_user_decisions('example_user_id')
|
|
196
206
|
|
197
207
|
# Get the latest decisions for an order
|
198
208
|
response = client.get_order_decisions('example_order_id')
|
209
|
+
|
210
|
+
# Get the latest decisions for an content
|
211
|
+
response = client.get_content_decisions('example_user_id', 'example_order_id')
|
199
212
|
```
|
200
213
|
|
201
214
|
## Response Object
|
data/lib/sift.rb
CHANGED
@@ -33,6 +33,11 @@ module Sift
|
|
33
33
|
"/v3/accounts/#{account_id}/orders/#{order_id}/decisions"
|
34
34
|
end
|
35
35
|
|
36
|
+
# Returns the path for Content Decisions API
|
37
|
+
def self.content_decisions_api_path(account_id, user_id, content_id)
|
38
|
+
"/v3/accounts/#{account_id}/users/#{user_id}/content/#{content_id}/decisions"
|
39
|
+
end
|
40
|
+
|
36
41
|
# Module-scoped public API key
|
37
42
|
class << self
|
38
43
|
attr_accessor :api_key
|
data/lib/sift/client.rb
CHANGED
@@ -118,7 +118,7 @@ module Sift
|
|
118
118
|
#
|
119
119
|
# :version::
|
120
120
|
# The version of the Events API, Score API, and Labels API to call.
|
121
|
-
# By default, version
|
121
|
+
# By default, version 205.
|
122
122
|
#
|
123
123
|
# :path::
|
124
124
|
# The URL path to use for Events API path. By default, the
|
@@ -132,7 +132,7 @@ module Sift
|
|
132
132
|
@timeout = opts[:timeout] || 2 # 2-second timeout by default
|
133
133
|
@path = opts[:path] || Sift.rest_api_path(@version)
|
134
134
|
|
135
|
-
raise("api_key
|
135
|
+
raise("api_key") if !@api_key.is_a?(String) || @api_key.empty?
|
136
136
|
raise("path must be a non-empty string") if !@path.is_a?(String) || @path.empty?
|
137
137
|
end
|
138
138
|
|
@@ -504,6 +504,47 @@ module Sift
|
|
504
504
|
Response.new(response.body, response.code, response.response)
|
505
505
|
end
|
506
506
|
|
507
|
+
|
508
|
+
# Gets the decision status of a piece of content.
|
509
|
+
#
|
510
|
+
# See https://siftscience.com/developers/docs/ruby/decisions-api/decision-status .
|
511
|
+
#
|
512
|
+
# ==== Parameters
|
513
|
+
#
|
514
|
+
# user_id::
|
515
|
+
# The ID of the owner of the content.
|
516
|
+
#
|
517
|
+
# content_id::
|
518
|
+
# The ID of a piece of content.
|
519
|
+
#
|
520
|
+
# opts (optional)::
|
521
|
+
# A Hash of optional parameters for this request --
|
522
|
+
#
|
523
|
+
# :account_id::
|
524
|
+
# Overrides the API key for this call.
|
525
|
+
#
|
526
|
+
# :api_key::
|
527
|
+
# Overrides the API key for this call.
|
528
|
+
#
|
529
|
+
# :timeout::
|
530
|
+
# Overrides the timeout (in seconds) for this call.
|
531
|
+
#
|
532
|
+
def get_content_decisions(user_id, content_id, opts = {})
|
533
|
+
account_id = opts[:account_id] || @account_id
|
534
|
+
api_key = opts[:api_key] || @api_key
|
535
|
+
timeout = opts[:timeout] || @timeout
|
536
|
+
|
537
|
+
options = {
|
538
|
+
:headers => { "User-Agent" => user_agent },
|
539
|
+
:basic_auth => { :username => api_key, :password => "" }
|
540
|
+
}
|
541
|
+
options.merge!(:timeout => timeout) unless timeout.nil?
|
542
|
+
|
543
|
+
uri = API3_ENDPOINT + Sift.content_decisions_api_path(account_id, user_id, content_id)
|
544
|
+
response = self.class.get(uri, options)
|
545
|
+
Response.new(response.body, response.code, response.response)
|
546
|
+
end
|
547
|
+
|
507
548
|
def decisions(opts = {})
|
508
549
|
decision_instance.list(opts)
|
509
550
|
end
|
@@ -15,6 +15,7 @@ module Sift
|
|
15
15
|
description
|
16
16
|
order_id
|
17
17
|
session_id
|
18
|
+
content_id
|
18
19
|
user_id
|
19
20
|
account_id
|
20
21
|
time
|
@@ -93,11 +94,17 @@ module Sift
|
|
93
94
|
configs.has_key?("session_id") || configs.has_key?(:session_id)
|
94
95
|
end
|
95
96
|
|
97
|
+
def applying_to_content?
|
98
|
+
configs.has_key?("content_id") || configs.has_key?(:content_id)
|
99
|
+
end
|
100
|
+
|
96
101
|
def path
|
97
102
|
if applying_to_order?
|
98
103
|
"#{user_path}/orders/#{CGI.escape(order_id)}/decisions"
|
99
104
|
elsif applying_to_session?
|
100
105
|
"#{user_path}/sessions/#{CGI.escape(session_id)}/decisions"
|
106
|
+
elsif applying_to_content?
|
107
|
+
"#{user_path}/content/#{CGI.escape(content_id)}/decisions"
|
101
108
|
else
|
102
109
|
"#{user_path}/decisions"
|
103
110
|
end
|
data/lib/sift/version.rb
CHANGED
@@ -25,7 +25,7 @@ describe Sift::Client do
|
|
25
25
|
response_json = { :status => 0, :error_message => "OK" }
|
26
26
|
user_id = "frodo_baggins"
|
27
27
|
|
28
|
-
stub_request(:post, "https://api.siftscience.com/
|
28
|
+
stub_request(:post, "https://api.siftscience.com/v205/users/frodo_baggins/labels")
|
29
29
|
.with(:body => ('{"$abuse_type":"content_abuse","$is_bad":true,"$description":"Listed a fake item","$type":"$label","$api_key":"foobar"}'))
|
30
30
|
.to_return(:body => MultiJson.dump(response_json), :status => 200,
|
31
31
|
:headers => {"content-type"=>"application/json; charset=UTF-8",
|
@@ -45,7 +45,7 @@ describe Sift::Client do
|
|
45
45
|
user_id = "frodo_baggins"
|
46
46
|
|
47
47
|
stub_request(:delete,
|
48
|
-
"https://api.siftscience.com/
|
48
|
+
"https://api.siftscience.com/v205/users/frodo_baggins/labels?api_key=foobar&abuse_type=payment_abuse")
|
49
49
|
.to_return(:status => 204)
|
50
50
|
|
51
51
|
api_key = "foobar"
|
data/spec/unit/client_spec.rb
CHANGED
@@ -169,7 +169,7 @@ describe Sift::Client do
|
|
169
169
|
it "Successfuly handles an event and returns OK" do
|
170
170
|
response_json = { :status => 0, :error_message => "OK" }
|
171
171
|
|
172
|
-
stub_request(:post, "https://api.siftscience.com/
|
172
|
+
stub_request(:post, "https://api.siftscience.com/v205/events").
|
173
173
|
with { |request|
|
174
174
|
parsed_body = JSON.parse(request.body)
|
175
175
|
expect(parsed_body).to include("$buyer_user_id" => "123456")
|
@@ -190,7 +190,7 @@ describe Sift::Client do
|
|
190
190
|
|
191
191
|
it "Successfully submits event with overridden key" do
|
192
192
|
response_json = { :status => 0, :error_message => "OK"}
|
193
|
-
stub_request(:post, "https://api.siftscience.com/
|
193
|
+
stub_request(:post, "https://api.siftscience.com/v205/events").
|
194
194
|
with { | request|
|
195
195
|
parsed_body = JSON.parse(request.body)
|
196
196
|
expect(parsed_body).to include("$buyer_user_id" => "123456")
|
@@ -212,7 +212,7 @@ describe Sift::Client do
|
|
212
212
|
it "Successfully scrubs nils" do
|
213
213
|
response_json = { :status => 0, :error_message => "OK" }
|
214
214
|
|
215
|
-
stub_request(:post, "https://api.siftscience.com/
|
215
|
+
stub_request(:post, "https://api.siftscience.com/v205/events")
|
216
216
|
.with { |request|
|
217
217
|
parsed_body = JSON.parse(request.body)
|
218
218
|
expect(parsed_body).not_to include("fake_property")
|
@@ -241,7 +241,7 @@ describe Sift::Client do
|
|
241
241
|
api_key = "foobar"
|
242
242
|
response_json = score_response_json
|
243
243
|
|
244
|
-
stub_request(:get, "https://api.siftscience.com/
|
244
|
+
stub_request(:get, "https://api.siftscience.com/v205/score/247019/?api_key=foobar")
|
245
245
|
.to_return(:status => 200, :body => MultiJson.dump(response_json),
|
246
246
|
:headers => {"content-type"=>"application/json; charset=UTF-8",
|
247
247
|
"content-length"=> "74"})
|
@@ -259,7 +259,7 @@ describe Sift::Client do
|
|
259
259
|
api_key = "foobar"
|
260
260
|
response_json = score_response_json
|
261
261
|
|
262
|
-
stub_request(:get, "https://api.siftscience.com/
|
262
|
+
stub_request(:get, "https://api.siftscience.com/v205/score/247019/?api_key=overridden")
|
263
263
|
.to_return(:status => 200, :body => MultiJson.dump(response_json), :headers => {})
|
264
264
|
|
265
265
|
response = Sift::Client.new(:api_key => api_key)
|
@@ -280,7 +280,7 @@ describe Sift::Client do
|
|
280
280
|
:score_response => score_response_json
|
281
281
|
}
|
282
282
|
|
283
|
-
stub_request(:post, "https://api.siftscience.com/
|
283
|
+
stub_request(:post, "https://api.siftscience.com/v205/events?return_score=true")
|
284
284
|
.to_return(:status => 200, :body => MultiJson.dump(response_json),
|
285
285
|
:headers => {"content-type"=>"application/json; charset=UTF-8",
|
286
286
|
"content-length"=> "74"})
|
@@ -304,7 +304,7 @@ describe Sift::Client do
|
|
304
304
|
:score_response => action_response_json
|
305
305
|
}
|
306
306
|
|
307
|
-
stub_request(:post, "https://api.siftscience.com/
|
307
|
+
stub_request(:post, "https://api.siftscience.com/v205/events?return_action=true")
|
308
308
|
.to_return(:status => 200, :body => MultiJson.dump(response_json),
|
309
309
|
:headers => {"content-type"=>"application/json; charset=UTF-8",
|
310
310
|
"content-length"=> "74"})
|
@@ -332,7 +332,7 @@ describe Sift::Client do
|
|
332
332
|
}
|
333
333
|
|
334
334
|
stub_request(:post,
|
335
|
-
"https://api.siftscience.com/
|
335
|
+
"https://api.siftscience.com/v205/events?return_workflow_status=true&abuse_types=legacy,payment_abuse")
|
336
336
|
.to_return(:status => 200, :body => MultiJson.dump(response_json),
|
337
337
|
:headers => {"content-type"=>"application/json; charset=UTF-8",
|
338
338
|
"content-length"=> "74"})
|
@@ -390,4 +390,18 @@ describe Sift::Client do
|
|
390
390
|
expect(response.body["decisions"]["payment_abuse"]["decision"]["id"]).to eq("decision7")
|
391
391
|
end
|
392
392
|
|
393
|
+
|
394
|
+
it "Successfully make an content decisions request" do
|
395
|
+
response_text = '{"decisions":{"content_abuse":{"decision":{"id":"decision7"},"time":1468599638005,"webhook_succeeded":false}}}'
|
396
|
+
|
397
|
+
stub_request(:get, "https://foobar:@api3.siftscience.com/v3/accounts/ACCT/users/USER/content/example_content/decisions")
|
398
|
+
.to_return(:status => 200, :body => response_text, :headers => {})
|
399
|
+
|
400
|
+
client = Sift::Client.new(:api_key => "foobar", :account_id => "ACCT")
|
401
|
+
response = client.get_content_decisions("USER", "example_content", :timeout => 3)
|
402
|
+
|
403
|
+
expect(response.ok?).to eq(true)
|
404
|
+
expect(response.body["decisions"]["content_abuse"]["decision"]["id"]).to eq("decision7")
|
405
|
+
end
|
406
|
+
|
393
407
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sift
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fred Sadaghiani
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2018-
|
13
|
+
date: 2018-04-05 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|