unleashed 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ab9f52896f8b680ac28a67a8716d0e1bafb0213be69e5e3c4ff6ceb1f6898f0e
4
- data.tar.gz: 9facbcd5c5592d277b3cb3220534a38629c7d109556c971fd48f129e73c05331
3
+ metadata.gz: 147bdc99b6e8ce42af1eb564d90374ccaa7ae220b41b3ccc5fed0fee3e23bb6e
4
+ data.tar.gz: b5f3fc37b96ee6c404c95e00b33822f8025015b6e2dbe781ec25711d469a1d5d
5
5
  SHA512:
6
- metadata.gz: e4195bce78819508d81b6ec88b7b166e7a4cb84a7338e26b90bb58e6b5e88e45d2e35a1428af19df4447cab4599e698e78516abc9fa455a1c828c3975ea5b3eb
7
- data.tar.gz: 2f045fc73f056945c9288efb6cf1144ce8f6e29032dbe1a76445614f441e48b32f1d8bd1ec1f42260b1e667147af27d0b1d1a359d903bd3f182f4ad5d3dbb731
6
+ metadata.gz: 334ecfd9f511222c578654b81e2a7054c16a7a2ed9f05b6b670e41119b8527c6cb714a024e5c56efb0a00fc1756f847d4b2285efccc0684ac1d5ae8211c0686a
7
+ data.tar.gz: c9534ae24edb3ec3b933f1cbb5dc47510883583d93f9d20ca197a757542efc6d17085e8bc2cae1863ba14f16fd9846b25e04caa224e3ac517003923ef7c8468d
data/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [0.1.4] - 2019-11-11
6
+
7
+ - Add `Customer` resource
8
+ - Add `json` and `faraday` gems
9
+
10
+ ## [0.1.0] - 2019-11-08
11
+
12
+ - Init project
13
+
14
+ ### Added
15
+
16
+ - Added ability to request data.
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ task default: :spec
@@ -0,0 +1,159 @@
1
+ require_relative 'configurable'
2
+ require_relative 'error'
3
+ require_relative 'models/base_model'
4
+ require_relative 'models/customer'
5
+ require_relative 'resources/base_resource'
6
+ require_relative 'resources/customer_resource'
7
+ require 'json'
8
+ require 'faraday'
9
+
10
+ module Unleashed
11
+ # Client for the Unleashed API
12
+ #
13
+ # @see https://apidocs.unleashedsoftware.com
14
+ class Client
15
+ include Unleashed::Configurable
16
+
17
+ def initialize(options = {})
18
+ # Use options passed in, but fall back to module defaults
19
+ Unleashed::Configurable.keys.each do |key|
20
+ instance_variable_set(
21
+ :"@#{key}", options[key] || Unleashed.instance_variable_get(:"@#{key}")
22
+ )
23
+ end
24
+ end
25
+
26
+ # Create a new Faraday connection
27
+ #
28
+ # @return [Faraday::Connection]
29
+ def connection
30
+ Faraday.new(url: @api_endpoint) do |faraday|
31
+ faraday.adapter :net_http
32
+ end
33
+ end
34
+
35
+ # Create a signature for request
36
+ def signature(params = '')
37
+ hash = OpenSSL::HMAC.digest('sha256', @api_key, params)
38
+ Base64.strict_encode64(hash)
39
+ end
40
+
41
+ def init_default_headers(request)
42
+ request.headers['client-type'] = @client_type_header
43
+ request.headers['Accept'] = 'application/json'
44
+ request.headers['Content-Type'] = 'application/json'
45
+ request.headers['api-auth-id'] = @api_id
46
+ request.headers['api-auth-signature'] = signature(request.params.to_query)
47
+ end
48
+
49
+ # Make a HTTP GET request
50
+ #
51
+ # @param url [String] The path, relative to {api_endpoint}
52
+ # @param parameters [Hash] Query params for request
53
+ # @return [Faraday::Response]
54
+ def get(url, parameters = {}, headers = {}, skip_status_check = false)
55
+ response = connection.get do |request|
56
+ request.url "#{api_endpoint}#{url}"
57
+ request.params = parameters
58
+
59
+ # Set headers
60
+ init_default_headers(request)
61
+
62
+ # Assign more custom headers
63
+ headers.each do |key, value|
64
+ request.headers[key] = value
65
+ end
66
+ end
67
+
68
+ on_complete(response) unless skip_status_check
69
+ response
70
+ end
71
+
72
+ # # Make a HTTP POST request
73
+ # #
74
+ # # @param url [String] The path, relative to {#api_endpoint}
75
+ # # @param parameters [Hash] Query params for request
76
+ # # @return [Faraday::Response]
77
+ # def post(url, parameters = {})
78
+ # response = connection.post do |req|
79
+ # req.url "#{api_endpoint}#{url}"
80
+ # req.headers['Content-Type'] = 'application/json'
81
+ # req.body = parameters.to_json
82
+ # end
83
+ # on_complete(response)
84
+ # response
85
+ # end
86
+
87
+ # # Make a HTTP PATCH request
88
+ # #
89
+ # # @param url [String] The path, relative to {#api_endpoint}
90
+ # # @param parameters [Hash] Query params for request
91
+ # # @return [Faraday::Response]
92
+ # def patch(url, parameters = {})
93
+ # response = connection.patch do |req|
94
+ # req.url "#{api_endpoint}#{url}"
95
+ # req.headers['Content-Type'] = 'application/json'
96
+ # req.body = parameters.to_json
97
+ # end
98
+ # on_complete(response)
99
+ # response
100
+ # end
101
+
102
+ # # Make a HTTP DELETE request
103
+ # #
104
+ # # @param url [String] The path, relative to {#api_endpoint}
105
+ # # @param parameters [Hash] Query params for request
106
+ # # @return [Faraday::Response]
107
+ # def delete(url, parameters = {})
108
+ # response = connection.delete do |req|
109
+ # req.url "#{api_endpoint}#{url}"
110
+ # req.headers['Content-Type'] = 'application/json'
111
+ # req.body = parameters.to_json
112
+ # end
113
+ # on_complete(response)
114
+ # response
115
+ # end
116
+
117
+ # Show details of your Platform.
118
+ #
119
+ # @see https://reference.Unleashed.com/#show-marketplace
120
+ #
121
+ # @return [Hash]
122
+ def marketplace
123
+ JSON.parse(get('marketplace').body)['marketplaces']
124
+ end
125
+
126
+ # Available resources for {Client}
127
+ #
128
+ # @return [Hash]
129
+ def self.resources
130
+ {
131
+ customers: CustomerResource
132
+ }
133
+ end
134
+
135
+ # Catch calls for resources
136
+ #
137
+ def method_missing(name, *args, &block)
138
+ if self.class.resources.keys.include?(name)
139
+ resources[name] ||= self.class.resources[name].new(self)
140
+ resources[name]
141
+ else
142
+ super
143
+ end
144
+ end
145
+
146
+ # Resources being currently used
147
+ #
148
+ # @return [Hash]
149
+ def resources
150
+ @resources ||= {}
151
+ end
152
+
153
+ private
154
+
155
+ def on_complete(response)
156
+ fail Unleashed::Error.from_response(response, @errors_format) unless response.success?
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,40 @@
1
+ module Unleashed
2
+ # Configuration options for {Client}, defaulting to values in {Default}.
3
+ module Configurable
4
+ attr_accessor :api_domain, :api_id, :api_key, :client_type_header, :errors_format
5
+
6
+ class << self
7
+ # List of configurable keys for {Unleashed::Client}.
8
+ #
9
+ # @return [Array] of option keys
10
+ def keys
11
+ @keys ||= [
12
+ :api_domain,
13
+ :api_id,
14
+ :api_key,
15
+ :client_type_header,
16
+ :errors_format
17
+ ]
18
+ end
19
+ end
20
+
21
+ # Reset configuration options to default values.
22
+ def reset!
23
+ Unleashed::Configurable.keys.each do |key|
24
+ instance_variable_set(:"@#{key}", Unleashed::Default.options[key])
25
+ end
26
+
27
+ self
28
+ end
29
+
30
+ alias setup reset!
31
+
32
+ # API endpoint to be used by {Unleashed::Client}.
33
+ # Built from {#api_domain}
34
+ #
35
+ # @return [String]
36
+ def api_endpoint
37
+ "https://#{@api_domain}/"
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,53 @@
1
+ module Unleashed
2
+ # Default configuration options for {Client}
3
+ module Default
4
+ # Default API domain
5
+ API_DOMAIN = 'api.unleashedsoftware.com'.freeze
6
+ # Default client_type_header
7
+ CLIENT_TYPE_HEADER = 'API-Sandbox'.freeze
8
+
9
+ class << self
10
+ # Configuration options.
11
+ #
12
+ # @return [Hash]
13
+ def options
14
+ Hash[Unleashed::Configurable.keys.map { |key| [key, send(key)] }]
15
+ end
16
+
17
+ # Default API domain from ENV or {API_DOMAIN}.
18
+ #
19
+ # @return [String]
20
+ def api_domain
21
+ ENV['UNLEASHED_API_DOMAIN'] || API_DOMAIN
22
+ end
23
+
24
+ # Default api_id from ENV.
25
+ #
26
+ # @return [String]
27
+ def api_id
28
+ ENV['UNLEASHED_API_ID']
29
+ end
30
+
31
+ # Default api_key from ENV.
32
+ #
33
+ # @return [String]
34
+ def api_key
35
+ ENV['UNLEASHED_API_KEY']
36
+ end
37
+
38
+ # Default client_type_header from ENV.
39
+ #
40
+ # @return [String]
41
+ def client_type_header
42
+ ENV['UNLEASHED_CLIENT_TYPE_HEADER'] || CLIENT_TYPE_HEADER
43
+ end
44
+
45
+ # Default errors_format from ENV.
46
+ #
47
+ # @return [String]
48
+ def errors_format
49
+ ENV['UNLEASHED_ERRORS_FORMAT'] || 'processed'
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,97 @@
1
+ module Unleashed
2
+ # Custom error class for rescuing from all Unleashed errors
3
+ class Error < StandardError
4
+ # Returns the appropriate Unleashed::Error subclass based on status
5
+ #
6
+ # @param [Faraday::Response] response Faraday HTTP response
7
+ # @return [Unleashed::Error]
8
+ def self.from_response(response, errors_format = nil)
9
+ klass = case response.status
10
+ when 400 then Unleashed::BadRequest
11
+ when 401 then Unleashed::Unauthorized
12
+ when 403 then Unleashed::Forbidden
13
+ when 404 then Unleashed::NotFound
14
+ when 405 then Unleashed::MethodNotAllowed
15
+ when 406 then Unleashed::NotAcceptable
16
+ when 409 then Unleashed::Conflict
17
+ when 422 then Unleashed::UnprocessableEntity
18
+ when 400..499 then Unleashed::ClientError
19
+ when 500 then Unleashed::InternalServerError
20
+ when 501 then Unleashed::NotImplemented
21
+ when 502 then Unleashed::BadGateway
22
+ when 503 then Unleashed::ServiceUnavailable
23
+ when 500..599 then Unleashed::ServerError
24
+ end
25
+ klass ? klass.new(response, errors_format) : new(response, errors_format)
26
+ end
27
+
28
+ def initialize(response = nil, errors_format = nil)
29
+ @response = response
30
+ @errors_format = errors_format
31
+ super(build_error_message)
32
+ end
33
+
34
+ private
35
+
36
+ def build_error_message
37
+ return nil if @response.nil? || @response.body.nil?
38
+
39
+ case @errors_format
40
+ when 'raw'
41
+ @response.body
42
+ else
43
+ json_response = JSON.parse(@response.body)
44
+ message = ''
45
+ message << json_response['message'] if json_response.key?('message')
46
+
47
+ if json_response.key?('errors')
48
+ message << json_response['errors'].map { |attribute, content| "#{attribute}: #{content}" }.join(', ')
49
+ end
50
+
51
+ message
52
+ end
53
+ end
54
+ end
55
+
56
+ # Raised on errors in the 400-499 range
57
+ class ClientError < Error; end
58
+
59
+ # Raised when Unleashed returns a 400 HTTP status code
60
+ class BadRequest < ClientError; end
61
+
62
+ # Raised when Unleashed returns a 401 HTTP status code
63
+ class Unauthorized < ClientError; end
64
+
65
+ # Raised when Unleashed returns a 403 HTTP status code
66
+ class Forbidden < ClientError; end
67
+
68
+ # Raised when Unleashed returns a 404 HTTP status code
69
+ class NotFound < ClientError; end
70
+
71
+ # Raised when Unleashed returns a 405 HTTP status code
72
+ class MethodNotAllowed < ClientError; end
73
+
74
+ # Raised when Unleashed returns a 406 HTTP status code
75
+ class NotAcceptable < ClientError; end
76
+
77
+ # Raised when Unleashed returns a 409 HTTP status code
78
+ class Conflict < ClientError; end
79
+
80
+ # Raised when Unleashed returns a 422 HTTP status code
81
+ class UnprocessableEntity < ClientError; end
82
+
83
+ # Raised on errors in the 500-599 range
84
+ class ServerError < Error; end
85
+
86
+ # Raised when Unleashed returns a 500 HTTP status code
87
+ class InternalServerError < ServerError; end
88
+
89
+ # Raised when Unleashed returns a 501 HTTP status code
90
+ class NotImplemented < ServerError; end
91
+
92
+ # Raised when Unleashed returns a 502 HTTP status code
93
+ class BadGateway < ServerError; end
94
+
95
+ # Raised when Unleashed returns a 503 HTTP status code
96
+ class ServiceUnavailable < ServerError; end
97
+ end
@@ -0,0 +1,23 @@
1
+ module Unleashed
2
+ # Base model for all the other models to inherit from
3
+ class BaseModel
4
+ def initialize(client, attributes = {})
5
+ @client = client
6
+ @attributes = stringify_keys(attributes)
7
+ end
8
+
9
+ def method_missing(name, *args, &block)
10
+ if @attributes.key?(name.to_s)
11
+ @attributes[name.to_s]
12
+ else
13
+ super
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def stringify_keys(hash)
20
+ Hash[hash.map { |key, value| [key.to_s, value] }]
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,6 @@
1
+
2
+ module Unleashed
3
+ # Manage Customers
4
+ class Customer < BaseModel
5
+ end
6
+ end
@@ -0,0 +1,20 @@
1
+ module Unleashed
2
+ # Base resource for all the other resources to inherit from
3
+ class BaseResource
4
+ def initialize(client)
5
+ @client = client
6
+ end
7
+
8
+ def method_missing(name, *args, &block)
9
+ if instance_methods.include?(model) && respond_to?(name)
10
+ model.new(@client, id: args[0]).send(name, *args[1..-1])
11
+ else
12
+ super
13
+ end
14
+ end
15
+
16
+ def respond_to?(name, include_all = false)
17
+ super || model.new(@client).respond_to?(name, include_all)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,38 @@
1
+ module Unleashed
2
+ # Resource for the Customers API
3
+ # The Customers resource allows Customers to be listed, viewed, created, and updated.
4
+ # An individual Customer's details can be viewed, or updated by appending its identifier
5
+ # (a GUID formatted as XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX) to the URI
6
+ #
7
+ # @see https://apidocs.unleashedsoftware.com/Customers
8
+ class CustomerResource < BaseResource
9
+ def model
10
+ Unleashed::Customer
11
+ end
12
+
13
+ # List all customers
14
+ # /Customers - also returns the first 200 customers because page number 1 is the default.
15
+ #
16
+ # @param options [Hash] Optional options.
17
+ # @option options [Integer] :page_size Can ask for up to 200 customers. default: 10
18
+ # @option options [Integer] :page Page index. default: 1
19
+ #
20
+ # @return [Array<Unleashed::Customer>] List all customers.
21
+ def all(options = { page: 1, page_size: 10 })
22
+ response = JSON.parse(@client.get('Customers', options).body)
23
+ customers = response.key?('Items') ? response['Items'] : []
24
+ customers.map { |attributes| Unleashed::Customer.new(@client, attributes) }
25
+ end
26
+
27
+ # Get a single customer
28
+ # /Customers/E6E8163F-6911-40e9-B740-90E5A0A3A996 - returns details of a particular customer.
29
+ #
30
+ # @param id [String] customer ID.
31
+ #
32
+ # @return [Unleashed::Customer]
33
+ def find(id)
34
+ response = JSON.parse(@client.get("Customers/#{id}").body)
35
+ Unleashed::Customer.new(@client, response)
36
+ end
37
+ end
38
+ end
@@ -2,7 +2,7 @@ module Unleashed
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- TINY = 3
5
+ TINY = 4
6
6
 
7
7
  STRING = "#{MAJOR}.#{MINOR}.#{TINY}".freeze
8
8
  end
data/lib/unleashed.rb CHANGED
@@ -1,5 +1,12 @@
1
- require 'unleashed/version'
1
+ require_relative 'unleashed/client'
2
+ require_relative 'unleashed/default'
3
+ require_relative 'unleashed/error'
4
+ require_relative 'unleashed/version'
2
5
 
3
6
  module Unleashed
4
- # Your code goes here...
7
+ class << self
8
+ include Unleashed::Configurable
9
+ end
5
10
  end
11
+
12
+ Unleashed.setup
data/unleashed.gemspec CHANGED
@@ -40,6 +40,8 @@ Gem::Specification.new do |spec|
40
40
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
41
41
  spec.require_paths = ['lib']
42
42
 
43
+ spec.add_dependency 'faraday'
44
+ spec.add_dependency 'json'
43
45
  spec.add_development_dependency 'bundler', '~> 1.16', '>= 1.16.1'
44
46
  spec.add_development_dependency 'rake', '~> 10.0'
45
47
  spec.add_development_dependency 'rspec', '~> 3.0'
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unleashed
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nhan Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-11-10 00:00:00.000000000 Z
11
+ date: 2019-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: bundler
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -69,6 +97,7 @@ files:
69
97
  - ".rspec"
70
98
  - ".ruby-version"
71
99
  - ".travis.yml"
100
+ - CHANGELOG.md
72
101
  - CODE_OF_CONDUCT.md
73
102
  - Gemfile
74
103
  - LICENSE
@@ -78,6 +107,14 @@ files:
78
107
  - bin/console
79
108
  - bin/setup
80
109
  - lib/unleashed.rb
110
+ - lib/unleashed/client.rb
111
+ - lib/unleashed/configurable.rb
112
+ - lib/unleashed/default.rb
113
+ - lib/unleashed/error.rb
114
+ - lib/unleashed/models/base_model.rb
115
+ - lib/unleashed/models/customer.rb
116
+ - lib/unleashed/resources/base_resource.rb
117
+ - lib/unleashed/resources/customer_resource.rb
81
118
  - lib/unleashed/version.rb
82
119
  - unleashed.gemspec
83
120
  homepage: https://github.com/nnhansg/unleashed-ruby