beautydate_api 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +34 -0
  4. data/lib/beautydate_api/api_consumer.rb +42 -0
  5. data/lib/beautydate_api/api_request.rb +77 -0
  6. data/lib/beautydate_api/api_resource.rb +39 -0
  7. data/lib/beautydate_api/api_session.rb +71 -0
  8. data/lib/beautydate_api/business.rb +57 -0
  9. data/lib/beautydate_api/business_payment.rb +29 -0
  10. data/lib/beautydate_api/object.rb +53 -0
  11. data/lib/beautydate_api/version.rb +3 -0
  12. data/lib/beautydate_api.rb +66 -0
  13. data/lib/tasks/beautydate_api_tasks.rake +4 -0
  14. data/test/beautydate_api_test.rb +7 -0
  15. data/test/dummy/README.rdoc +28 -0
  16. data/test/dummy/Rakefile +6 -0
  17. data/test/dummy/app/assets/javascripts/application.js +13 -0
  18. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  19. data/test/dummy/app/controllers/application_controller.rb +5 -0
  20. data/test/dummy/app/helpers/application_helper.rb +2 -0
  21. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  22. data/test/dummy/bin/bundle +3 -0
  23. data/test/dummy/bin/rails +4 -0
  24. data/test/dummy/bin/rake +4 -0
  25. data/test/dummy/bin/setup +29 -0
  26. data/test/dummy/config/application.rb +26 -0
  27. data/test/dummy/config/boot.rb +5 -0
  28. data/test/dummy/config/database.yml +25 -0
  29. data/test/dummy/config/environment.rb +5 -0
  30. data/test/dummy/config/environments/development.rb +41 -0
  31. data/test/dummy/config/environments/production.rb +79 -0
  32. data/test/dummy/config/environments/test.rb +42 -0
  33. data/test/dummy/config/initializers/assets.rb +11 -0
  34. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  35. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  36. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  37. data/test/dummy/config/initializers/inflections.rb +16 -0
  38. data/test/dummy/config/initializers/mime_types.rb +4 -0
  39. data/test/dummy/config/initializers/session_store.rb +3 -0
  40. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  41. data/test/dummy/config/locales/en.yml +23 -0
  42. data/test/dummy/config/routes.rb +56 -0
  43. data/test/dummy/config/secrets.yml +22 -0
  44. data/test/dummy/config.ru +4 -0
  45. data/test/dummy/public/404.html +67 -0
  46. data/test/dummy/public/422.html +67 -0
  47. data/test/dummy/public/500.html +66 -0
  48. data/test/dummy/public/favicon.ico +0 -0
  49. data/test/test_helper.rb +19 -0
  50. metadata +156 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1a0aeb3a713b9e47bda7213a36efdcfe293a53d8
4
+ data.tar.gz: 404b80c584df0862619cbc949842625a9daf4957
5
+ SHA512:
6
+ metadata.gz: c7c111fa70677bd421fc7e34b998177f8a8d72e284290c40d2430a086909d206aa9d3d8a35c77ff581d2c5263fa8e7d85614e507b742292ceb391ce505c7d2fc
7
+ data.tar.gz: c8cd12f0661324c624d10d77fb4edaa472ed0ce9471670efd3a4d8cd96916dadb7953e7056aff022d26130988a53b9bb34a699e3be23f18e737ed07b82b71c48
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2016 Fábio Tomio
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'BeautydateApi'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
@@ -0,0 +1,42 @@
1
+ module BeautydateApi
2
+ class APIConsumer
3
+
4
+ def authenticate token
5
+ request = {
6
+ method: 'POST',
7
+ url: "#{BeautydateApi.base_uri}/consumers/auth",
8
+ timeout: 30,
9
+ headers: {
10
+ user_agent: "BeautyDate/#{BeautydateApi::VERSION}; Ruby Client",
11
+ content_type: 'application/vnd.api+json'
12
+ },
13
+ payload: {
14
+ data: {
15
+ type: 'consumers',
16
+ attributes: {
17
+ uuid: token
18
+ }
19
+ }
20
+ }.to_json
21
+ }
22
+ result = JSON.parse(RestClient::Request.execute request)
23
+ @bearer_key = result.dig('data', 'attributes', 'token')
24
+ @expires_at = result.dig('data', 'attributes', 'token_expires_at')
25
+ true
26
+ rescue
27
+ raise AuthenticationException
28
+ end
29
+
30
+ def authenticated?
31
+ @bearer_key.present?
32
+ end
33
+
34
+ def valid?
35
+ authenticated? and Time.now <= Time.at(@expires_at)
36
+ end
37
+
38
+ def bearer
39
+ "Bearer #{@bearer_key}"
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,77 @@
1
+ #encoding: UTF-8
2
+ require 'rest_client'
3
+ require 'base64'
4
+ require 'json'
5
+
6
+ module BeautydateApi
7
+ class APIRequest
8
+ class << self
9
+ def consumer
10
+ @consumer ||= BeautydateApi::APIConsumer.new
11
+ unless @consumer.valid?
12
+ @consumer.authenticate(BeautydateApi.api_key)
13
+ end
14
+ @consumer
15
+ rescue BeautydateApi::ObjectNotFound => e
16
+ raise BeautydateApi::AuthenticationException, 'Não foi possível autenticar o Consumer, verifique o BEAUTYDATE_TOKEN'
17
+ end
18
+
19
+ def session
20
+ @session ||= BeautydateApi::APISession.new(BeautydateApi.api_session_token)
21
+ unless @session.valid?
22
+ @session.authenticate(
23
+ consumer.bearer,
24
+ BeautydateApi.api_email,
25
+ BeautydateApi.api_password
26
+ )
27
+ end
28
+ @session
29
+ rescue BeautydateApi::ObjectNotFound => e
30
+ raise BeautydateApi::AuthenticationException, 'Não foi possível autenticar a sessão, verifique o email e senha'
31
+ end
32
+
33
+ def request(method, url, data = {})
34
+ handle_response send_request(method, url, data)
35
+ end
36
+
37
+ private
38
+
39
+ def send_request(method, url, data)
40
+ RestClient::Request.execute build_request(method, url, data)
41
+ rescue RestClient::ResourceNotFound
42
+ raise ObjectNotFound
43
+ rescue RestClient::UnprocessableEntity => e
44
+ raise RequestWithErrors.new JSON.parse(e.response)
45
+ rescue RestClient::BadRequest => e
46
+ raise RequestWithErrors.new JSON.parse(e.response)
47
+ end
48
+
49
+ def handle_response(response)
50
+ JSON.parse(response.body)
51
+ rescue JSON::ParserError
52
+ raise RequestFailed
53
+ end
54
+
55
+ def build_request(method, url, data)
56
+ {
57
+ method: method,
58
+ url: url,
59
+ headers: headers,
60
+ payload: {
61
+ data: data
62
+ }.to_json,
63
+ timeout: 30
64
+ }
65
+ end
66
+
67
+ def headers
68
+ {
69
+ user_agent: "BeautyDate/#{BeautydateApi::VERSION}; Ruby Client",
70
+ content_type: 'application/vnd.api+json',
71
+ authorization: self.consumer.bearer,
72
+ 'X-BeautyDate-Session-Token' => self.session.token
73
+ }
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,39 @@
1
+ module BeautydateApi
2
+ class APIResource < BeautydateApi::Object
3
+
4
+ def is_new?
5
+ @attributes['id'].nil?
6
+ end
7
+
8
+ class << self
9
+ def url(options=nil)
10
+ endpoint_url + self.relative_url(options)
11
+ end
12
+
13
+ def endpoint_url
14
+ "#{BeautydateApi.base_uri}/#{object_base_uri}"
15
+ end
16
+
17
+ def relative_url(options=nil)
18
+ id = case options.class.name
19
+ when 'Hash'
20
+ options[:id] || options["id"]
21
+ when 'Iugu::APIResource'
22
+ options.id
23
+ else
24
+ options
25
+ end
26
+ id ? "/#{id}" : ""
27
+ end
28
+
29
+ def object_base_uri
30
+ self.name # BeautydateApi::BusinessPayment
31
+ .to_s # "BeautydateApi::BusinessPayment"
32
+ .demodulize # "BusinessPayment"
33
+ .titleize # "Business Payment"
34
+ .pluralize # "Business Payments"
35
+ .parameterize # "business-payments"
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,71 @@
1
+ module BeautydateApi
2
+ class APISession
3
+ attr_accessor :token_key, :expires_at
4
+
5
+ def initialize(token_key = nil)
6
+ @token_key = token_key
7
+ @expires_at = extract_expires_at
8
+ end
9
+
10
+ def authenticate(authorization, email, password)
11
+ request = meta
12
+ .merge(headers(authorization))
13
+ .merge(payload(email, password))
14
+
15
+ result = JSON.parse(RestClient::Request.execute request)
16
+ @token_key = result.dig('data', 'attributes', 'token')
17
+ @expires_at = result.dig('data', 'attributes', 'expires_at')
18
+
19
+ authenticated?
20
+ rescue => e
21
+ raise AuthenticationException
22
+ end
23
+
24
+ def meta
25
+ { method: 'POST', url: "#{BeautydateApi.base_uri}/sessions", timeout: 30 }
26
+ end
27
+
28
+ def headers(authorization)
29
+ {
30
+ headers: {
31
+ user_agent: "BeautyDate/#{BeautydateApi::VERSION}; Ruby Client",
32
+ content_type: 'application/vnd.api+json',
33
+ authorization: authorization
34
+ }
35
+ }
36
+ end
37
+
38
+ def payload(email, password)
39
+ {
40
+ payload: {
41
+ data: {
42
+ type: 'sessions',
43
+ attributes: {
44
+ provider: 'b2beauty', email: email, password: password
45
+ }
46
+ }
47
+ }.to_json
48
+ }
49
+ end
50
+
51
+ def authenticated?
52
+ @token_key.present?
53
+ end
54
+
55
+ def valid?
56
+ authenticated? and Time.now <= Time.at(@expires_at)
57
+ end
58
+
59
+ def token
60
+ "Token=#{@token_key}"
61
+ end
62
+
63
+ private
64
+
65
+ def extract_expires_at
66
+ return if @token_key.nil?
67
+ payload = @token_key.split('.')[1]
68
+ JSON.load(Base64.decode64(payload)).dig('exp')
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,57 @@
1
+ module BeautydateApi
2
+ class Business < APIResource
3
+
4
+ # Update object data from Beauty Data
5
+ def refresh
6
+ result = APIRequest.request("GET", "#{self.class.url(self.id)}")
7
+ self.errors = nil
8
+ update_attributes_from_result result
9
+ true
10
+ rescue BeautydateApi::RequestWithErrors => e
11
+ self.errors = e.errors
12
+ false
13
+ end
14
+
15
+ # commercial_name, type, zipcode, street, street_number, neighborhood, city, state, phone, description, az_id
16
+ def create(attributes)
17
+ result = APIRequest.request("POST", "#{self.class.endpoint_url}", { type: "businesses", attributes: attributes })
18
+ self.errors = nil
19
+ update_attributes_from_result result
20
+ true
21
+ rescue BeautydateApi::RequestWithErrors => e
22
+ self.errors = e.errors
23
+ false
24
+ end
25
+
26
+ def update
27
+ result = APIRequest.request("PUT", "#{self.class.url(self.id)}", { type: "businesses", id: self.id, attributes: unsaved_data })
28
+ self.errors = nil
29
+ update_attributes_from_result result
30
+ true
31
+ rescue BeautydateApi::RequestWithErrors => e
32
+ self.errors = e.errors
33
+ false
34
+ end
35
+
36
+ def add_trial_days(days, update_data=false)
37
+ APIRequest.request("POST", "#{self.class.url(self.id)}/add_trial_days/#{days}")
38
+ self.errors = nil
39
+ refresh if update_data
40
+ true
41
+ rescue BeautydateApi::RequestWithErrors => e
42
+ self.errors = e.errors
43
+ false
44
+ end
45
+
46
+ def manual_payment(status, update_data=false)
47
+ status = !!status ? 'enable' : 'disable'
48
+ APIRequest.request("PUT", "#{self.class.url(self.id)}/manual_payment/#{status}")
49
+ refresh if update_data
50
+ self.errors = nil
51
+ true
52
+ rescue BeautydateApi::RequestWithErrors => e
53
+ self.errors = e.errors
54
+ false
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,29 @@
1
+ module BeautydateApi
2
+ class BusinessPayment < APIResource
3
+ def create(attributes)
4
+ result = APIRequest.request('POST', self.class.endpoint_url, create_params(attributes))
5
+ self.errors = nil
6
+ update_attributes_from_result result
7
+ true
8
+ rescue BeautydateApi::RequestWithErrors => e
9
+ self.errors = e.errors
10
+ false
11
+ end
12
+
13
+ private
14
+
15
+ def create_params(attributes)
16
+ business_id = attributes.delete(:business_id)
17
+ business_plan_id = attributes.delete(:business_plan_id)
18
+
19
+ {
20
+ type: 'business_payments',
21
+ attributes: attributes,
22
+ relationships: {
23
+ business: { data: { type: 'businesses', id: business_id } },
24
+ business_plan: { data: { type: 'business_plans', id: business_plan_id } }
25
+ }
26
+ }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,53 @@
1
+ module BeautydateApi
2
+ class Object
3
+ attr_accessor :id
4
+ attr_accessor :errors
5
+
6
+ def initialize(attributes = {})
7
+ @unsaved_attributes = Set.new
8
+ set_attributes attributes
9
+ end
10
+
11
+ def set_attributes(attributes)
12
+ @attributes = attributes
13
+ @attributes.each do |attribute, value|
14
+ add_accessor(attribute)
15
+ end
16
+ end
17
+
18
+ def add_accessor(name)
19
+ name = name.to_s
20
+ return if name == 'id'
21
+ singleton_class.class_eval do
22
+ # get
23
+ define_method(name) do
24
+ self.attributes[name]
25
+ end
26
+
27
+ # set
28
+ define_method("#{name}=") do |value|
29
+ self.attributes[name] = value
30
+ self.unsaved_attributes.add name
31
+ end
32
+ end
33
+ end
34
+
35
+ def unsaved_attributes
36
+ @unsaved_attributes
37
+ end
38
+
39
+ def unsaved_data
40
+ @attributes.select { |key| @unsaved_attributes.include? key }
41
+ end
42
+
43
+ def attributes
44
+ @attributes
45
+ end
46
+
47
+ protected
48
+ def update_attributes_from_result(result)
49
+ set_attributes result["data"]["attributes"]
50
+ @id = result["data"]["id"]
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,3 @@
1
+ module BeautydateApi
2
+ VERSION = '0.1.3'
3
+ end