sift 1.1.7.3 → 2.0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -13
- data/.travis.yml +5 -0
- data/HISTORY +6 -2
- data/README.rdoc +36 -11
- data/lib/sift.rb +33 -8
- data/lib/sift/client.rb +347 -107
- data/lib/sift/version.rb +2 -2
- data/sift.gemspec +2 -2
- data/spec/unit/client_203_spec.rb +192 -0
- data/spec/unit/client_label_spec.rb +55 -11
- data/spec/unit/client_spec.rb +141 -49
- metadata +26 -17
    
        checksums.yaml
    CHANGED
    
    | @@ -1,15 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 | 
            -
             | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
             | 
| 5 | 
            -
              data.tar.gz: !binary |-
         | 
| 6 | 
            -
                NjJmY2FmYWQxMWEyNjFlY2MwMDdmOGZlN2ZiMWE0ODFiMGI1N2MyYg==
         | 
| 2 | 
            +
            SHA1:
         | 
| 3 | 
            +
              metadata.gz: 5116181929ffbab6a17941eb341a852a7c4c75c6
         | 
| 4 | 
            +
              data.tar.gz: 4699c62cdadc3fd2f9123b929925abcf45cfb19b
         | 
| 7 5 | 
             
            SHA512:
         | 
| 8 | 
            -
              metadata.gz:  | 
| 9 | 
            -
             | 
| 10 | 
            -
                ZjhkNmZlMzA5MGRiNGU1OWM3NGI4MzFjMDZkODE5NzQ3NDkyZGQwYmVhNzIy
         | 
| 11 | 
            -
                NzI3ZmIzZjkzMzMyMWEwMTBmMzMxYTIwMjA0YTExN2UxZThhNDE=
         | 
| 12 | 
            -
              data.tar.gz: !binary |-
         | 
| 13 | 
            -
                ZGQ0Zjk1YTRmM2YyYzBhMjkzYzcxNzZkOWIxNTIxNTY2MzcyZmUyY2U3ZDRi
         | 
| 14 | 
            -
                YTk1OGExNzBlZDFjNjhlZjhlOTE4NDUzOWJjNjI0Y2MwOTFmYmEwMmY1MDI0
         | 
| 15 | 
            -
                OWU1MDQ0YzBmN2EzMmE1ZmQyMDRmNTJkNTI5Y2IzNzAwNTlmN2M=
         | 
| 6 | 
            +
              metadata.gz: 5d228bd45520217fe3e06a0e2673e4a176b497ff83fc5f73940a6e656006b7725521597fb263d64cc133020162400562380b30aee1f29c9a3bde91ce080e03a3
         | 
| 7 | 
            +
              data.tar.gz: bce89304cbf0eb1c963e05c9ec76248ba5e06d9c0829df983735dfaf5828288faf8e73fd3c81a53876ee39081cf3695364a929775ffdb5665caa99fc4dc6f957
         | 
    
        data/.travis.yml
    CHANGED
    
    
    
        data/HISTORY
    CHANGED
    
    | @@ -1,5 +1,9 @@ | |
| 1 | 
            -
            ===  | 
| 2 | 
            -
            *  | 
| 1 | 
            +
            === 2.0.0.0 2016-07-19
         | 
| 2 | 
            +
            * adds support for v204 of Sift Science's APIs
         | 
| 3 | 
            +
            * adds Workflow Status API, User Decisions API, Order Decisions API
         | 
| 4 | 
            +
            * v204 APIs are now called by default -- this is an incompatible change
         | 
| 5 | 
            +
              (use :version => 203 to call the previous API version)
         | 
| 6 | 
            +
            * uses Hash arg for optional params in Client methods -- incompatible change
         | 
| 3 7 |  | 
| 4 8 | 
             
            === 1.1.7.2 2015-04-13
         | 
| 5 9 | 
             
            * Fixed backwards compatibility issue
         | 
    
        data/README.rdoc
    CHANGED
    
    | @@ -1,5 +1,6 @@ | |
| 1 1 | 
             
            = Sift Science Ruby bindings {<img src="https://travis-ci.org/SiftScience/sift-ruby.png?branch=master" alt="Build Status" />}[https://travis-ci.org/SiftScience/sift-ruby]
         | 
| 2 2 |  | 
| 3 | 
            +
             | 
| 3 4 | 
             
            == Requirements
         | 
| 4 5 |  | 
| 5 6 | 
             
              * Ruby 1.8.7 or above. (Ruby 1.8.6 might work if you load ActiveSupport.)
         | 
| @@ -12,6 +13,7 @@ For development only: | |
| 12 13 | 
             
              * webmock, 1.16 or greater
         | 
| 13 14 | 
             
              * rake, any version
         | 
| 14 15 |  | 
| 16 | 
            +
             | 
| 15 17 | 
             
            == Installation
         | 
| 16 18 |  | 
| 17 19 | 
             
            If you want to build the gem from source:
         | 
| @@ -22,16 +24,19 @@ Alternatively, you can install the gem from Rubyforge: | |
| 22 24 |  | 
| 23 25 | 
             
              $ gem install sift
         | 
| 24 26 |  | 
| 27 | 
            +
             | 
| 25 28 | 
             
            == Usage
         | 
| 29 | 
            +
             | 
| 26 30 | 
             
              require "sift"
         | 
| 27 31 |  | 
| 28 32 | 
             
              Sift.api_key = '<your_api_key_here>'
         | 
| 33 | 
            +
              Sift.account_id = '<your_account_id_here>'
         | 
| 29 34 | 
             
              client = Sift::Client.new()
         | 
| 30 35 |  | 
| 31 36 | 
             
              # send a transaction event -- note this is blocking 
         | 
| 32 37 | 
             
              event = "$transaction"
         | 
| 33 38 |  | 
| 34 | 
            -
              user_id = "23056" | 
| 39 | 
            +
              user_id = "23056"  # User ID's may only contain a-z, A-Z, 0-9, =, ., -, _, +, @, :, &, ^, %, !, $
         | 
| 35 40 |  | 
| 36 41 | 
             
              properties = {
         | 
| 37 42 | 
             
               "$user_id" => user_id, 
         | 
| @@ -50,20 +55,39 @@ Alternatively, you can install the gem from Rubyforge: | |
| 50 55 | 
             
              }
         | 
| 51 56 |  | 
| 52 57 | 
             
              response = client.track(event, properties)
         | 
| 53 | 
            -
              
         | 
| 54 | 
            -
              response.ok? # returns true or false
         | 
| 55 | 
            -
              
         | 
| 56 | 
            -
              response.http_status_code # HTTP response code, 200 is ok.
         | 
| 57 | 
            -
             | 
| 58 | 
            -
              response.api_status # status field in the return body, Link to Error Codes
         | 
| 59 58 |  | 
| 60 | 
            -
              response. | 
| 59 | 
            +
              response.ok?  # returns true or false
         | 
| 60 | 
            +
              response.body  # API response body
         | 
| 61 | 
            +
              response.http_status_code  # HTTP response code, 200 is ok.
         | 
| 62 | 
            +
              response.api_status  # status field in the return body, Link to Error Codes
         | 
| 63 | 
            +
              response.api_error_message  # Error message associated with status Error Code
         | 
| 61 64 |  | 
| 62 | 
            -
             | 
| 65 | 
            +
             | 
| 66 | 
            +
              # Request a score for the user with user_id 23056
         | 
| 63 67 | 
             
              response = client.score(user_id)
         | 
| 64 | 
            -
             | 
| 68 | 
            +
             | 
| 69 | 
            +
             | 
| 65 70 | 
             
              # Label the user with user_id 23056 as Bad with all optional fields
         | 
| 66 | 
            -
              response = client.label(user_id,{ | 
| 71 | 
            +
              response = client.label(user_id, {
         | 
| 72 | 
            +
                "$is_bad" => true,
         | 
| 73 | 
            +
                "$abuse_type" => "payment_abuse",
         | 
| 74 | 
            +
                "$description" => "Chargeback issued",
         | 
| 75 | 
            +
                "$source" => "Manual Review",
         | 
| 76 | 
            +
                "$analyst" => "analyst.name@your_domain.com"
         | 
| 77 | 
            +
              })
         | 
| 78 | 
            +
             | 
| 79 | 
            +
             | 
| 80 | 
            +
              # Get the status of a workflow run
         | 
| 81 | 
            +
              response = client.get_workflow_status('my_run_id')
         | 
| 82 | 
            +
             | 
| 83 | 
            +
             | 
| 84 | 
            +
              # Get the latest decisions for a user
         | 
| 85 | 
            +
              response = client.get_user_decisions('example_user_id')
         | 
| 86 | 
            +
             | 
| 87 | 
            +
             | 
| 88 | 
            +
              # Get the latest decisions for an order
         | 
| 89 | 
            +
              response = client.get_order_decisions('example_order_id')
         | 
| 90 | 
            +
             | 
| 67 91 |  | 
| 68 92 | 
             
            == Building
         | 
| 69 93 |  | 
| @@ -78,6 +102,7 @@ Building and publishing the gem is captured by the following steps: | |
| 78 102 | 
             
              $ rake install
         | 
| 79 103 | 
             
              $ rake release
         | 
| 80 104 |  | 
| 105 | 
            +
             | 
| 81 106 | 
             
            == Testing
         | 
| 82 107 |  | 
| 83 108 | 
             
            To run the various tests use the rake command as follows:
         | 
    
        data/lib/sift.rb
    CHANGED
    
    | @@ -3,21 +3,46 @@ require "sift/client" | |
| 3 3 |  | 
| 4 4 | 
             
            module Sift
         | 
| 5 5 |  | 
| 6 | 
            -
              # Returns the path for the  | 
| 7 | 
            -
              def self. | 
| 8 | 
            -
                "/v#{ | 
| 6 | 
            +
              # Returns the path for the specified API version
         | 
| 7 | 
            +
              def self.rest_api_path(version=API_VERSION)
         | 
| 8 | 
            +
                "/v#{version}/events"
         | 
| 9 9 | 
             
              end
         | 
| 10 10 |  | 
| 11 | 
            -
               | 
| 12 | 
            -
             | 
| 13 | 
            -
                "/v#{ | 
| 11 | 
            +
              # Returns the Score API path for the specified user ID and API version
         | 
| 12 | 
            +
              def self.score_api_path(user_id, version=API_VERSION)
         | 
| 13 | 
            +
                "/v#{version}/score/#{URI.encode(user_id)}/"
         | 
| 14 14 | 
             
              end
         | 
| 15 | 
            -
             | 
| 16 | 
            -
              #  | 
| 15 | 
            +
             | 
| 16 | 
            +
              # Returns the users API path for the specified user ID and API version
         | 
| 17 | 
            +
              def self.users_label_api_path(user_id, version=API_VERSION)
         | 
| 18 | 
            +
                "/v#{version}/users/#{URI.encode(user_id)}/labels"
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              # Returns the path for the Workflow Status API
         | 
| 22 | 
            +
              def self.workflow_status_path(account_id, run_id)
         | 
| 23 | 
            +
                "/v3/accounts/#{account_id}/workflows/runs/#{run_id}"
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              # Returns the path for User Decisions API
         | 
| 27 | 
            +
              def self.user_decisions_api_path(account_id, user_id)
         | 
| 28 | 
            +
                "/v3/accounts/#{account_id}/users/#{user_id}/decisions"
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              # Returns the path for Orders Decisions API
         | 
| 32 | 
            +
              def self.order_decisions_api_path(account_id, order_id)
         | 
| 33 | 
            +
                "/v3/accounts/#{account_id}/orders/#{order_id}/decisions"
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              # Module-scoped public API key
         | 
| 17 37 | 
             
              class << self
         | 
| 18 38 | 
             
                attr_accessor :api_key
         | 
| 19 39 | 
             
              end
         | 
| 20 40 |  | 
| 41 | 
            +
              # Module-scoped account ID
         | 
| 42 | 
            +
              class << self
         | 
| 43 | 
            +
                attr_accessor :account_id
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 21 46 | 
             
              # Sets the Output logger to use within the client. This can be left uninitializaed
         | 
| 22 47 | 
             
              # but is useful for debugging.
         | 
| 23 48 | 
             
              def self.logger=(logger)
         | 
    
        data/lib/sift/client.rb
    CHANGED
    
    | @@ -15,8 +15,9 @@ module Sift | |
| 15 15 |  | 
| 16 16 | 
             
                # Constructor
         | 
| 17 17 | 
             
                #
         | 
| 18 | 
            -
                #  | 
| 19 | 
            -
                # | 
| 18 | 
            +
                # ==== Parameters:
         | 
| 19 | 
            +
                #
         | 
| 20 | 
            +
                # http_response::
         | 
| 20 21 | 
             
                #   The HTTP body text returned from the API call. The body is expected to be
         | 
| 21 22 | 
             
                #   a JSON object that can be decoded into status, message and request
         | 
| 22 23 | 
             
                #   sections.
         | 
| @@ -37,10 +38,11 @@ module Sift | |
| 37 38 | 
             
                # Helper method returns true if and only if the response from the API call was
         | 
| 38 39 | 
             
                # successful
         | 
| 39 40 | 
             
                #
         | 
| 40 | 
            -
                #  | 
| 41 | 
            -
                # | 
| 41 | 
            +
                # ==== Returns:
         | 
| 42 | 
            +
                #
         | 
| 43 | 
            +
                # true on success; false otherwise
         | 
| 44 | 
            +
                #
         | 
| 42 45 | 
             
                def ok?
         | 
| 43 | 
            -
             | 
| 44 46 | 
             
                  if @http_raw_response.kind_of? Net::HTTPNoContent
         | 
| 45 47 | 
             
                    #if there is no content expected, use HTTP code
         | 
| 46 48 | 
             
                    204 == @http_status_code
         | 
| @@ -51,14 +53,14 @@ module Sift | |
| 51 53 | 
             
                end
         | 
| 52 54 |  | 
| 53 55 |  | 
| 54 | 
            -
                #  | 
| 55 | 
            -
                # Getter method for  | 
| 56 | 
            +
                # DEPRECATED
         | 
| 57 | 
            +
                # Getter method for deprecated 'json' member variable.
         | 
| 56 58 | 
             
                def json
         | 
| 57 59 | 
             
                  @body
         | 
| 58 60 | 
             
                end
         | 
| 59 61 |  | 
| 60 | 
            -
                #  | 
| 61 | 
            -
                # Getter method for  | 
| 62 | 
            +
                # DEPRECATED
         | 
| 63 | 
            +
                # Getter method for deprecated 'original_request' member variable.
         | 
| 62 64 | 
             
                def original_request
         | 
| 63 65 | 
             
                  @request
         | 
| 64 66 | 
             
                end
         | 
| @@ -67,29 +69,50 @@ module Sift | |
| 67 69 | 
             
              # This class wraps accesses through the API
         | 
| 68 70 | 
             
              #
         | 
| 69 71 | 
             
              class Client
         | 
| 70 | 
            -
                API_ENDPOINT =  | 
| 71 | 
            -
                 | 
| 72 | 
            +
                API_ENDPOINT = 'https://api.siftscience.com'
         | 
| 73 | 
            +
                API3_ENDPOINT = 'https://api3.siftscience.com'
         | 
| 72 74 |  | 
| 73 75 | 
             
                include HTTParty
         | 
| 74 76 | 
             
                base_uri API_ENDPOINT
         | 
| 75 77 |  | 
| 78 | 
            +
             | 
| 76 79 | 
             
                # Constructor
         | 
| 77 80 | 
             
                #
         | 
| 78 | 
            -
                #  | 
| 79 | 
            -
                # api_key
         | 
| 80 | 
            -
                #   The Sift Science API key associated with your customer account. This parameter
         | 
| 81 | 
            -
                #   cannot be nil or blank.
         | 
| 82 | 
            -
                # path
         | 
| 83 | 
            -
                #   The path to the event API, e.g., "/v201/events"
         | 
| 81 | 
            +
                # ==== Parameters:
         | 
| 84 82 | 
             
                #
         | 
| 85 | 
            -
                 | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 83 | 
            +
                # opts (optional)::
         | 
| 84 | 
            +
                #   A Hash of optional parameters for this Client --
         | 
| 85 | 
            +
                #
         | 
| 86 | 
            +
                #   :api_key::
         | 
| 87 | 
            +
                #     The Sift Science API key associated with your account.
         | 
| 88 | 
            +
                #     Sift.api_key is used if this parameter is not set.
         | 
| 89 | 
            +
                #
         | 
| 90 | 
            +
                #   :account_id::
         | 
| 91 | 
            +
                #     The ID of your Sift Science account.  Sift.account_id is
         | 
| 92 | 
            +
                #     used if this parameter is not set.
         | 
| 93 | 
            +
                #
         | 
| 94 | 
            +
                #   :timeout::
         | 
| 95 | 
            +
                #     The number of seconds to wait before failing a request. By
         | 
| 96 | 
            +
                #     default this is configured to 2 seconds.
         | 
| 97 | 
            +
                #
         | 
| 98 | 
            +
                #   :version::
         | 
| 99 | 
            +
                #     The version of the Events API, Score API, and Labels API to call.
         | 
| 100 | 
            +
                #     By default, version 204.
         | 
| 101 | 
            +
                #
         | 
| 102 | 
            +
                #   :path::
         | 
| 103 | 
            +
                #     The URL path to use for Events API path.  By default, the
         | 
| 104 | 
            +
                #     official path of the specified-version of the Events API.
         | 
| 105 | 
            +
                #
         | 
| 106 | 
            +
                #
         | 
| 107 | 
            +
                def initialize(opts = {})
         | 
| 108 | 
            +
                  @api_key = opts[:api_key] || Sift.api_key
         | 
| 109 | 
            +
                  @account_id = opts[:account_id] || Sift.account_id
         | 
| 110 | 
            +
                  @version = opts[:version] || API_VERSION
         | 
| 111 | 
            +
                  @timeout = opts[:timeout] || 2  # 2-second timeout by default
         | 
| 112 | 
            +
                  @path = opts[:path] || Sift.rest_api_path(@version)
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                  raise("api_key must be a non-empty string") if !@api_key.is_a?(String) || @api_key.empty?
         | 
| 115 | 
            +
                  raise("path must be a non-empty string") if !@path.is_a?(String) || @path.empty?
         | 
| 93 116 | 
             
                end
         | 
| 94 117 |  | 
| 95 118 | 
             
                def api_key
         | 
| @@ -97,64 +120,95 @@ module Sift | |
| 97 120 | 
             
                end
         | 
| 98 121 |  | 
| 99 122 | 
             
                def user_agent
         | 
| 100 | 
            -
                  "SiftScience/v#{ | 
| 123 | 
            +
                  "SiftScience/v#{@version} sift-ruby/#{VERSION}"
         | 
| 101 124 | 
             
                end
         | 
| 102 125 |  | 
| 103 | 
            -
             | 
| 104 | 
            -
                #  | 
| 126 | 
            +
             | 
| 127 | 
            +
                # Sends an event to the Sift Science Events API.
         | 
| 105 128 | 
             
                #
         | 
| 106 | 
            -
                #  | 
| 107 | 
            -
                # event
         | 
| 108 | 
            -
                #   The name of the event to send. This can be either a reserved event name, like
         | 
| 109 | 
            -
                #   $transaction or $label or a custom event name (that does not start with a $).
         | 
| 110 | 
            -
                #   This parameter must be specified.
         | 
| 129 | 
            +
                # See https://siftscience.com/developers/docs/ruby/events-api .
         | 
| 111 130 | 
             
                #
         | 
| 112 | 
            -
                #  | 
| 113 | 
            -
                # | 
| 114 | 
            -
                # | 
| 131 | 
            +
                # ==== Parameters:
         | 
| 132 | 
            +
                #
         | 
| 133 | 
            +
                # event::
         | 
| 134 | 
            +
                #   The name of the event to send. This can be either a reserved
         | 
| 135 | 
            +
                #   event name, like $transaction or $label or a custom event name
         | 
| 136 | 
            +
                #   (that does not start with a $).  This parameter must be
         | 
| 137 | 
            +
                #   specified.
         | 
| 138 | 
            +
                #
         | 
| 139 | 
            +
                # properties::
         | 
| 140 | 
            +
                #   A hash of name-value pairs that specify the event-specific
         | 
| 141 | 
            +
                #   attributes to track.  This parameter must be specified.
         | 
| 142 | 
            +
                #
         | 
| 143 | 
            +
                # opts (optional)::
         | 
| 144 | 
            +
                #   A Hash of optional parameters for the request --
         | 
| 145 | 
            +
                #
         | 
| 146 | 
            +
                #   :return_score::
         | 
| 147 | 
            +
                #     If true, requests that the response include a score for this
         | 
| 148 | 
            +
                #     user, computed using the submitted event.  See
         | 
| 149 | 
            +
                #     https://siftscience.com/developers/docs/ruby/score-api/synchronous-scores
         | 
| 150 | 
            +
                #
         | 
| 151 | 
            +
                #   :abuse_types::
         | 
| 152 | 
            +
                #     List of abuse types, specifying for which abuse types a
         | 
| 153 | 
            +
                #     score should be returned (if scoring was requested).  By
         | 
| 154 | 
            +
                #     default, a score is returned for every abuse type to which
         | 
| 155 | 
            +
                #     you are subscribed.
         | 
| 115 156 | 
             
                #
         | 
| 116 | 
            -
                # | 
| 117 | 
            -
                # | 
| 118 | 
            -
                # | 
| 157 | 
            +
                #   :return_action::
         | 
| 158 | 
            +
                #     If true, requests that the response include any actions
         | 
| 159 | 
            +
                #     triggered as a result of the tracked event.
         | 
| 119 160 | 
             
                #
         | 
| 120 | 
            -
                # | 
| 121 | 
            -
                # | 
| 161 | 
            +
                #   :return_workflow_status::
         | 
| 162 | 
            +
                #     If true, requests that the response include the status of
         | 
| 163 | 
            +
                #     any workflow run as a result of the tracked event.  See
         | 
| 164 | 
            +
                #     https://siftscience.com/developers/docs/ruby/workflows-api/workflow-decisions
         | 
| 122 165 | 
             
                #
         | 
| 123 | 
            -
                # | 
| 124 | 
            -
                # | 
| 125 | 
            -
                #   be calculated using the submitted event.  This feature must be
         | 
| 126 | 
            -
                #   enabled for your account in order to use it.  Please contact
         | 
| 127 | 
            -
                #   support@siftscience.com if you are interested in using this feature.
         | 
| 166 | 
            +
                #   :timeout::
         | 
| 167 | 
            +
                #     Overrides the timeout (in seconds) for this call.
         | 
| 128 168 | 
             
                #
         | 
| 129 | 
            -
                # | 
| 130 | 
            -
                # | 
| 169 | 
            +
                #   :api_key::
         | 
| 170 | 
            +
                #     Overrides the API key for this call.
         | 
| 131 171 | 
             
                #
         | 
| 132 | 
            -
                # | 
| 133 | 
            -
                # | 
| 134 | 
            -
                #   method returns nil; otherwise, a Response object is returned and captures
         | 
| 135 | 
            -
                #   the status message and status code. In general, you can ignore the returned
         | 
| 136 | 
            -
                #   result, though.
         | 
| 172 | 
            +
                #   :version::
         | 
| 173 | 
            +
                #     Overrides the version of the Events API to call.
         | 
| 137 174 | 
             
                #
         | 
| 138 | 
            -
                 | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 175 | 
            +
                #   :path::
         | 
| 176 | 
            +
                #     Overrides the URI path for this API call.
         | 
| 177 | 
            +
                #
         | 
| 178 | 
            +
                # ==== Returns:
         | 
| 179 | 
            +
                #
         | 
| 180 | 
            +
                # In the case of a connection error (timeout, broken connection,
         | 
| 181 | 
            +
                # etc.), this method returns nil; otherwise, a Response object is
         | 
| 182 | 
            +
                # returned that captures the status message and status code.
         | 
| 183 | 
            +
                #
         | 
| 184 | 
            +
                def track(event, properties = {}, opts = {})
         | 
| 185 | 
            +
                  api_key = opts[:api_key] || @api_key
         | 
| 186 | 
            +
                  version = opts[:version] || @version
         | 
| 187 | 
            +
                  path = opts[:path] || (version && Sift.rest_api_path(version)) || @path
         | 
| 188 | 
            +
                  timeout = opts[:timeout] || @timeout
         | 
| 189 | 
            +
                  return_score = opts[:return_score]
         | 
| 190 | 
            +
                  return_action = opts[:return_action]
         | 
| 191 | 
            +
                  return_workflow_status = opts[:return_workflow_status]
         | 
| 192 | 
            +
                  abuse_types = opts[:abuse_types]
         | 
| 193 | 
            +
             | 
| 141 194 | 
             
                  raise("event must be a non-empty string") if (!event.is_a? String) || event.empty?
         | 
| 142 195 | 
             
                  raise("properties cannot be empty") if properties.empty?
         | 
| 143 | 
            -
                  raise(" | 
| 144 | 
            -
                  path ||= @path
         | 
| 145 | 
            -
                  timeout ||= @timeout
         | 
| 196 | 
            +
                  raise("api_key cannot be empty") if api_key.empty?
         | 
| 146 197 |  | 
| 147 | 
            -
                   | 
| 148 | 
            -
                   | 
| 149 | 
            -
                   | 
| 150 | 
            -
                   | 
| 198 | 
            +
                  query = {}
         | 
| 199 | 
            +
                  query["return_score"] = "true" if return_score
         | 
| 200 | 
            +
                  query["return_action"] = "true" if return_action
         | 
| 201 | 
            +
                  query["return_workflow_status"] = "true" if return_workflow_status
         | 
| 202 | 
            +
                  query["abuse_types"] = abuse_types.join(",") if abuse_types
         | 
| 151 203 |  | 
| 152 204 | 
             
                  options = {
         | 
| 153 205 | 
             
                    :body => MultiJson.dump(delete_nils(properties).merge({"$type" => event,
         | 
| 154 206 | 
             
                                                                           "$api_key" => api_key})),
         | 
| 155 | 
            -
                    :headers => {"User-Agent" => user_agent}
         | 
| 207 | 
            +
                    :headers => {"User-Agent" => user_agent},
         | 
| 208 | 
            +
                    :query => query
         | 
| 156 209 | 
             
                  }
         | 
| 157 210 | 
             
                  options.merge!(:timeout => timeout) unless timeout.nil?
         | 
| 211 | 
            +
             | 
| 158 212 | 
             
                  begin
         | 
| 159 213 | 
             
                    response = self.class.post(path, options)
         | 
| 160 214 | 
             
                    Response.new(response.body, response.code, response.response)
         | 
| @@ -165,91 +219,277 @@ module Sift | |
| 165 219 | 
             
                  end
         | 
| 166 220 | 
             
                end
         | 
| 167 221 |  | 
| 168 | 
            -
             | 
| 169 | 
            -
                #  | 
| 222 | 
            +
             | 
| 223 | 
            +
                # Retrieves a user's fraud score from the Sift Science API.
         | 
| 170 224 | 
             
                #
         | 
| 171 | 
            -
                #  | 
| 172 | 
            -
                # | 
| 225 | 
            +
                # See https://siftscience.com/developers/docs/ruby/score-api/score-api .
         | 
| 226 | 
            +
                #
         | 
| 227 | 
            +
                # ==== Parameters:
         | 
| 228 | 
            +
                #
         | 
| 229 | 
            +
                # user_id::
         | 
| 173 230 | 
             
                #   A user's id. This id should be the same as the user_id used in
         | 
| 174 231 | 
             
                #   event calls.
         | 
| 175 232 | 
             
                #
         | 
| 176 | 
            -
                #  | 
| 177 | 
            -
                #   A  | 
| 178 | 
            -
                # | 
| 233 | 
            +
                # opts (optional)::
         | 
| 234 | 
            +
                #   A Hash of optional parameters for the request --
         | 
| 235 | 
            +
                #
         | 
| 236 | 
            +
                #   :abuse_types::
         | 
| 237 | 
            +
                #     List of abuse types, specifying for which abuse types a
         | 
| 238 | 
            +
                #     score should be returned.  By default, a score is returned
         | 
| 239 | 
            +
                #     for every abuse type to which you are subscribed.
         | 
| 240 | 
            +
                #
         | 
| 241 | 
            +
                #   :api_key::
         | 
| 242 | 
            +
                #     Overrides the API key for this call.
         | 
| 243 | 
            +
                #
         | 
| 244 | 
            +
                #   :timeout::
         | 
| 245 | 
            +
                #     Overrides the timeout (in seconds) for this call.
         | 
| 246 | 
            +
                #
         | 
| 247 | 
            +
                #   :version::
         | 
| 248 | 
            +
                #     Overrides the version of the Events API to call.
         | 
| 249 | 
            +
                #
         | 
| 250 | 
            +
                # ==== Returns:
         | 
| 179 251 | 
             
                #
         | 
| 180 | 
            -
                 | 
| 252 | 
            +
                # A Response object containing a status code, status message, and,
         | 
| 253 | 
            +
                # if successful, the user's score(s).
         | 
| 254 | 
            +
                #
         | 
| 255 | 
            +
                def score(user_id, opts = {})
         | 
| 256 | 
            +
                  abuse_types = opts[:abuse_types]
         | 
| 257 | 
            +
                  api_key = opts[:api_key] || @api_key
         | 
| 258 | 
            +
                  timeout = opts[:timeout] || @timeout
         | 
| 259 | 
            +
                  version = opts[:version] || @version
         | 
| 181 260 |  | 
| 182 261 | 
             
                  raise("user_id must be a non-empty string") if (!user_id.is_a? String) || user_id.to_s.empty?
         | 
| 183 262 | 
             
                  raise("Bad api_key parameter") if api_key.empty?
         | 
| 184 | 
            -
                  timetout ||= @timeout
         | 
| 185 263 |  | 
| 186 | 
            -
                   | 
| 264 | 
            +
                  query = {}
         | 
| 265 | 
            +
                  query["api_key"] = api_key
         | 
| 266 | 
            +
                  query["abuse_types"] = abuse_types.join(",") if abuse_types
         | 
| 267 | 
            +
             | 
| 268 | 
            +
                  options = {
         | 
| 269 | 
            +
                    :headers => {"User-Agent" => user_agent},
         | 
| 270 | 
            +
                    :query => query
         | 
| 271 | 
            +
                  }
         | 
| 187 272 | 
             
                  options.merge!(:timeout => timeout) unless timeout.nil?
         | 
| 188 273 |  | 
| 189 | 
            -
                  response = self.class.get( | 
| 274 | 
            +
                  response = self.class.get(Sift.score_api_path(user_id, version), options)
         | 
| 190 275 | 
             
                  Response.new(response.body, response.code, response.response)
         | 
| 191 | 
            -
             | 
| 192 276 | 
             
                end
         | 
| 193 277 |  | 
| 194 | 
            -
             | 
| 278 | 
            +
             | 
| 279 | 
            +
                # Labels a user.
         | 
| 280 | 
            +
                #
         | 
| 281 | 
            +
                # See https://siftscience.com/developers/docs/ruby/labels-api/label-user .
         | 
| 195 282 | 
             
                #
         | 
| 196 | 
            -
                #  | 
| 197 | 
            -
                # | 
| 283 | 
            +
                # ==== Parameters:
         | 
| 284 | 
            +
                #
         | 
| 285 | 
            +
                # user_id::
         | 
| 198 286 | 
             
                #   A user's id. This id should be the same as the user_id used in
         | 
| 199 287 | 
             
                #   event calls.
         | 
| 200 288 | 
             
                #
         | 
| 201 | 
            -
                # properties
         | 
| 289 | 
            +
                # properties::
         | 
| 202 290 | 
             
                #   A hash of name-value pairs that specify the label attributes.
         | 
| 203 291 | 
             
                #   This parameter must be specified.
         | 
| 204 292 | 
             
                #
         | 
| 205 | 
            -
                #  | 
| 206 | 
            -
                #    | 
| 207 | 
            -
                # | 
| 293 | 
            +
                # opts (optional)::
         | 
| 294 | 
            +
                #   A Hash of optional parameters for the request --
         | 
| 295 | 
            +
                #
         | 
| 296 | 
            +
                #   :api_key::
         | 
| 297 | 
            +
                #     Overrides the API key for this call.
         | 
| 298 | 
            +
                #
         | 
| 299 | 
            +
                #   :timeout::
         | 
| 300 | 
            +
                #     Overrides the timeout (in seconds) for this call.
         | 
| 301 | 
            +
                #
         | 
| 302 | 
            +
                #   :version::
         | 
| 303 | 
            +
                #     Overrides the version of the Events API to call.
         | 
| 208 304 | 
             
                #
         | 
| 209 | 
            -
                #  | 
| 210 | 
            -
                #   A Response object is returned and captures the status message and
         | 
| 211 | 
            -
                #   status code. In general, you can ignore the returned result, though.
         | 
| 305 | 
            +
                # ==== Returns:
         | 
| 212 306 | 
             
                #
         | 
| 213 | 
            -
                 | 
| 307 | 
            +
                # In the case of a connection error (timeout, broken connection,
         | 
| 308 | 
            +
                # etc.), this method returns nil; otherwise, a Response object is
         | 
| 309 | 
            +
                # returned that captures the status message and status code.
         | 
| 310 | 
            +
                #
         | 
| 311 | 
            +
                def label(user_id, properties = {}, opts = {})
         | 
| 312 | 
            +
                  api_key = opts[:api_key] || @api_key
         | 
| 313 | 
            +
                  timeout = opts[:timeout] || @timeout
         | 
| 314 | 
            +
                  version = opts[:version] || @version
         | 
| 315 | 
            +
                  path = Sift.users_label_api_path(user_id, version)
         | 
| 214 316 |  | 
| 215 317 | 
             
                  raise("user_id must be a non-empty string") if (!user_id.is_a? String) || user_id.to_s.empty?
         | 
| 216 318 |  | 
| 217 | 
            -
                   | 
| 218 | 
            -
             | 
| 219 | 
            -
                  # No return_action logic supported when using labels.
         | 
| 220 | 
            -
                  track("$label", delete_nils(properties), timeout, path, false, api_key, false)
         | 
| 319 | 
            +
                  track("$label", delete_nils(properties),
         | 
| 320 | 
            +
                        :path => path, :api_key => api_key, :timeout => timeout)
         | 
| 221 321 | 
             
                end
         | 
| 222 322 |  | 
| 223 | 
            -
             | 
| 323 | 
            +
             | 
| 324 | 
            +
                # Unlabels a user.
         | 
| 224 325 | 
             
                #
         | 
| 225 | 
            -
                #  | 
| 226 | 
            -
                # | 
| 326 | 
            +
                # See https://siftscience.com/developers/docs/ruby/labels-api/unlabel-user .
         | 
| 327 | 
            +
                #
         | 
| 328 | 
            +
                # ==== Parameters:
         | 
| 329 | 
            +
                #
         | 
| 330 | 
            +
                # user_id::
         | 
| 227 331 | 
             
                #   A user's id. This id should be the same as the user_id used in
         | 
| 228 332 | 
             
                #   event calls.
         | 
| 229 333 | 
             
                #
         | 
| 230 | 
            -
                #  | 
| 231 | 
            -
                #    | 
| 232 | 
            -
                # | 
| 334 | 
            +
                # opts (optional)::
         | 
| 335 | 
            +
                #   A Hash of optional parameters for this request --
         | 
| 336 | 
            +
                #
         | 
| 337 | 
            +
                #   :abuse_type::
         | 
| 338 | 
            +
                #     The abuse type for which the user should be unlabeled.  If
         | 
| 339 | 
            +
                #     omitted, the user is unlabeled for all abuse types.
         | 
| 340 | 
            +
                #
         | 
| 341 | 
            +
                #   :api_key::
         | 
| 342 | 
            +
                #     Overrides the API key for this call.
         | 
| 343 | 
            +
                #
         | 
| 344 | 
            +
                #   :timeout::
         | 
| 345 | 
            +
                #     Overrides the timeout (in seconds) for this call.
         | 
| 346 | 
            +
                #
         | 
| 347 | 
            +
                #   :version::
         | 
| 348 | 
            +
                #     Overrides the version of the Events API to call.
         | 
| 349 | 
            +
                #
         | 
| 350 | 
            +
                # ==== Returns:
         | 
| 233 351 | 
             
                #
         | 
| 234 | 
            -
                #  | 
| 235 | 
            -
                #   A Response object is returned with only an http code of 204.
         | 
| 352 | 
            +
                # A Response object is returned with only an http code of 204.
         | 
| 236 353 | 
             
                #
         | 
| 237 | 
            -
                def unlabel(user_id,  | 
| 354 | 
            +
                def unlabel(user_id, opts = {})
         | 
| 355 | 
            +
                  abuse_type = opts[:abuse_type]
         | 
| 356 | 
            +
                  api_key = opts[:api_key] || @api_key
         | 
| 357 | 
            +
                  timeout = opts[:timeout] || @timeout
         | 
| 358 | 
            +
                  version = opts[:version] || @version
         | 
| 238 359 |  | 
| 239 360 | 
             
                  raise("user_id must be a non-empty string") if (!user_id.is_a? String) || user_id.to_s.empty?
         | 
| 240 | 
            -
                  timetout ||= @timeout
         | 
| 241 361 |  | 
| 242 | 
            -
                   | 
| 362 | 
            +
                  query = {}
         | 
| 363 | 
            +
                  query[:api_key] = api_key
         | 
| 364 | 
            +
                  query[:abuse_type] = abuse_type if abuse_type
         | 
| 365 | 
            +
             | 
| 366 | 
            +
                  options = {
         | 
| 367 | 
            +
                    :headers => {},
         | 
| 368 | 
            +
                    :query => query
         | 
| 369 | 
            +
                  }
         | 
| 243 370 | 
             
                  options.merge!(:timeout => timeout) unless timeout.nil?
         | 
| 244 | 
            -
             | 
| 245 | 
            -
                  response = self.class.delete( | 
| 371 | 
            +
             | 
| 372 | 
            +
                  response = self.class.delete(Sift.users_label_api_path(user_id, version), options)
         | 
| 246 373 | 
             
                  Response.new(response.body, response.code, response.response)
         | 
| 247 374 | 
             
                end
         | 
| 248 375 |  | 
| 376 | 
            +
             | 
| 377 | 
            +
                # Gets the status of a workflow run.
         | 
| 378 | 
            +
                #
         | 
| 379 | 
            +
                # See https://siftscience.com/developers/docs/ruby/workflows-api/workflow-status .
         | 
| 380 | 
            +
                #
         | 
| 381 | 
            +
                # ==== Parameters
         | 
| 382 | 
            +
                #
         | 
| 383 | 
            +
                # run_id::
         | 
| 384 | 
            +
                #   The ID of a workflow run.
         | 
| 385 | 
            +
                #
         | 
| 386 | 
            +
                # opts (optional)::
         | 
| 387 | 
            +
                #   A Hash of optional parameters for this request --
         | 
| 388 | 
            +
                #
         | 
| 389 | 
            +
                #   :account_id::
         | 
| 390 | 
            +
                #     Overrides the API key for this call.
         | 
| 391 | 
            +
                #
         | 
| 392 | 
            +
                #   :api_key::
         | 
| 393 | 
            +
                #     Overrides the API key for this call.
         | 
| 394 | 
            +
                #
         | 
| 395 | 
            +
                #   :timeout::
         | 
| 396 | 
            +
                #     Overrides the timeout (in seconds) for this call.
         | 
| 397 | 
            +
                #
         | 
| 398 | 
            +
                def get_workflow_status(run_id, opts = {})
         | 
| 399 | 
            +
                  account_id = opts[:account_id] || @account_id
         | 
| 400 | 
            +
                  api_key = opts[:api_key] || @api_key
         | 
| 401 | 
            +
                  timeout = opts[:timeout] || @timeout
         | 
| 402 | 
            +
             | 
| 403 | 
            +
                  options = {
         | 
| 404 | 
            +
                    :headers => { "User-Agent" => user_agent },
         | 
| 405 | 
            +
                    :basic_auth => { :username => api_key, :password => "" }
         | 
| 406 | 
            +
                  }
         | 
| 407 | 
            +
                  options.merge!(:timeout => timeout) unless timeout.nil?
         | 
| 408 | 
            +
             | 
| 409 | 
            +
                  uri = API3_ENDPOINT + Sift.workflow_status_path(account_id, run_id)
         | 
| 410 | 
            +
                  response = self.class.get(uri, options)
         | 
| 411 | 
            +
                  Response.new(response.body, response.code, response.response)
         | 
| 412 | 
            +
                end
         | 
| 413 | 
            +
             | 
| 414 | 
            +
             | 
| 415 | 
            +
                # Gets the decision status of a user.
         | 
| 416 | 
            +
                #
         | 
| 417 | 
            +
                # See https://siftscience.com/developers/docs/ruby/decisions-api/decision-status .
         | 
| 418 | 
            +
                #
         | 
| 419 | 
            +
                # ==== Parameters
         | 
| 420 | 
            +
                #
         | 
| 421 | 
            +
                # user_id::
         | 
| 422 | 
            +
                #   The ID of user.
         | 
| 423 | 
            +
                #
         | 
| 424 | 
            +
                # opts (optional)::
         | 
| 425 | 
            +
                #   A Hash of optional parameters for this request --
         | 
| 426 | 
            +
                #
         | 
| 427 | 
            +
                #   :account_id::
         | 
| 428 | 
            +
                #     Overrides the API key for this call.
         | 
| 429 | 
            +
                #
         | 
| 430 | 
            +
                #   :api_key::
         | 
| 431 | 
            +
                #     Overrides the API key for this call.
         | 
| 432 | 
            +
                #
         | 
| 433 | 
            +
                #   :timeout::
         | 
| 434 | 
            +
                #     Overrides the timeout (in seconds) for this call.
         | 
| 435 | 
            +
                #
         | 
| 436 | 
            +
                def get_user_decisions(user_id, opts = {})
         | 
| 437 | 
            +
                  account_id = opts[:account_id] || @account_id
         | 
| 438 | 
            +
                  api_key = opts[:api_key] || @api_key
         | 
| 439 | 
            +
                  timeout = opts[:timeout] || @timeout
         | 
| 440 | 
            +
             | 
| 441 | 
            +
                  options = {
         | 
| 442 | 
            +
                    :headers => { "User-Agent" => user_agent },
         | 
| 443 | 
            +
                    :basic_auth => { :username => api_key, :password => "" }
         | 
| 444 | 
            +
                  }
         | 
| 445 | 
            +
                  options.merge!(:timeout => timeout) unless timeout.nil?
         | 
| 446 | 
            +
             | 
| 447 | 
            +
                  uri = API3_ENDPOINT + Sift.user_decisions_api_path(account_id, user_id)
         | 
| 448 | 
            +
                  response = self.class.get(uri, options)
         | 
| 449 | 
            +
                  Response.new(response.body, response.code, response.response)
         | 
| 450 | 
            +
                end
         | 
| 451 | 
            +
             | 
| 452 | 
            +
             | 
| 453 | 
            +
                # Gets the decision status of an order.
         | 
| 454 | 
            +
                #
         | 
| 455 | 
            +
                # See https://siftscience.com/developers/docs/ruby/decisions-api/decision-status .
         | 
| 456 | 
            +
                #
         | 
| 457 | 
            +
                # ==== Parameters
         | 
| 458 | 
            +
                #
         | 
| 459 | 
            +
                # order_id::
         | 
| 460 | 
            +
                #   The ID of an order.
         | 
| 461 | 
            +
                #
         | 
| 462 | 
            +
                # opts (optional)::
         | 
| 463 | 
            +
                #   A Hash of optional parameters for this request --
         | 
| 464 | 
            +
                #
         | 
| 465 | 
            +
                #   :account_id::
         | 
| 466 | 
            +
                #     Overrides the API key for this call.
         | 
| 467 | 
            +
                #
         | 
| 468 | 
            +
                #   :api_key::
         | 
| 469 | 
            +
                #     Overrides the API key for this call.
         | 
| 470 | 
            +
                #
         | 
| 471 | 
            +
                #   :timeout::
         | 
| 472 | 
            +
                #     Overrides the timeout (in seconds) for this call.
         | 
| 473 | 
            +
                #
         | 
| 474 | 
            +
                def get_order_decisions(order_id, opts = {})
         | 
| 475 | 
            +
                  account_id = opts[:account_id] || @account_id
         | 
| 476 | 
            +
                  api_key = opts[:api_key] || @api_key
         | 
| 477 | 
            +
                  timeout = opts[:timeout] || @timeout
         | 
| 478 | 
            +
             | 
| 479 | 
            +
                  options = {
         | 
| 480 | 
            +
                    :headers => { "User-Agent" => user_agent },
         | 
| 481 | 
            +
                    :basic_auth => { :username => api_key, :password => "" }
         | 
| 482 | 
            +
                  }
         | 
| 483 | 
            +
                  options.merge!(:timeout => timeout) unless timeout.nil?
         | 
| 484 | 
            +
             | 
| 485 | 
            +
                  uri = API3_ENDPOINT + Sift.order_decisions_api_path(account_id, order_id)
         | 
| 486 | 
            +
                  response = self.class.get(uri, options)
         | 
| 487 | 
            +
                  Response.new(response.body, response.code, response.response)
         | 
| 488 | 
            +
                end
         | 
| 489 | 
            +
             | 
| 490 | 
            +
             | 
| 249 491 | 
             
                private
         | 
| 250 | 
            -
             | 
| 251 | 
            -
                #   uri = URI.parse(API_ENDPOINT)
         | 
| 252 | 
            -
                # end
         | 
| 492 | 
            +
             | 
| 253 493 | 
             
                def delete_nils(properties)
         | 
| 254 494 | 
             
                  properties.delete_if do |k, v|
         | 
| 255 495 | 
             
                    case v
         |