revere_mobile 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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