revere_mobile 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +98 -0
  3. data/bin/console +8 -0
  4. data/lib/revere_mobile/client/authentication.rb +28 -0
  5. data/lib/revere_mobile/client/campaign.rb +19 -0
  6. data/lib/revere_mobile/client/mobile_flow.rb +11 -0
  7. data/lib/revere_mobile/client/shortcode.rb +11 -0
  8. data/lib/revere_mobile/client.rb +29 -0
  9. data/lib/revere_mobile/configuration.rb +107 -0
  10. data/lib/revere_mobile/connection.rb +30 -0
  11. data/lib/revere_mobile/default.rb +45 -0
  12. data/lib/revere_mobile/error.rb +121 -0
  13. data/lib/revere_mobile/request.rb +39 -0
  14. data/lib/revere_mobile/response/raise_error.rb +18 -0
  15. data/lib/revere_mobile/response.rb +13 -0
  16. data/lib/revere_mobile/version.rb +5 -0
  17. data/lib/revere_mobile.rb +51 -0
  18. data/spec/revere_mobile/client/campaign_spec.rb +105 -0
  19. data/spec/revere_mobile/client/mobile_flow_spec.rb +51 -0
  20. data/spec/revere_mobile/client/shortcode_spec.rb +49 -0
  21. data/spec/revere_mobile/client_spec.rb +36 -0
  22. data/spec/revere_mobile/configuration_spec.rb +140 -0
  23. data/spec/revere_mobile/errors_spec.rb +84 -0
  24. data/spec/revere_mobile/request_spec.rb +125 -0
  25. data/spec/revere_mobile/revere_mobile_spec.rb +21 -0
  26. data/spec/revere_mobile/support/fixtures/campaigns/create_campaign.json +11 -0
  27. data/spec/revere_mobile/support/fixtures/campaigns/get_all_campaigns.json +49 -0
  28. data/spec/revere_mobile/support/fixtures/mobile_flows/get_all_mobile_flows.json +39 -0
  29. data/spec/revere_mobile/support/fixtures/shortcodes/get_all_shortcodes.json +34 -0
  30. data/spec/revere_mobile/support/path_helpers.rb +9 -0
  31. data/spec/revere_mobile/support/url_helpers.rb +5 -0
  32. data/spec/revere_mobile/support/webmock.rb +5 -0
  33. data/spec/spec_helper.rb +23 -0
  34. metadata +257 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 83455b42722c1f3d5a04a9a735942bf4e1cb055d
4
+ data.tar.gz: c0e462db54408ac3c37a0eae6f5a55b92f1fec9c
5
+ SHA512:
6
+ metadata.gz: 278df3e7393a4a2a597e236b9a8ceeb857de7964e1f5c06e6705cdbdd4be2d81b6c2a1092f402515af69d509dba1fc0e3a7d709e8b87da5116d4af36851b4d4c
7
+ data.tar.gz: ef0be38bccefcd987c5364bab81500c9f1244a6e049d7597552ad22af4b88f3abc5d4224dd798e550c98d63213156571f8f2cc66f9afb9ef0ba67cbfe1b39947
data/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # The Revere Mobile Ruby Gem
2
+
3
+ - TODO: Put some build status things here
4
+
5
+ # Quick Start
6
+
7
+ Add this line to your applications Gemfile:
8
+
9
+ ```ruby
10
+ gem 'revere_mobile'
11
+ ```
12
+
13
+ And then execute
14
+
15
+ ```sh
16
+ $ bundle
17
+ ```
18
+
19
+ Or install as standalone gem:
20
+
21
+ ```sh
22
+ $ gem install revere_mobile
23
+ ```
24
+
25
+ # Configuration
26
+
27
+ Revere Mobile takes a block to be configured:
28
+
29
+ ```ruby
30
+ RevereMobile.configure do |config|
31
+ # Configure the API Endpoint
32
+ # See https://mobile-developers.reverehq.com for more info for API Versions
33
+ config.api_endpoint = 'https://mobile.reverehq.com/api/v1'
34
+ # Configure an API Key
35
+ config.api_key = 'd1286a1a-f2e7-421a-91b8-f8cc8201558f'
36
+ # Defaults to "Revere Mobile Ruby Gem #{RevereMobile::VERSION}"
37
+ config.user_agent = 'CustomUserAgent'
38
+ end
39
+ ```
40
+
41
+ You can also configure options in a configuration object like so:
42
+
43
+ ```ruby
44
+ RevereMobile.configuration.api_key = 'd1286a1a-f2e7-421a-91b8-f8cc8201558f'
45
+ ```
46
+
47
+ For workers, for many instances you can create multiple configurations. This is also helpful for switching sessions based on
48
+ username and password authentication.
49
+
50
+ ```ruby
51
+ configuration = RevereMobile::Configuration.new
52
+ configuration.username = 'example'
53
+ configuration.password = 'example'
54
+ client = RevereMobile::Client.new(configuration)
55
+ client.login
56
+ ```
57
+
58
+ # Requests
59
+
60
+ Using a `Username` and `Password` this sets the session via the `#login` method.
61
+
62
+ ```ruby
63
+ configuration = RevereMobile::Configuration.new
64
+ configuration.username = 'example'
65
+ configuration.password = 'example'
66
+ client = RevereMobile::Client.new(configuration)
67
+ client.login # saves the session cookie for the instance of the client
68
+ client.campaigns # returns lists of campaigns
69
+ ```
70
+
71
+ You can also make requests directly with the module by just defining the `api_key`:
72
+
73
+ ```ruby
74
+ RevereMobile.configuration.api_key = 'd1286a1a-f2e7-421a-91b8-f8cc8201558f'
75
+ RevereMobile.campaigns
76
+ ```
77
+
78
+
79
+ # Development
80
+
81
+ Download this repo and run `rake spec` to run the tests.
82
+
83
+ A console method has also been included, run `bin/console` to get a pry prompt in which to experiment.
84
+
85
+ ```ruby
86
+ % bin/console
87
+ [1] pry(main)> RevereMobile::VERSION
88
+ # => "x.x.x"
89
+ [2] pry(main)> RevereMobile.configuration.api_key = 'd1286a1a-f2e7-421a-91b8-f8cc8201558f'
90
+ # => "d1286a1a-f2e7-421a-91b8-f8cc8201558f"
91
+ [3] pry(main)> RevereMobile.campaigns
92
+ # => {
93
+ # "page"=>1,
94
+ # "size"=>-1,
95
+ # "total"=>119,
96
+ # "collection"=>
97
+ # ...}
98
+ ```
data/bin/console ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'revere_mobile'
6
+ require 'pry'
7
+
8
+ Pry.start
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday-cookie_jar'
4
+
5
+ module RevereMobile
6
+ class Client
7
+ module Authentication
8
+ def login
9
+ conn = Faraday.new(url: config.api_endpoint) { |f| f.use :cookie_jar; f.adapter Faraday.default_adapter; }
10
+ response = conn.post do |req|
11
+ req.url '/api/v1/authenticate'
12
+ req.headers['Content-Type'] = 'application/json'
13
+ req.body = JSON.generate({ username: config.username, password: config.password })
14
+ end
15
+ config.session = response.headers['set-cookie']
16
+ response
17
+ end
18
+
19
+ def who_am_i
20
+ get(path: 'authenticate/whoami')
21
+ end
22
+
23
+ def logout
24
+ post(path: 'authenticate/logout')
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RevereMobile
4
+ class Client
5
+ module Campaign
6
+ def campaigns(params = { size: RevereMobile::Default.query_size })
7
+ get(path: 'campaign', params: params)
8
+ end
9
+
10
+ def create_campaign(body = {})
11
+ post(path: 'campaign', body: body)
12
+ end
13
+
14
+ def update_campaign(body = {})
15
+ put(path: "campaign/#{body[:id]}", body: body)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RevereMobile
4
+ class Client
5
+ module MobileFlow
6
+ def mobileflows(params:{ size: RevereMobile::Default.query_size })
7
+ get(path: 'mobileflow', params: params)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RevereMobile
4
+ class Client
5
+ module Shortcode
6
+ def shortcodes(params: { size: RevereMobile::Default.query_size })
7
+ get(path: 'shortcode', params: params)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'revere_mobile/connection'
4
+ require 'revere_mobile/request'
5
+ require 'revere_mobile/response'
6
+ require 'revere_mobile/client/authentication'
7
+ require 'revere_mobile/client/campaign'
8
+ require 'revere_mobile/client/shortcode'
9
+ require 'revere_mobile/client/mobile_flow'
10
+
11
+ module RevereMobile
12
+ class Client
13
+ def initialize(configuration = nil)
14
+ @config = configuration
15
+ end
16
+
17
+ def config
18
+ @config || RevereMobile.configuration
19
+ end
20
+
21
+ include RevereMobile::Connection
22
+ include RevereMobile::Request
23
+ include RevereMobile::Response
24
+ include RevereMobile::Client::Authentication
25
+ include RevereMobile::Client::Campaign
26
+ include RevereMobile::Client::Shortcode
27
+ include RevereMobile::Client::MobileFlow
28
+ end
29
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'revere_mobile/default'
4
+ require 'revere_mobile/version'
5
+
6
+ module RevereMobile
7
+ class Configuration
8
+ # The Revere Mobile Username
9
+ #
10
+ # The `username` setting is used for authenticating requests.
11
+ #
12
+ # @return [String, nil]
13
+ attr_accessor :username
14
+
15
+ # The Revere Mobile Password
16
+ #
17
+ # The `password` setting is used for authenticating requests.
18
+ #
19
+ # @return [String, nil]
20
+ attr_accessor :password
21
+
22
+ # The Revere Mobile Shortcode Session
23
+ #
24
+ # The `shortcode_id` setting is used for changing the shortcode session.
25
+ # Most accounts will have access to only one of these.
26
+ #
27
+ # @return [String, nil]
28
+ attr_accessor :api_key
29
+
30
+ # The Revere Mobile API KEY
31
+ #
32
+ # The `api_key` setting is used for authenticating requests.
33
+ # This approach does not require an active session ID.
34
+ # This method is more appropriate for integrations
35
+ # that always use the same credentials
36
+ # and do not want to add the complexity of session logic.
37
+ #
38
+ # @return [String, nil]
39
+ attr_accessor :shortcode_id
40
+
41
+ # The API Endpoint url. Which endpoint you should use is determined by which
42
+ # version with which you're working.
43
+ # Some features may be require to use multiple versions of the endpoint
44
+ # and thus you may want to change this configuration.
45
+ # @note See https://mobile-developers.reverehq.com
46
+ # @return [String]
47
+ attr_accessor :api_endpoint
48
+
49
+ # The User-Agent sent to the API endpoint. This defaults to the gem name,
50
+ # suffixed with the current version number.
51
+ # @return [String]
52
+ attr_accessor :user_agent
53
+
54
+ # The query size sent to the API endpoint. This defaults to 10,
55
+ # and determines the number of records to return.
56
+ # @return [number]
57
+ attr_accessor :query_size
58
+
59
+ # The user session. This defaults to nil but is written to
60
+ # once the authentication request has been made.
61
+ #
62
+ # @return [String]
63
+ attr_accessor :session
64
+
65
+ def initialize
66
+ setup
67
+ end
68
+
69
+ # Reset all configuration to default values.
70
+ # @return [RevereMobile::Configuration]
71
+ def reset!
72
+ @username = RevereMobile::Default.username
73
+ @password = RevereMobile::Default.password
74
+ @shortcode_id = RevereMobile::Default.shortcode_id
75
+ @api_endpoint = RevereMobile::Default.api_endpoint
76
+ @api_key = RevereMobile::Default.api_key
77
+ @user_agent = RevereMobile::Default.user_agent
78
+ @query_size = RevereMobile::Default.query_size
79
+ @session = nil
80
+ self
81
+ end
82
+
83
+ alias setup reset!
84
+
85
+ # Inspect the configuration object, masking private values.
86
+ # @return [String]
87
+ def inspect
88
+ inspected = super
89
+
90
+ if RevereMobile.configuration.password
91
+ filter_value!(inspected, RevereMobile.configuration.password)
92
+ end
93
+
94
+ if RevereMobile.configuration.api_key
95
+ filter_value!(inspected, RevereMobile.configuration.api_key)
96
+ end
97
+
98
+ inspected
99
+ end
100
+
101
+ private
102
+
103
+ def filter_value!(source, str)
104
+ source.gsub!(str, '[FILTERED]')
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'revere_mobile/response/raise_error'
4
+ require 'faraday_middleware'
5
+ require 'faraday-cookie_jar'
6
+
7
+ module RevereMobile
8
+ module Connection
9
+ private
10
+
11
+ def connection
12
+ options = {
13
+ url: config.api_endpoint,
14
+ headers: {
15
+ 'Accept' => 'application/json; charset=utf-8',
16
+ 'User-Agent ' => config.user_agent,
17
+ 'Cookie' => config.session,
18
+ 'Authorization' => config.api_key
19
+ }
20
+ }
21
+
22
+ Faraday::Connection.new(options) do |connection|
23
+ connection.request(:json)
24
+ connection.use :cookie_jar
25
+ connection.use RevereMobile::Response::RaiseError
26
+ connection.adapter Faraday.default_adapter
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'revere_mobile/version'
4
+
5
+ module RevereMobile
6
+ module Default
7
+ USERNAME = nil
8
+ PASSWORD = nil
9
+ API_KEY = nil
10
+ API_ENDPOINT = 'https://mobile.reverehq.com/api/v1/'
11
+ SHORTCODE_ID = nil
12
+ USER_AGENT = "Revere Mobile Ruby Gem #{RevereMobile::VERSION}"
13
+ QUERY_SIZE = 10
14
+
15
+ class << self
16
+ def username
17
+ USERNAME
18
+ end
19
+
20
+ def password
21
+ PASSWORD
22
+ end
23
+
24
+ def api_key
25
+ API_KEY
26
+ end
27
+
28
+ def api_endpoint
29
+ API_ENDPOINT
30
+ end
31
+
32
+ def shortcode_id
33
+ SHORTCODE_ID
34
+ end
35
+
36
+ def user_agent
37
+ USER_AGENT
38
+ end
39
+
40
+ def query_size
41
+ QUERY_SIZE
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RevereMobile
4
+ class Error < StandardError
5
+ attr_reader :body
6
+ attr_reader :response
7
+ attr_reader :status
8
+ attr_reader :errors
9
+
10
+ # Returns a RevereMobile::Error subclass, depending on status and
11
+ # response message.
12
+ #
13
+ # @param [Hash] response HTTP response
14
+ # @return [RevereMobile::Error]
15
+ def self.from_response(response)
16
+ status = response[:status].to_i
17
+
18
+ error_klass =
19
+ case status
20
+ when 400 then RevereMobile::BadRequest
21
+ when 401 then RevereMobile::Unauthorized
22
+ when 403 then RevereMobile::Forbidden
23
+ when 405 then RevereMobile::MethodNotAllowed
24
+ when 406 then RevereMobile::NotAcceptable
25
+ when 408 then RevereMobile::RequestTimeout
26
+ when 409 then RevereMobile::Conflict
27
+ when 413 then RevereMobile::RequestEntityTooLarge
28
+ when 415 then RevereMobile::UnsupportedMediaType
29
+ when 422 then RevereMobile::UnprocessableEntity
30
+ when 429 then RevereMobile::TooManyRequests
31
+ when 404 then RevereMobile::NotFound
32
+ when 400..499 then RevereMobile::ClientError
33
+ when 500 then RevereMobile::InternalServerError
34
+ when 501 then RevereMobile::NotImplemented
35
+ when 502 then RevereMobile::BadGateway
36
+ when 503 then RevereMobile::ServiceUnavailable
37
+ when 504 then RevereMobile::GatewayTimeout
38
+ when 500..599 then RevereMobile::ServerError
39
+ end
40
+
41
+ error_klass.new(response) if error_klass
42
+ end
43
+
44
+ def initialize(response = nil)
45
+ @response = response
46
+ @body = response[:body]
47
+ @status = response[:status]
48
+ @errors = body.delete('errors')
49
+
50
+ super(build_error)
51
+ end
52
+
53
+ private
54
+
55
+ def build_error
56
+ return nil if response.nil?
57
+
58
+ {
59
+ status: status,
60
+ errors: errors
61
+ }
62
+ end
63
+ end
64
+
65
+ # Errors in the 400-499 range
66
+ class ClientError < Error; end
67
+
68
+ # 400 Bad request
69
+ class BadRequest < ClientError; end
70
+
71
+ # 401 Unauthorized
72
+ class Unauthorized < ClientError; end
73
+
74
+ # 403 Forbidden
75
+ class Forbidden < ClientError; end
76
+
77
+ # 404 Not found
78
+ class NotFound < ClientError; end
79
+
80
+ # 405 Method not allowed
81
+ class MethodNotAllowed < ClientError; end
82
+
83
+ # 406 Not acceptable
84
+ class NotAcceptable < ClientError; end
85
+
86
+ # 408 Request timeout
87
+ class RequestTimeout < ClientError; end
88
+
89
+ # 409 Conflict
90
+ class Conflict < ClientError; end
91
+
92
+ # 413 Request entity too large
93
+ class RequestEntityTooLarge < ClientError; end
94
+
95
+ # 415 Unsupported media type
96
+ class UnsupportedMediaType < ClientError; end
97
+
98
+ # 422 Unprocessable entity
99
+ class UnprocessableEntity < ClientError; end
100
+
101
+ # 429 Too many requests
102
+ class TooManyRequests < ClientError; end
103
+
104
+ # Errors in the 500-599 range
105
+ class ServerError < Error; end
106
+
107
+ # 500 Internal server error
108
+ class InternalServerError < ServerError; end
109
+
110
+ # 501 Not implemented
111
+ class NotImplemented < ServerError; end
112
+
113
+ # 502 Bad gateway
114
+ class BadGateway < ServerError; end
115
+
116
+ # 503 Service unavailable
117
+ class ServiceUnavailable < ServerError; end
118
+
119
+ # 504 Gateway timeout
120
+ class GatewayTimeout < ServerError; end
121
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module RevereMobile
6
+ module Request
7
+ # Perform an HTTP GET request
8
+ def get(path:, params: {})
9
+ request(method: :get, path: path, params: params)
10
+ end
11
+
12
+ # Perform an HTTP POST request
13
+ def post(path:, body: {})
14
+ request(method: :post, path: path, body: body)
15
+ end
16
+
17
+ # Perform an HTTP PUT request
18
+ def put(path:, body: {})
19
+ request(method: :put, path: path, body: body)
20
+ end
21
+
22
+ # Perform an HTTP DELETE request
23
+ def delete(path:, params: {})
24
+ request(method: :delete, path: path, params: params)
25
+ end
26
+
27
+ private
28
+
29
+ def request(method:, path:, params: {}, body: {})
30
+ response = connection.send(method) do |request|
31
+ request.path = URI.encode(path)
32
+ request.params = params
33
+ request.body = ::JSON.generate(body) unless body.empty?
34
+ end
35
+
36
+ Response.create(response.body)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'revere_mobile/error'
4
+ require 'faraday'
5
+
6
+ module RevereMobile
7
+ module Response
8
+ # Raises erors on Faraday Responses
9
+ class RaiseError < Faraday::Response::Middleware
10
+ private
11
+
12
+ def on_complete(response)
13
+ error = RevereMobile::Error.from_response(response)
14
+ raise error if error
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RevereMobile
4
+ module Response
5
+ def self.create(body)
6
+ JSON.parse(body)
7
+ # The Mobile API does not always return JSON. For cases like this, we
8
+ # will just return the body un-parsed.
9
+ rescue JSON::ParserError
10
+ body
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RevereMobile
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ require 'revere_mobile/client'
5
+ require 'revere_mobile/configuration'
6
+
7
+ module RevereMobile
8
+ class << self
9
+ # The RevereMobile configuration object.
10
+ # @return [RevereMobile::Configuration]
11
+ attr_reader :configuration
12
+
13
+ def client
14
+ @client ||= RevereMobile::Client.new
15
+ end
16
+
17
+ # Delegate methods called on RevereMobile to the client.
18
+ def method_missing(method_name, *args, &block)
19
+ return super unless client.respond_to?(method_name)
20
+ client.send(method_name, *args, &block)
21
+ end
22
+ end
23
+
24
+ # The current configuration.
25
+ # @return [RevereMobile::Configuration]
26
+ def self.configuration
27
+ @configuration ||= Configuration.new
28
+ end
29
+
30
+ # Set new configuration
31
+ # @param config [RevereMobile::Configuration]
32
+ def self.configuration=(config)
33
+ @configuration = config
34
+ end
35
+
36
+ # Modify the current configuration
37
+ #
38
+ # @yieldparam [RevereMobile::Configuration] config
39
+ # The current RevereMobile config
40
+ #
41
+ # ```
42
+ # RevereMobile.configure do |config|
43
+ # config.api_endpoint = 'https://mobile.reverehq.com/api/v1'
44
+ # config.username = 'example'
45
+ # config.password = 'example'
46
+ # end
47
+ # ```
48
+ def self.configure
49
+ yield configuration
50
+ end
51
+ end