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,71 @@
1
+ # encoding: utf-8
2
+
3
+ require 'assembla_api/api/config'
4
+
5
+ module Assembla
6
+ # Stores the configuration
7
+ class Configuration < API::Config
8
+
9
+ # Other adapters are :typhoeus, :patron, :em_synchrony, :excon, :test
10
+ property :adapter, default: :net_http
11
+
12
+ # By default, don't traverse the page links
13
+ property :auto_pagination, default: false
14
+
15
+ # Basic authentication
16
+ property :basic_auth
17
+
18
+ # By default, don't set an application key
19
+ property :client_id
20
+
21
+ # By default, don't set an application secret
22
+ property :client_secret
23
+
24
+ # By default, don't set an api key
25
+ property :api_key
26
+
27
+ # By default, don't set an api secret
28
+ property :api_secret
29
+
30
+ # By default, don't set a user oauth access token
31
+ property :oauth_token
32
+
33
+ # The api endpoint used to connect to Assembla if none is set
34
+ property :endpoint, default: 'https://api.assembla.com/v1'.freeze
35
+
36
+ # The web endpoint used to connect to Assembla if none is set
37
+ property :site, default: 'https://www.assembla.com'.freeze
38
+
39
+ # The default SSL configuration
40
+ property :ssl, default: {
41
+ :ca_file => File.expand_path('../ssl_certs/cacerts.pem', __FILE__)
42
+ }
43
+
44
+ # By default the Accept header will make a request for JSON
45
+ property :mime_type
46
+
47
+ # The value sent in the http header for 'User-Agent' if none is set
48
+ property :user_agent, default: "Assembla API Ruby Gem #{Assembla::VERSION::STRING}".freeze
49
+
50
+ # By default uses the Faraday connection options if none is set
51
+ property :connection_options, default: {}
52
+
53
+ # Global repository name
54
+ property :repo
55
+
56
+ property :user
57
+
58
+ # TODO Portfolio
59
+ property :org
60
+
61
+ property :login
62
+
63
+ property :password
64
+
65
+ # By default display 30 resources
66
+ property :per_page, default: 30
67
+
68
+ # Add Faraday::RackBuilder to overwrite middleware
69
+ property :stack
70
+ end # Configuration
71
+ end # Assembla
@@ -0,0 +1,66 @@
1
+ # encoding: utf-8
2
+
3
+ module Assembla
4
+ # Specifies Http connection options
5
+ module Connection
6
+ extend self
7
+ include Assembla::Constants
8
+
9
+ ALLOWED_OPTIONS = [
10
+ :headers,
11
+ :url,
12
+ :params,
13
+ :request,
14
+ :ssl
15
+ ].freeze
16
+
17
+ def default_options(options = {})
18
+ accept = options[:headers] && options[:headers][:accept]
19
+ {
20
+ headers: {
21
+ ACCEPT => accept || 'application/vnd.assembla.v1+json,' \
22
+ 'application/vnd.assembla.beta+json;q=0.5,' \
23
+ 'application/json;q=0.1',
24
+ ACCEPT_CHARSET => 'utf-8',
25
+ USER_AGENT => options[:user_agent]
26
+ },
27
+ ssl: options[:ssl],
28
+ url: options[:endpoint]
29
+ }
30
+ end
31
+
32
+ def clear_cache
33
+ @connection = nil
34
+ end
35
+
36
+ def caching?
37
+ !@connection.nil?
38
+ end
39
+
40
+ # Exposes middleware builder to facilitate custom stacks and easy
41
+ # addition of new extensions such as cache adapter.
42
+ #
43
+ # @api public
44
+ def stack(options = {})
45
+ @stack ||= begin
46
+ builder_class = defined?(Faraday::RackBuilder) ? Faraday::RackBuilder : Faraday::Builder
47
+ builder_class.new(&Assembla.default_middleware(options))
48
+ end
49
+ end
50
+
51
+ # Creates http connection
52
+ #
53
+ # Returns a Fraday::Connection object
54
+ def connection(api, options = {})
55
+ connection_options = default_options(options)
56
+ clear_cache unless options.empty?
57
+ builder = api.stack ? api.stack : stack(options.merge!(api: api))
58
+ connection_options.merge!(builder: builder)
59
+ if ENV['DEBUG']
60
+ p "Connection options : \n"
61
+ pp connection_options
62
+ end
63
+ @connection ||= Faraday.new(connection_options)
64
+ end
65
+ end # Connection
66
+ end # Assembla
@@ -0,0 +1,74 @@
1
+ module Assembla
2
+ module Constants
3
+ extend self
4
+
5
+ # Response headers
6
+ RATELIMIT_REMAINING = 'X-RateLimit-Remaining'.freeze
7
+
8
+ RATELIMIT_LIMIT = 'X-RateLimit-Limit'.freeze
9
+
10
+ CONTENT_TYPE = 'Content-Type'.freeze
11
+
12
+ CONTENT_LENGTH = 'content-length'.freeze
13
+
14
+ CACHE_CONTROL = 'cache-control'.freeze
15
+
16
+ ETAG = 'ETag'.freeze
17
+
18
+ SERVER = 'Server'.freeze
19
+
20
+ DATE = 'Date'.freeze
21
+
22
+ LOCATION = 'Location'.freeze
23
+
24
+ USER_AGENT = 'User-Agent'.freeze
25
+
26
+ ACCEPT = 'Accept'.freeze
27
+
28
+ ACCEPT_CHARSET = 'Accept-Charset'.freeze
29
+
30
+ OAUTH_SCOPES = 'X-Oauth-Scopes'.freeze
31
+
32
+ ACCEPTED_OAUTH_SCOPES = 'X-Accepted-Oauth-Scopes'.freeze
33
+
34
+ # Link headers
35
+ HEADER_LINK = "Link".freeze
36
+
37
+ HEADER_NEXT = "X-Next".freeze
38
+
39
+ HEADER_LAST = "X-Last".freeze
40
+
41
+ META_REL = "rel".freeze
42
+
43
+ META_LAST = "last".freeze
44
+
45
+ META_NEXT = "next".freeze
46
+
47
+ META_FIRST = "first".freeze
48
+
49
+ META_PREV = "prev".freeze
50
+
51
+ PARAM_PAGE = "page".freeze
52
+
53
+ PARAM_PER_PAGE = "per_page".freeze
54
+
55
+ PARAM_START_PAGE = "start_page".freeze
56
+
57
+ class ToolTypes
58
+ MILESTONES = 9
59
+ STANDUP = 10
60
+ TICKETS = 13
61
+ FILES = 18
62
+ MESSAGES = 21
63
+ WIKI = 23
64
+ WEBHOOKS = 112
65
+ GIT = 128
66
+ SSH = 200
67
+ # TODO add all tools
68
+ ALL = [ MESSAGES, TICKETS, MILESTONES, FILES, STANDUP, GIT, WIKI, WEBHOOKS,
69
+ SSH
70
+ ]
71
+ end
72
+
73
+ end # Constants
74
+ end # Assembla
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ class Array # :nodoc:
4
+
5
+ # Returns a new arrray with keys removed
6
+ #
7
+ def except(*keys)
8
+ self.dup.except!(*keys)
9
+ end unless method_defined? :except
10
+
11
+ # Similar to except but modifies self
12
+ #
13
+ def except!(*items)
14
+ copy = self.dup
15
+ copy.reject! { |item| items.include? item }
16
+ copy
17
+ end unless method_defined? :except!
18
+
19
+ # Selects a hash from the arguments list
20
+ #
21
+ def extract_options!
22
+ last.is_a?(::Hash) ? pop : {}
23
+ end unless method_defined? :extract_options!
24
+
25
+ end # Array
@@ -0,0 +1,92 @@
1
+ # encoding: utf-8
2
+
3
+ class Hash # :nodoc:
4
+
5
+ # Returns a new hash with keys removed
6
+ #
7
+ def except(*items)
8
+ self.dup.except!(*items)
9
+ end unless method_defined? :except
10
+
11
+ # Similar to except but modifies self
12
+ #
13
+ def except!(*keys)
14
+ copy = self.dup
15
+ keys.each { |key| copy.delete!(key) }
16
+ copy
17
+ end unless method_defined? :except!
18
+
19
+ # Returns a new hash with all the keys converted to symbols
20
+ #
21
+ def symbolize_keys
22
+ inject({}) do |hash, (key, value)|
23
+ hash[(key.to_sym rescue key) || key] = value
24
+ hash
25
+ end
26
+ end unless method_defined? :symbolize_keys
27
+
28
+ # Similar to symbolize_keys but modifies self
29
+ #
30
+ def symbolize_keys!
31
+ hash = symbolize_keys
32
+ hash.each do |key, val|
33
+ hash[key] = case val
34
+ when Hash
35
+ val.symbolize_keys!
36
+ when Array
37
+ val.map do |item|
38
+ item.is_a?(Hash) ? item.symbolize_keys! : item
39
+ end
40
+ else
41
+ val
42
+ end
43
+ end
44
+ return hash
45
+ end unless method_defined? :symbolize_keys!
46
+
47
+ # Returns hash collapsed into a query string
48
+ #
49
+ def serialize
50
+ self.map { |key, val| [key, val].join("=") }.join("&")
51
+ end unless method_defined? :serialize
52
+
53
+ # Searches for all deeply nested keys
54
+ #
55
+ def deep_keys
56
+ keys = self.keys
57
+ keys.each do |key|
58
+ if self[key].is_a?(Hash)
59
+ keys << self[key].deep_keys.compact.flatten
60
+ next
61
+ end
62
+ end
63
+ keys.flatten
64
+ end unless method_defined? :deep_keys
65
+
66
+ # Returns true if the given key is present inside deeply nested hash
67
+ #
68
+ def deep_key?(key)
69
+ self.deep_keys.include? key
70
+ end unless method_defined? :deep_key?
71
+
72
+ # Recursively merges self with other hash and returns new hash.
73
+ #
74
+ def deep_merge(other, &block)
75
+ dup.deep_merge!(other, &block)
76
+ end unless method_defined? :deep_merge
77
+
78
+ # Similar as deep_merge but modifies self
79
+ #
80
+ def deep_merge!(other, &block)
81
+ other.each_pair do |key, val|
82
+ tval = self[key]
83
+ if tval.is_a?(Hash) && val.is_a?(Hash)
84
+ self[key] = tval.deep_merge(val)
85
+ else
86
+ self[key] = block && tval ? block.call(k, tval, val) : val
87
+ end
88
+ end
89
+ self
90
+ end unless method_defined? :deep_merge!
91
+
92
+ end # Hash
@@ -0,0 +1,107 @@
1
+ # encoding: utf-8
2
+
3
+ module Assembla
4
+ module CoreExt #:nodoc:
5
+
6
+ if RUBY_VERSION >= '1.9'
7
+ class OrderedHash < ::Hash; end
8
+ else
9
+ class OrderedHash < ::Hash
10
+ attr_accessor :order
11
+
12
+ class << self
13
+ def [](*args)
14
+ hsh = OrderedHash.new
15
+ if Hash == args[0]
16
+ hsh.replace args[0]
17
+ elsif (args.size % 2) != 0
18
+ pp args
19
+ raise ArgumentError, "odd number of elements for Hash"
20
+ else
21
+ 0.step(args.size - 1, 2) do |a|
22
+ b = a + 1
23
+ hsh[args[a]] = args[b]
24
+ end
25
+ end
26
+ hsh
27
+ end
28
+ end
29
+
30
+ def initialize(*args, &block)
31
+ super
32
+ @order = []
33
+ end
34
+
35
+ def []=(key, value)
36
+ @order.push key unless member?(key)
37
+ super key, value
38
+ end
39
+
40
+ def ==(hsh2)
41
+ return false if @order != hsh2.order
42
+ super hsh2
43
+ end
44
+
45
+ def clear
46
+ @order = []
47
+ super
48
+ end
49
+
50
+ def delete(key)
51
+ @order.delete key
52
+ super
53
+ end
54
+
55
+ def each_key
56
+ @order.each { |k| yield k }
57
+ self
58
+ end
59
+
60
+ def each_value
61
+ @order.each { |k| yield self[k] }
62
+ self
63
+ end
64
+
65
+ def each
66
+ @order.each { |k| yield k, self[k] }
67
+ self
68
+ end
69
+ alias :each_pair :each
70
+
71
+ def delete_if
72
+ @order.clone.each { |k| delete k if yield }
73
+ self
74
+ end
75
+
76
+ def values
77
+ ary = []
78
+ @order.each { |k| ary.push self[k] }
79
+ ary
80
+ end
81
+
82
+ def keys
83
+ @order
84
+ end
85
+
86
+ def replace(hsh2)
87
+ @order = hsh2.keys
88
+ super hsh2
89
+ end
90
+
91
+ def shift
92
+ key = @order.first
93
+ key ? [key, delete(key)] : super
94
+ end
95
+
96
+ def class
97
+ Hash
98
+ end
99
+
100
+ def __class__
101
+ OrderedHash
102
+ end
103
+ end # OrderedHash
104
+ end
105
+
106
+ end # CoreExt
107
+ end # Assembla
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+
3
+ module Assembla
4
+
5
+ DEPRECATION_PREFIX = "[AssemblaAPI] Deprecation warning:"
6
+
7
+ class << self
8
+
9
+ attr_writer :deprecation_tracker
10
+
11
+ def deprecation_tracker
12
+ @deprecation_tracker ||= []
13
+ end
14
+
15
+ # Displays deprecation message to the user.
16
+ # Each message is printed once.
17
+ def deprecate(method, alternate_method=nil)
18
+ return if deprecation_tracker.include? method
19
+ deprecation_tracker << method
20
+
21
+ message = <<-NOTICE
22
+ #{DEPRECATION_PREFIX}
23
+
24
+ * #{method} is deprecated.
25
+ NOTICE
26
+ if alternate_method
27
+ message << <<-ADDITIONAL
28
+ * please use #{alternate_method} instead.
29
+ ADDITIONAL
30
+ end
31
+ warn_deprecation(message)
32
+ end
33
+
34
+ def warn_deprecation(message)
35
+ send :warn, message
36
+ end
37
+ end
38
+
39
+ end # Assembla