sift 2.2.1 → 4.1.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 +5 -5
 - data/.circleci/config.yml +43 -0
 - data/HISTORY +31 -0
 - data/README.md +27 -8
 - data/lib/sift/client/decision/apply_to.rb +7 -0
 - data/lib/sift/client.rb +217 -21
 - data/lib/sift/validate/decision.rb +6 -0
 - data/lib/sift/version.rb +2 -2
 - data/lib/sift.rb +30 -8
 - data/sift.gemspec +1 -0
 - data/spec/unit/client_label_spec.rb +2 -2
 - data/spec/unit/client_spec.rb +182 -18
 - metadata +21 -8
 - data/.travis.yml +0 -18
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 4b20b0230176dc6340e5ea4939e51b6e1ed2642e788c25fa2f7f4e829b5c61ff
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 28932a0fddd658fe868c6c6b6b408ab1d8529060cfbe0766ffeef76e2398e43e
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: b905f6002c28777a4cf82cc6b0e59b2c79c300fdf1f4b4b3bf8b0bff8691946325d83794da812d5abc4b344b5e35d24f72b720aae1ddc0783b7e935117f35588
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: e161d32f1c210f3fc4562b985537ceb6e2f304330a3fb14ddbce142cd105b0a0c567f6e177dd3c29c99e6c50133e3a7eb40c5ba922071914d9cf56b540c8f427
         
     | 
| 
         @@ -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,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            === 4.1.0 2022-06-22
         
     | 
| 
      
 2 
     | 
    
         
            +
            - Add return_route_info query param
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            === 4.0.0 2019-05-15
         
     | 
| 
      
 5 
     | 
    
         
            +
            - 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.
         
     | 
| 
      
 6 
     | 
    
         
            +
            - Fix URL encoding
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Add Circle build
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            === 3.3.0 2018-07-31
         
     | 
| 
      
 10 
     | 
    
         
            +
            - Add support for rescore_user and get_user_score APIs
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            === 3.2.0 2018-07-05
         
     | 
| 
      
 13 
     | 
    
         
            +
            - Add new query parameter force_workflow_run
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            === 3.1.0 2018-06-04
         
     | 
| 
      
 16 
     | 
    
         
            +
            - Adds support for get session decisions to [Decisions API](https://siftscience.com/developers/docs/curl/decisions-api)
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            === 3.0.1 2018-04-06
         
     | 
| 
      
 19 
     | 
    
         
            +
            - Improved documentation on HISTORY and README.MD
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            === 3.0.0 2018-03-05
         
     | 
| 
      
 22 
     | 
    
         
            +
            - 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
         
     | 
| 
      
 23 
     | 
    
         
            +
            - V205 APIs are now called -- **this is an incompatible change**
         
     | 
| 
      
 24 
     | 
    
         
            +
               - (use `:version => 204` to call the previous API version)
         
     | 
| 
      
 25 
     | 
    
         
            +
            - Adds support for content decisions to [Decisions API](https://siftscience.com/developers/docs/curl/decisions-api)
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            INCOMPATIBLE CHANGES INTRODUCED IN API V205:
         
     | 
| 
      
 28 
     | 
    
         
            +
            - `$create_content` and `$update_content` have significantly changed, and the old format will be rejected
         
     | 
| 
      
 29 
     | 
    
         
            +
            - `$send_message` and `$submit_review` events are no longer valid
         
     | 
| 
      
 30 
     | 
    
         
            +
            - 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.**
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
       1 
32 
     | 
    
         
             
            === 2.2.1.0 2018-02-12
         
     | 
| 
       2 
33 
     | 
    
         
             
            * Add session level decisions in Apply Decisions APIs.
         
     | 
| 
       3 
34 
     | 
    
         | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,8 +1,11 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            #  
     | 
| 
      
 1 
     | 
    
         
            +
            # sift-ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            [](https://circleci.com/gh/SiftScience/sift-ruby)
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            The official Ruby bindings for the latest version (v205) of the [Sift API](https://sift.com/developers/docs/java/apis-overview).
         
     | 
| 
       2 
5 
     | 
    
         | 
| 
       3 
6 
     | 
    
         
             
            ## Requirements
         
     | 
| 
       4 
7 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
              * Ruby  
     | 
| 
      
 8 
     | 
    
         
            +
              * Ruby 2.0.0 or above.
         
     | 
| 
       6 
9 
     | 
    
         | 
| 
       7 
10 
     | 
    
         | 
| 
       8 
11 
     | 
    
         
             
            ## Installation
         
     | 
| 
         @@ -32,7 +35,7 @@ client = Sift::Client.new() 
     | 
|
| 
       32 
35 
     | 
    
         | 
| 
       33 
36 
     | 
    
         
             
            ##### OR
         
     | 
| 
       34 
37 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
            client = Sift::Client.new(api_key: '<your_api_key_here>', account_id: '<your_account_id_here>'
         
     | 
| 
      
 38 
     | 
    
         
            +
            client = Sift::Client.new(api_key: '<your_api_key_here>', account_id: '<your_account_id_here>')
         
     | 
| 
       36 
39 
     | 
    
         | 
| 
       37 
40 
     | 
    
         
             
            ```
         
     | 
| 
       38 
41 
     | 
    
         | 
| 
         @@ -73,14 +76,14 @@ response = client.score(user_id) 
     | 
|
| 
       73 
76 
     | 
    
         | 
| 
       74 
77 
     | 
    
         
             
            ## Decisions
         
     | 
| 
       75 
78 
     | 
    
         | 
| 
       76 
     | 
    
         
            -
            To learn more about the decisions endpoint visit our [developer docs](https:// 
     | 
| 
      
 79 
     | 
    
         
            +
            To learn more about the decisions endpoint visit our [developer docs](https://sift.com/developers/docs/ruby/decisions-api/get-decisions).
         
     | 
| 
       77 
80 
     | 
    
         | 
| 
       78 
81 
     | 
    
         
             
            ### List of Configured Decisions
         
     | 
| 
       79 
82 
     | 
    
         | 
| 
       80 
83 
     | 
    
         
             
            Get a list of your decisions.
         
     | 
| 
       81 
84 
     | 
    
         | 
| 
       82 
85 
     | 
    
         
             
            **Optional Params**
         
     | 
| 
       83 
     | 
    
         
            -
             - `entity_type`: `:user` or `:order` or `:session`
         
     | 
| 
      
 86 
     | 
    
         
            +
             - `entity_type`: `:user` or `:order` or `:session` or `:content`
         
     | 
| 
       84 
87 
     | 
    
         
             
             - `abuse_types`: `["payment_abuse", "content_abuse", "content_abuse",
         
     | 
| 
       85 
88 
     | 
    
         
             
               "account_abuse", "legacy", "account_takeover"]`
         
     | 
| 
       86 
89 
     | 
    
         | 
| 
         @@ -117,7 +120,7 @@ end 
     | 
|
| 
       117 
120 
     | 
    
         | 
| 
       118 
121 
     | 
    
         
             
            ### Apply a decision
         
     | 
| 
       119 
122 
     | 
    
         | 
| 
       120 
     | 
    
         
            -
            Applies a decision to an entity. Visit our [developer docs](http:// 
     | 
| 
      
 123 
     | 
    
         
            +
            Applies a decision to an entity. Visit our [developer docs](http://sift.com/developers/docs/ruby/decisions-api/apply-decision) for more information.
         
     | 
| 
       121 
124 
     | 
    
         | 
| 
       122 
125 
     | 
    
         
             
            **Required Params:**
         
     | 
| 
       123 
126 
     | 
    
         
             
            - `decision_id`, `source`, `user_id`
         
     | 
| 
         @@ -140,7 +143,7 @@ response = client.apply_decision({ 
     | 
|
| 
       140 
143 
     | 
    
         
             
              user_id: "john@example.com"
         
     | 
| 
       141 
144 
     | 
    
         
             
            })
         
     | 
| 
       142 
145 
     | 
    
         | 
| 
       143 
     | 
    
         
            -
            # apply decision to " 
     | 
| 
      
 146 
     | 
    
         
            +
            # apply decision to "john@example.com"'s order
         
     | 
| 
       144 
147 
     | 
    
         
             
            response = client.apply_decision({
         
     | 
| 
       145 
148 
     | 
    
         
             
              decision_id: "block_bad_order",
         
     | 
| 
       146 
149 
     | 
    
         
             
              source: "manual_review",
         
     | 
| 
         @@ -149,7 +152,7 @@ response = client.apply_decision({ 
     | 
|
| 
       149 
152 
     | 
    
         
             
              order_id: "ORDER_1234"
         
     | 
| 
       150 
153 
     | 
    
         
             
            })
         
     | 
| 
       151 
154 
     | 
    
         | 
| 
       152 
     | 
    
         
            -
            # apply decision to " 
     | 
| 
      
 155 
     | 
    
         
            +
            # apply decision to "john@example.com"'s session
         
     | 
| 
       153 
156 
     | 
    
         
             
            response = client.apply_decision({
         
     | 
| 
       154 
157 
     | 
    
         
             
              decision_id: "block_bad_session",
         
     | 
| 
       155 
158 
     | 
    
         
             
              source: "manual_review",
         
     | 
| 
         @@ -158,6 +161,16 @@ response = client.apply_decision({ 
     | 
|
| 
       158 
161 
     | 
    
         
             
              session_id: "SESSION_ID_1234"
         
     | 
| 
       159 
162 
     | 
    
         
             
            })
         
     | 
| 
       160 
163 
     | 
    
         | 
| 
      
 164 
     | 
    
         
            +
            # apply decision to "john@example.com"'s content
         
     | 
| 
      
 165 
     | 
    
         
            +
            response = client.apply_decision({
         
     | 
| 
      
 166 
     | 
    
         
            +
              decision_id: "block_bad_session",
         
     | 
| 
      
 167 
     | 
    
         
            +
              source: "manual_review",
         
     | 
| 
      
 168 
     | 
    
         
            +
              analyst: "bob@your_company.com",
         
     | 
| 
      
 169 
     | 
    
         
            +
              user_id: "john@example.com",
         
     | 
| 
      
 170 
     | 
    
         
            +
              content_id: "CONTENT_ID_1234"
         
     | 
| 
      
 171 
     | 
    
         
            +
            })
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
       161 
174 
     | 
    
         
             
            # Make sure you handle the response after applying a decision:
         
     | 
| 
       162 
175 
     | 
    
         | 
| 
       163 
176 
     | 
    
         
             
            if response.ok?
         
     | 
| 
         @@ -196,6 +209,12 @@ response = client.get_user_decisions('example_user_id') 
     | 
|
| 
       196 
209 
     | 
    
         | 
| 
       197 
210 
     | 
    
         
             
            # Get the latest decisions for an order
         
     | 
| 
       198 
211 
     | 
    
         
             
            response = client.get_order_decisions('example_order_id')
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
            # Get the latest decisions for a session
         
     | 
| 
      
 214 
     | 
    
         
            +
            response = client.get_session_decisions('example_user_id', 'example_session_id')
         
     | 
| 
      
 215 
     | 
    
         
            +
             
     | 
| 
      
 216 
     | 
    
         
            +
            # Get the latest decisions for an content
         
     | 
| 
      
 217 
     | 
    
         
            +
            response = client.get_content_decisions('example_user_id', 'example_order_id')
         
     | 
| 
       199 
218 
     | 
    
         
             
            ```
         
     | 
| 
       200 
219 
     | 
    
         | 
| 
       201 
220 
     | 
    
         
             
            ## Response Object
         
     | 
| 
         @@ -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/client.rb
    CHANGED
    
    | 
         @@ -34,15 +34,25 @@ module Sift 
     | 
|
| 
       34 
34 
     | 
    
         | 
| 
       35 
35 
     | 
    
         
             
                  # only set these variables if a message-body is expected.
         
     | 
| 
       36 
36 
     | 
    
         
             
                  if not @http_raw_response.kind_of? Net::HTTPNoContent
         
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
                     
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
                     
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
                       
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 39 
     | 
    
         
            +
                      @body = MultiJson.load(http_response) unless http_response.nil?
         
     | 
| 
      
 40 
     | 
    
         
            +
                    rescue
         
     | 
| 
      
 41 
     | 
    
         
            +
                      if @http_status_code == 200
         
     | 
| 
      
 42 
     | 
    
         
            +
                        raise TypeError.new
         
     | 
| 
      
 43 
     | 
    
         
            +
                      end
         
     | 
| 
      
 44 
     | 
    
         
            +
                    end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                    if not @body.nil?
         
     | 
| 
      
 47 
     | 
    
         
            +
                      @request = MultiJson.load(@body["request"].to_s) if @body["request"]
         
     | 
| 
      
 48 
     | 
    
         
            +
                      @api_status = @body["status"].to_i if @body["status"]
         
     | 
| 
      
 49 
     | 
    
         
            +
                      @api_error_message = @body["error_message"]
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                      if @body["error"]
         
     | 
| 
      
 52 
     | 
    
         
            +
                        @api_error_message = @body["error"]
         
     | 
| 
      
 53 
     | 
    
         
            +
                        @api_error_description = @body["description"]
         
     | 
| 
      
 54 
     | 
    
         
            +
                        @api_error_issues = @body["issues"] || {}
         
     | 
| 
      
 55 
     | 
    
         
            +
                      end
         
     | 
| 
       46 
56 
     | 
    
         
             
                    end
         
     | 
| 
       47 
57 
     | 
    
         
             
                  end
         
     | 
| 
       48 
58 
     | 
    
         
             
                end
         
     | 
| 
         @@ -118,7 +128,7 @@ module Sift 
     | 
|
| 
       118 
128 
     | 
    
         
             
                #
         
     | 
| 
       119 
129 
     | 
    
         
             
                #   :version::
         
     | 
| 
       120 
130 
     | 
    
         
             
                #     The version of the Events API, Score API, and Labels API to call.
         
     | 
| 
       121 
     | 
    
         
            -
                #     By default, version  
     | 
| 
      
 131 
     | 
    
         
            +
                #     By default, version 205.
         
     | 
| 
       122 
132 
     | 
    
         
             
                #
         
     | 
| 
       123 
133 
     | 
    
         
             
                #   :path::
         
     | 
| 
       124 
134 
     | 
    
         
             
                #     The URL path to use for Events API path.  By default, the
         
     | 
| 
         @@ -132,7 +142,7 @@ module Sift 
     | 
|
| 
       132 
142 
     | 
    
         
             
                  @timeout = opts[:timeout] || 2  # 2-second timeout by default
         
     | 
| 
       133 
143 
     | 
    
         
             
                  @path = opts[:path] || Sift.rest_api_path(@version)
         
     | 
| 
       134 
144 
     | 
    
         | 
| 
       135 
     | 
    
         
            -
                  raise("api_key 
     | 
| 
      
 145 
     | 
    
         
            +
                  raise("api_key") if !@api_key.is_a?(String) || @api_key.empty?
         
     | 
| 
       136 
146 
     | 
    
         
             
                  raise("path must be a non-empty string") if !@path.is_a?(String) || @path.empty?
         
     | 
| 
       137 
147 
     | 
    
         
             
                end
         
     | 
| 
       138 
148 
     | 
    
         | 
| 
         @@ -194,8 +204,8 @@ module Sift 
     | 
|
| 
       194 
204 
     | 
    
         
             
                #
         
     | 
| 
       195 
205 
     | 
    
         
             
                # ==== Returns:
         
     | 
| 
       196 
206 
     | 
    
         
             
                #
         
     | 
| 
       197 
     | 
    
         
            -
                # In the case of a  
     | 
| 
       198 
     | 
    
         
            -
                #  
     | 
| 
      
 207 
     | 
    
         
            +
                # In the case of a network error (timeout, broken connection, etc.),
         
     | 
| 
      
 208 
     | 
    
         
            +
                # this method propagates the exception, otherwise, a Response object is
         
     | 
| 
       199 
209 
     | 
    
         
             
                # returned that captures the status message and status code.
         
     | 
| 
       200 
210 
     | 
    
         
             
                #
         
     | 
| 
       201 
211 
     | 
    
         
             
                def track(event, properties = {}, opts = {})
         
     | 
| 
         @@ -206,6 +216,8 @@ module Sift 
     | 
|
| 
       206 
216 
     | 
    
         
             
                  return_score = opts[:return_score]
         
     | 
| 
       207 
217 
     | 
    
         
             
                  return_action = opts[:return_action]
         
     | 
| 
       208 
218 
     | 
    
         
             
                  return_workflow_status = opts[:return_workflow_status]
         
     | 
| 
      
 219 
     | 
    
         
            +
                  return_route_info = opts[:return_route_info]
         
     | 
| 
      
 220 
     | 
    
         
            +
                  force_workflow_run = opts[:force_workflow_run]
         
     | 
| 
       209 
221 
     | 
    
         
             
                  abuse_types = opts[:abuse_types]
         
     | 
| 
       210 
222 
     | 
    
         | 
| 
       211 
223 
     | 
    
         
             
                  raise("event must be a non-empty string") if (!event.is_a? String) || event.empty?
         
     | 
| 
         @@ -216,6 +228,8 @@ module Sift 
     | 
|
| 
       216 
228 
     | 
    
         
             
                  query["return_score"] = "true" if return_score
         
     | 
| 
       217 
229 
     | 
    
         
             
                  query["return_action"] = "true" if return_action
         
     | 
| 
       218 
230 
     | 
    
         
             
                  query["return_workflow_status"] = "true" if return_workflow_status
         
     | 
| 
      
 231 
     | 
    
         
            +
                  query["return_route_info"] = "true" if return_route_info
         
     | 
| 
      
 232 
     | 
    
         
            +
                  query["force_workflow_run"] = "true" if force_workflow_run
         
     | 
| 
       219 
233 
     | 
    
         
             
                  query["abuse_types"] = abuse_types.join(",") if abuse_types
         
     | 
| 
       220 
234 
     | 
    
         | 
| 
       221 
235 
     | 
    
         
             
                  options = {
         
     | 
| 
         @@ -226,14 +240,8 @@ module Sift 
     | 
|
| 
       226 
240 
     | 
    
         
             
                  }
         
     | 
| 
       227 
241 
     | 
    
         
             
                  options.merge!(:timeout => timeout) unless timeout.nil?
         
     | 
| 
       228 
242 
     | 
    
         | 
| 
       229 
     | 
    
         
            -
                   
     | 
| 
       230 
     | 
    
         
            -
             
     | 
| 
       231 
     | 
    
         
            -
                    Response.new(response.body, response.code, response.response)
         
     | 
| 
       232 
     | 
    
         
            -
                  rescue StandardError => e
         
     | 
| 
       233 
     | 
    
         
            -
                    Sift.warn("Failed to track event: " + e.to_s)
         
     | 
| 
       234 
     | 
    
         
            -
                    Sift.warn(e.backtrace)
         
     | 
| 
       235 
     | 
    
         
            -
                    nil
         
     | 
| 
       236 
     | 
    
         
            -
                  end
         
     | 
| 
      
 243 
     | 
    
         
            +
                  response = self.class.post(path, options)
         
     | 
| 
      
 244 
     | 
    
         
            +
                  Response.new(response.body, response.code, response.response)
         
     | 
| 
       237 
245 
     | 
    
         
             
                end
         
     | 
| 
       238 
246 
     | 
    
         | 
| 
       239 
247 
     | 
    
         | 
| 
         @@ -293,6 +301,114 @@ module Sift 
     | 
|
| 
       293 
301 
     | 
    
         
             
                end
         
     | 
| 
       294 
302 
     | 
    
         | 
| 
       295 
303 
     | 
    
         | 
| 
      
 304 
     | 
    
         
            +
                # Fetches the latest score(s) computed for the specified user and abuse types.
         
     | 
| 
      
 305 
     | 
    
         
            +
                #
         
     | 
| 
      
 306 
     | 
    
         
            +
                # As opposed to client.score() and client.rescore_user(), this *does not* compute
         
     | 
| 
      
 307 
     | 
    
         
            +
                # a new score for the user; it simply fetches the latest score(s) which have computed.
         
     | 
| 
      
 308 
     | 
    
         
            +
                # These scores may be arbitrarily old.
         
     | 
| 
      
 309 
     | 
    
         
            +
                #
         
     | 
| 
      
 310 
     | 
    
         
            +
                # See https://siftscience.com/developers/docs/ruby/score-api/get-score for more details.
         
     | 
| 
      
 311 
     | 
    
         
            +
                #
         
     | 
| 
      
 312 
     | 
    
         
            +
                # ==== Parameters:
         
     | 
| 
      
 313 
     | 
    
         
            +
                #
         
     | 
| 
      
 314 
     | 
    
         
            +
                # user_id::
         
     | 
| 
      
 315 
     | 
    
         
            +
                #   A user's id. This id should be the same as the user_id used in
         
     | 
| 
      
 316 
     | 
    
         
            +
                #   event calls.
         
     | 
| 
      
 317 
     | 
    
         
            +
                #
         
     | 
| 
      
 318 
     | 
    
         
            +
                # opts (optional)::
         
     | 
| 
      
 319 
     | 
    
         
            +
                #   A Hash of optional parameters for the request --
         
     | 
| 
      
 320 
     | 
    
         
            +
                #
         
     | 
| 
      
 321 
     | 
    
         
            +
                #   :abuse_types::
         
     | 
| 
      
 322 
     | 
    
         
            +
                #     List of abuse types, specifying for which abuse types a
         
     | 
| 
      
 323 
     | 
    
         
            +
                #     score should be returned.  By default, a score is returned
         
     | 
| 
      
 324 
     | 
    
         
            +
                #     for every abuse type to which you are subscribed.
         
     | 
| 
      
 325 
     | 
    
         
            +
                #
         
     | 
| 
      
 326 
     | 
    
         
            +
                #   :api_key::
         
     | 
| 
      
 327 
     | 
    
         
            +
                #     Overrides the API key for this call.
         
     | 
| 
      
 328 
     | 
    
         
            +
                #
         
     | 
| 
      
 329 
     | 
    
         
            +
                #   :timeout::
         
     | 
| 
      
 330 
     | 
    
         
            +
                #     Overrides the timeout (in seconds) for this call.
         
     | 
| 
      
 331 
     | 
    
         
            +
                #
         
     | 
| 
      
 332 
     | 
    
         
            +
                # ==== Returns:
         
     | 
| 
      
 333 
     | 
    
         
            +
                #
         
     | 
| 
      
 334 
     | 
    
         
            +
                # A Response object containing a status code, status message, and,
         
     | 
| 
      
 335 
     | 
    
         
            +
                # if successful, the user's score(s).
         
     | 
| 
      
 336 
     | 
    
         
            +
                #
         
     | 
| 
      
 337 
     | 
    
         
            +
                def get_user_score(user_id, opts = {})
         
     | 
| 
      
 338 
     | 
    
         
            +
                  abuse_types = opts[:abuse_types]
         
     | 
| 
      
 339 
     | 
    
         
            +
                  api_key = opts[:api_key] || @api_key
         
     | 
| 
      
 340 
     | 
    
         
            +
                  timeout = opts[:timeout] || @timeout
         
     | 
| 
      
 341 
     | 
    
         
            +
             
     | 
| 
      
 342 
     | 
    
         
            +
                  raise("user_id must be a non-empty string") if (!user_id.is_a? String) || user_id.to_s.empty?
         
     | 
| 
      
 343 
     | 
    
         
            +
                  raise("Bad api_key parameter") if api_key.empty?
         
     | 
| 
      
 344 
     | 
    
         
            +
             
     | 
| 
      
 345 
     | 
    
         
            +
                  query = {}
         
     | 
| 
      
 346 
     | 
    
         
            +
                  query["api_key"] = api_key
         
     | 
| 
      
 347 
     | 
    
         
            +
                  query["abuse_types"] = abuse_types.join(",") if abuse_types
         
     | 
| 
      
 348 
     | 
    
         
            +
             
     | 
| 
      
 349 
     | 
    
         
            +
                  options = {
         
     | 
| 
      
 350 
     | 
    
         
            +
                    :headers => {"User-Agent" => user_agent},
         
     | 
| 
      
 351 
     | 
    
         
            +
                    :query => query
         
     | 
| 
      
 352 
     | 
    
         
            +
                  }
         
     | 
| 
      
 353 
     | 
    
         
            +
                  options.merge!(:timeout => timeout) unless timeout.nil?
         
     | 
| 
      
 354 
     | 
    
         
            +
             
     | 
| 
      
 355 
     | 
    
         
            +
                  response = self.class.get(Sift.user_score_api_path(user_id, @version), options)
         
     | 
| 
      
 356 
     | 
    
         
            +
                  Response.new(response.body, response.code, response.response)
         
     | 
| 
      
 357 
     | 
    
         
            +
                end
         
     | 
| 
      
 358 
     | 
    
         
            +
             
     | 
| 
      
 359 
     | 
    
         
            +
             
     | 
| 
      
 360 
     | 
    
         
            +
                # Rescores the specified user for the specified abuse types and returns the resulting score(s).
         
     | 
| 
      
 361 
     | 
    
         
            +
                #
         
     | 
| 
      
 362 
     | 
    
         
            +
                # See https://siftscience.com/developers/docs/ruby/score-api/rescore for more details.
         
     | 
| 
      
 363 
     | 
    
         
            +
                #
         
     | 
| 
      
 364 
     | 
    
         
            +
                # ==== Parameters:
         
     | 
| 
      
 365 
     | 
    
         
            +
                #
         
     | 
| 
      
 366 
     | 
    
         
            +
                # user_id::
         
     | 
| 
      
 367 
     | 
    
         
            +
                #   A user's id. This id should be the same as the user_id used in
         
     | 
| 
      
 368 
     | 
    
         
            +
                #   event calls.
         
     | 
| 
      
 369 
     | 
    
         
            +
                #
         
     | 
| 
      
 370 
     | 
    
         
            +
                # opts (optional)::
         
     | 
| 
      
 371 
     | 
    
         
            +
                #   A Hash of optional parameters for the request --
         
     | 
| 
      
 372 
     | 
    
         
            +
                #
         
     | 
| 
      
 373 
     | 
    
         
            +
                #   :abuse_types::
         
     | 
| 
      
 374 
     | 
    
         
            +
                #     List of abuse types, specifying for which abuse types a
         
     | 
| 
      
 375 
     | 
    
         
            +
                #     score should be returned.  By default, a score is returned
         
     | 
| 
      
 376 
     | 
    
         
            +
                #     for every abuse type to which you are subscribed.
         
     | 
| 
      
 377 
     | 
    
         
            +
                #
         
     | 
| 
      
 378 
     | 
    
         
            +
                #   :api_key::
         
     | 
| 
      
 379 
     | 
    
         
            +
                #     Overrides the API key for this call.
         
     | 
| 
      
 380 
     | 
    
         
            +
                #
         
     | 
| 
      
 381 
     | 
    
         
            +
                #   :timeout::
         
     | 
| 
      
 382 
     | 
    
         
            +
                #     Overrides the timeout (in seconds) for this call.
         
     | 
| 
      
 383 
     | 
    
         
            +
                #
         
     | 
| 
      
 384 
     | 
    
         
            +
                # ==== Returns:
         
     | 
| 
      
 385 
     | 
    
         
            +
                #
         
     | 
| 
      
 386 
     | 
    
         
            +
                # A Response object containing a status code, status message, and,
         
     | 
| 
      
 387 
     | 
    
         
            +
                # if successful, the user's score(s).
         
     | 
| 
      
 388 
     | 
    
         
            +
                #
         
     | 
| 
      
 389 
     | 
    
         
            +
                def rescore_user(user_id, opts = {})
         
     | 
| 
      
 390 
     | 
    
         
            +
                  abuse_types = opts[:abuse_types]
         
     | 
| 
      
 391 
     | 
    
         
            +
                  api_key = opts[:api_key] || @api_key
         
     | 
| 
      
 392 
     | 
    
         
            +
                  timeout = opts[:timeout] || @timeout
         
     | 
| 
      
 393 
     | 
    
         
            +
             
     | 
| 
      
 394 
     | 
    
         
            +
                  raise("user_id must be a non-empty string") if (!user_id.is_a? String) || user_id.to_s.empty?
         
     | 
| 
      
 395 
     | 
    
         
            +
                  raise("Bad api_key parameter") if api_key.empty?
         
     | 
| 
      
 396 
     | 
    
         
            +
             
     | 
| 
      
 397 
     | 
    
         
            +
                  query = {}
         
     | 
| 
      
 398 
     | 
    
         
            +
                  query["api_key"] = api_key
         
     | 
| 
      
 399 
     | 
    
         
            +
                  query["abuse_types"] = abuse_types.join(",") if abuse_types
         
     | 
| 
      
 400 
     | 
    
         
            +
             
     | 
| 
      
 401 
     | 
    
         
            +
                  options = {
         
     | 
| 
      
 402 
     | 
    
         
            +
                    :headers => {"User-Agent" => user_agent},
         
     | 
| 
      
 403 
     | 
    
         
            +
                    :query => query
         
     | 
| 
      
 404 
     | 
    
         
            +
                  }
         
     | 
| 
      
 405 
     | 
    
         
            +
                  options.merge!(:timeout => timeout) unless timeout.nil?
         
     | 
| 
      
 406 
     | 
    
         
            +
             
     | 
| 
      
 407 
     | 
    
         
            +
                  response = self.class.post(Sift.user_score_api_path(user_id, @version), options)
         
     | 
| 
      
 408 
     | 
    
         
            +
                  Response.new(response.body, response.code, response.response)
         
     | 
| 
      
 409 
     | 
    
         
            +
                end
         
     | 
| 
      
 410 
     | 
    
         
            +
             
     | 
| 
      
 411 
     | 
    
         
            +
             
     | 
| 
       296 
412 
     | 
    
         
             
                # Labels a user.
         
     | 
| 
       297 
413 
     | 
    
         
             
                #
         
     | 
| 
       298 
414 
     | 
    
         
             
                # See https://siftscience.com/developers/docs/ruby/labels-api/label-user .
         
     | 
| 
         @@ -504,6 +620,86 @@ module Sift 
     | 
|
| 
       504 
620 
     | 
    
         
             
                  Response.new(response.body, response.code, response.response)
         
     | 
| 
       505 
621 
     | 
    
         
             
                end
         
     | 
| 
       506 
622 
     | 
    
         | 
| 
      
 623 
     | 
    
         
            +
                # Gets the decision status of a session.
         
     | 
| 
      
 624 
     | 
    
         
            +
                #
         
     | 
| 
      
 625 
     | 
    
         
            +
                # See https://siftscience.com/developers/docs/ruby/decisions-api/decision-status .
         
     | 
| 
      
 626 
     | 
    
         
            +
                #
         
     | 
| 
      
 627 
     | 
    
         
            +
                # ==== Parameters
         
     | 
| 
      
 628 
     | 
    
         
            +
                #
         
     | 
| 
      
 629 
     | 
    
         
            +
                # user_id::
         
     | 
| 
      
 630 
     | 
    
         
            +
                #   The ID of the user in the session.
         
     | 
| 
      
 631 
     | 
    
         
            +
                #
         
     | 
| 
      
 632 
     | 
    
         
            +
                # session_id::
         
     | 
| 
      
 633 
     | 
    
         
            +
                #   The ID of a session.
         
     | 
| 
      
 634 
     | 
    
         
            +
                #
         
     | 
| 
      
 635 
     | 
    
         
            +
                # opts (optional)::
         
     | 
| 
      
 636 
     | 
    
         
            +
                #   A Hash of optional parameters for this request --
         
     | 
| 
      
 637 
     | 
    
         
            +
                #
         
     | 
| 
      
 638 
     | 
    
         
            +
                #   :account_id::
         
     | 
| 
      
 639 
     | 
    
         
            +
                #     Overrides the account id for this call.
         
     | 
| 
      
 640 
     | 
    
         
            +
                #
         
     | 
| 
      
 641 
     | 
    
         
            +
                #   :api_key::
         
     | 
| 
      
 642 
     | 
    
         
            +
                #     Overrides the API key for this call.
         
     | 
| 
      
 643 
     | 
    
         
            +
                #
         
     | 
| 
      
 644 
     | 
    
         
            +
                #   :timeout::
         
     | 
| 
      
 645 
     | 
    
         
            +
                #     Overrides the timeout (in seconds) for this call.
         
     | 
| 
      
 646 
     | 
    
         
            +
                #
         
     | 
| 
      
 647 
     | 
    
         
            +
                def get_session_decisions(user_id, session_id, opts = {})
         
     | 
| 
      
 648 
     | 
    
         
            +
                  account_id = opts[:account_id] || @account_id
         
     | 
| 
      
 649 
     | 
    
         
            +
                  api_key = opts[:api_key] || @api_key
         
     | 
| 
      
 650 
     | 
    
         
            +
                  timeout = opts[:timeout] || @timeout
         
     | 
| 
      
 651 
     | 
    
         
            +
             
     | 
| 
      
 652 
     | 
    
         
            +
                  options = {
         
     | 
| 
      
 653 
     | 
    
         
            +
                    :headers => { "User-Agent" => user_agent },
         
     | 
| 
      
 654 
     | 
    
         
            +
                    :basic_auth => { :username => api_key, :password => "" }
         
     | 
| 
      
 655 
     | 
    
         
            +
                  }
         
     | 
| 
      
 656 
     | 
    
         
            +
                  options.merge!(:timeout => timeout) unless timeout.nil?
         
     | 
| 
      
 657 
     | 
    
         
            +
             
     | 
| 
      
 658 
     | 
    
         
            +
                  uri = API3_ENDPOINT + Sift.session_decisions_api_path(account_id, user_id, session_id)
         
     | 
| 
      
 659 
     | 
    
         
            +
                  response = self.class.get(uri, options)
         
     | 
| 
      
 660 
     | 
    
         
            +
                  Response.new(response.body, response.code, response.response)
         
     | 
| 
      
 661 
     | 
    
         
            +
                end
         
     | 
| 
      
 662 
     | 
    
         
            +
             
     | 
| 
      
 663 
     | 
    
         
            +
                # Gets the decision status of a piece of content.
         
     | 
| 
      
 664 
     | 
    
         
            +
                #
         
     | 
| 
      
 665 
     | 
    
         
            +
                # See https://siftscience.com/developers/docs/ruby/decisions-api/decision-status .
         
     | 
| 
      
 666 
     | 
    
         
            +
                #
         
     | 
| 
      
 667 
     | 
    
         
            +
                # ==== Parameters
         
     | 
| 
      
 668 
     | 
    
         
            +
                #
         
     | 
| 
      
 669 
     | 
    
         
            +
                # user_id::
         
     | 
| 
      
 670 
     | 
    
         
            +
                #   The ID of the owner of the content.
         
     | 
| 
      
 671 
     | 
    
         
            +
                #
         
     | 
| 
      
 672 
     | 
    
         
            +
                # content_id::
         
     | 
| 
      
 673 
     | 
    
         
            +
                #   The ID of a piece of content.
         
     | 
| 
      
 674 
     | 
    
         
            +
                #
         
     | 
| 
      
 675 
     | 
    
         
            +
                # opts (optional)::
         
     | 
| 
      
 676 
     | 
    
         
            +
                #   A Hash of optional parameters for this request --
         
     | 
| 
      
 677 
     | 
    
         
            +
                #
         
     | 
| 
      
 678 
     | 
    
         
            +
                #   :account_id::
         
     | 
| 
      
 679 
     | 
    
         
            +
                #     Overrides the API key for this call.
         
     | 
| 
      
 680 
     | 
    
         
            +
                #
         
     | 
| 
      
 681 
     | 
    
         
            +
                #   :api_key::
         
     | 
| 
      
 682 
     | 
    
         
            +
                #     Overrides the API key for this call.
         
     | 
| 
      
 683 
     | 
    
         
            +
                #
         
     | 
| 
      
 684 
     | 
    
         
            +
                #   :timeout::
         
     | 
| 
      
 685 
     | 
    
         
            +
                #     Overrides the timeout (in seconds) for this call.
         
     | 
| 
      
 686 
     | 
    
         
            +
                #
         
     | 
| 
      
 687 
     | 
    
         
            +
                def get_content_decisions(user_id, content_id, opts = {})
         
     | 
| 
      
 688 
     | 
    
         
            +
                  account_id = opts[:account_id] || @account_id
         
     | 
| 
      
 689 
     | 
    
         
            +
                  api_key = opts[:api_key] || @api_key
         
     | 
| 
      
 690 
     | 
    
         
            +
                  timeout = opts[:timeout] || @timeout
         
     | 
| 
      
 691 
     | 
    
         
            +
             
     | 
| 
      
 692 
     | 
    
         
            +
                  options = {
         
     | 
| 
      
 693 
     | 
    
         
            +
                    :headers => { "User-Agent" => user_agent },
         
     | 
| 
      
 694 
     | 
    
         
            +
                    :basic_auth => { :username => api_key, :password => "" }
         
     | 
| 
      
 695 
     | 
    
         
            +
                  }
         
     | 
| 
      
 696 
     | 
    
         
            +
                  options.merge!(:timeout => timeout) unless timeout.nil?
         
     | 
| 
      
 697 
     | 
    
         
            +
             
     | 
| 
      
 698 
     | 
    
         
            +
                  uri = API3_ENDPOINT + Sift.content_decisions_api_path(account_id, user_id, content_id)
         
     | 
| 
      
 699 
     | 
    
         
            +
                  response = self.class.get(uri, options)
         
     | 
| 
      
 700 
     | 
    
         
            +
                  Response.new(response.body, response.code, response.response)
         
     | 
| 
      
 701 
     | 
    
         
            +
                end
         
     | 
| 
      
 702 
     | 
    
         
            +
             
     | 
| 
       507 
703 
     | 
    
         
             
                def decisions(opts = {})
         
     | 
| 
       508 
704 
     | 
    
         
             
                  decision_instance.list(opts)
         
     | 
| 
       509 
705 
     | 
    
         
             
                end
         
     | 
    
        data/lib/sift/version.rb
    CHANGED
    
    
    
        data/lib/sift.rb
    CHANGED
    
    | 
         @@ -1,5 +1,6 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require_relative  
     | 
| 
       2 
     | 
    
         
            -
            require_relative  
     | 
| 
      
 1 
     | 
    
         
            +
            require_relative './sift/version'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require_relative './sift/client'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'erb'
         
     | 
| 
       3 
4 
     | 
    
         | 
| 
       4 
5 
     | 
    
         
             
            module Sift
         
     | 
| 
       5 
6 
     | 
    
         | 
| 
         @@ -10,27 +11,49 @@ module Sift 
     | 
|
| 
       10 
11 
     | 
    
         | 
| 
       11 
12 
     | 
    
         
             
              # Returns the Score API path for the specified user ID and API version
         
     | 
| 
       12 
13 
     | 
    
         
             
              def self.score_api_path(user_id, version=API_VERSION)
         
     | 
| 
       13 
     | 
    
         
            -
                "/v#{version}/score/#{ 
     | 
| 
      
 14 
     | 
    
         
            +
                "/v#{version}/score/#{ERB::Util.url_encode(user_id)}/"
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              # Returns the User Score API path for the specified user ID and API version
         
     | 
| 
      
 18 
     | 
    
         
            +
              def self.user_score_api_path(user_id, version=API_VERSION)
         
     | 
| 
      
 19 
     | 
    
         
            +
                "/v#{version}/users/#{ERB::Util.url_encode(user_id)}/score"
         
     | 
| 
       14 
20 
     | 
    
         
             
              end
         
     | 
| 
       15 
21 
     | 
    
         | 
| 
       16 
22 
     | 
    
         
             
              # Returns the users API path for the specified user ID and API version
         
     | 
| 
       17 
23 
     | 
    
         
             
              def self.users_label_api_path(user_id, version=API_VERSION)
         
     | 
| 
       18 
     | 
    
         
            -
                "/v#{version}/users/#{ 
     | 
| 
      
 24 
     | 
    
         
            +
                "/v#{version}/users/#{ERB::Util.url_encode(user_id)}/labels"
         
     | 
| 
       19 
25 
     | 
    
         
             
              end
         
     | 
| 
       20 
26 
     | 
    
         | 
| 
       21 
27 
     | 
    
         
             
              # Returns the path for the Workflow Status API
         
     | 
| 
       22 
28 
     | 
    
         
             
              def self.workflow_status_path(account_id, run_id)
         
     | 
| 
       23 
     | 
    
         
            -
                "/v3/accounts/#{account_id} 
     | 
| 
      
 29 
     | 
    
         
            +
                "/v3/accounts/#{ERB::Util.url_encode(account_id)}" \
         
     | 
| 
      
 30 
     | 
    
         
            +
                  "/workflows/runs/#{ERB::Util.url_encode(run_id)}"
         
     | 
| 
       24 
31 
     | 
    
         
             
              end
         
     | 
| 
       25 
32 
     | 
    
         | 
| 
       26 
33 
     | 
    
         
             
              # Returns the path for User Decisions API
         
     | 
| 
       27 
34 
     | 
    
         
             
              def self.user_decisions_api_path(account_id, user_id)
         
     | 
| 
       28 
     | 
    
         
            -
                "/v3/accounts/#{account_id} 
     | 
| 
      
 35 
     | 
    
         
            +
                "/v3/accounts/#{ERB::Util.url_encode(account_id)}" \
         
     | 
| 
      
 36 
     | 
    
         
            +
                  "/users/#{ERB::Util.url_encode(user_id)}/decisions"
         
     | 
| 
       29 
37 
     | 
    
         
             
              end
         
     | 
| 
       30 
38 
     | 
    
         | 
| 
       31 
39 
     | 
    
         
             
              # Returns the path for Orders Decisions API
         
     | 
| 
       32 
40 
     | 
    
         
             
              def self.order_decisions_api_path(account_id, order_id)
         
     | 
| 
       33 
     | 
    
         
            -
                "/v3/accounts/#{account_id} 
     | 
| 
      
 41 
     | 
    
         
            +
                "/v3/accounts/#{ERB::Util.url_encode(account_id)}" \
         
     | 
| 
      
 42 
     | 
    
         
            +
                  "/orders/#{ERB::Util.url_encode(order_id)}/decisions"
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              # Returns the path for Session Decisions API
         
     | 
| 
      
 46 
     | 
    
         
            +
              def self.session_decisions_api_path(account_id, user_id, session_id)
         
     | 
| 
      
 47 
     | 
    
         
            +
                "/v3/accounts/#{ERB::Util.url_encode(account_id)}" \
         
     | 
| 
      
 48 
     | 
    
         
            +
                  "/users/#{ERB::Util.url_encode(user_id)}" \
         
     | 
| 
      
 49 
     | 
    
         
            +
                  "/sessions/#{ERB::Util.url_encode(session_id)}/decisions"
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              # Returns the path for Content Decisions API
         
     | 
| 
      
 53 
     | 
    
         
            +
              def self.content_decisions_api_path(account_id, user_id, content_id)
         
     | 
| 
      
 54 
     | 
    
         
            +
                "/v3/accounts/#{ERB::Util.url_encode(account_id)}" \
         
     | 
| 
      
 55 
     | 
    
         
            +
                  "/users/#{ERB::Util.url_encode(user_id)}" \
         
     | 
| 
      
 56 
     | 
    
         
            +
                  "/content/#{ERB::Util.url_encode(content_id)}/decisions"
         
     | 
| 
       34 
57 
     | 
    
         
             
              end
         
     | 
| 
       35 
58 
     | 
    
         | 
| 
       36 
59 
     | 
    
         
             
              # Module-scoped public API key
         
     | 
| 
         @@ -64,5 +87,4 @@ module Sift 
     | 
|
| 
       64 
87 
     | 
    
         
             
              def self.fatal(msg)
         
     | 
| 
       65 
88 
     | 
    
         
             
                @logger.fatal(msg) if @logger
         
     | 
| 
       66 
89 
     | 
    
         
             
              end
         
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
90 
     | 
    
         
             
            end
         
     | 
    
        data/sift.gemspec
    CHANGED
    
    | 
         @@ -21,6 +21,7 @@ Gem::Specification.new do |s| 
     | 
|
| 
       21 
21 
     | 
    
         | 
| 
       22 
22 
     | 
    
         
             
              # Gems that must be intalled for sift to compile and build
         
     | 
| 
       23 
23 
     | 
    
         
             
              s.add_development_dependency "rspec", "~> 3.5"
         
     | 
| 
      
 24 
     | 
    
         
            +
              s.add_development_dependency "rspec_junit_formatter"
         
     | 
| 
       24 
25 
     | 
    
         
             
              s.add_development_dependency "pry"
         
     | 
| 
       25 
26 
     | 
    
         
             
              s.add_development_dependency "webmock", ">= 1.16.0", "< 2"
         
     | 
| 
       26 
27 
     | 
    
         | 
| 
         @@ -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
    
    | 
         @@ -43,6 +43,38 @@ describe Sift::Client do 
     | 
|
| 
       43 
43 
     | 
    
         
             
                }
         
     | 
| 
       44 
44 
     | 
    
         
             
              end
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
      
 46 
     | 
    
         
            +
              def user_score_response_json
         
     | 
| 
      
 47 
     | 
    
         
            +
                {
         
     | 
| 
      
 48 
     | 
    
         
            +
                  :entity_type => "user",
         
     | 
| 
      
 49 
     | 
    
         
            +
                  :entity_id => "247019",
         
     | 
| 
      
 50 
     | 
    
         
            +
                  :scores => {
         
     | 
| 
      
 51 
     | 
    
         
            +
                    :payment_abuse => {
         
     | 
| 
      
 52 
     | 
    
         
            +
                      :score => 0.78
         
     | 
| 
      
 53 
     | 
    
         
            +
                    },
         
     | 
| 
      
 54 
     | 
    
         
            +
                    :content_abuse => {
         
     | 
| 
      
 55 
     | 
    
         
            +
                      :score => 0.11
         
     | 
| 
      
 56 
     | 
    
         
            +
                    }
         
     | 
| 
      
 57 
     | 
    
         
            +
                  },
         
     | 
| 
      
 58 
     | 
    
         
            +
                  :latest_decisions => {
         
     | 
| 
      
 59 
     | 
    
         
            +
                    :payment_abuse => {
         
     | 
| 
      
 60 
     | 
    
         
            +
                      :id => "user_looks_bad_payment_abuse",
         
     | 
| 
      
 61 
     | 
    
         
            +
                      :category => "block",
         
     | 
| 
      
 62 
     | 
    
         
            +
                      :source => "AUTOMATED_RULE",
         
     | 
| 
      
 63 
     | 
    
         
            +
                      :time => 1352201880,
         
     | 
| 
      
 64 
     | 
    
         
            +
                      :description => "Bad Fraudster"
         
     | 
| 
      
 65 
     | 
    
         
            +
                    }
         
     | 
| 
      
 66 
     | 
    
         
            +
                  },
         
     | 
| 
      
 67 
     | 
    
         
            +
                  :latest_labels => {
         
     | 
| 
      
 68 
     | 
    
         
            +
                    :payment_abuse => {
         
     | 
| 
      
 69 
     | 
    
         
            +
                      :is_bad => true,
         
     | 
| 
      
 70 
     | 
    
         
            +
                      :time => 1352201880
         
     | 
| 
      
 71 
     | 
    
         
            +
                    }
         
     | 
| 
      
 72 
     | 
    
         
            +
                  },
         
     | 
| 
      
 73 
     | 
    
         
            +
                  :status => 0,
         
     | 
| 
      
 74 
     | 
    
         
            +
                  :error_message => "OK"
         
     | 
| 
      
 75 
     | 
    
         
            +
                }
         
     | 
| 
      
 76 
     | 
    
         
            +
              end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
       46 
78 
     | 
    
         
             
              def action_response_json
         
     | 
| 
       47 
79 
     | 
    
         
             
                {
         
     | 
| 
       48 
80 
     | 
    
         
             
                  :user_id => "247019",
         
     | 
| 
         @@ -140,36 +172,59 @@ describe Sift::Client do 
     | 
|
| 
       140 
172 
     | 
    
         
             
              end
         
     | 
| 
       141 
173 
     | 
    
         | 
| 
       142 
174 
     | 
    
         | 
| 
       143 
     | 
    
         
            -
              it " 
     | 
| 
      
 175 
     | 
    
         
            +
              it "Handles parse exceptions for 500 status" do
         
     | 
| 
       144 
176 
     | 
    
         
             
                api_key = "foobar"
         
     | 
| 
       145 
177 
     | 
    
         
             
                event = "$transaction"
         
     | 
| 
       146 
178 
     | 
    
         
             
                properties = valid_transaction_properties
         
     | 
| 
      
 179 
     | 
    
         
            +
                res = nil
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                stub_request(:any, /.*/).to_return(:body => "{123", :status => 500)
         
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
      
 183 
     | 
    
         
            +
                expect { res = Sift::Client.new(:api_key => api_key).track(event, properties) }.not_to raise_error
         
     | 
| 
      
 184 
     | 
    
         
            +
                expect(res.http_status_code).to eq(500)
         
     | 
| 
      
 185 
     | 
    
         
            +
              end
         
     | 
| 
      
 186 
     | 
    
         
            +
             
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
      
 188 
     | 
    
         
            +
              it "Handles parse exceptions for 200 status" do
         
     | 
| 
      
 189 
     | 
    
         
            +
                api_key = "foobar"
         
     | 
| 
      
 190 
     | 
    
         
            +
                event = "$transaction"
         
     | 
| 
      
 191 
     | 
    
         
            +
                properties = valid_transaction_properties
         
     | 
| 
      
 192 
     | 
    
         
            +
                res = nil
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                stub_request(:any, /.*/).to_return(:body => "{123", :status => 200)
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                expect { res = Sift::Client.new(:api_key => api_key).track(event, properties) }.to raise_error(TypeError)
         
     | 
| 
      
 197 
     | 
    
         
            +
              end
         
     | 
| 
      
 198 
     | 
    
         
            +
             
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
              it "Preserves response on HTTP errors but does not raise an exception" do
         
     | 
| 
      
 201 
     | 
    
         
            +
                api_key = "foobar"
         
     | 
| 
      
 202 
     | 
    
         
            +
                event = "$transaction"
         
     | 
| 
      
 203 
     | 
    
         
            +
                properties = valid_transaction_properties
         
     | 
| 
      
 204 
     | 
    
         
            +
                res = nil
         
     | 
| 
       147 
205 
     | 
    
         | 
| 
       148 
206 
     | 
    
         
             
                stub_request(:any, /.*/).to_return(:status => 401)
         
     | 
| 
       149 
207 
     | 
    
         | 
| 
       150 
     | 
    
         
            -
                 
     | 
| 
       151 
     | 
    
         
            -
                 
     | 
| 
       152 
     | 
    
         
            -
                expect(Sift::Client.new(:api_key => api_key).track(event, properties)).to eq(nil)
         
     | 
| 
      
 208 
     | 
    
         
            +
                expect { res = Sift::Client.new(:api_key => api_key).track(event, properties) }.not_to raise_error
         
     | 
| 
      
 209 
     | 
    
         
            +
                expect(res.http_status_code).to eq(401)
         
     | 
| 
       153 
210 
     | 
    
         
             
              end
         
     | 
| 
       154 
211 
     | 
    
         | 
| 
       155 
212 
     | 
    
         | 
| 
       156 
     | 
    
         
            -
              it " 
     | 
| 
      
 213 
     | 
    
         
            +
              it "Propagates exception when a StandardError occurs within the request" do
         
     | 
| 
       157 
214 
     | 
    
         
             
                api_key = "foobar"
         
     | 
| 
       158 
215 
     | 
    
         
             
                event = "$transaction"
         
     | 
| 
       159 
216 
     | 
    
         
             
                properties = valid_transaction_properties
         
     | 
| 
       160 
217 
     | 
    
         | 
| 
       161 
218 
     | 
    
         
             
                stub_request(:any, /.*/).to_raise(StandardError)
         
     | 
| 
       162 
219 
     | 
    
         | 
| 
       163 
     | 
    
         
            -
                 
     | 
| 
       164 
     | 
    
         
            -
                # a StandardError exception was thrown
         
     | 
| 
       165 
     | 
    
         
            -
                expect(Sift::Client.new(:api_key => api_key).track(event, properties)).to eq(nil)
         
     | 
| 
      
 220 
     | 
    
         
            +
                expect { Sift::Client.new(:api_key => api_key).track(event, properties) }.to raise_error(StandardError)
         
     | 
| 
       166 
221 
     | 
    
         
             
              end
         
     | 
| 
       167 
222 
     | 
    
         | 
| 
       168 
223 
     | 
    
         | 
| 
       169 
224 
     | 
    
         
             
              it "Successfuly handles an event and returns OK" do
         
     | 
| 
       170 
225 
     | 
    
         
             
                response_json = { :status => 0, :error_message => "OK" }
         
     | 
| 
       171 
226 
     | 
    
         | 
| 
       172 
     | 
    
         
            -
                stub_request(:post, "https://api.siftscience.com/ 
     | 
| 
      
 227 
     | 
    
         
            +
                stub_request(:post, "https://api.siftscience.com/v205/events").
         
     | 
| 
       173 
228 
     | 
    
         
             
                  with { |request|
         
     | 
| 
       174 
229 
     | 
    
         
             
                    parsed_body = JSON.parse(request.body)
         
     | 
| 
       175 
230 
     | 
    
         
             
                    expect(parsed_body).to include("$buyer_user_id" => "123456")
         
     | 
| 
         @@ -190,7 +245,7 @@ describe Sift::Client do 
     | 
|
| 
       190 
245 
     | 
    
         | 
| 
       191 
246 
     | 
    
         
             
              it "Successfully submits event with overridden key" do
         
     | 
| 
       192 
247 
     | 
    
         
             
                response_json = { :status => 0, :error_message => "OK"}
         
     | 
| 
       193 
     | 
    
         
            -
                stub_request(:post, "https://api.siftscience.com/ 
     | 
| 
      
 248 
     | 
    
         
            +
                stub_request(:post, "https://api.siftscience.com/v205/events").
         
     | 
| 
       194 
249 
     | 
    
         
             
                  with { | request|
         
     | 
| 
       195 
250 
     | 
    
         
             
                    parsed_body = JSON.parse(request.body)
         
     | 
| 
       196 
251 
     | 
    
         
             
                    expect(parsed_body).to include("$buyer_user_id" => "123456")
         
     | 
| 
         @@ -212,7 +267,7 @@ describe Sift::Client do 
     | 
|
| 
       212 
267 
     | 
    
         
             
              it "Successfully scrubs nils" do
         
     | 
| 
       213 
268 
     | 
    
         
             
                response_json = { :status => 0, :error_message => "OK" }
         
     | 
| 
       214 
269 
     | 
    
         | 
| 
       215 
     | 
    
         
            -
                stub_request(:post, "https://api.siftscience.com/ 
     | 
| 
      
 270 
     | 
    
         
            +
                stub_request(:post, "https://api.siftscience.com/v205/events")
         
     | 
| 
       216 
271 
     | 
    
         
             
                  .with { |request|
         
     | 
| 
       217 
272 
     | 
    
         
             
                    parsed_body = JSON.parse(request.body)
         
     | 
| 
       218 
273 
     | 
    
         
             
                    expect(parsed_body).not_to include("fake_property")
         
     | 
| 
         @@ -241,7 +296,7 @@ describe Sift::Client do 
     | 
|
| 
       241 
296 
     | 
    
         
             
                api_key = "foobar"
         
     | 
| 
       242 
297 
     | 
    
         
             
                response_json = score_response_json
         
     | 
| 
       243 
298 
     | 
    
         | 
| 
       244 
     | 
    
         
            -
                stub_request(:get, "https://api.siftscience.com/ 
     | 
| 
      
 299 
     | 
    
         
            +
                stub_request(:get, "https://api.siftscience.com/v205/score/247019/?api_key=foobar")
         
     | 
| 
       245 
300 
     | 
    
         
             
                  .to_return(:status => 200, :body => MultiJson.dump(response_json),
         
     | 
| 
       246 
301 
     | 
    
         
             
                             :headers => {"content-type"=>"application/json; charset=UTF-8",
         
     | 
| 
       247 
302 
     | 
    
         
             
                                          "content-length"=> "74"})
         
     | 
| 
         @@ -259,7 +314,7 @@ describe Sift::Client do 
     | 
|
| 
       259 
314 
     | 
    
         
             
                api_key = "foobar"
         
     | 
| 
       260 
315 
     | 
    
         
             
                response_json = score_response_json
         
     | 
| 
       261 
316 
     | 
    
         | 
| 
       262 
     | 
    
         
            -
                stub_request(:get, "https://api.siftscience.com/ 
     | 
| 
      
 317 
     | 
    
         
            +
                stub_request(:get, "https://api.siftscience.com/v205/score/247019/?api_key=overridden")
         
     | 
| 
       263 
318 
     | 
    
         
             
                  .to_return(:status => 200, :body => MultiJson.dump(response_json), :headers => {})
         
     | 
| 
       264 
319 
     | 
    
         | 
| 
       265 
320 
     | 
    
         
             
                response = Sift::Client.new(:api_key => api_key)
         
     | 
| 
         @@ -272,6 +327,88 @@ describe Sift::Client do 
     | 
|
| 
       272 
327 
     | 
    
         
             
              end
         
     | 
| 
       273 
328 
     | 
    
         | 
| 
       274 
329 
     | 
    
         | 
| 
      
 330 
     | 
    
         
            +
              it "Successfully executes client.get_user_score()" do
         
     | 
| 
      
 331 
     | 
    
         
            +
                api_key = "foobar"
         
     | 
| 
      
 332 
     | 
    
         
            +
                response_json = user_score_response_json
         
     | 
| 
      
 333 
     | 
    
         
            +
             
     | 
| 
      
 334 
     | 
    
         
            +
                stub_request(:get, "https://api.siftscience.com/v205/users/247019/score?api_key=foobar")
         
     | 
| 
      
 335 
     | 
    
         
            +
                  .to_return(:status => 200, :body => MultiJson.dump(response_json),
         
     | 
| 
      
 336 
     | 
    
         
            +
                             :headers => {"content-type"=>"application/json; charset=UTF-8",
         
     | 
| 
      
 337 
     | 
    
         
            +
                                          "content-length"=> "74"})
         
     | 
| 
      
 338 
     | 
    
         
            +
             
     | 
| 
      
 339 
     | 
    
         
            +
                response = Sift::Client.new(:api_key => api_key).get_user_score(user_score_response_json[:entity_id])
         
     | 
| 
      
 340 
     | 
    
         
            +
                expect(response.ok?).to eq(true)
         
     | 
| 
      
 341 
     | 
    
         
            +
                expect(response.api_status).to eq(0)
         
     | 
| 
      
 342 
     | 
    
         
            +
                expect(response.api_error_message).to eq("OK")
         
     | 
| 
      
 343 
     | 
    
         
            +
             
     | 
| 
      
 344 
     | 
    
         
            +
                expect(response.body["entity_id"]).to eq("247019")
         
     | 
| 
      
 345 
     | 
    
         
            +
                expect(response.body["scores"]["payment_abuse"]["score"]).to eq(0.78)
         
     | 
| 
      
 346 
     | 
    
         
            +
              end
         
     | 
| 
      
 347 
     | 
    
         
            +
             
     | 
| 
      
 348 
     | 
    
         
            +
             
     | 
| 
      
 349 
     | 
    
         
            +
              it "Successfully executes client.get_user_score() with abuse types specified" do
         
     | 
| 
      
 350 
     | 
    
         
            +
                api_key = "foobar"
         
     | 
| 
      
 351 
     | 
    
         
            +
                response_json = user_score_response_json
         
     | 
| 
      
 352 
     | 
    
         
            +
             
     | 
| 
      
 353 
     | 
    
         
            +
                stub_request(:get, "https://api.siftscience.com/v205/users/247019/score" +
         
     | 
| 
      
 354 
     | 
    
         
            +
                             "?api_key=foobar&abuse_types=content_abuse,payment_abuse")
         
     | 
| 
      
 355 
     | 
    
         
            +
                  .to_return(:status => 200, :body => MultiJson.dump(response_json),
         
     | 
| 
      
 356 
     | 
    
         
            +
                             :headers => {"content-type"=>"application/json; charset=UTF-8",
         
     | 
| 
      
 357 
     | 
    
         
            +
                                          "content-length"=> "74"})
         
     | 
| 
      
 358 
     | 
    
         
            +
             
     | 
| 
      
 359 
     | 
    
         
            +
                response = Sift::Client.new(:api_key => api_key).get_user_score(user_score_response_json[:entity_id],
         
     | 
| 
      
 360 
     | 
    
         
            +
                                                                                :abuse_types => ["content_abuse",
         
     | 
| 
      
 361 
     | 
    
         
            +
                                                                                                 "payment_abuse"])
         
     | 
| 
      
 362 
     | 
    
         
            +
                expect(response.ok?).to eq(true)
         
     | 
| 
      
 363 
     | 
    
         
            +
                expect(response.api_status).to eq(0)
         
     | 
| 
      
 364 
     | 
    
         
            +
                expect(response.api_error_message).to eq("OK")
         
     | 
| 
      
 365 
     | 
    
         
            +
             
     | 
| 
      
 366 
     | 
    
         
            +
                expect(response.body["entity_id"]).to eq("247019")
         
     | 
| 
      
 367 
     | 
    
         
            +
                expect(response.body["scores"]["payment_abuse"]["score"]).to eq(0.78)
         
     | 
| 
      
 368 
     | 
    
         
            +
              end
         
     | 
| 
      
 369 
     | 
    
         
            +
             
     | 
| 
      
 370 
     | 
    
         
            +
             
     | 
| 
      
 371 
     | 
    
         
            +
              it "Successfully executes client.rescore_user()" do
         
     | 
| 
      
 372 
     | 
    
         
            +
                api_key = "foobar"
         
     | 
| 
      
 373 
     | 
    
         
            +
                response_json = user_score_response_json
         
     | 
| 
      
 374 
     | 
    
         
            +
             
     | 
| 
      
 375 
     | 
    
         
            +
                stub_request(:post, "https://api.siftscience.com/v205/users/247019/score?api_key=foobar")
         
     | 
| 
      
 376 
     | 
    
         
            +
                  .to_return(:status => 200, :body => MultiJson.dump(response_json),
         
     | 
| 
      
 377 
     | 
    
         
            +
                             :headers => {"content-type"=>"application/json; charset=UTF-8",
         
     | 
| 
      
 378 
     | 
    
         
            +
                                          "content-length"=> "74"})
         
     | 
| 
      
 379 
     | 
    
         
            +
             
     | 
| 
      
 380 
     | 
    
         
            +
                response = Sift::Client.new(:api_key => api_key).rescore_user(user_score_response_json[:entity_id])
         
     | 
| 
      
 381 
     | 
    
         
            +
                expect(response.ok?).to eq(true)
         
     | 
| 
      
 382 
     | 
    
         
            +
                expect(response.api_status).to eq(0)
         
     | 
| 
      
 383 
     | 
    
         
            +
                expect(response.api_error_message).to eq("OK")
         
     | 
| 
      
 384 
     | 
    
         
            +
             
     | 
| 
      
 385 
     | 
    
         
            +
                expect(response.body["entity_id"]).to eq("247019")
         
     | 
| 
      
 386 
     | 
    
         
            +
                expect(response.body["scores"]["payment_abuse"]["score"]).to eq(0.78)
         
     | 
| 
      
 387 
     | 
    
         
            +
              end
         
     | 
| 
      
 388 
     | 
    
         
            +
             
     | 
| 
      
 389 
     | 
    
         
            +
             
     | 
| 
      
 390 
     | 
    
         
            +
              it "Successfully executes client.rescore_user() with abuse types specified" do
         
     | 
| 
      
 391 
     | 
    
         
            +
                api_key = "foobar"
         
     | 
| 
      
 392 
     | 
    
         
            +
                response_json = user_score_response_json
         
     | 
| 
      
 393 
     | 
    
         
            +
             
     | 
| 
      
 394 
     | 
    
         
            +
                stub_request(:post, "https://api.siftscience.com/v205/users/247019/score" +
         
     | 
| 
      
 395 
     | 
    
         
            +
                             "?api_key=foobar&abuse_types=content_abuse,payment_abuse")
         
     | 
| 
      
 396 
     | 
    
         
            +
                  .to_return(:status => 200, :body => MultiJson.dump(response_json),
         
     | 
| 
      
 397 
     | 
    
         
            +
                             :headers => {"content-type"=>"application/json; charset=UTF-8",
         
     | 
| 
      
 398 
     | 
    
         
            +
                                          "content-length"=> "74"})
         
     | 
| 
      
 399 
     | 
    
         
            +
             
     | 
| 
      
 400 
     | 
    
         
            +
                response = Sift::Client.new(:api_key => api_key).rescore_user(user_score_response_json[:entity_id],
         
     | 
| 
      
 401 
     | 
    
         
            +
                                                                              :abuse_types => ["content_abuse",
         
     | 
| 
      
 402 
     | 
    
         
            +
                                                                                               "payment_abuse"])
         
     | 
| 
      
 403 
     | 
    
         
            +
                expect(response.ok?).to eq(true)
         
     | 
| 
      
 404 
     | 
    
         
            +
                expect(response.api_status).to eq(0)
         
     | 
| 
      
 405 
     | 
    
         
            +
                expect(response.api_error_message).to eq("OK")
         
     | 
| 
      
 406 
     | 
    
         
            +
             
     | 
| 
      
 407 
     | 
    
         
            +
                expect(response.body["entity_id"]).to eq("247019")
         
     | 
| 
      
 408 
     | 
    
         
            +
                expect(response.body["scores"]["payment_abuse"]["score"]).to eq(0.78)
         
     | 
| 
      
 409 
     | 
    
         
            +
              end
         
     | 
| 
      
 410 
     | 
    
         
            +
             
     | 
| 
      
 411 
     | 
    
         
            +
             
     | 
| 
       275 
412 
     | 
    
         
             
              it "Successfully make a sync score request" do
         
     | 
| 
       276 
413 
     | 
    
         
             
                api_key = "foobar"
         
     | 
| 
       277 
414 
     | 
    
         
             
                response_json = {
         
     | 
| 
         @@ -280,7 +417,7 @@ describe Sift::Client do 
     | 
|
| 
       280 
417 
     | 
    
         
             
                  :score_response => score_response_json
         
     | 
| 
       281 
418 
     | 
    
         
             
                }
         
     | 
| 
       282 
419 
     | 
    
         | 
| 
       283 
     | 
    
         
            -
                stub_request(:post, "https://api.siftscience.com/ 
     | 
| 
      
 420 
     | 
    
         
            +
                stub_request(:post, "https://api.siftscience.com/v205/events?return_score=true")
         
     | 
| 
       284 
421 
     | 
    
         
             
                  .to_return(:status => 200, :body => MultiJson.dump(response_json),
         
     | 
| 
       285 
422 
     | 
    
         
             
                             :headers => {"content-type"=>"application/json; charset=UTF-8",
         
     | 
| 
       286 
423 
     | 
    
         
             
                                          "content-length"=> "74"})
         
     | 
| 
         @@ -304,7 +441,7 @@ describe Sift::Client do 
     | 
|
| 
       304 
441 
     | 
    
         
             
                  :score_response => action_response_json
         
     | 
| 
       305 
442 
     | 
    
         
             
                }
         
     | 
| 
       306 
443 
     | 
    
         | 
| 
       307 
     | 
    
         
            -
                stub_request(:post, "https://api.siftscience.com/ 
     | 
| 
      
 444 
     | 
    
         
            +
                stub_request(:post, "https://api.siftscience.com/v205/events?return_action=true")
         
     | 
| 
       308 
445 
     | 
    
         
             
                  .to_return(:status => 200, :body => MultiJson.dump(response_json),
         
     | 
| 
       309 
446 
     | 
    
         
             
                             :headers => {"content-type"=>"application/json; charset=UTF-8",
         
     | 
| 
       310 
447 
     | 
    
         
             
                                          "content-length"=> "74"})
         
     | 
| 
         @@ -332,7 +469,7 @@ describe Sift::Client do 
     | 
|
| 
       332 
469 
     | 
    
         
             
                }
         
     | 
| 
       333 
470 
     | 
    
         | 
| 
       334 
471 
     | 
    
         
             
                stub_request(:post,
         
     | 
| 
       335 
     | 
    
         
            -
                             "https://api.siftscience.com/ 
     | 
| 
      
 472 
     | 
    
         
            +
                             "https://api.siftscience.com/v205/events?return_workflow_status=true&return_route_info=true&abuse_types=legacy,payment_abuse")
         
     | 
| 
       336 
473 
     | 
    
         
             
                  .to_return(:status => 200, :body => MultiJson.dump(response_json),
         
     | 
| 
       337 
474 
     | 
    
         
             
                             :headers => {"content-type"=>"application/json; charset=UTF-8",
         
     | 
| 
       338 
475 
     | 
    
         
             
                                          "content-length"=> "74"})
         
     | 
| 
         @@ -341,7 +478,8 @@ describe Sift::Client do 
     | 
|
| 
       341 
478 
     | 
    
         
             
                properties = valid_transaction_properties
         
     | 
| 
       342 
479 
     | 
    
         
             
                response = Sift::Client.new(:api_key => api_key)
         
     | 
| 
       343 
480 
     | 
    
         
             
                           .track(event, properties,
         
     | 
| 
       344 
     | 
    
         
            -
                                  :return_workflow_status => true, : 
     | 
| 
      
 481 
     | 
    
         
            +
                                  :return_workflow_status => true, :return_route_info => true,
         
     | 
| 
      
 482 
     | 
    
         
            +
                                  :abuse_types => ['legacy', 'payment_abuse'])
         
     | 
| 
       345 
483 
     | 
    
         
             
                expect(response.ok?).to eq(true)
         
     | 
| 
       346 
484 
     | 
    
         
             
                expect(response.api_status).to eq(0)
         
     | 
| 
       347 
485 
     | 
    
         
             
                expect(response.api_error_message).to eq("OK")
         
     | 
| 
         @@ -363,7 +501,7 @@ describe Sift::Client do 
     | 
|
| 
       363 
501 
     | 
    
         
             
              end
         
     | 
| 
       364 
502 
     | 
    
         | 
| 
       365 
503 
     | 
    
         | 
| 
       366 
     | 
    
         
            -
             
     | 
| 
      
 504 
     | 
    
         
            +
              it "Successfully make a user decisions request" do
         
     | 
| 
       367 
505 
     | 
    
         
             
                response_text = '{"decisions":{"content_abuse":{"decision":{"id":"user_decision"},"time":1468707128659,"webhook_succeeded":false}}}'
         
     | 
| 
       368 
506 
     | 
    
         | 
| 
       369 
507 
     | 
    
         
             
                stub_request(:get, "https://foobar:@api3.siftscience.com/v3/accounts/ACCT/users/example_user/decisions")
         
     | 
| 
         @@ -390,4 +528,30 @@ describe Sift::Client do 
     | 
|
| 
       390 
528 
     | 
    
         
             
                expect(response.body["decisions"]["payment_abuse"]["decision"]["id"]).to eq("decision7")
         
     | 
| 
       391 
529 
     | 
    
         
             
              end
         
     | 
| 
       392 
530 
     | 
    
         | 
| 
      
 531 
     | 
    
         
            +
              it "Successfully make a session decisions request" do
         
     | 
| 
      
 532 
     | 
    
         
            +
                response_text = '{"decisions":{"account_takeover":{"decision":{"id":"session_decision"},"time":1468707128659,"webhook_succeeded":false}}}'
         
     | 
| 
      
 533 
     | 
    
         
            +
             
     | 
| 
      
 534 
     | 
    
         
            +
                stub_request(:get, "https://foobar:@api3.siftscience.com/v3/accounts/ACCT/users/example_user/sessions/example_session/decisions")
         
     | 
| 
      
 535 
     | 
    
         
            +
                  .to_return(:status => 200, :body => response_text, :headers => {})
         
     | 
| 
      
 536 
     | 
    
         
            +
             
     | 
| 
      
 537 
     | 
    
         
            +
                client = Sift::Client.new(:api_key => "foobar", :account_id => "ACCT")
         
     | 
| 
      
 538 
     | 
    
         
            +
                response = client.get_session_decisions("example_user", "example_session")
         
     | 
| 
      
 539 
     | 
    
         
            +
             
     | 
| 
      
 540 
     | 
    
         
            +
                expect(response.ok?).to eq(true)
         
     | 
| 
      
 541 
     | 
    
         
            +
                expect(response.body["decisions"]["account_takeover"]["decision"]["id"]).to eq("session_decision")
         
     | 
| 
      
 542 
     | 
    
         
            +
              end
         
     | 
| 
      
 543 
     | 
    
         
            +
             
     | 
| 
      
 544 
     | 
    
         
            +
              it "Successfully make an content decisions request" do
         
     | 
| 
      
 545 
     | 
    
         
            +
                response_text = '{"decisions":{"content_abuse":{"decision":{"id":"decision7"},"time":1468599638005,"webhook_succeeded":false}}}'
         
     | 
| 
      
 546 
     | 
    
         
            +
             
     | 
| 
      
 547 
     | 
    
         
            +
                stub_request(:get, "https://foobar:@api3.siftscience.com/v3/accounts/ACCT/users/USER/content/example_content/decisions")
         
     | 
| 
      
 548 
     | 
    
         
            +
                  .to_return(:status => 200, :body => response_text, :headers => {})
         
     | 
| 
      
 549 
     | 
    
         
            +
             
     | 
| 
      
 550 
     | 
    
         
            +
                client = Sift::Client.new(:api_key => "foobar", :account_id => "ACCT")
         
     | 
| 
      
 551 
     | 
    
         
            +
                response = client.get_content_decisions("USER", "example_content", :timeout => 3)
         
     | 
| 
      
 552 
     | 
    
         
            +
             
     | 
| 
      
 553 
     | 
    
         
            +
                expect(response.ok?).to eq(true)
         
     | 
| 
      
 554 
     | 
    
         
            +
                expect(response.body["decisions"]["content_abuse"]["decision"]["id"]).to eq("decision7")
         
     | 
| 
      
 555 
     | 
    
         
            +
              end
         
     | 
| 
      
 556 
     | 
    
         
            +
             
     | 
| 
       393 
557 
     | 
    
         
             
            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 
     | 
    
         
            +
              version: 4.1.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:  
     | 
| 
      
 13 
     | 
    
         
            +
            date: 2022-07-11 00:00:00.000000000 Z
         
     | 
| 
       14 
14 
     | 
    
         
             
            dependencies:
         
     | 
| 
       15 
15 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       16 
16 
     | 
    
         
             
              name: rspec
         
     | 
| 
         @@ -26,6 +26,20 @@ dependencies: 
     | 
|
| 
       26 
26 
     | 
    
         
             
                - - "~>"
         
     | 
| 
       27 
27 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       28 
28 
     | 
    
         
             
                    version: '3.5'
         
     | 
| 
      
 29 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 30 
     | 
    
         
            +
              name: rspec_junit_formatter
         
     | 
| 
      
 31 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 32 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 33 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 34 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 35 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 36 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 37 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 38 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 39 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 40 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 41 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 42 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
       29 
43 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       30 
44 
     | 
    
         
             
              name: pry
         
     | 
| 
       31 
45 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
         @@ -109,8 +123,8 @@ executables: [] 
     | 
|
| 
       109 
123 
     | 
    
         
             
            extensions: []
         
     | 
| 
       110 
124 
     | 
    
         
             
            extra_rdoc_files: []
         
     | 
| 
       111 
125 
     | 
    
         
             
            files:
         
     | 
| 
      
 126 
     | 
    
         
            +
            - ".circleci/config.yml"
         
     | 
| 
       112 
127 
     | 
    
         
             
            - ".gitignore"
         
     | 
| 
       113 
     | 
    
         
            -
            - ".travis.yml"
         
     | 
| 
       114 
128 
     | 
    
         
             
            - Gemfile
         
     | 
| 
       115 
129 
     | 
    
         
             
            - HISTORY
         
     | 
| 
       116 
130 
     | 
    
         
             
            - LICENSE
         
     | 
| 
         @@ -142,7 +156,7 @@ files: 
     | 
|
| 
       142 
156 
     | 
    
         
             
            homepage: http://siftscience.com
         
     | 
| 
       143 
157 
     | 
    
         
             
            licenses: []
         
     | 
| 
       144 
158 
     | 
    
         
             
            metadata: {}
         
     | 
| 
       145 
     | 
    
         
            -
            post_install_message: 
     | 
| 
      
 159 
     | 
    
         
            +
            post_install_message:
         
     | 
| 
       146 
160 
     | 
    
         
             
            rdoc_options: []
         
     | 
| 
       147 
161 
     | 
    
         
             
            require_paths:
         
     | 
| 
       148 
162 
     | 
    
         
             
            - lib
         
     | 
| 
         @@ -157,9 +171,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       157 
171 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       158 
172 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       159 
173 
     | 
    
         
             
            requirements: []
         
     | 
| 
       160 
     | 
    
         
            -
             
     | 
| 
       161 
     | 
    
         
            -
             
     | 
| 
       162 
     | 
    
         
            -
            signing_key: 
         
     | 
| 
      
 174 
     | 
    
         
            +
            rubygems_version: 3.1.4
         
     | 
| 
      
 175 
     | 
    
         
            +
            signing_key:
         
     | 
| 
       163 
176 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       164 
177 
     | 
    
         
             
            summary: Sift Science Ruby API Gem
         
     | 
| 
       165 
178 
     | 
    
         
             
            test_files:
         
     | 
    
        data/.travis.yml
    DELETED
    
    | 
         @@ -1,18 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            language: ruby
         
     | 
| 
       2 
     | 
    
         
            -
            script: "bundle exec rake spec"
         
     | 
| 
       3 
     | 
    
         
            -
            rvm:
         
     | 
| 
       4 
     | 
    
         
            -
              - 1.9.3
         
     | 
| 
       5 
     | 
    
         
            -
              - 2.0.0
         
     | 
| 
       6 
     | 
    
         
            -
              - 2.1.5
         
     | 
| 
       7 
     | 
    
         
            -
              - 2.2.1
         
     | 
| 
       8 
     | 
    
         
            -
            before_install:
         
     | 
| 
       9 
     | 
    
         
            -
              - gem install bundler
         
     | 
| 
       10 
     | 
    
         
            -
              - bundle --version
         
     | 
| 
       11 
     | 
    
         
            -
            env:
         
     | 
| 
       12 
     | 
    
         
            -
              # None for now
         
     | 
| 
       13 
     | 
    
         
            -
            gemfile:
         
     | 
| 
       14 
     | 
    
         
            -
              - Gemfile
         
     | 
| 
       15 
     | 
    
         
            -
            services:
         
     | 
| 
       16 
     | 
    
         
            -
              # None for now
         
     | 
| 
       17 
     | 
    
         
            -
            notifications:
         
     | 
| 
       18 
     | 
    
         
            -
              # None for now
         
     |