assembla_api 0.1.2

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 (112) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +20 -0
  3. data/Rakefile +22 -0
  4. data/lib/assembla_api.rb +130 -0
  5. data/lib/assembla_api/api.rb +373 -0
  6. data/lib/assembla_api/api/actions.rb +58 -0
  7. data/lib/assembla_api/api/arguments.rb +248 -0
  8. data/lib/assembla_api/api/config.rb +107 -0
  9. data/lib/assembla_api/api/config/property.rb +30 -0
  10. data/lib/assembla_api/api/config/property_set.rb +119 -0
  11. data/lib/assembla_api/api/factory.rb +33 -0
  12. data/lib/assembla_api/authorization.rb +76 -0
  13. data/lib/assembla_api/client.rb +21 -0
  14. data/lib/assembla_api/client/activity.rb +30 -0
  15. data/lib/assembla_api/client/authorizations.rb +143 -0
  16. data/lib/assembla_api/client/authorizations/app.rb +98 -0
  17. data/lib/assembla_api/client/portfolio.rb +19 -0
  18. data/lib/assembla_api/client/portfolio/invitations.rb +30 -0
  19. data/lib/assembla_api/client/portfolio/spaces.rb +13 -0
  20. data/lib/assembla_api/client/portfolio/standup_reports.rb +34 -0
  21. data/lib/assembla_api/client/portfolio/tasks.rb +13 -0
  22. data/lib/assembla_api/client/portfolio/ticket_reports.rb +13 -0
  23. data/lib/assembla_api/client/portfolio/tickets.rb +13 -0
  24. data/lib/assembla_api/client/portfolio/users.rb +13 -0
  25. data/lib/assembla_api/client/spaces.rb +140 -0
  26. data/lib/assembla_api/client/spaces/documents.rb +87 -0
  27. data/lib/assembla_api/client/spaces/milestones.rb +102 -0
  28. data/lib/assembla_api/client/spaces/space_tools.rb +65 -0
  29. data/lib/assembla_api/client/spaces/space_tools/merge_requests.rb +105 -0
  30. data/lib/assembla_api/client/spaces/space_tools/merge_requests/versions.rb +41 -0
  31. data/lib/assembla_api/client/spaces/space_tools/merge_requests/versions/comments.rb +34 -0
  32. data/lib/assembla_api/client/spaces/space_tools/merge_requests/versions/votes.rb +46 -0
  33. data/lib/assembla_api/client/spaces/ssh.rb +14 -0
  34. data/lib/assembla_api/client/spaces/ssh/actions.rb +76 -0
  35. data/lib/assembla_api/client/spaces/ssh/actions/launches.rb +14 -0
  36. data/lib/assembla_api/client/spaces/ssh/keys.rb +18 -0
  37. data/lib/assembla_api/client/spaces/ssh/launches.rb +29 -0
  38. data/lib/assembla_api/client/spaces/ssh/servers.rb +63 -0
  39. data/lib/assembla_api/client/spaces/standup_away_reports.rb +41 -0
  40. data/lib/assembla_api/client/spaces/standup_reports.rb +41 -0
  41. data/lib/assembla_api/client/spaces/tags.rb +96 -0
  42. data/lib/assembla_api/client/spaces/tickets.rb +154 -0
  43. data/lib/assembla_api/client/spaces/tickets/associations.rb +57 -0
  44. data/lib/assembla_api/client/spaces/tickets/comments.rb +45 -0
  45. data/lib/assembla_api/client/spaces/tickets/custom_fields.rb +57 -0
  46. data/lib/assembla_api/client/spaces/tickets/statuses.rb +55 -0
  47. data/lib/assembla_api/client/spaces/user_roles.rb +61 -0
  48. data/lib/assembla_api/client/spaces/users.rb +11 -0
  49. data/lib/assembla_api/client/spaces/webhooks.rb +63 -0
  50. data/lib/assembla_api/client/spaces/wiki_pages.rb +78 -0
  51. data/lib/assembla_api/client/spaces/wiki_pages/versions.rb +20 -0
  52. data/lib/assembla_api/client/tasks.rb +72 -0
  53. data/lib/assembla_api/client/users.rb +49 -0
  54. data/lib/assembla_api/client/users/keys.rb +97 -0
  55. data/lib/assembla_api/configuration.rb +71 -0
  56. data/lib/assembla_api/connection.rb +66 -0
  57. data/lib/assembla_api/constants.rb +74 -0
  58. data/lib/assembla_api/core_ext/array.rb +25 -0
  59. data/lib/assembla_api/core_ext/hash.rb +92 -0
  60. data/lib/assembla_api/core_ext/ordered_hash.rb +107 -0
  61. data/lib/assembla_api/deprecation.rb +39 -0
  62. data/lib/assembla_api/error.rb +37 -0
  63. data/lib/assembla_api/error/bad_request.rb +14 -0
  64. data/lib/assembla_api/error/client_error.rb +20 -0
  65. data/lib/assembla_api/error/forbidden.rb +14 -0
  66. data/lib/assembla_api/error/internal_server_error.rb +15 -0
  67. data/lib/assembla_api/error/invalid_options.rb +18 -0
  68. data/lib/assembla_api/error/not_acceptable.rb +15 -0
  69. data/lib/assembla_api/error/not_found.rb +14 -0
  70. data/lib/assembla_api/error/required_params.rb +18 -0
  71. data/lib/assembla_api/error/service_error.rb +68 -0
  72. data/lib/assembla_api/error/service_unavailable.rb +15 -0
  73. data/lib/assembla_api/error/unauthorized.rb +15 -0
  74. data/lib/assembla_api/error/unknown_media.rb +18 -0
  75. data/lib/assembla_api/error/unknown_value.rb +18 -0
  76. data/lib/assembla_api/error/unprocessable_entity.rb +14 -0
  77. data/lib/assembla_api/error/validations.rb +18 -0
  78. data/lib/assembla_api/ext/faraday.rb +38 -0
  79. data/lib/assembla_api/jsonable.rb +18 -0
  80. data/lib/assembla_api/middleware.rb +31 -0
  81. data/lib/assembla_api/mime_type.rb +33 -0
  82. data/lib/assembla_api/normalizer.rb +25 -0
  83. data/lib/assembla_api/null_encoder.rb +25 -0
  84. data/lib/assembla_api/page_iterator.rb +142 -0
  85. data/lib/assembla_api/page_links.rb +45 -0
  86. data/lib/assembla_api/paged_request.rb +40 -0
  87. data/lib/assembla_api/pagination.rb +102 -0
  88. data/lib/assembla_api/parameter_filter.rb +32 -0
  89. data/lib/assembla_api/params_hash.rb +101 -0
  90. data/lib/assembla_api/rate_limit.rb +25 -0
  91. data/lib/assembla_api/request.rb +85 -0
  92. data/lib/assembla_api/request/basic_auth.rb +33 -0
  93. data/lib/assembla_api/request/jsonize.rb +53 -0
  94. data/lib/assembla_api/request/key_auth.rb +31 -0
  95. data/lib/assembla_api/request/oauth2.rb +42 -0
  96. data/lib/assembla_api/request/verbs.rb +60 -0
  97. data/lib/assembla_api/response.rb +28 -0
  98. data/lib/assembla_api/response/header.rb +76 -0
  99. data/lib/assembla_api/response/jsonize.rb +29 -0
  100. data/lib/assembla_api/response/mashify.rb +24 -0
  101. data/lib/assembla_api/response/raise_error.rb +18 -0
  102. data/lib/assembla_api/response/xmlize.rb +26 -0
  103. data/lib/assembla_api/response_wrapper.rb +157 -0
  104. data/lib/assembla_api/ssl_certs/cacerts.pem +2183 -0
  105. data/lib/assembla_api/utils/url.rb +59 -0
  106. data/lib/assembla_api/validations.rb +25 -0
  107. data/lib/assembla_api/validations/format.rb +24 -0
  108. data/lib/assembla_api/validations/presence.rb +30 -0
  109. data/lib/assembla_api/validations/required.rb +24 -0
  110. data/lib/assembla_api/validations/token.rb +41 -0
  111. data/lib/assembla_api/version.rb +12 -0
  112. metadata +347 -0
@@ -0,0 +1,101 @@
1
+ # encoding: utf-8
2
+
3
+ require 'delegate'
4
+ require 'base64'
5
+
6
+ module Assembla
7
+
8
+ # Class responsible for holding request parameters
9
+ class ParamsHash < DelegateClass(Hash)
10
+ include Normalizer
11
+ include MimeType
12
+
13
+ def initialize(hash)
14
+ super(normalize!(Hash[hash]))
15
+ end
16
+
17
+ # Create empty hash
18
+ #
19
+ def self.empty
20
+ new({})
21
+ end
22
+
23
+ # Extract and parse media type param
24
+ #
25
+ # [.version].param[+json]
26
+ #
27
+ def media
28
+ parse(delete('media'))
29
+ end
30
+
31
+ # Return accept header if present
32
+ #
33
+ def accept
34
+ if has_key?('accept')
35
+ delete('accept')
36
+ elsif has_key?('media')
37
+ media
38
+ else
39
+ nil
40
+ end
41
+ end
42
+
43
+ # Extract request data from parameters
44
+ #
45
+ def data
46
+ if has_key?('data') && !self['data'].nil?
47
+ return delete('data')
48
+ else
49
+ return to_hash
50
+ end
51
+ end
52
+
53
+ def encoder
54
+ if has_key?('encoder') && self['encoder']
55
+ return delete('encoder')
56
+ else
57
+ return {}
58
+ end
59
+ end
60
+
61
+ # Any client configuration options
62
+ #
63
+ def options
64
+ opts = has_key?('options') ? delete('options') : {}
65
+ headers = opts.fetch(:headers) { {} }
66
+ if value = accept
67
+ headers[:accept] = value
68
+ end
69
+ if value = delete('content_type')
70
+ headers[:content_type] = value
71
+ end
72
+ opts[:raw] = has_key?('raw') ? delete('raw') : false
73
+ opts[:headers] = headers unless headers.empty?
74
+ opts
75
+ end
76
+
77
+ # Update hash with default parameters for non existing keys
78
+ #
79
+ def merge_default(defaults)
80
+ if defaults && !defaults.empty?
81
+ defaults.each do |key, value|
82
+ self[key] = value unless self.has_key?(key)
83
+ end
84
+ end
85
+ self
86
+ end
87
+
88
+ # Base64 encode string removing newline characters
89
+ #
90
+ def strict_encode64(key)
91
+ value = self[key]
92
+ encoded = if Base64.respond_to?(:strict_encode64)
93
+ Base64.strict_encode64(value)
94
+ else
95
+ [value].pack("m0")
96
+ end
97
+ self[key] = encoded.delete("\n\r")
98
+ end
99
+
100
+ end # ParamsHash
101
+ end # Assembla
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ module Assembla
4
+ module RateLimit
5
+
6
+ def ratelimit(*args)
7
+ arguments(args)
8
+
9
+ get_request("/rate_limit", arguments.params).rate.limit
10
+ end
11
+
12
+ def ratelimit_remaining(*args)
13
+ arguments(args)
14
+
15
+ get_request("/rate_limit", arguments.params).rate.remaining
16
+ end
17
+
18
+ def ratelimit_reset(*args)
19
+ arguments(args)
20
+
21
+ get_request("/rate_limit", arguments.params).rate.reset
22
+ end
23
+
24
+ end # RateLimit
25
+ end # Assembla
@@ -0,0 +1,85 @@
1
+ # encoding: utf-8
2
+
3
+ require 'assembla_api/request/oauth2'
4
+ require 'assembla_api/request/basic_auth'
5
+ require 'assembla_api/request/key_auth'
6
+ require 'assembla_api/request/jsonize'
7
+
8
+ require 'assembla_api/connection'
9
+
10
+ module Assembla
11
+ # A class responsible for dispatching http requests
12
+ class Request
13
+ include Connection
14
+
15
+ HTTP_METHODS = [:get, :head, :post, :put, :delete, :patch]
16
+
17
+ METHODS_WITH_BODIES = [:post, :put, :patch]
18
+
19
+ # Return http verb
20
+ #
21
+ # @return [Symbol]
22
+ attr_reader :action
23
+
24
+ # Return url
25
+ #
26
+ # @return [String]
27
+ attr_accessor :path
28
+
29
+ # Return api this request is associated with
30
+ #
31
+ # @return [Assembla::API]
32
+ attr_reader :api
33
+
34
+ # Create a new Request
35
+ #
36
+ # @return [Assembla::Request]
37
+ #
38
+ # @api public
39
+ def initialize(action, path, api)
40
+ @action = action
41
+ @path = path
42
+ @api = api
43
+ end
44
+
45
+ # Performs a request
46
+ #
47
+ # @param [Symbol] method - The Symbol the HTTP verb
48
+ # @param [String] path - String relative URL to access
49
+ # @param [ParamsHash] params - ParamsHash to configure the request API
50
+ #
51
+ # @return [Assembla::ResponseWrapper]
52
+ #
53
+ # @api private
54
+ def call(current_options, params)
55
+ unless HTTP_METHODS.include?(action)
56
+ raise ArgumentError, "unknown http method: #{method}"
57
+ end
58
+
59
+ puts "EXECUTED: #{action} - #{path} with PARAMS: #{params}" if ENV['DEBUG']
60
+
61
+ request_options = params.options
62
+ connection_options = current_options.merge(request_options)
63
+ conn = connection(api, connection_options)
64
+
65
+ if conn.path_prefix != '/' && self.path.index(conn.path_prefix) != 0
66
+ self.path = (conn.path_prefix + self.path).gsub(/\/(\/)*/, '/')
67
+ end
68
+
69
+ response = conn.send(action) do |request|
70
+ case action.to_sym
71
+ when *(HTTP_METHODS - METHODS_WITH_BODIES)
72
+ request.body = params.data if params.has_key?('data')
73
+ if params.has_key?('encoder')
74
+ request.params.params_encoder(params.encoder)
75
+ end
76
+ request.url(self.path, params.to_hash)
77
+ when *METHODS_WITH_BODIES
78
+ request.url(self.path, connection_options[:query] || {})
79
+ request.body = params.data unless params.empty?
80
+ end
81
+ end
82
+ ResponseWrapper.new(response, api)
83
+ end
84
+ end # Request
85
+ end # Assembla
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ require 'faraday'
4
+ require 'base64'
5
+
6
+ module Assembla
7
+ class Request
8
+ class BasicAuth < Faraday::Middleware
9
+ dependency 'base64'
10
+
11
+ def call(env)
12
+ unless @auth.to_s.empty?
13
+ env[:request_headers].merge!('Authorization' => "Basic #{@auth}\"")
14
+ end
15
+
16
+ @app.call env
17
+ end
18
+
19
+ def initialize(app, *args)
20
+ @app = app
21
+ credentials = ""
22
+ options = args.extract_options!
23
+ if options.has_key? :login
24
+ credentials = "#{options[:login]}:#{options[:password]}"
25
+ elsif options.has_key? :basic_auth
26
+ credentials = "#{options[:basic_auth]}"
27
+ end
28
+ @auth = Base64.encode64(credentials)
29
+ @auth.gsub!("\n", "")
30
+ end
31
+ end # BasicAuth
32
+ end # Request
33
+ end # Assembla
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require 'faraday'
4
+
5
+ module Assembla
6
+ class Request::Jsonize < Faraday::Middleware
7
+
8
+ CONTENT_TYPE = 'Content-Type'.freeze
9
+ MIME_TYPE = 'application/json'.freeze
10
+
11
+ dependency 'multi_json'
12
+
13
+ def call(env)
14
+ unless env[:request_headers][CONTENT_TYPE].to_s =~ /^multipart/
15
+ if request_with_body?(env)
16
+ env[:request_headers][CONTENT_TYPE] ||= MIME_TYPE
17
+ env[:body] = encode_body env[:body] unless env[:body].respond_to?(:to_str)
18
+ else
19
+ # Ensure valid body for put and post requests
20
+ if [:put, :patch, :post].include? env[:method]
21
+ env[:body] = encode_body({})
22
+ end
23
+ end
24
+ end
25
+
26
+ @app.call env
27
+ end
28
+
29
+ def encode_body(value)
30
+ if MultiJson.respond_to?(:dump)
31
+ MultiJson.dump(value)
32
+ else
33
+ MultiJson.encode(value)
34
+ end
35
+ end
36
+
37
+ def request_with_body?(env)
38
+ type = request_type(env)
39
+ has_body?(env) and (type.empty? or type == MIME_TYPE)
40
+ end
41
+
42
+ # Don't encode bodies in string form
43
+ def has_body?(env)
44
+ body = env[:body] and !(body.respond_to?(:to_str) and body.empty?)
45
+ end
46
+
47
+ def request_type(env)
48
+ type = env[:request_headers][CONTENT_TYPE].to_s
49
+ type = type.split(';', 2).first if type.index(';')
50
+ type
51
+ end
52
+ end # Request::Jsonize
53
+ end # Assembla
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ require 'faraday'
4
+ require 'base64'
5
+
6
+ module Assembla
7
+ class Request
8
+ class KeyAuth < Faraday::Middleware
9
+ dependency 'base64'
10
+
11
+ def call(env)
12
+ unless @api_key.to_s.empty?
13
+ env[:request_headers].merge!('X-Api-Key' => @api_key,
14
+ 'X-Api-Secret' => @api_secret)
15
+ end
16
+
17
+ @app.call env
18
+ end
19
+
20
+ def initialize(app, *args)
21
+ @app = app
22
+ options = args.extract_options!
23
+
24
+ if options.has_key? :api_key
25
+ @api_key = options[:api_key]
26
+ @api_secret = options[:api_secret]
27
+ end
28
+ end
29
+ end # KeyAuth
30
+ end # Request
31
+ end # Assembla
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+
3
+ require 'faraday'
4
+
5
+ module Assembla
6
+ class Request
7
+ class OAuth2 < Faraday::Middleware
8
+ include Assembla::Utils::Url
9
+
10
+ ACCESS_TOKEN = 'access_token'.freeze
11
+ AUTH_HEADER = 'Authorization'.freeze
12
+
13
+ dependency 'oauth2'
14
+
15
+ def call(env)
16
+ # Extract parameters from the query
17
+ params = { ACCESS_TOKEN => @token }.update query_params(env[:url])
18
+
19
+ if token = params[ACCESS_TOKEN] and !token.empty?
20
+ env[:url].query = build_query params
21
+ env[:request_headers].merge!(AUTH_HEADER => "Token token=\"#{token}\"")
22
+ end
23
+
24
+ @app.call env
25
+ end
26
+
27
+ def initialize(app, *args)
28
+ super app
29
+ @app = app
30
+ @token = args.shift
31
+ end
32
+
33
+ def query_params(url)
34
+ if url.query.nil? or url.query.empty?
35
+ {}
36
+ else
37
+ parse_query url.query
38
+ end
39
+ end
40
+ end # OAuth2
41
+ end # Request
42
+ end # Assembla
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+
3
+ module Assembla
4
+ # A class responsible for dispatching http requests
5
+ class Request
6
+
7
+ # Defines HTTP verbs
8
+ module Verbs
9
+ # Make a head request
10
+ #
11
+ # @api public
12
+ def head_request(path, params = ParamsHash.empty)
13
+ Request.new(:head, path, self).call(current_options, params)
14
+ end
15
+
16
+ # Make a get request
17
+ #
18
+ # @api public
19
+ def get_request(path, params = ParamsHash.empty)
20
+ request = Request.new(:get, path, self).call(current_options, params)
21
+ request.auto_paginate
22
+ end
23
+
24
+ # Make a patch request
25
+ #
26
+ # @api public
27
+ def patch_request(path, params = ParamsHash.empty)
28
+ Request.new(:patch, path, self).call(current_options, params)
29
+ end
30
+
31
+ # Make a post request
32
+ #
33
+ # @api public
34
+ def post_request(path, params = ParamsHash.empty)
35
+ Request.new(:post, path, self).call(current_options, params)
36
+ end
37
+
38
+ # Make a put request
39
+ #
40
+ # @api public
41
+ def put_request(path, params = ParamsHash.empty)
42
+ Request.new(:put, path, self).call(current_options, params)
43
+ end
44
+
45
+ # Make a delete request
46
+ #
47
+ # @api public
48
+ def delete_request(path, params = ParamsHash.empty)
49
+ Request.new(:delete, path, self).call(current_options, params)
50
+ end
51
+
52
+ # Make a options request
53
+ #
54
+ # @api public
55
+ def options_request(path, params = ParamsHash.empty)
56
+ Request.new(:options, path, self).call(current_options, params)
57
+ end
58
+ end # Verbs
59
+ end # Request
60
+ end # Assembla
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+
3
+ require 'faraday'
4
+
5
+ module Assembla
6
+ # Contains methods and attributes that act on the response returned from the
7
+ # request
8
+ class Response < Faraday::Response::Middleware
9
+ CONTENT_TYPE = 'Content-Type'.freeze
10
+
11
+ class << self
12
+ attr_accessor :parser
13
+ end
14
+
15
+ def self.define_parser(&block)
16
+ @parser = block
17
+ end
18
+
19
+ def response_type(env)
20
+ env[:response_headers][CONTENT_TYPE].to_s
21
+ end
22
+
23
+ def parse_response?(env)
24
+ env[:body].respond_to? :to_str
25
+ end
26
+
27
+ end # Response
28
+ end # Assembla