redbooth-ruby 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +11 -0
- data/.rspec +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +10 -0
- data/LICENSE +22 -0
- data/README.md +429 -0
- data/Rakefile +8 -0
- data/lib/redbooth-ruby/base.rb +43 -0
- data/lib/redbooth-ruby/client.rb +85 -0
- data/lib/redbooth-ruby/conversation.rb +20 -0
- data/lib/redbooth-ruby/me.rb +16 -0
- data/lib/redbooth-ruby/membership.rb +17 -0
- data/lib/redbooth-ruby/operations/base.rb +47 -0
- data/lib/redbooth-ruby/operations/create.rb +25 -0
- data/lib/redbooth-ruby/operations/delete.rb +26 -0
- data/lib/redbooth-ruby/operations/index.rb +49 -0
- data/lib/redbooth-ruby/operations/meta.rb +15 -0
- data/lib/redbooth-ruby/operations/show.rb +25 -0
- data/lib/redbooth-ruby/operations/update.rb +26 -0
- data/lib/redbooth-ruby/organization.rb +34 -0
- data/lib/redbooth-ruby/person.rb +23 -0
- data/lib/redbooth-ruby/project.rb +26 -0
- data/lib/redbooth-ruby/request/base.rb +41 -0
- data/lib/redbooth-ruby/request/collection.rb +105 -0
- data/lib/redbooth-ruby/request/connection.rb +140 -0
- data/lib/redbooth-ruby/request/helpers.rb +36 -0
- data/lib/redbooth-ruby/request/info.rb +41 -0
- data/lib/redbooth-ruby/request/response.rb +34 -0
- data/lib/redbooth-ruby/request/validator.rb +85 -0
- data/lib/redbooth-ruby/session.rb +46 -0
- data/lib/redbooth-ruby/task.rb +37 -0
- data/lib/redbooth-ruby/user.rb +13 -0
- data/lib/redbooth-ruby/version.rb +3 -0
- data/lib/redbooth-ruby.rb +113 -0
- data/redbooth-ruby.gemspec +30 -0
- metadata +37 -2
@@ -0,0 +1,34 @@
|
|
1
|
+
module RedboothRuby
|
2
|
+
module Request
|
3
|
+
# Wraps the API response parsing the json body and keeping interesting headers
|
4
|
+
#
|
5
|
+
class Response
|
6
|
+
attr_accessor :body, :headers, :data, :status
|
7
|
+
|
8
|
+
def initialize(attrs={})
|
9
|
+
@body = attrs[:body]
|
10
|
+
@headers = attrs[:headers]
|
11
|
+
@status = attrs[:status]
|
12
|
+
initialize_data
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
# initializes the json data with the request body
|
18
|
+
# or empty array if not
|
19
|
+
def initialize_data
|
20
|
+
@data = parse_body || {}
|
21
|
+
end
|
22
|
+
|
23
|
+
# Parses the json body if is a json valid string
|
24
|
+
#
|
25
|
+
def parse_body
|
26
|
+
return unless body.is_a?(String)
|
27
|
+
JSON.parse(body)
|
28
|
+
rescue
|
29
|
+
# not a valid json body
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module RedboothRuby
|
2
|
+
module Request
|
3
|
+
class Validator
|
4
|
+
attr_reader :info
|
5
|
+
attr_accessor :raw_response, :response
|
6
|
+
|
7
|
+
def initialize(info)
|
8
|
+
@info = info
|
9
|
+
end
|
10
|
+
|
11
|
+
# Validates the given http response creating a response object or
|
12
|
+
# failing with an error and description
|
13
|
+
#
|
14
|
+
# param incoming_response [] http response object
|
15
|
+
# return [RedboothRuby::Request::Response]
|
16
|
+
def validated_response_for(incoming_response)
|
17
|
+
self.raw_response = incoming_response
|
18
|
+
@response = RedboothRuby::Request::Response.new(headers: raw_response.headers,
|
19
|
+
body: raw_response.body,
|
20
|
+
status: raw_response.status.to_i)
|
21
|
+
verify_response_code
|
22
|
+
info.data = response.data
|
23
|
+
validate_response_data
|
24
|
+
response
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
# Verifies the response status code in case it fails with the dessired error
|
30
|
+
# and message
|
31
|
+
#
|
32
|
+
def verify_response_code
|
33
|
+
status = raw_response.status.to_i
|
34
|
+
case
|
35
|
+
when status == 401
|
36
|
+
verify_authentication_header
|
37
|
+
fail AuthenticationError
|
38
|
+
when status >= 500
|
39
|
+
fail APIError
|
40
|
+
when status >= 404
|
41
|
+
fail NotFound
|
42
|
+
when [102, 202].include?(status)
|
43
|
+
fail Processing, response
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Checks the authetication header to ensure wich is the best error to throw
|
48
|
+
#
|
49
|
+
def verify_authentication_header
|
50
|
+
case raw_response.headers['WWW-Authenticate']
|
51
|
+
when /error\=\"invalid_token\".*expired/
|
52
|
+
fail OauhtTokenExpired
|
53
|
+
when /error\=\"invalid_token\".*revoked/
|
54
|
+
fail OauhtTokenRevoked
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Validates the body data returned in the response in case there is
|
59
|
+
# an embed error it will fail with the dessired error and message
|
60
|
+
#
|
61
|
+
def validate_response_data
|
62
|
+
if response.data.is_a?(Hash)
|
63
|
+
if response.data['error']
|
64
|
+
handle_api_error(response.data['error']['code'], response.data['error']['message'])
|
65
|
+
elsif response.data['errors']
|
66
|
+
response.data['errors'].each do |error|
|
67
|
+
handle_api_error(error['code'], error['message'])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def handle_api_error(code, message)
|
74
|
+
error = case code
|
75
|
+
when 1021, 1024 then ObjectNotFound.new(message)
|
76
|
+
when 1300, 1303 then BadRequest.new(message)
|
77
|
+
when 2000 then AuthenticationError.new(message)
|
78
|
+
else
|
79
|
+
APIError.new(message)
|
80
|
+
end
|
81
|
+
fail error
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'oauth2'
|
2
|
+
|
3
|
+
module RedboothRuby
|
4
|
+
class Session
|
5
|
+
|
6
|
+
attr_accessor :token, :refresh_token, :access_token
|
7
|
+
attr_accessor :consumer_key, :consumer_secret
|
8
|
+
attr_accessor :oauth_verifier, :oauth_token
|
9
|
+
|
10
|
+
OAUTH_URLS = {
|
11
|
+
:site => 'https://redbooth.com/api/3',
|
12
|
+
:authorize_url => 'https://redbooth.com/oauth2/authorize',
|
13
|
+
:token_url => 'https://redbooth.com/oauth2/token'
|
14
|
+
}
|
15
|
+
|
16
|
+
def initialize(opts = {})
|
17
|
+
@token = opts[:token]
|
18
|
+
@consumer_key = opts[:consumer_key] || RedboothRuby.configuration[:consumer_key]
|
19
|
+
@consumer_secret = opts[:consumer_secret] || RedboothRuby.configuration[:consumer_secret]
|
20
|
+
@oauth_verifier = opts[:oauth_verifier]
|
21
|
+
@oauth_token = opts[:oauth_token]
|
22
|
+
end
|
23
|
+
|
24
|
+
def valid?
|
25
|
+
return false unless token
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
def client
|
30
|
+
@client ||= OAuth2::Client.new(consumer_key, consumer_secret, OAUTH_URLS)
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_access_token_url
|
34
|
+
url = OAUTH_URLS[:request_token_url]
|
35
|
+
url += "?oauth_verifier=#{oauth_verifier}" if oauth_verifier
|
36
|
+
url += "&oauth_token=#{oauth_token}" if oauth_token
|
37
|
+
end
|
38
|
+
|
39
|
+
def access_token
|
40
|
+
@access_token ||= OAuth2::AccessToken.new(client, token)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module RedboothRuby
|
2
|
+
class Task < Base
|
3
|
+
include RedboothRuby::Operations::Index
|
4
|
+
include RedboothRuby::Operations::Create
|
5
|
+
include RedboothRuby::Operations::Update
|
6
|
+
include RedboothRuby::Operations::Show
|
7
|
+
include RedboothRuby::Operations::Delete
|
8
|
+
|
9
|
+
attr_accessor :id,
|
10
|
+
:name,
|
11
|
+
:task_list_id,
|
12
|
+
:comments_count,
|
13
|
+
:assigned_id,
|
14
|
+
:is_private,
|
15
|
+
:project_id,
|
16
|
+
:urgent,
|
17
|
+
:user_id,
|
18
|
+
:position,
|
19
|
+
:last_activity_id,
|
20
|
+
:record_conversion_type,
|
21
|
+
:record_conversion_id,
|
22
|
+
:metadata,
|
23
|
+
:subtasks_count,
|
24
|
+
:resolved_subtasks_count,
|
25
|
+
:watcher_ids,
|
26
|
+
:description,
|
27
|
+
:description_html,
|
28
|
+
:description_updated_by_user_id,
|
29
|
+
:updated_by_id,
|
30
|
+
:deleted,
|
31
|
+
:status,
|
32
|
+
:due_on,
|
33
|
+
:created_at,
|
34
|
+
:updated_at
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module RedboothRuby
|
2
|
+
class User < Base
|
3
|
+
include RedboothRuby::Operations::Index
|
4
|
+
include RedboothRuby::Operations::Show
|
5
|
+
|
6
|
+
attr_accessor :id, :email, :first_name, :last_name, :developer, :created_time,
|
7
|
+
:emails, :storage, :confirmed, :user_id
|
8
|
+
|
9
|
+
def id
|
10
|
+
@id || @user_id
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
require 'json'
|
4
|
+
require 'redbooth-ruby/version'
|
5
|
+
|
6
|
+
module RedboothRuby
|
7
|
+
DOMAIN_BASE = nil
|
8
|
+
API_BASE_PATH = 'api'
|
9
|
+
API_VERSION = '3'
|
10
|
+
ROOT_PATH = File.dirname(__FILE__)
|
11
|
+
|
12
|
+
autoload :Base, 'redbooth-ruby/base'
|
13
|
+
autoload :Client, 'redbooth-ruby/client'
|
14
|
+
autoload :Session, 'redbooth-ruby/session'
|
15
|
+
autoload :Me, 'redbooth-ruby/me'
|
16
|
+
autoload :User, 'redbooth-ruby/user'
|
17
|
+
autoload :Task, 'redbooth-ruby/task'
|
18
|
+
autoload :Organization, 'redbooth-ruby/organization'
|
19
|
+
autoload :Person, 'redbooth-ruby/person'
|
20
|
+
autoload :Project, 'redbooth-ruby/project'
|
21
|
+
autoload :Conversation, 'redbooth-ruby/conversation'
|
22
|
+
autoload :Membership, 'redbooth-ruby/membership'
|
23
|
+
|
24
|
+
module Operations
|
25
|
+
autoload :Base, 'redbooth-ruby/operations/base'
|
26
|
+
autoload :Index, 'redbooth-ruby/operations/index'
|
27
|
+
autoload :Create, 'redbooth-ruby/operations/create'
|
28
|
+
autoload :Delete, 'redbooth-ruby/operations/delete'
|
29
|
+
autoload :Show, 'redbooth-ruby/operations/show'
|
30
|
+
autoload :Update, 'redbooth-ruby/operations/update'
|
31
|
+
autoload :Meta, 'redbooth-ruby/operations/meta'
|
32
|
+
end
|
33
|
+
|
34
|
+
module Request
|
35
|
+
autoload :Base, 'redbooth-ruby/request/base'
|
36
|
+
autoload :Connection, 'redbooth-ruby/request/connection'
|
37
|
+
autoload :Helpers, 'redbooth-ruby/request/helpers'
|
38
|
+
autoload :Info, 'redbooth-ruby/request/info'
|
39
|
+
autoload :Validator, 'redbooth-ruby/request/validator'
|
40
|
+
autoload :Response, 'redbooth-ruby/request/response'
|
41
|
+
autoload :Collection, 'redbooth-ruby/request/collection'
|
42
|
+
end
|
43
|
+
|
44
|
+
class RedboothError < StandardError; end
|
45
|
+
class AuthenticationError < RedboothError; end
|
46
|
+
class OauhtTokenExpired < AuthenticationError; end
|
47
|
+
class OauhtTokenRevoked < AuthenticationError; end
|
48
|
+
class NotFound < RedboothError; end
|
49
|
+
class APIError < RedboothError; end
|
50
|
+
class ObjectNotFound < APIError; end
|
51
|
+
class BadRequest < APIError; end
|
52
|
+
|
53
|
+
# Signals. Usign errors as control flow
|
54
|
+
#
|
55
|
+
class RedboothSignal < StandardError; end
|
56
|
+
class Processing < RedboothSignal
|
57
|
+
attr_accessor :response
|
58
|
+
|
59
|
+
def initialize(response, message='')
|
60
|
+
@response = response
|
61
|
+
super(message)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
# Gives configuration abilities
|
67
|
+
# to setup api_key and api_secret
|
68
|
+
#
|
69
|
+
# @example
|
70
|
+
# Copy.config do |configuration|
|
71
|
+
# configuration[:api_key] = '_your_api_key'
|
72
|
+
# configuration[:api_secret] = '_your_api_secret'
|
73
|
+
# end
|
74
|
+
#
|
75
|
+
# @return [String] The api key
|
76
|
+
def self.config(&block)
|
77
|
+
default_configuration
|
78
|
+
yield(@@configuration)
|
79
|
+
@@configuration
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.configuration
|
83
|
+
default_configuration
|
84
|
+
@@configuration
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.configuration=(value)
|
88
|
+
default_configuration
|
89
|
+
@@configuration = value
|
90
|
+
end
|
91
|
+
|
92
|
+
# Makes a request against the Copy API
|
93
|
+
#
|
94
|
+
# @param [Symbol] http_method The http method to use, must be one of :get, :post, :put and :delete
|
95
|
+
# @param [String] domain The API domain to use
|
96
|
+
# @param [String] api_url The API url to use
|
97
|
+
# @param [Hash] data The data to send, e.g. used when creating new objects.
|
98
|
+
# @return [Array] The parsed JSON response.
|
99
|
+
def self.request(http_method, domain, api_url, data, options = {})
|
100
|
+
info = Request::Info.new(http_method, domain, api_url, data, options)
|
101
|
+
Request::Base.new(info).perform
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.default_configuration
|
105
|
+
return if defined?(@@configuration)
|
106
|
+
@@configuration ||= {}
|
107
|
+
@@configuration[:api_base] ||= 'redbooth.com'
|
108
|
+
@@configuration[:domain_base] ||= nil
|
109
|
+
@@configuration[:api_base_path] ||= 'api'
|
110
|
+
@@configuration[:api_version] ||= '3'
|
111
|
+
@@configuration[:use_ssl] ||= true
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'redbooth-ruby/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'redbooth-ruby'
|
8
|
+
s.version = RedboothRuby::VERSION
|
9
|
+
s.authors = ['Andres Bravo', 'Carlos Saura']
|
10
|
+
s.email = ['support@redbooth.com']
|
11
|
+
s.homepage = 'https://github.com/teambox/redbooth-ruby'
|
12
|
+
s.summary = %q{API wrapper for Redbooth.}
|
13
|
+
s.description = %q{API wrapper for Redbooth.}
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ['lib']
|
19
|
+
|
20
|
+
s.required_ruby_version = '>= 1.9.3'
|
21
|
+
|
22
|
+
s.add_dependency 'json', '>= 1.8.1'
|
23
|
+
s.add_dependency 'oauth2', '>= 0.9.3'
|
24
|
+
s.add_dependency(%q<multipart-post>, ['>= 1.1.0'])
|
25
|
+
|
26
|
+
s.add_development_dependency 'rspec'
|
27
|
+
s.add_development_dependency 'pry'
|
28
|
+
s.add_development_dependency 'vcr'
|
29
|
+
s.add_development_dependency 'fakeweb'
|
30
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redbooth-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andres Bravo
|
@@ -116,6 +116,41 @@ executables: []
|
|
116
116
|
extensions: []
|
117
117
|
extra_rdoc_files: []
|
118
118
|
files:
|
119
|
+
- .gitignore
|
120
|
+
- .rspec
|
121
|
+
- .travis.yml
|
122
|
+
- Gemfile
|
123
|
+
- LICENSE
|
124
|
+
- README.md
|
125
|
+
- Rakefile
|
126
|
+
- lib/redbooth-ruby.rb
|
127
|
+
- lib/redbooth-ruby/base.rb
|
128
|
+
- lib/redbooth-ruby/client.rb
|
129
|
+
- lib/redbooth-ruby/conversation.rb
|
130
|
+
- lib/redbooth-ruby/me.rb
|
131
|
+
- lib/redbooth-ruby/membership.rb
|
132
|
+
- lib/redbooth-ruby/operations/base.rb
|
133
|
+
- lib/redbooth-ruby/operations/create.rb
|
134
|
+
- lib/redbooth-ruby/operations/delete.rb
|
135
|
+
- lib/redbooth-ruby/operations/index.rb
|
136
|
+
- lib/redbooth-ruby/operations/meta.rb
|
137
|
+
- lib/redbooth-ruby/operations/show.rb
|
138
|
+
- lib/redbooth-ruby/operations/update.rb
|
139
|
+
- lib/redbooth-ruby/organization.rb
|
140
|
+
- lib/redbooth-ruby/person.rb
|
141
|
+
- lib/redbooth-ruby/project.rb
|
142
|
+
- lib/redbooth-ruby/request/base.rb
|
143
|
+
- lib/redbooth-ruby/request/collection.rb
|
144
|
+
- lib/redbooth-ruby/request/connection.rb
|
145
|
+
- lib/redbooth-ruby/request/helpers.rb
|
146
|
+
- lib/redbooth-ruby/request/info.rb
|
147
|
+
- lib/redbooth-ruby/request/response.rb
|
148
|
+
- lib/redbooth-ruby/request/validator.rb
|
149
|
+
- lib/redbooth-ruby/session.rb
|
150
|
+
- lib/redbooth-ruby/task.rb
|
151
|
+
- lib/redbooth-ruby/user.rb
|
152
|
+
- lib/redbooth-ruby/version.rb
|
153
|
+
- redbooth-ruby.gemspec
|
119
154
|
- spec/cassettes/RedboothRuby_Conversation/_create/.yml
|
120
155
|
- spec/cassettes/RedboothRuby_Conversation/_create/makes_a_new_POST_request_using_the_correct_API_endpoint_to_create_a_specific_conversation.yml
|
121
156
|
- spec/cassettes/RedboothRuby_Conversation/_delete/makes_a_new_DELETE_request_using_the_correct_API_endpoint_to_delete_a_specific_conversation.yml
|
@@ -262,7 +297,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
262
297
|
requirements:
|
263
298
|
- - '>='
|
264
299
|
- !ruby/object:Gem::Version
|
265
|
-
version:
|
300
|
+
version: 1.9.3
|
266
301
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
267
302
|
requirements:
|
268
303
|
- - '>='
|