sift 1.1.0 → 4.0.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 +7 -0
- data/.circleci/config.yml +43 -0
- data/HISTORY +88 -0
- data/LICENSE +19 -0
- data/README.md +253 -0
- data/lib/sift/client/decision/apply_to.rb +129 -0
- data/lib/sift/client/decision.rb +66 -0
- data/lib/sift/client.rb +672 -88
- data/lib/sift/error.rb +13 -0
- data/lib/sift/router.rb +41 -0
- data/lib/sift/utils/hash_getter.rb +15 -0
- data/lib/sift/validate/decision.rb +65 -0
- data/lib/sift/validate/primitive.rb +43 -0
- data/lib/sift/version.rb +2 -1
- data/lib/sift.rb +61 -9
- data/sift.gemspec +8 -7
- data/spec/fixtures/fake_responses.rb +16 -0
- data/spec/spec_helper.rb +3 -3
- data/spec/unit/client/decision/apply_to_spec.rb +262 -0
- data/spec/unit/client/decision_spec.rb +83 -0
- data/spec/unit/client_203_spec.rb +193 -0
- data/spec/unit/client_label_spec.rb +68 -12
- data/spec/unit/client_spec.rb +484 -48
- data/spec/unit/router_spec.rb +37 -0
- data/spec/unit/validate/decision_spec.rb +85 -0
- data/spec/unit/validate/primitive_spec.rb +73 -0
- metadata +83 -54
- data/README.rdoc +0 -40
- data/spec/unit/sift_spec.rb +0 -6
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 57a679adbe12a556895633060cde177cf89fcb06
|
4
|
+
data.tar.gz: d3eff77b83c2ba5696c4c391f82d592a8df7443a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5809b998556c975ff30faceacf5468a812e815dead3e836640343fe681c1d612192a9a26615f8a0c35c4c13a3cb9b232f3aff1bbf7649d6b3e6c8250cd7f2896
|
7
|
+
data.tar.gz: 8b941c79e41784d1452f8ae4fe8b1052f7f32ed3954f8afb16b16f3e7346a0bf6e5cfc71f6080c6475ff75a0fce78172a58e4f8ece8f73ab47385ffd57d3001a
|
@@ -0,0 +1,43 @@
|
|
1
|
+
version: 2
|
2
|
+
|
3
|
+
jobs:
|
4
|
+
build:
|
5
|
+
parallelism: 3 # run three instances of this job in parallel
|
6
|
+
docker:
|
7
|
+
- image: circleci/ruby:2.4.2-jessie-node
|
8
|
+
environment:
|
9
|
+
BUNDLE_JOBS: 3
|
10
|
+
BUNDLE_RETRY: 3
|
11
|
+
BUNDLE_PATH: vendor/bundle
|
12
|
+
steps:
|
13
|
+
- checkout
|
14
|
+
|
15
|
+
- run:
|
16
|
+
name: Which bundler?
|
17
|
+
command: bundle -v
|
18
|
+
|
19
|
+
- restore_cache:
|
20
|
+
keys:
|
21
|
+
- sift-bundle-{{ checksum "sift.gemspec" }}
|
22
|
+
- sift-bundle-
|
23
|
+
|
24
|
+
- run:
|
25
|
+
name: Bundle Install
|
26
|
+
command: bundle check || bundle install
|
27
|
+
|
28
|
+
- save_cache:
|
29
|
+
key: sift-bundle-{{ checksum "sift.gemspec" }}
|
30
|
+
paths:
|
31
|
+
- vendor/bundle
|
32
|
+
|
33
|
+
- run:
|
34
|
+
name: Run rspec in parallel
|
35
|
+
command: |
|
36
|
+
bundle exec rspec --profile 10 \
|
37
|
+
--format RspecJunitFormatter \
|
38
|
+
--out test_results/rspec.xml \
|
39
|
+
--format progress \
|
40
|
+
$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)
|
41
|
+
|
42
|
+
- store_test_results:
|
43
|
+
path: test_results
|
data/HISTORY
CHANGED
@@ -1,3 +1,91 @@
|
|
1
|
+
=== 4.0.0 2019-05-15
|
2
|
+
- Breaking change: Propagate exception in Client.track() – previously we were silently swallowing exceptions and now we are bubbling them up. You will need to add exception handling code.
|
3
|
+
- Fix URL encoding
|
4
|
+
- Add Circle build
|
5
|
+
|
6
|
+
=== 3.3.0 2018-07-31
|
7
|
+
- Add support for rescore_user and get_user_score APIs
|
8
|
+
|
9
|
+
=== 3.2.0 2018-07-05
|
10
|
+
- Add new query parameter force_workflow_run
|
11
|
+
|
12
|
+
=== 3.1.0 2018-06-04
|
13
|
+
- Adds support for get session decisions to [Decisions API](https://siftscience.com/developers/docs/curl/decisions-api)
|
14
|
+
|
15
|
+
=== 3.0.1 2018-04-06
|
16
|
+
- Improved documentation on HISTORY and README.MD
|
17
|
+
|
18
|
+
=== 3.0.0 2018-03-05
|
19
|
+
- Adds support for Sift Science API Version 205, including new [`$create_content`](https://siftscience.com/developers/docs/curl/events-api/reserved-events/create-content) and [`$update_content`](https://siftscience.com/developers/docs/curl/events-api/reserved-events/update-content) formats
|
20
|
+
- V205 APIs are now called -- **this is an incompatible change**
|
21
|
+
- (use `:version => 204` to call the previous API version)
|
22
|
+
- Adds support for content decisions to [Decisions API](https://siftscience.com/developers/docs/curl/decisions-api)
|
23
|
+
|
24
|
+
INCOMPATIBLE CHANGES INTRODUCED IN API V205:
|
25
|
+
- `$create_content` and `$update_content` have significantly changed, and the old format will be rejected
|
26
|
+
- `$send_message` and `$submit_review` events are no longer valid
|
27
|
+
- V205 improves server-side event data validation. In V204 and earlier, server-side validation accepted some events that did not conform to the published APIs in our [developer documentation](https://siftscience.com/developers/docs/curl/events-api). V205 does not modify existing event APIs other than those mentioned above, but may reject invalid event data that were previously accepted. **Please test your integration on V205 in sandbox before using in production.**
|
28
|
+
|
29
|
+
=== 2.2.1.0 2018-02-12
|
30
|
+
* Add session level decisions in Apply Decisions APIs.
|
31
|
+
|
32
|
+
=== 2.0.0.0 2016-07-19
|
33
|
+
* adds support for v204 of Sift Science's APIs
|
34
|
+
* adds Workflow Status API, User Decisions API, Order Decisions API
|
35
|
+
* v204 APIs are now called by default -- this is an incompatible change
|
36
|
+
(use :version => 203 to call the previous API version)
|
37
|
+
* uses Hash arg for optional params in Client methods -- incompatible change
|
38
|
+
|
39
|
+
=== 1.1.7.2 2015-04-13
|
40
|
+
* Fixed backwards compatibility issue
|
41
|
+
|
42
|
+
=== 1.1.7.0 2015-02-24
|
43
|
+
* Added Unlabel functionality
|
44
|
+
|
45
|
+
=== 1.1.6.2 2014-09-19
|
46
|
+
* added API key parameter to track and label functions
|
47
|
+
|
48
|
+
=== 1.1.6.0 2014-09-03
|
49
|
+
* added module scoped API key variable
|
50
|
+
|
51
|
+
=== 1.1.4 2014-01-02
|
52
|
+
* removed support for ruby 1.9.2
|
53
|
+
* track/label return nil on failure
|
54
|
+
|
55
|
+
=== 1.1.3 2013-12-10
|
56
|
+
* nil values are removed from JSON body sent to track/label now.
|
57
|
+
* relaxed multi_json requirement to 1.0 or newer
|
58
|
+
* relaxed httparty requirement to 0.11.0 or newer
|
59
|
+
* migrated from fakeweb to webmock 1.16.0 or newer
|
60
|
+
|
61
|
+
=== 1.1.1 2013-11-14
|
62
|
+
* score request now requires API key
|
63
|
+
|
64
|
+
=== 1.1.0 2013-11-08
|
65
|
+
* now uses v203 API endpoint by default
|
66
|
+
|
67
|
+
=== 1.0.13 2014-10-22
|
68
|
+
* added path parameter to track function
|
69
|
+
* added label function for applying labels
|
70
|
+
* now requires httparty 0.12.0 or newer
|
71
|
+
* now requires multi_json 1.8.2 or newer
|
72
|
+
* now requires rspec 2.14.1 or newer for compilation only
|
73
|
+
|
74
|
+
=== 1.0.12 2013-06-13
|
75
|
+
* added score function for getting user scores.
|
76
|
+
* now requires httparty 0.10.0 or newer
|
77
|
+
* added rspec 2.0 or newer and rake dependency
|
78
|
+
|
79
|
+
=== 1.0.10 2013-01-09
|
80
|
+
* Add configurable path variable to Client
|
81
|
+
|
82
|
+
=== 1.0.5 2012-07-20
|
83
|
+
|
84
|
+
=== 1.0.3 2012-05-05
|
85
|
+
|
86
|
+
=== 1.0.2 2012-05-03
|
87
|
+
|
88
|
+
=== 1.0.1 2012-05-02
|
1
89
|
|
2
90
|
=== 1.0 2012-05-02
|
3
91
|
* Initial release
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2013 Sift Science
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,253 @@
|
|
1
|
+
# Sift Ruby bindings
|
2
|
+
|
3
|
+
[](https://circleci.com/gh/SiftScience/sift-ruby)
|
4
|
+
|
5
|
+
## Requirements
|
6
|
+
|
7
|
+
* Ruby 2.0.0 or above.
|
8
|
+
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
If you want to build the gem from source:
|
13
|
+
|
14
|
+
```
|
15
|
+
$ gem build sift.gemspec
|
16
|
+
```
|
17
|
+
|
18
|
+
Alternatively, you can install the gem from rubygems.org:
|
19
|
+
|
20
|
+
```
|
21
|
+
gem install sift
|
22
|
+
```
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
### Creating a Client:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
require "sift"
|
30
|
+
|
31
|
+
Sift.api_key = '<your_api_key_here>'
|
32
|
+
Sift.account_id = '<your_account_id_here>'
|
33
|
+
client = Sift::Client.new()
|
34
|
+
|
35
|
+
##### OR
|
36
|
+
|
37
|
+
client = Sift::Client.new(api_key: '<your_api_key_here>', account_id: '<your_account_id_here>')
|
38
|
+
|
39
|
+
```
|
40
|
+
|
41
|
+
### Sending a transaction event
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
event = "$transaction"
|
45
|
+
|
46
|
+
user_id = "23056" # User ID's may only contain a-z, A-Z, 0-9, =, ., -, _, +, @, :, &, ^, %, !, $
|
47
|
+
|
48
|
+
properties = {
|
49
|
+
"$user_id" => user_id,
|
50
|
+
"$user_email" => "buyer@gmail.com",
|
51
|
+
"$seller_user_id" => "2371",
|
52
|
+
"seller_user_email" => "seller@gmail.com",
|
53
|
+
"$transaction_id" => "573050",
|
54
|
+
"$payment_method" => {
|
55
|
+
"$payment_type" => "$credit_card",
|
56
|
+
"$payment_gateway" => "$braintree",
|
57
|
+
"$card_bin" => "542486",
|
58
|
+
"$card_last4" => "4444"
|
59
|
+
},
|
60
|
+
"$currency_code" => "USD",
|
61
|
+
"$amount" => 15230000,
|
62
|
+
}
|
63
|
+
|
64
|
+
response = client.track(event, properties)
|
65
|
+
|
66
|
+
response.ok? # returns true or false
|
67
|
+
response.body # API response body
|
68
|
+
response.http_status_code # HTTP response code, 200 is ok.
|
69
|
+
response.api_status # status field in the return body, Link to Error Codes
|
70
|
+
response.api_error_message # Error message associated with status Error Code
|
71
|
+
|
72
|
+
# Request a score for the user with user_id 23056
|
73
|
+
response = client.score(user_id)
|
74
|
+
```
|
75
|
+
|
76
|
+
## Decisions
|
77
|
+
|
78
|
+
To learn more about the decisions endpoint visit our [developer docs](https://sift.com/developers/docs/ruby/decisions-api/get-decisions).
|
79
|
+
|
80
|
+
### List of Configured Decisions
|
81
|
+
|
82
|
+
Get a list of your decisions.
|
83
|
+
|
84
|
+
**Optional Params**
|
85
|
+
- `entity_type`: `:user` or `:order` or `:session` or `:content`
|
86
|
+
- `abuse_types`: `["payment_abuse", "content_abuse", "content_abuse",
|
87
|
+
"account_abuse", "legacy", "account_takeover"]`
|
88
|
+
|
89
|
+
**Returns**
|
90
|
+
|
91
|
+
A `Response` object
|
92
|
+
|
93
|
+
**Example:**
|
94
|
+
```ruby
|
95
|
+
# fetch a list of all your decisions
|
96
|
+
response = client.decisions({
|
97
|
+
entity_type: :user,
|
98
|
+
abuse_types: ["payment_abuse", "content_abuse"]
|
99
|
+
})
|
100
|
+
|
101
|
+
# Check that response is okay.
|
102
|
+
unless response.ok?
|
103
|
+
raise "Unable to fetch decisions #{response.api_error_message} " +
|
104
|
+
"#{response.api_error_description}"
|
105
|
+
end
|
106
|
+
|
107
|
+
# find a decisions with the id "block_bad_user"
|
108
|
+
user_decision = response.body["data"].find do |decision|
|
109
|
+
decision["id"] == "block_bad_user"
|
110
|
+
end
|
111
|
+
|
112
|
+
# Get the next page
|
113
|
+
|
114
|
+
if response.body["has_more"]
|
115
|
+
client.decisions(response.body)
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
|
120
|
+
### Apply a decision
|
121
|
+
|
122
|
+
Applies a decision to an entity. Visit our [developer docs](http://sift.com/developers/docs/ruby/decisions-api/apply-decision) for more information.
|
123
|
+
|
124
|
+
**Required Params:**
|
125
|
+
- `decision_id`, `source`, `user_id`
|
126
|
+
|
127
|
+
**Other Params**
|
128
|
+
- `order_id`: when applying a decision to an order, you must pass in the `order_id`
|
129
|
+
- `session_id`: when applying a decision to a session, you must pass in the `session_id`
|
130
|
+
- `analyst`: when `source` is set to `manual_review`, this field *is required*
|
131
|
+
|
132
|
+
**Returns**
|
133
|
+
`Response` object.
|
134
|
+
|
135
|
+
**Examples:**
|
136
|
+
```ruby
|
137
|
+
# apply decision to a user
|
138
|
+
response = client.apply_decision({
|
139
|
+
decision_id: "block_bad_user",
|
140
|
+
source: "manual_review",
|
141
|
+
analyst: "bob@your_company.com",
|
142
|
+
user_id: "john@example.com"
|
143
|
+
})
|
144
|
+
|
145
|
+
# apply decision to "john@example.com"'s order
|
146
|
+
response = client.apply_decision({
|
147
|
+
decision_id: "block_bad_order",
|
148
|
+
source: "manual_review",
|
149
|
+
analyst: "bob@your_company.com",
|
150
|
+
user_id: "john@example.com",
|
151
|
+
order_id: "ORDER_1234"
|
152
|
+
})
|
153
|
+
|
154
|
+
# apply decision to "john@example.com"'s session
|
155
|
+
response = client.apply_decision({
|
156
|
+
decision_id: "block_bad_session",
|
157
|
+
source: "manual_review",
|
158
|
+
analyst: "bob@your_company.com",
|
159
|
+
user_id: "john@example.com",
|
160
|
+
session_id: "SESSION_ID_1234"
|
161
|
+
})
|
162
|
+
|
163
|
+
# apply decision to "john@example.com"'s content
|
164
|
+
response = client.apply_decision({
|
165
|
+
decision_id: "block_bad_session",
|
166
|
+
source: "manual_review",
|
167
|
+
analyst: "bob@your_company.com",
|
168
|
+
user_id: "john@example.com",
|
169
|
+
content_id: "CONTENT_ID_1234"
|
170
|
+
})
|
171
|
+
|
172
|
+
|
173
|
+
# Make sure you handle the response after applying a decision:
|
174
|
+
|
175
|
+
if response.ok?
|
176
|
+
# do stuff
|
177
|
+
else
|
178
|
+
# Error message
|
179
|
+
response.api_error_message
|
180
|
+
|
181
|
+
# Summary of the error
|
182
|
+
response.api_error_description
|
183
|
+
|
184
|
+
# hash of errors:
|
185
|
+
# key: field in question
|
186
|
+
# value: description of the issue
|
187
|
+
response.api_error_issues
|
188
|
+
end
|
189
|
+
```
|
190
|
+
|
191
|
+
## Sending a Label
|
192
|
+
|
193
|
+
```ruby
|
194
|
+
# Label the user with user_id 23056 as Bad with all optional fields
|
195
|
+
response = client.label(user_id, {
|
196
|
+
"$is_bad" => true,
|
197
|
+
"$abuse_type" => "payment_abuse",
|
198
|
+
"$description" => "Chargeback issued",
|
199
|
+
"$source" => "Manual Review",
|
200
|
+
"$analyst" => "analyst.name@your_domain.com"
|
201
|
+
})
|
202
|
+
|
203
|
+
# Get the status of a workflow run
|
204
|
+
response = client.get_workflow_status('my_run_id')
|
205
|
+
|
206
|
+
# Get the latest decisions for a user
|
207
|
+
response = client.get_user_decisions('example_user_id')
|
208
|
+
|
209
|
+
# Get the latest decisions for an order
|
210
|
+
response = client.get_order_decisions('example_order_id')
|
211
|
+
|
212
|
+
# Get the latest decisions for a session
|
213
|
+
response = client.get_session_decisions('example_user_id', 'example_session_id')
|
214
|
+
|
215
|
+
# Get the latest decisions for an content
|
216
|
+
response = client.get_content_decisions('example_user_id', 'example_order_id')
|
217
|
+
```
|
218
|
+
|
219
|
+
## Response Object
|
220
|
+
|
221
|
+
All requests to our apis will return a `Response` instance.
|
222
|
+
|
223
|
+
### Public Methods:
|
224
|
+
- `ok?` returns `true` when the response is a `200`-`299`, `false` if it isn't
|
225
|
+
- `body` returns a hash representation of the json body returned.
|
226
|
+
- `api_error_message` returns a string describing the api error code.
|
227
|
+
- `api_error_description` a summary of the error that occured.
|
228
|
+
- `api_error_issues` a hash describing the items the error occured. The `key` is the item and the `value` is the description of the error.
|
229
|
+
|
230
|
+
|
231
|
+
## Building
|
232
|
+
|
233
|
+
Building and publishing the gem is captured by the following steps:
|
234
|
+
|
235
|
+
```ruby
|
236
|
+
$ gem build sift.gemspec
|
237
|
+
$ gem push sift-<current version>.gem
|
238
|
+
|
239
|
+
$ bundle
|
240
|
+
$ rake -T
|
241
|
+
$ rake build
|
242
|
+
$ rake install
|
243
|
+
$ rake release
|
244
|
+
```
|
245
|
+
|
246
|
+
|
247
|
+
## Testing
|
248
|
+
|
249
|
+
To run the various tests use the rake command as follows:
|
250
|
+
|
251
|
+
```ruby
|
252
|
+
$ rake spec
|
253
|
+
```
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require "multi_json"
|
2
|
+
|
3
|
+
require_relative "../../validate/decision"
|
4
|
+
require_relative "../../client"
|
5
|
+
require_relative "../../router"
|
6
|
+
require_relative "../../utils/hash_getter"
|
7
|
+
|
8
|
+
module Sift
|
9
|
+
class Client
|
10
|
+
class Decision
|
11
|
+
class ApplyTo
|
12
|
+
PROPERTIES = %w{
|
13
|
+
source
|
14
|
+
analyst
|
15
|
+
description
|
16
|
+
order_id
|
17
|
+
session_id
|
18
|
+
content_id
|
19
|
+
user_id
|
20
|
+
account_id
|
21
|
+
time
|
22
|
+
}
|
23
|
+
|
24
|
+
attr_reader :decision_id, :configs, :getter, :api_key
|
25
|
+
|
26
|
+
PROPERTIES.each do |attribute|
|
27
|
+
class_eval %{
|
28
|
+
def #{attribute}
|
29
|
+
getter.get(:#{attribute})
|
30
|
+
end
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(api_key, decision_id, configs)
|
35
|
+
@api_key = api_key
|
36
|
+
@decision_id = decision_id
|
37
|
+
@configs = configs
|
38
|
+
@getter = Utils::HashGetter.new(configs)
|
39
|
+
end
|
40
|
+
|
41
|
+
def run
|
42
|
+
if errors.empty?
|
43
|
+
send_request
|
44
|
+
else
|
45
|
+
Response.new(
|
46
|
+
MultiJson.dump({
|
47
|
+
status: 55,
|
48
|
+
error_message: errors.join(", ")
|
49
|
+
}),
|
50
|
+
400,
|
51
|
+
nil
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def send_request
|
59
|
+
Router.post(path, {
|
60
|
+
body: request_body,
|
61
|
+
headers: headers
|
62
|
+
})
|
63
|
+
end
|
64
|
+
|
65
|
+
def request_body
|
66
|
+
{
|
67
|
+
source: source,
|
68
|
+
description: description,
|
69
|
+
analyst: analyst,
|
70
|
+
decision_id: decision_id,
|
71
|
+
time: time
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def errors
|
76
|
+
validator = Validate::Decision.new(configs)
|
77
|
+
|
78
|
+
if applying_to_order?
|
79
|
+
validator.valid_order?
|
80
|
+
elsif applying_to_session?
|
81
|
+
validator.valid_session?
|
82
|
+
else
|
83
|
+
validator.valid_user?
|
84
|
+
end
|
85
|
+
|
86
|
+
validator.error_messages
|
87
|
+
end
|
88
|
+
|
89
|
+
def applying_to_order?
|
90
|
+
configs.has_key?("order_id") || configs.has_key?(:order_id)
|
91
|
+
end
|
92
|
+
|
93
|
+
def applying_to_session?
|
94
|
+
configs.has_key?("session_id") || configs.has_key?(:session_id)
|
95
|
+
end
|
96
|
+
|
97
|
+
def applying_to_content?
|
98
|
+
configs.has_key?("content_id") || configs.has_key?(:content_id)
|
99
|
+
end
|
100
|
+
|
101
|
+
def path
|
102
|
+
if applying_to_order?
|
103
|
+
"#{user_path}/orders/#{CGI.escape(order_id)}/decisions"
|
104
|
+
elsif applying_to_session?
|
105
|
+
"#{user_path}/sessions/#{CGI.escape(session_id)}/decisions"
|
106
|
+
elsif applying_to_content?
|
107
|
+
"#{user_path}/content/#{CGI.escape(content_id)}/decisions"
|
108
|
+
else
|
109
|
+
"#{user_path}/decisions"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def user_path
|
114
|
+
"#{base_path}/users/#{CGI.escape(user_id)}"
|
115
|
+
end
|
116
|
+
|
117
|
+
def base_path
|
118
|
+
"#{Client::API3_ENDPOINT}/v3/accounts/#{account_id}"
|
119
|
+
end
|
120
|
+
|
121
|
+
def headers
|
122
|
+
{
|
123
|
+
"Content-type" => "application/json"
|
124
|
+
}.merge(Client.build_auth_header(api_key))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "cgi"
|
2
|
+
|
3
|
+
require_relative "../router"
|
4
|
+
require_relative "../validate/decision"
|
5
|
+
require_relative "../utils/hash_getter"
|
6
|
+
require_relative "./decision/apply_to"
|
7
|
+
|
8
|
+
module Sift
|
9
|
+
class Client
|
10
|
+
class Decision
|
11
|
+
FILTER_PARAMS = %w{ limit entity_type abuse_types from }
|
12
|
+
|
13
|
+
attr_reader :account_id, :api_key
|
14
|
+
|
15
|
+
def initialize(api_key, account_id)
|
16
|
+
@account_id = account_id
|
17
|
+
@api_key = api_key
|
18
|
+
end
|
19
|
+
|
20
|
+
def list(options = {})
|
21
|
+
getter = Utils::HashGetter.new(options)
|
22
|
+
|
23
|
+
if path = getter.get(:next_ref)
|
24
|
+
request_next_page(path)
|
25
|
+
else
|
26
|
+
Router.get(index_path, {
|
27
|
+
query: build_query(getter),
|
28
|
+
headers: auth_header
|
29
|
+
})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def build_query(getter)
|
34
|
+
FILTER_PARAMS.inject({}) do |result, filter|
|
35
|
+
if value = getter.get(filter)
|
36
|
+
result[filter] = value.is_a?(Array) ? value.join(",") : value
|
37
|
+
end
|
38
|
+
|
39
|
+
result
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def apply_to(configs = {})
|
44
|
+
getter = Utils::HashGetter.new(configs)
|
45
|
+
configs[:account_id] = account_id
|
46
|
+
|
47
|
+
ApplyTo.new(api_key, getter.get(:decision_id), configs).run
|
48
|
+
end
|
49
|
+
|
50
|
+
def index_path
|
51
|
+
"#{Client::API3_ENDPOINT}/v3/accounts/#{account_id}/decisions"
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def request_next_page(path)
|
57
|
+
Router.get(path, headers: auth_header)
|
58
|
+
end
|
59
|
+
|
60
|
+
def auth_header
|
61
|
+
Client.build_auth_header(api_key)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|