passworks 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/CHANGELOG.md +7 -0
  4. data/Gemfile +4 -0
  5. data/README.md +319 -0
  6. data/Rakefile +2 -0
  7. data/lib/passworks.rb +49 -0
  8. data/lib/passworks/asset_resource.rb +11 -0
  9. data/lib/passworks/campaign_resource.rb +40 -0
  10. data/lib/passworks/client.rb +53 -0
  11. data/lib/passworks/collection_proxy.rb +46 -0
  12. data/lib/passworks/configuration.rb +58 -0
  13. data/lib/passworks/exception.rb +5 -0
  14. data/lib/passworks/exceptions/bad_gateway.rb +8 -0
  15. data/lib/passworks/exceptions/bad_request.rb +8 -0
  16. data/lib/passworks/exceptions/enhance_your_calm.rb +9 -0
  17. data/lib/passworks/exceptions/file_not_found.rb +8 -0
  18. data/lib/passworks/exceptions/forbidden.rb +8 -0
  19. data/lib/passworks/exceptions/gateway_timeout.rb +8 -0
  20. data/lib/passworks/exceptions/internal_server_error.rb +8 -0
  21. data/lib/passworks/exceptions/method_not_allowed.rb +8 -0
  22. data/lib/passworks/exceptions/not_found.rb +8 -0
  23. data/lib/passworks/exceptions/not_implemented.rb +8 -0
  24. data/lib/passworks/exceptions/payment_required.rb +8 -0
  25. data/lib/passworks/exceptions/precondition_failed.rb +8 -0
  26. data/lib/passworks/exceptions/service_unavailable.rb +8 -0
  27. data/lib/passworks/exceptions/unauthorized.rb +8 -0
  28. data/lib/passworks/exceptions/unprocessable_entity.rb +8 -0
  29. data/lib/passworks/faraday/http_exception_middleware.rb +73 -0
  30. data/lib/passworks/inflector.rb +38 -0
  31. data/lib/passworks/pass_resource.rb +40 -0
  32. data/lib/passworks/request.rb +49 -0
  33. data/lib/passworks/request_proxy.rb +115 -0
  34. data/lib/passworks/resource.rb +18 -0
  35. data/lib/passworks/response.rb +56 -0
  36. data/lib/passworks/version.rb +3 -0
  37. data/passworks.gemspec +34 -0
  38. metadata +208 -0
@@ -0,0 +1,53 @@
1
+ module Passworks
2
+
3
+ # Client is the HTTP API Wrapper to comunicate with the Passworks API
4
+ #
5
+ class Client
6
+
7
+ include Passworks::Configuration
8
+ include Passworks::Request
9
+
10
+ def initialize(params={})
11
+ Configuration::VALID_CONFIG_KEYS.each do |key|
12
+ self.instance_variable_set(:"@#{key}", params[key])
13
+ end
14
+ end
15
+
16
+ # Check if the current {Client} instance options are equal to the passed ones
17
+ # @param options [Hash] options
18
+ # @return [Boolean]
19
+ def same_options?(options)
20
+ self.options == options
21
+ end
22
+
23
+ # @!method assets
24
+ # Allows to to access the Assets API
25
+ # @return [Passworks::RequestProxy]
26
+ # @!method boarding_passes
27
+ # Allows to to access the Boarding Pass API
28
+ # @return [Passworks::RequestProxy]
29
+ # @!method store_cards
30
+ # Allows to to access the Store Cards API
31
+ # @return [Passworks::RequestProxy]
32
+ # @!method coupons
33
+ # Allows to to access the Coupons API
34
+ # @return [Passworks::RequestProxy]
35
+ # @!method generics
36
+ # Allows to to access the Generic API
37
+ # @return [Passworks::RequestProxy]
38
+
39
+ %w(assets boarding_passes store_cards coupons generics).each do |collection_name|
40
+ define_method(collection_name) do
41
+ Passworks::RequestProxy.new(self, collection_name, nil)
42
+ end
43
+ end
44
+
45
+ def inspect
46
+ inspected = super
47
+ inspected.gsub!(/\@api_secret=(.+)/){ "@api_secret=\"**********\"" }
48
+ inspected
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,46 @@
1
+ require 'passworks/inflector'
2
+
3
+ module Passworks
4
+ class CollectionProxy
5
+
6
+ include Enumerable
7
+ include Passworks::Inflector
8
+
9
+ attr_reader :collection_name, :collection_uuid, :client, :options
10
+
11
+ def initialize(client, collection_name, collection_uuid=nil, options={})
12
+ @collection_name = collection_name
13
+ @collection_uuid = collection_uuid
14
+ @client = client
15
+ @options = options
16
+ end
17
+
18
+ def each(&block)
19
+ next_page = nil
20
+ loop do
21
+ if next_page
22
+ response = client.get(collection_url, options.merge({query: {page: next_page}}))
23
+ else
24
+ response = client.get(collection_url, options)
25
+ end
26
+ response.data.each do |item_data|
27
+ yield resource_class.new(client, collection_name, item_data)
28
+ end
29
+ next_page = response.next_page
30
+ break if next_page.nil?
31
+ end
32
+ self
33
+ end
34
+
35
+ private
36
+
37
+ def collection_url
38
+ if collection_uuid
39
+ "#{collection_name}/#{collection_uuid}/passes"
40
+ else
41
+ collection_name
42
+ end
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,58 @@
1
+ require 'passworks/version'
2
+
3
+ module Passworks
4
+ module Configuration
5
+
6
+ VALID_CONNECTION_KEYS = [:endpoint, :user_agent].freeze
7
+
8
+ VALID_OPTION_KEYS = [:api_username, :api_secret, :debug].freeze
9
+
10
+ # @!visibility private
11
+ VALID_CONFIG_KEYS = VALID_CONNECTION_KEYS + VALID_OPTION_KEYS
12
+
13
+ DEFAULT_ENDPOINT = 'https://api.passworks.io'
14
+
15
+ DEFAULT_USER_AGENT = "Passworks Ruby API Client/#{Passworks::VERSION} Ruby/#{RUBY_VERSION} Platform/#{RUBY_PLATFORM}"
16
+
17
+ attr_accessor *VALID_CONFIG_KEYS
18
+
19
+ def configure
20
+ yield self
21
+ end
22
+
23
+ def reset!
24
+ Configuration.default_options.each do |key, value|
25
+ self.instance_variable_set(:"@#{key}", value)
26
+ end
27
+ end
28
+
29
+ def options
30
+ Configuration.default_options.keys.inject({}) do |hash, key|
31
+ hash[key] = self.instance_variable_get(:"@#{key}")
32
+ hash
33
+ end
34
+ end
35
+
36
+ # @!visibility private
37
+ def self.default_options
38
+ @default_options ||= {
39
+ endpoint: ENV['PASSWORKS_ENDPOINT'] || DEFAULT_ENDPOINT ,
40
+ user_agent: ENV['PASSWORKS_USER_AGENT'] || DEFAULT_USER_AGENT ,
41
+ api_username: ENV['PASSWORKS_API_USERNAME'] ,
42
+ api_secret: ENV['PASSWORKS_API_SECRET'] ,
43
+ debug: false
44
+ }
45
+ end
46
+ # @return the endpoint address with API version appended
47
+ def endpoint
48
+ File.join(@endpoint, 'v1').to_s
49
+ end
50
+
51
+ class << self
52
+ def extended(base)
53
+ base.reset!
54
+ end
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,5 @@
1
+ module Passworks
2
+ class Exception < ::StandardError
3
+ end
4
+ end
5
+ Dir[File.dirname(__FILE__) + "/exceptions/*.rb"].each { |file| require file }
@@ -0,0 +1,8 @@
1
+ require 'passworks/exception'
2
+
3
+ module Passworks
4
+ module Exceptions
5
+ class BadGateway < Exception
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'passworks/exception'
2
+
3
+ module Passworks
4
+ module Exceptions
5
+ class BadRequest < Exception
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ require 'passworks/exception'
2
+
3
+ module Passworks
4
+ module Exceptions
5
+ class EnhanceYourCalm < Exception
6
+ end
7
+ end
8
+ end
9
+
@@ -0,0 +1,8 @@
1
+ require 'passworks/exception'
2
+
3
+ module Passworks
4
+ module Exceptions
5
+ class FileNotFound < Exception
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'passworks/exception'
2
+
3
+ module Passworks
4
+ module Exceptions
5
+ class Forbidden < Exception
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'passworks/exception'
2
+
3
+ module Passworks
4
+ module Exceptions
5
+ class GatewayTimeout < Exception
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'passworks/exception'
2
+
3
+ module Passworks
4
+ module Exceptions
5
+ class InternalServerError < Exception
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'passworks/exception'
2
+
3
+ module Passworks
4
+ module Exceptions
5
+ class MethodNotAllowed < Exception
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'passworks/exception'
2
+
3
+ module Passworks
4
+ module Exceptions
5
+ class NotFound < Exception
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'passworks/exception'
2
+
3
+ module Passworks
4
+ module Exceptions
5
+ class NotImplemented < Exception
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'passworks/exception'
2
+
3
+ module Passworks
4
+ module Exceptions
5
+ class PaymentRequired < Exception
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'passworks/exception'
2
+
3
+ module Passworks
4
+ module Exceptions
5
+ class PreconditionFailed < Exception
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'passworks/exception'
2
+
3
+ module Passworks
4
+ module Exceptions
5
+ class ServiceUnavailable < Exception
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'passworks/exception'
2
+
3
+ module Passworks
4
+ module Exceptions
5
+ class Unauthorized < Exception
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'passworks/exception'
2
+
3
+ module Passworks
4
+ module Exceptions
5
+ class UnprocessableEntity < Exception
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,73 @@
1
+ require 'passworks/exception'
2
+ require 'faraday'
3
+
4
+ module Passworks
5
+ module Faraday
6
+ class HttpExceptionMiddleware < ::Faraday::Middleware
7
+
8
+ def call(env)
9
+ @app.call(env).on_complete do |response|
10
+ case response[:status].to_i
11
+ when 400
12
+ raise Passworks::Exceptions::BadRequest, error_400(response)
13
+ when 401
14
+ raise Passworks::Exceptions::Unauthorized, error_400(response)
15
+ when 402
16
+ raise Passworks::Exceptions::PaymentRequired, error_400(response)
17
+ when 403
18
+ raise Passworks::Exceptions::Forbidden, error_400(response)
19
+ when 404
20
+ raise Passworks::Exceptions::NotFound, error_400(response)
21
+ when 405
22
+ raise Passworks::Exceptions::MethodNotAllowed, error_400(response)
23
+ when 412
24
+ raise Passworks::Exceptions::PreconditionFailed, error_400(response)
25
+ when 420
26
+ raise Passworks::Exceptions::EnhanceYourCalm, error_400(response)
27
+ when 422
28
+ raise Passworks::Exceptions::UnprocessableEntity, error_400(response)
29
+ when 500
30
+ raise Passworks::Exceptions::InternalServerError, error_500(response, 'Internal Server Error' , 'The server encountered an unexpected condition which prevented it from fulfilling the request.')
31
+ when 501
32
+ raise Passworks::Exceptions::NotImplemented, error_500(response, 'Not Implemented' , 'Current method not implemented.')
33
+ when 502
34
+ raise Passworks::Exceptions::BadGateway, error_500(response, 'Bad Gateway', 'The server, while acting as a gateway or proxy, received an invalid response from the upstream server it accessed in attempting to fulfill the request.')
35
+ when 503
36
+ raise Passworks::Exceptions::ServiceUnavailable, error_500(response, 'Service Unavailable', 'The server is currently unable to handle the request due to a temporary overloading or maintenance of the server.')
37
+ when 504
38
+ raise Passworks::Exceptions::GatewayTimeout, error_500(response, 'Gateway Timeout', 'The server, while acting as a gateway or proxy, did not receive a timely response from the upstream server specified by the URI.')
39
+ end
40
+ end
41
+ end
42
+
43
+ def initialize(app)
44
+ super
45
+ @parser = nil
46
+ end
47
+
48
+ private
49
+ def error_400(response)
50
+ "#{response[:method].to_s.upcase} #{response[:url].to_s}: #{response[:status]} - #{error_body(response)}"
51
+ end
52
+
53
+ def error_500(response, short_description, long_description)
54
+ end
55
+
56
+ # {"status_code"=>412, "error_code"=>10103, "message"=>"Asset in use by 1 templates, e.g.: Cocacola"}
57
+ def error_body(response)
58
+ body = response[:body]
59
+ # body gets passed as a string, not sure if it is passed as something else from other spots?
60
+ if not body.nil? and not body.empty? and body.kind_of?(String)
61
+ body = ::JSON.parse(body)
62
+ end
63
+
64
+ if body.nil?
65
+ nil
66
+ elsif body['message']
67
+ "(#{body['error_code']}) #{body['message']}"
68
+ end
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,38 @@
1
+ module Passworks
2
+ module Inflector
3
+
4
+ # Return the singular version of the *curren_collection* name
5
+ # @return [String] singular version of the current collection name
6
+ def single_name
7
+ case collection_name
8
+ when 'assets'
9
+ 'asset'
10
+ when 'boarding_passes'
11
+ 'boarding_pass'
12
+ when 'coupons'
13
+ 'coupon'
14
+ when 'store_cards'
15
+ 'store_card'
16
+ when 'event_tickets'
17
+ 'event_ticket'
18
+ when 'generics'
19
+ 'generic'
20
+ else
21
+ raise 'Invalid Collection Name'
22
+ end
23
+ end
24
+
25
+ # Return resource class based in collection_name and collection_uuid
26
+ # If collection_name return [Passworks::AssetResource]
27
+ # If collection_uuid == nil return [Passworks::CampaignResource] else return [Passworks::PassResource]
28
+ def resource_class
29
+ return Passworks::AssetResource if collection_name == 'assets'
30
+ if collection_uuid
31
+ Passworks::PassResource
32
+ else
33
+ Passworks::CampaignResource
34
+ end
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,40 @@
1
+ require 'passworks/resource'
2
+
3
+ module Passworks
4
+
5
+ # Represents a Pass of a given collection type Coupon, Boarding Pass, Event Ticket, Generic, Store Card
6
+ #
7
+ class PassResource < Resource
8
+
9
+ # Deletes the current pass
10
+ # @return [Boolean] True in case the pass is deleted
11
+ def delete
12
+ client.delete("#{collection_name}/#{collection_uuid}/passes/#{id}").ok?
13
+ end
14
+
15
+ # Sends a push notification to all clients with this pass installed
16
+ # @return [Boolean] True in case the pass
17
+ def push
18
+ client.post("#{collection_name}/#{collection_uuid}/passes/#{id}/push").ok?
19
+ end
20
+
21
+ # Updates the {PassResource} and returns the updated instance
22
+ # @return [PassResource] Updated instance
23
+ def update(data, params={})
24
+ content = {
25
+ body: {
26
+ pass: data
27
+ }.merge(params)
28
+ }
29
+ response = client.patch("#{collection_name}/#{collection_uuid}/passes/#{id}", content)
30
+ self.class.new(client, collection_name, response.data)
31
+ end
32
+
33
+ private
34
+ def collection_uuid
35
+ @collection_uuid ||= send("#{single_name}_id")
36
+ end
37
+
38
+ end
39
+
40
+ end