vhx-ruby 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/Gemfile +2 -0
- data/README.md +59 -0
- data/Rakefile +1 -0
- data/lib/vhx.rb +66 -0
- data/lib/vhx/client.rb +86 -0
- data/lib/vhx/error.rb +24 -0
- data/lib/vhx/middleware/error_response.rb +32 -0
- data/lib/vhx/middleware/oauth2.rb +22 -0
- data/lib/vhx/oauth_token.rb +11 -0
- data/lib/vhx/objects/authorization.rb +5 -0
- data/lib/vhx/objects/collection.rb +8 -0
- data/lib/vhx/objects/collection_item.rb +4 -0
- data/lib/vhx/objects/customer.rb +8 -0
- data/lib/vhx/objects/product.rb +6 -0
- data/lib/vhx/objects/site.rb +4 -0
- data/lib/vhx/objects/user.rb +10 -0
- data/lib/vhx/objects/video.rb +7 -0
- data/lib/vhx/objects/video_file.rb +4 -0
- data/lib/vhx/utilities/api_operations/create.rb +22 -0
- data/lib/vhx/utilities/api_operations/delete.rb +16 -0
- data/lib/vhx/utilities/api_operations/list.rb +21 -0
- data/lib/vhx/utilities/api_operations/request.rb +17 -0
- data/lib/vhx/utilities/api_operations/update.rb +15 -0
- data/lib/vhx/utilities/vhx_helper.rb +20 -0
- data/lib/vhx/utilities/vhx_list_object.rb +44 -0
- data/lib/vhx/utilities/vhx_object.rb +106 -0
- data/lib/vhx/version.rb +3 -0
- data/spec/client_spec.rb +69 -0
- data/spec/fixtures/sample_array_list.json +15 -0
- data/spec/fixtures/sample_file_response.json +18 -0
- data/spec/fixtures/sample_hash_list.json +23 -0
- data/spec/fixtures/sample_package_response.json +185 -0
- data/spec/fixtures/sample_site_response.json +26 -0
- data/spec/fixtures/sample_user_response.json +21 -0
- data/spec/fixtures/sample_video_response.json +51 -0
- data/spec/middleware/error_response_spec.rb +11 -0
- data/spec/middleware/oauth2_spec.rb +14 -0
- data/spec/objects/file_spec.rb +29 -0
- data/spec/objects/package_spec.rb +74 -0
- data/spec/objects/site_spec.rb +44 -0
- data/spec/objects/user_spec.rb +51 -0
- data/spec/objects/video_spec.rb +36 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/test_data.rb +55 -0
- data/spec/utilities/vhx_collection_spec.rb +27 -0
- data/spec/utilities/vhx_helper_spec.rb +47 -0
- data/spec/utilities/vhx_object_spec.rb +53 -0
- data/spec/vcr/Vhx_Client/application_user/_refresh_access_token/access_token_changed.yml +57 -0
- data/spec/vcr/Vhx_Client/application_user/_refresh_access_token/oauth_token_refreshed.yml +57 -0
- data/spec/vcr/Vhx_File/associations/are_present.yml +409 -0
- data/spec/vcr/Vhx_Middleware_ErrorResponse/unauthorized_user_credentials.yml +122 -0
- data/spec/vcr/Vhx_Middleware_OAuth2/access_token_refresh.yml +797 -0
- data/spec/vcr/Vhx_Package/_add_video/with_hypermedia/returns_package_object.yml +51 -0
- data/spec/vcr/Vhx_Package/_add_video/with_id/returns_package_object.yml +51 -0
- data/spec/vcr/Vhx_Package/_create/returns_package_object.yml +140 -0
- data/spec/vcr/Vhx_Package/_find/with_hypermedia.yml +243 -0
- data/spec/vcr/Vhx_Package/_find/with_id.yml +243 -0
- data/spec/vcr/Vhx_Package/_remove_video/with_hypermedia/returns_success.yml +51 -0
- data/spec/vcr/Vhx_Package/_remove_video/with_id/returns_success.yml +51 -0
- data/spec/vcr/Vhx_Package/associations/are_present.yml +195 -0
- data/spec/vcr/Vhx_Site/_create/returns_site_object.yml +91 -0
- data/spec/vcr/Vhx_Site/_find/with_hypermedia.yml +195 -0
- data/spec/vcr/Vhx_Site/_find/with_id.yml +195 -0
- data/spec/vcr/Vhx_User/_find/with_hypermedia.yml +81 -0
- data/spec/vcr/Vhx_User/_find/with_id.yml +81 -0
- data/spec/vcr/Vhx_User/_me/returns_user_object.yml +720 -0
- data/spec/vcr/Vhx_User/_update/returns_user_object.yml +212 -0
- data/spec/vcr/Vhx_VhxObject/associations/cache/retreive_if_available.yml +195 -0
- data/spec/vcr/Vhx_VhxObject/associations/falls_back_to_links.yml +310 -0
- data/spec/vcr/Vhx_Video/_create/returns_video_object.yml +125 -0
- data/spec/vcr/Vhx_Video/associations/are_present.yml +294 -0
- data/vhx.gemspec +27 -0
- metadata +204 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: beb4e508443c33c4e403dc3af8968963b782b16d
|
4
|
+
data.tar.gz: 252a387534bc8e8eb38c6e9189cac2a6e9e501a1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6e06429c037251651ce2b8ccb192f5e04f46dd0e6311e9c77282841799ad0997de16482be0db7f390b8eee227df018d4de512f149f3616f63357b6b7cc54a5d2
|
7
|
+
data.tar.gz: bbe96986befef7b8b2679d51e8c4f4a6d51207402a29a5fd237c6b93ad4ffb66ff64b6f0753e273802c1a8234cfa0781328991a07419c9268f87ae41bd865c49
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# VHX Ruby API Client
|
2
|
+
|
3
|
+
The VHX API is currently Private Beta. You can request an API key by emailing api@vhx.tv.
|
4
|
+
|
5
|
+
### Installation
|
6
|
+
|
7
|
+
`gem install vhx-ruby`
|
8
|
+
|
9
|
+
### Documentation
|
10
|
+
|
11
|
+
Documentation is available at http://dev.vhx.tv/docs/api/ruby.
|
12
|
+
Full API reference is available at http://dev.vhx.tv/docs/api?ruby.
|
13
|
+
|
14
|
+
## Getting Started
|
15
|
+
|
16
|
+
Before requesting your first resource, you must setup an instance of the Vhx Client:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
vhx = Vhx.setup({ api_key: 'your VHX API key'} )
|
20
|
+
```
|
21
|
+
|
22
|
+
Here's an example of creating a Vhx resource with payload options. You can handle errors by rescuing Vhx::VhxError.
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
begin
|
26
|
+
# Example Customer Create
|
27
|
+
customer = Vhx::Customer.create({
|
28
|
+
email: 'customer@email.com',
|
29
|
+
name: 'First Last',
|
30
|
+
subscription: 'https://api.vhx.tv/subscriptions/1'
|
31
|
+
})
|
32
|
+
rescue Vhx::VhxError
|
33
|
+
# Handle error
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
### Resources & methods
|
38
|
+
|
39
|
+
customers
|
40
|
+
* [`create`](http://dev.vhx.tv/docs/api?ruby#create_customer)
|
41
|
+
* [`update`](http://dev.vhx.tv/docs/api?ruby#update_customer)
|
42
|
+
* [`retrieve`](http://dev.vhx.tv/docs/api?ruby#retrieve_customer)
|
43
|
+
* [`list`](http://dev.vhx.tv/docs/api?ruby#list_customers)
|
44
|
+
|
45
|
+
authorizations
|
46
|
+
* [`create`](http://dev.vhx.tv/docs/api?ruby#create_authorization)
|
47
|
+
|
48
|
+
videos
|
49
|
+
* [`create`](http://dev.vhx.tv/docs/api?ruby#create_customer)
|
50
|
+
* [`update`](http://dev.vhx.tv/docs/api?ruby#update_customer)
|
51
|
+
* [`retrieve`](http://dev.vhx.tv/docs/api?ruby#retrieve_customer)
|
52
|
+
* [`list`](http://dev.vhx.tv/docs/api?ruby#list_customers)
|
53
|
+
|
54
|
+
collections
|
55
|
+
* [`create`](http://dev.vhx.tv/docs/api?ruby#create_collection)
|
56
|
+
* [`update`](http://dev.vhx.tv/docs/api?ruby#update_collection)
|
57
|
+
* [`retrieve`](http://dev.vhx.tv/docs/api?ruby#retrieve_collection)
|
58
|
+
* [`list`](http://dev.vhx.tv/docs/api?ruby#list_collections)
|
59
|
+
* [`items`](http://dev.vhx.tv/docs/api?ruby#list_collection_items)
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/vhx.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday_middleware'
|
3
|
+
|
4
|
+
require "vhx/version"
|
5
|
+
require "vhx/error"
|
6
|
+
require "vhx/oauth_token"
|
7
|
+
|
8
|
+
require 'vhx/middleware/error_response'
|
9
|
+
require 'vhx/middleware/oauth2'
|
10
|
+
|
11
|
+
require "vhx/client"
|
12
|
+
|
13
|
+
require "vhx/utilities/vhx_helper"
|
14
|
+
require "vhx/utilities/api_operations/create"
|
15
|
+
require "vhx/utilities/api_operations/delete"
|
16
|
+
require "vhx/utilities/api_operations/list"
|
17
|
+
require "vhx/utilities/api_operations/request"
|
18
|
+
require "vhx/utilities/api_operations/update"
|
19
|
+
|
20
|
+
require "vhx/utilities/vhx_object"
|
21
|
+
require "vhx/utilities/vhx_list_object"
|
22
|
+
|
23
|
+
require "vhx/objects/user"
|
24
|
+
require "vhx/objects/collection"
|
25
|
+
require "vhx/objects/collection_item"
|
26
|
+
require "vhx/objects/product"
|
27
|
+
require "vhx/objects/site"
|
28
|
+
require "vhx/objects/video"
|
29
|
+
require "vhx/objects/video_file"
|
30
|
+
require "vhx/objects/customer"
|
31
|
+
require "vhx/objects/authorization"
|
32
|
+
|
33
|
+
module Vhx
|
34
|
+
API_BASE_URL = 'https://api.vhx.tv'
|
35
|
+
|
36
|
+
class << self
|
37
|
+
def setup(options = {})
|
38
|
+
options[:client_id] ||= @client_id
|
39
|
+
options[:client_secret] ||= @client_secret
|
40
|
+
options[:api_key] ||= @api_key
|
41
|
+
options[:api_base] ||= @api_base_url
|
42
|
+
options[:skip_auto_refresh] = @skip_auto_refresh if options[:skip_auto_refresh].nil?
|
43
|
+
Vhx.client = Vhx::Client.new(options)
|
44
|
+
end
|
45
|
+
|
46
|
+
def config(config = {})
|
47
|
+
@client_id = config[:client_id]
|
48
|
+
@client_secret = config[:client_secret]
|
49
|
+
@api_key = config[:api_key]
|
50
|
+
@skip_auto_refresh = config[:skip_auto_refresh] || false
|
51
|
+
@api_base_url = config[:api_base]
|
52
|
+
end
|
53
|
+
|
54
|
+
def client
|
55
|
+
@client
|
56
|
+
end
|
57
|
+
|
58
|
+
def client=(new_client)
|
59
|
+
@client = new_client
|
60
|
+
end
|
61
|
+
|
62
|
+
def connection
|
63
|
+
client ? client.connection : nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/vhx/client.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
module Vhx
|
2
|
+
class Client
|
3
|
+
attr_reader :client_id, :client_secret, :api_base_url, :oauth_token, :api_key, :connection, :ssl
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
options = Hash[options.map{ |k, v| [k.to_sym, v] }]
|
7
|
+
@api_base_url = options[:api_base] || API_BASE_URL
|
8
|
+
@client_id = options[:client_id]
|
9
|
+
@client_secret = options[:client_secret]
|
10
|
+
@oauth_token = options[:api_key] ? nil : OAuthToken.new(options, refreshed = false)
|
11
|
+
@api_key = options[:api_key]
|
12
|
+
@skip_auto_refresh = options[:skip_auto_refresh]
|
13
|
+
@ssl = options[:ssl] || {}
|
14
|
+
@headers = {}
|
15
|
+
|
16
|
+
configure_connection
|
17
|
+
end
|
18
|
+
|
19
|
+
def configure_connection
|
20
|
+
@connection = Faraday::Connection.new(url: api_base_url, headers: configured_headers, ssl: ssl) do |faraday|
|
21
|
+
faraday.request :url_encoded
|
22
|
+
faraday.request :json
|
23
|
+
faraday.response :logger
|
24
|
+
faraday.use Vhx::Middleware::OAuth2, :vhx_client => self unless @skip_auto_refresh
|
25
|
+
|
26
|
+
faraday.adapter Faraday.default_adapter
|
27
|
+
|
28
|
+
faraday.use Vhx::Middleware::ErrorResponse
|
29
|
+
faraday.response :json
|
30
|
+
end
|
31
|
+
@connection
|
32
|
+
end
|
33
|
+
|
34
|
+
def configured_headers
|
35
|
+
if access_token
|
36
|
+
@headers[:Authorization] = "Bearer #{access_token}"
|
37
|
+
elsif api_key
|
38
|
+
@headers[:Authorization] = Faraday::Request::BasicAuthentication.header(api_key, '')
|
39
|
+
end
|
40
|
+
|
41
|
+
@headers
|
42
|
+
end
|
43
|
+
|
44
|
+
def access_token
|
45
|
+
unless oauth_token
|
46
|
+
return nil
|
47
|
+
end
|
48
|
+
|
49
|
+
oauth_token.access_token
|
50
|
+
end
|
51
|
+
|
52
|
+
def expired?
|
53
|
+
unless oauth_token
|
54
|
+
return false
|
55
|
+
end
|
56
|
+
|
57
|
+
oauth_token.expires && oauth_token.expires_at < Time.now.to_i
|
58
|
+
end
|
59
|
+
|
60
|
+
def credentials
|
61
|
+
unless oauth_token
|
62
|
+
return nil
|
63
|
+
end
|
64
|
+
|
65
|
+
oauth_token.to_h
|
66
|
+
end
|
67
|
+
|
68
|
+
def refresh_access_token!
|
69
|
+
conn = @connection.dup
|
70
|
+
conn.headers.delete(:Authorization)
|
71
|
+
response = conn.post do |req|
|
72
|
+
req.url '/oauth/token'
|
73
|
+
req.headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
74
|
+
req.body = {
|
75
|
+
grant_type: 'refresh_token',
|
76
|
+
refresh_token: oauth_token.refresh_token,
|
77
|
+
client_id: client_id,
|
78
|
+
client_secret: client_secret
|
79
|
+
}
|
80
|
+
end
|
81
|
+
@oauth_token = OAuthToken.new(response.body, refreshed = true)
|
82
|
+
|
83
|
+
configure_connection
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/vhx/error.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module Vhx
|
2
|
+
class VhxError < StandardError
|
3
|
+
attr_reader :response_body, :response_status, :url, :message
|
4
|
+
|
5
|
+
def initialize(response_body, response_status, url)
|
6
|
+
@response_body = response_body
|
7
|
+
@response_status = response_status
|
8
|
+
@url = url
|
9
|
+
@message = response_body.is_a?(Hash) ? response_body['message'] : response_body.to_s
|
10
|
+
|
11
|
+
super(@message)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class BadRequestError < VhxError; end
|
16
|
+
class UnauthorizedError < VhxError; end
|
17
|
+
class InvalidTokenError < VhxError; end
|
18
|
+
class PaymentRequiredError < VhxError; end
|
19
|
+
class NotFoundError < VhxError; end
|
20
|
+
class NotAcceptableError < VhxError; end
|
21
|
+
class ServerError < VhxError; end
|
22
|
+
|
23
|
+
class InvalidResourceError < StandardError; end
|
24
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Vhx
|
2
|
+
module Middleware
|
3
|
+
class ErrorResponse < Faraday::Response::Middleware
|
4
|
+
def on_complete(env)
|
5
|
+
error_class = case env[:status]
|
6
|
+
when 200, 201, 204
|
7
|
+
when 304
|
8
|
+
when 400
|
9
|
+
BadRequestError
|
10
|
+
when 401
|
11
|
+
if env[:body].fetch('message', '').match(/token/)
|
12
|
+
InvalidTokenError
|
13
|
+
else
|
14
|
+
UnauthorizedError
|
15
|
+
end
|
16
|
+
when 402
|
17
|
+
PaymentRequiredError
|
18
|
+
when 404
|
19
|
+
NotFoundError
|
20
|
+
when 406
|
21
|
+
NotAcceptableError
|
22
|
+
else
|
23
|
+
ServerError
|
24
|
+
end
|
25
|
+
|
26
|
+
if error_class
|
27
|
+
raise error_class.new(env[:body], env[:status], env[:url])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Vhx
|
2
|
+
module Middleware
|
3
|
+
class OAuth2 < Faraday::Middleware
|
4
|
+
def call(env)
|
5
|
+
orig_env = env.dup
|
6
|
+
|
7
|
+
begin
|
8
|
+
@app.call(env)
|
9
|
+
rescue InvalidTokenError
|
10
|
+
@vhx_client.refresh_access_token!
|
11
|
+
orig_env[:request_headers].merge!(@vhx_client.configured_headers)
|
12
|
+
@app.call(orig_env)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(app, options={})
|
17
|
+
super(app)
|
18
|
+
@vhx_client = options[:vhx_client]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class OAuthToken < Struct.new(:access_token, :refresh_token, :expires_at, :expires_in, :expires, :refreshed)
|
2
|
+
def initialize(params = {}, refreshed = false)
|
3
|
+
params = Hash[params.map{ |k, v| [k.to_sym, v] }]
|
4
|
+
self.access_token = params[:access_token]
|
5
|
+
self.refresh_token = params[:refresh_token]
|
6
|
+
self.expires_at = params[:expires_at] || Time.now.to_i + params[:expires_in].to_i
|
7
|
+
self.expires_in = params[:expires_in]
|
8
|
+
self.expires = (params[:expires_at] || params[:expires_in]) ? true : false
|
9
|
+
self.refreshed = refreshed
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Vhx
|
2
|
+
module ApiOperations
|
3
|
+
module Create
|
4
|
+
module ClassMethods
|
5
|
+
def create(payload)
|
6
|
+
klass = get_klass
|
7
|
+
response = Vhx.connection.post do |req|
|
8
|
+
req.url('/' + klass.downcase + 's') #This url is based purely on VHX's API convention.
|
9
|
+
req.body = payload
|
10
|
+
end
|
11
|
+
|
12
|
+
self.new(response.body)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.included(klass)
|
17
|
+
klass.extend(Vhx::HelperMethods)
|
18
|
+
klass.extend(ClassMethods)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Vhx
|
2
|
+
module ApiOperations
|
3
|
+
module Delete
|
4
|
+
module ClassMethods
|
5
|
+
def delete(identifier, payload = {})
|
6
|
+
Vhx.connection.delete(get_hypermedia(identifier), payload)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.included(klass)
|
11
|
+
klass.extend(Vhx::HelperMethods)
|
12
|
+
klass.extend(ClassMethods)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|