bugsnag-api 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4f70dd5425512569c5778aa3a89d852326195967
4
+ data.tar.gz: 254567403bf2c32834d25a7b4c23696f33748467
5
+ SHA512:
6
+ metadata.gz: 67c60e4aae21b293ad5b75b2cb60d26ba2774c43d512c49d3a140fd82b6f43d10de5739eec93ac7edceb481939bd86b1bdb80c92a952b5030f01e111ec6b1f29
7
+ data.tar.gz: 4b154b2bc908b61db969e19afc53a3f09f12a756d66292562d9d8a6a9fc9f2e7b60a0b1ac173404cb1d5099120dde7b41c5f0aadfa8641d771e247efefa4e357
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in bugsnag-api.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Bugsnag Inc.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,52 @@
1
+ Bugsnag API Ruby Toolkit
2
+ ========================
3
+
4
+ The library allows for quick read-write access to the [Bugsnag API](https://bugsnag.com/docs/api) from Ruby applications. Use this library if you want to build your own applications which leverage data found in your Bugsnag dashboard. If you are looking to automatically detect crashes in your Ruby apps, you should take a look at the [Bugsnag Ruby Detection Library](https://bugsnag.com/docs/notifiers/ruby) instead.
5
+
6
+ This library shares code and philosophies with the fantastic [Octokit](https://github.com/octokit/octokit.rb) library.
7
+
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem "bugsnag-api"
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install bugsnag-api
22
+
23
+
24
+ ## Usage
25
+
26
+ ```ruby
27
+ # Configure a Bugsnag API client
28
+ Bugsnag::Api.configure do |config|
29
+ config.api_token = "your-account-api-token"
30
+ end
31
+
32
+ # Fetch information about the authenticated account
33
+ account = Bugsnag::Api.account
34
+
35
+ # Get a list of users on this account
36
+ users = Bugsnag::Api.users(account.id)
37
+
38
+ # Get a list of the projects on this account
39
+ projects = Bugsnag::Api.projects(account.id)
40
+
41
+ # Get a list of errors on a project
42
+ errors = Bugsnag::Api.errors(projects.first.id)
43
+ ```
44
+
45
+
46
+ ## Contributing
47
+
48
+ 1. Fork it
49
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
50
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
51
+ 4. Push to the branch (`git push origin my-new-feature`)
52
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'bugsnag/api/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "bugsnag-api"
8
+ spec.version = Bugsnag::Api::VERSION
9
+ spec.authors = ["James Smith"]
10
+ spec.email = ["james@bugsnag.com"]
11
+ spec.description = %q{Bugsnag API toolkit for ruby}
12
+ spec.summary = %q{Bugsnag API toolkit for ruby}
13
+ spec.homepage = "https://github.com/bugsnag/bugsnag-api-ruby"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "sawyer", '~> 0.5.3'
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ end
@@ -0,0 +1,29 @@
1
+ require "bugsnag/api/client"
2
+ require "bugsnag/api/configuration"
3
+ require "bugsnag/api/error"
4
+ require "bugsnag/api/version"
5
+
6
+ module Bugsnag
7
+ module Api
8
+ class << self
9
+ def configure
10
+ yield(configuration) if block_given?
11
+ end
12
+
13
+ def configuration
14
+ @configuration ||= Bugsnag::Api::Configuration.new
15
+ end
16
+
17
+ def client
18
+ @client ||= Bugsnag::Api::Client.new(configuration)
19
+ end
20
+
21
+
22
+ private
23
+ def method_missing(method_name, *args, &block)
24
+ return super unless client.respond_to?(method_name)
25
+ client.send(method_name, *args, &block)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,200 @@
1
+ require "sawyer"
2
+
3
+ require "bugsnag/api/client/accounts"
4
+ require "bugsnag/api/client/comments"
5
+ require "bugsnag/api/client/errors"
6
+ require "bugsnag/api/client/events"
7
+ require "bugsnag/api/client/projects"
8
+ require "bugsnag/api/client/users"
9
+
10
+ module Bugsnag
11
+ module Api
12
+
13
+ # Client for the Bugsnag API
14
+ #
15
+ # @see https://bugsnag.com/docs/api
16
+ class Client
17
+ include Bugsnag::Api::Client::Accounts
18
+ include Bugsnag::Api::Client::Comments
19
+ include Bugsnag::Api::Client::Errors
20
+ include Bugsnag::Api::Client::Events
21
+ include Bugsnag::Api::Client::Projects
22
+ include Bugsnag::Api::Client::Users
23
+
24
+ # Header keys that can be passed in options hash to {#get},{#head}
25
+ CONVENIENCE_HEADERS = Set.new([:accept, :content_type])
26
+
27
+ def initialize(options = {})
28
+ if options.is_a?(Bugsnag::Api::Configuration)
29
+ @configuration = options
30
+ else
31
+ configuration.load(options)
32
+ end
33
+ end
34
+
35
+ def configuration
36
+ @configuration ||= Configuration.new
37
+ end
38
+
39
+ # Make a HTTP GET request
40
+ #
41
+ # @param url [String] The path, relative to {#endpoint}
42
+ # @param options [Hash] Query and header params for request
43
+ # @return [Sawyer::Resource]
44
+ def get(url, options = {})
45
+ request :get, url, parse_query_and_convenience_headers(options)
46
+ end
47
+
48
+ # Make a HTTP POST request
49
+ #
50
+ # @param url [String] The path, relative to {#endpoint}
51
+ # @param options [Hash] Body and header params for request
52
+ # @return [Sawyer::Resource]
53
+ def post(url, options = {})
54
+ request :post, url, options
55
+ end
56
+
57
+ # Make a HTTP PUT request
58
+ #
59
+ # @param url [String] The path, relative to {#endpoint}
60
+ # @param options [Hash] Body and header params for request
61
+ # @return [Sawyer::Resource]
62
+ def put(url, options = {})
63
+ request :put, url, options
64
+ end
65
+
66
+ # Make a HTTP PATCH request
67
+ #
68
+ # @param url [String] The path, relative to {#endpoint}
69
+ # @param options [Hash] Body and header params for request
70
+ # @return [Sawyer::Resource]
71
+ def patch(url, options = {})
72
+ request :patch, url, options
73
+ end
74
+
75
+ # Make a HTTP DELETE request
76
+ #
77
+ # @param url [String] The path, relative to {#endpoint}
78
+ # @param options [Hash] Query and header params for request
79
+ # @return [Sawyer::Resource]
80
+ def delete(url, options = {})
81
+ request :delete, url, options
82
+ end
83
+
84
+ # Make a HTTP HEAD request
85
+ #
86
+ # @param url [String] The path, relative to {#endpoint}
87
+ # @param options [Hash] Query and header params for request
88
+ # @return [Sawyer::Resource]
89
+ def head(url, options = {})
90
+ request :head, url, parse_query_and_convenience_headers(options)
91
+ end
92
+
93
+ # Make one or more HTTP GET requests, optionally fetching
94
+ # the next page of results from URL in Link response header based
95
+ # on value in {#auto_paginate}.
96
+ #
97
+ # @param url [String] The path, relative to {#endpoint}
98
+ # @param options [Hash] Query and header params for request
99
+ # @param block [Block] Block to perform the data concatination of the
100
+ # multiple requests. The block is called with two parameters, the first
101
+ # contains the contents of the requests so far and the second parameter
102
+ # contains the latest response.
103
+ # @return [Sawyer::Resource]
104
+ def paginate(url, options = {}, &block)
105
+ opts = parse_query_and_convenience_headers(options.dup)
106
+ if configuration.auto_paginate || configuration.per_page
107
+ opts[:query][:per_page] ||= configuration.per_page || (configuration.auto_paginate ? 100 : nil)
108
+ end
109
+
110
+ data = request(:get, url, opts)
111
+
112
+ if configuration.auto_paginate
113
+ while @last_response.rels[:next]
114
+ @last_response = @last_response.rels[:next].get
115
+ if block_given?
116
+ yield(data, @last_response)
117
+ else
118
+ data.concat(@last_response.data) if @last_response.data.is_a?(Array)
119
+ end
120
+ end
121
+ end
122
+
123
+ data
124
+ end
125
+
126
+ # Hypermedia agent for the Bugsnag API
127
+ #
128
+ # @return [Sawyer::Agent]
129
+ def agent
130
+ @agent ||= Sawyer::Agent.new(configuration.endpoint, sawyer_options) do |http|
131
+ http.headers[:content_type] = "application/json"
132
+ http.headers[:user_agent] = configuration.user_agent
133
+
134
+ if basic_authenticated?
135
+ http.basic_auth configuration.email, configuration.password
136
+ elsif token_authenticated?
137
+ http.authorization "token", configuration.api_token
138
+ end
139
+ end
140
+ end
141
+
142
+ # Response for last HTTP request
143
+ #
144
+ # @return [Sawyer::Response]
145
+ def last_response
146
+ @last_response if defined? @last_response
147
+ end
148
+
149
+ def basic_authenticated?
150
+ !!(configuration.email && configuration.password)
151
+ end
152
+
153
+ def token_authenticated?
154
+ !!configuration.api_token
155
+ end
156
+
157
+
158
+ private
159
+ def request(method, path, data, options = {})
160
+ if data.is_a?(Hash)
161
+ options[:query] = data.delete(:query) || {}
162
+ options[:headers] = data.delete(:headers) || {}
163
+ if accept = data.delete(:accept)
164
+ options[:headers][:accept] = accept
165
+ end
166
+ end
167
+
168
+ @last_response = response = agent.call(method, URI::Parser.new.escape(path.to_s), data, options)
169
+ response.data
170
+ end
171
+
172
+ def sawyer_options
173
+ opts = {
174
+ :links_parser => Sawyer::LinkParsers::Simple.new
175
+ }
176
+ conn_opts = configuration.connection_options
177
+ conn_opts[:builder] = configuration.middleware if configuration.middleware
178
+ conn_opts[:proxy] = configuration.proxy if configuration.proxy
179
+ opts[:faraday] = Faraday.new(conn_opts)
180
+
181
+ opts
182
+ end
183
+
184
+ def parse_query_and_convenience_headers(options)
185
+ headers = options.fetch(:headers, {})
186
+ CONVENIENCE_HEADERS.each do |h|
187
+ if header = options.delete(h)
188
+ headers[h] = header
189
+ end
190
+ end
191
+ query = options.delete(:query)
192
+ opts = {:query => options}
193
+ opts[:query].merge!(query) if query && query.is_a?(Hash)
194
+ opts[:headers] = headers unless headers.empty?
195
+
196
+ opts
197
+ end
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,37 @@
1
+ module Bugsnag
2
+ module Api
3
+ class Client
4
+
5
+ # Methods for the Accounts API
6
+ #
7
+ # @see https://bugsnag.com/docs/api/accounts
8
+ module Accounts
9
+ # List your accounts
10
+ #
11
+ # @return [Array<Sawyer::Resource>] List of users
12
+ # @see https://bugsnag.com/docs/api/accounts#list-your-accounts
13
+ # @example
14
+ # Bugsnag::Api.accounts
15
+ def accounts(options = {})
16
+ paginate "accounts", options
17
+ end
18
+
19
+ # Get a single account
20
+ #
21
+ # @param account [String] Bugsnag account id
22
+ # @return [Sawyer::Resource]
23
+ # @see https://bugsnag.com/docs/api/accounts#get-the-authenticated-account
24
+ # @see https://bugsnag.com/docs/api/accounts#get-account-details
25
+ # @example
26
+ # Bugsnag::Api.account("515fb9337c1074f6fd000009")
27
+ def account(account=nil, options = {})
28
+ if account.nil?
29
+ get "account", options
30
+ else
31
+ get "accounts/#{account}", options
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,64 @@
1
+ module Bugsnag
2
+ module Api
3
+ class Client
4
+
5
+ # Methods for the Comments API
6
+ #
7
+ # @see https://bugsnag.com/docs/api/comments
8
+ module Comments
9
+ # List an error's comments
10
+ #
11
+ # @param error [String] Bugsnag error for which to list comments
12
+ # @return [Array<Sawyer::Resource>] List of comments
13
+ # @see https://bugsnag.com/docs/api/comments#list-an-error-s-comments
14
+ # @example
15
+ # Bugsnag::Api.comments("515fb9337c1074f6fd000009")
16
+ def comments(error, options = {})
17
+ paginate "errors/#{error}/comments", options
18
+ end
19
+
20
+ # Get a single comment
21
+ #
22
+ # @param comment [String] A Bugsnag comment ID
23
+ # @return [Sawyer::Resource] The comment you requested, if it exists
24
+ # @see https://bugsnag.com/docs/api/comments#get-comment-details
25
+ # @example
26
+ # Bugsnag::Api.comment("50baed119bf39c1431000004")
27
+ def comment(comment, options = {})
28
+ get "comments/#{comment}", options
29
+ end
30
+
31
+ # Create a comment
32
+ #
33
+ # @param error [String] The Bugsnag error to create the comment on
34
+ # @option message [String] The comment's message
35
+ # @see https://bugsnag.com/docs/api/comments#create-a-comment
36
+ # @example
37
+ # Bugsnag::Api.create_comment("515fb9337c1074f6fd000009", message: "Oops!")
38
+ def create_comment(error, message, options = {})
39
+ post "errors/#{error}/comments", options.merge({:message => message})
40
+ end
41
+
42
+ # Update a comment
43
+ #
44
+ # @param error [String] The Bugsnag comment to update
45
+ # @return [Sawyer::Resource] The updated comment
46
+ # @see https://bugsnag.com/docs/api/comments#update-a-comment
47
+ # @example
48
+ # Bugsnag::Api.update_comment("50baed119bf39c1431000004", message: "Fixed!")
49
+ def update_comment(comment, message, options = {})
50
+ patch "comments/#{comment}", options.merge({:message => message})
51
+ end
52
+
53
+ # Delete a comment
54
+ #
55
+ # @param comment [String] The Bugsnag comment to delete
56
+ # @return [Boolean] `true` if comment was deleted
57
+ # @see https://bugsnag.com/docs/api/comments#delete-a-comment
58
+ def delete_comment(comment, options = {})
59
+ delete "comments/#{comment}", options
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,75 @@
1
+ module Bugsnag
2
+ module Api
3
+ class Client
4
+
5
+ # Methods for the Errors API
6
+ #
7
+ # @see https://bugsnag.com/docs/api/errors
8
+ module Errors
9
+ # List a project's errors
10
+ #
11
+ # @param project [String] Bugsnag project for which to list errors
12
+ # @return [Array<Sawyer::Resource>] List of errors
13
+ # @see https://bugsnag.com/docs/api/errors#list-a-project-s-errors
14
+ # @example
15
+ # Bugsnag::Api.errors("50baed119bf39c1431000004")
16
+ def errors(project, options = {})
17
+ paginate "projects/#{project}/errors", options
18
+ end
19
+
20
+ # Get a single error
21
+ #
22
+ # @param error [String] A Bugsnag error
23
+ # @return [Sawyer::Resource] The error you requested, if it exists
24
+ # @see https://bugsnag.com/docs/api/errors#get-error-details
25
+ # @example
26
+ # Bugsnag::Api.error("518031bcd775355c48a1cd4e")
27
+ def error(error, options = {})
28
+ get "errors/#{error}", options
29
+ end
30
+
31
+ # Resolve an error
32
+ #
33
+ # @param error [String] A Bugsnag error
34
+ # @return [Sawyer::Resource] The updated error
35
+ # @see https://bugsnag.com/docs/api/errors#update-an-error-s-status
36
+ # @example
37
+ # Bugsnag::Api.resolve_error("518031bcd775355c48a1cd4e")
38
+ def resolve_error(error, options = {})
39
+ patch "errors/#{error}", options.merge({:resolved => true})
40
+ end
41
+
42
+ # Re-open an error
43
+ #
44
+ # @param error [String] A Bugsnag error
45
+ # @return [Sawyer::Resource] The updated error
46
+ # @see https://bugsnag.com/docs/api/errors#update-an-error-s-status
47
+ # @example
48
+ # Bugsnag::Api.reopen_error("518031bcd775355c48a1cd4e")
49
+ def reopen_error(error, options = {})
50
+ patch "errors/#{error}", options.merge({:resolved => false})
51
+ end
52
+
53
+ # Update an error
54
+ #
55
+ # @param error [String] A Bugsnag error
56
+ # @return [Sawyer::Resource] The updated error
57
+ # @see https://bugsnag.com/docs/api/errors#update-an-error-s-status
58
+ # @example
59
+ # Bugsnag::Api.update_error("518031bcd775355c48a1cd4e")
60
+ def update_error(error, options = {})
61
+ patch "errors/#{error}", options
62
+ end
63
+
64
+ # Delete an error
65
+ #
66
+ # @param error [String] A Bugsnag error
67
+ # @return [Boolean] `true` if error was deleted
68
+ # @see https://bugsnag.com/docs/api/errors#delete-an-error
69
+ def delete_error(error, options = {})
70
+ delete "errors/#{error}", options
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,54 @@
1
+ module Bugsnag
2
+ module Api
3
+ class Client
4
+
5
+ # Methods for the Events API
6
+ #
7
+ # @see https://bugsnag.com/docs/api/events
8
+ module Events
9
+ # List a project's events
10
+ #
11
+ # @param project [String] Bugsnag project for which to list events
12
+ # @return [Array<Sawyer::Resource>] List of events
13
+ # @see https://bugsnag.com/docs/api/events#list-a-project-s-events
14
+ # @example
15
+ # Bugsnag::Api.events("50baed119bf39c1431000004")
16
+ def events(project, options = {})
17
+ paginate "projects/#{project}/events", options
18
+ end
19
+ alias :project_events :events
20
+
21
+ # List an error's events
22
+ #
23
+ # @param error [String] Bugsnag error for which to list events
24
+ # @return [Array<Sawyer::Resource>] List of events
25
+ # @see https://bugsnag.com/docs/api/events#list-an-error-s-events
26
+ # @example
27
+ # Bugsnag::Api.error_events("518031bcd775355c48a1cd4e")
28
+ def error_events(error, options = {})
29
+ paginate "error/#{error}/events", options
30
+ end
31
+
32
+ # Get a single event
33
+ #
34
+ # @param event [String] A Bugsnag event id
35
+ # @return [Sawyer::Resource] The event you requested, if it exists
36
+ # @see https://bugsnag.com/docs/api/events#get-event-details
37
+ # @example
38
+ # Bugsnag::Api.event("51f5d152f002c6686d013a22")
39
+ def event(error, options = {})
40
+ get "events/#{event}", options
41
+ end
42
+
43
+ # Delete an event
44
+ #
45
+ # @param event [String] A Bugsnag event
46
+ # @return [Boolean] `true` if event was deleted
47
+ # @see https://bugsnag.com/docs/api/events#delete-an-event
48
+ def delete_event(event, options = {})
49
+ delete "events/#{event}", options
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,77 @@
1
+ module Bugsnag
2
+ module Api
3
+ class Client
4
+
5
+ # Methods for the Projects API
6
+ #
7
+ # @see https://bugsnag.com/docs/api/projects
8
+ module Projects
9
+ # List account projects
10
+ #
11
+ # @param account [String] Bugsnag account for which to list projects
12
+ # @return [Array<Sawyer::Resource>] List of projects
13
+ # @see https://bugsnag.com/docs/api/projects#list-an-account-s-projects
14
+ # @example
15
+ # Bugsnag::Api.projects("515fb9337c1074f6fd000009")
16
+ def projects(account, options = {})
17
+ paginate "accounts/#{account}/projects", options
18
+ end
19
+ alias :account_projects :projects
20
+
21
+ # List user projects
22
+ #
23
+ # @param account [String] Bugsnag user for which to list projects
24
+ # @return [Array<Sawyer::Resource>] List of projects
25
+ # @see https://bugsnag.com/docs/api/projects#list-a-user-s-projects
26
+ # @example
27
+ # Bugsnag::Api.user_projects("515fb9337c1074f6fd000007")
28
+ def user_projects(user, options = {})
29
+ paginate "user/#{user}/projects", options
30
+ end
31
+
32
+ # Get a single project
33
+ #
34
+ # @param project [String] A Bugsnag project
35
+ # @return [Sawyer::Resource] The project you requested, if it exists
36
+ # @see https://bugsnag.com/docs/api/projects#get-project-details
37
+ # @example
38
+ # Bugsnag::Api.project("50baed119bf39c1431000004")
39
+ def project(project, options = {})
40
+ get "projects/#{project}", options
41
+ end
42
+
43
+ # Create a project
44
+ #
45
+ # @param account [String] The Bugsnag account to create project on
46
+ # @option name [String] The project's name
47
+ # @option type [String] The type of the project
48
+ # @see https://bugsnag.com/docs/api/projects#create-a-project
49
+ # @example
50
+ # Bugsnag::Api.create_project("515fb9337c1074f6fd000009", name: "Website")
51
+ def create_project(account, options = {})
52
+ post "accounts/#{account}/projects", options
53
+ end
54
+
55
+ # Update a project
56
+ #
57
+ # @param project [String] A Bugsnag project
58
+ # @return [Sawyer::Resource] The updated project
59
+ # @see https://bugsnag.com/docs/api/projects#update-a-project
60
+ # @example
61
+ # Bugsnag::Api.update_project("50baed119bf39c1431000004", name: "Dashboard")
62
+ def update_project(project, options = {})
63
+ patch "projects/#{project}", options
64
+ end
65
+
66
+ # Delete a project
67
+ #
68
+ # @param project [String] A Bugsnag project
69
+ # @return [Boolean] `true` if project was deleted
70
+ # @see https://bugsnag.com/docs/api/projects#delete-a-project
71
+ def delete_project(project, options = {})
72
+ delete "projects/#{project}", options
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,81 @@
1
+ module Bugsnag
2
+ module Api
3
+ class Client
4
+
5
+ # Methods for the Users API
6
+ #
7
+ # @see https://bugsnag.com/docs/api/users
8
+ module Users
9
+ # List account users
10
+ #
11
+ # @param account [String] Bugsnag account for which to list users
12
+ # @return [Array<Sawyer::Resource>] List of users
13
+ # @see https://bugsnag.com/docs/api/users#list-an-account-s-users
14
+ def users(account, options = {})
15
+ paginate "accounts/#{account}/users", options
16
+ end
17
+ alias :account_users :users
18
+
19
+ # List project users
20
+ #
21
+ # @param account [String] Bugsnag account for which to list users
22
+ # @return [Array<Sawyer::Resource>] List of users
23
+ # @see https://bugsnag.com/docs/api/users#list-an-project-s-users
24
+ def project_users(project, options = {})
25
+ paginate "projects/#{project}/users", options
26
+ end
27
+
28
+ # Get a single user
29
+ #
30
+ # @param user [String] Bugsnag user id.
31
+ # @return [Sawyer::Resource]
32
+ # @see https://bugsnag.com/docs/api/users#get-the-authenticated-user
33
+ # @see https://bugsnag.com/docs/api/users#get-user-details
34
+ # @example
35
+ # Bugsnag::Api.user("515fb9337c1074f6fd000007")
36
+ def user(user=nil, options = {})
37
+ if user.nil?
38
+ get "user", options
39
+ else
40
+ get "users/#{user}", options
41
+ end
42
+ end
43
+
44
+ # Invite a user to an account
45
+ #
46
+ # @param account [String] Bugsnag account to invite user to.
47
+ # @option email [String] The email address of the invitee
48
+ # @option admin [Boolean] Should the invitee be an account admin?
49
+ # @option project_ids [Array<String>] Array of accessible project ids
50
+ # @see https://bugsnag.com/docs/api/users#invite-a-user-to-an-account
51
+ # @example
52
+ # Bugsnag::Api.invite_user("515fb9337c1074f6fd000009", "james@example.com")
53
+ def invite_user(account, email, options = {})
54
+ post "accounts/#{account}/users", options.merge({:email => email})
55
+ end
56
+
57
+ # Update a user's account permissions
58
+ #
59
+ # @param account [String] Bugsnag account to update pemissions for
60
+ # @param user {String} Bugsnag user to update permissions for
61
+ # @see https://bugsnag.com/docs/api/users#update-a-user-s-account-permissions
62
+ # @example
63
+ # Bugsnag::Api.update_user_permissions("515fb9337c1074f6fd000009", "515fb9337c1074f6fd000007", admin: false)
64
+ def update_user_permissions(account, user, options = {})
65
+ patch "accounts/#{account}/users/#{user}", options
66
+ end
67
+
68
+ # Remove a user from an account
69
+ #
70
+ # @param account [String] Bugsnag account to remove user from
71
+ # @param user [String] Bugsnag user to remove
72
+ # @see https://bugsnag.com/docs/api/users#delete-a-user-from-an-account
73
+ # @example
74
+ # Bugsnag::Api.remove_user("515fb9337c1074f6fd000009", "515fb9337c1074f6fd000007")
75
+ def remove_user(account, user, options = {})
76
+ delete "accounts/#{account}/users/#{user}", options
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,48 @@
1
+ require "bugsnag/api/response/raise_error"
2
+
3
+ module Bugsnag
4
+ module Api
5
+
6
+ # Configuration storage and defaults for {Client}
7
+ class Configuration
8
+
9
+ # Default API endpoint
10
+ DEFAULT_ENDPOINT = "https://api.bugsnag.com"
11
+
12
+ # Default User Agent header string
13
+ DEFAULT_USER_AGENT = "Bugsnag API Ruby Gem #{Bugsnag::Api::VERSION}"
14
+
15
+ # In Faraday 0.9, Faraday::Builder was renamed to Faraday::RackBuilder
16
+ RACK_BUILDER_CLASS = defined?(Faraday::RackBuilder) ? Faraday::RackBuilder : Faraday::Builder
17
+
18
+ # Default Faraday middleware stack
19
+ DEFAULT_MIDDLEWARE = RACK_BUILDER_CLASS.new do |builder|
20
+ builder.use Bugsnag::Api::Response::RaiseError
21
+ builder.adapter Faraday.default_adapter
22
+ end
23
+
24
+ # Configuration options
25
+ attr_accessor :email, :password, :api_token, :endpoint, :user_agent,
26
+ :proxy, :middleware, :connection_options, :auto_paginate,
27
+ :per_page
28
+
29
+ # Set up configuration defaults
30
+ def initialize
31
+ @endpoint = DEFAULT_ENDPOINT
32
+ @user_agent = DEFAULT_USER_AGENT
33
+ @middleware = DEFAULT_MIDDLEWARE
34
+ @auto_paginate = false
35
+ @connection_options = {
36
+ :headers => {
37
+ :user_agent => DEFAULT_USER_AGENT
38
+ }
39
+ }
40
+ end
41
+
42
+ # Load configuration from hash
43
+ def load(options = {})
44
+ options.each {|k,v| self.send("#{k}=", v) if self.respond_to?("#{k}=")}
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,121 @@
1
+ module Bugsnag
2
+ module Api
3
+ # Custom error class for rescuing from all Bugsnag API errors
4
+ class Error < StandardError
5
+
6
+ # Returns the appropriate Bugnsag::Api::Error subclass based
7
+ # on status and response message
8
+ #
9
+ # @param [Hash] response HTTP response
10
+ # @return [Octokit::Error]
11
+ def self.from_response(response)
12
+ status = response[:status].to_i
13
+ body = response[:body].to_s
14
+ headers = response[:response_headers]
15
+
16
+ if klass = case status
17
+ when 400 then Bugsnag::Api::BadRequest
18
+ when 401 then Bugsnag::Api::Unauthorized
19
+ when 403 then Bugsnag::Api::Forbidden
20
+ when 404 then Bugsnag::Api::NotFound
21
+ when 405 then Bugsnag::Api::MethodNotAllowed
22
+ when 406 then Bugsnag::Api::NotAcceptable
23
+ when 409 then Bugsnag::Api::Conflict
24
+ when 415 then Bugsnag::Api::UnsupportedMediaType
25
+ when 422 then Bugsnag::Api::UnprocessableEntity
26
+ when 400..499 then Bugsnag::Api::ClientError
27
+ when 500 then Bugsnag::Api::InternalServerError
28
+ when 501 then Bugsnag::Api::NotImplemented
29
+ when 502 then Bugsnag::Api::BadGateway
30
+ when 503 then Bugsnag::Api::ServiceUnavailable
31
+ when 500..599 then Bugsnag::Api::ServerError
32
+ end
33
+ klass.new(response)
34
+ end
35
+ end
36
+
37
+ def initialize(response=nil)
38
+ @response = response
39
+ super(response_error)
40
+ end
41
+
42
+ private
43
+
44
+ def data
45
+ @data ||=
46
+ if (body = @response[:body]) && !body.empty?
47
+ if body.is_a?(String) &&
48
+ @response[:response_headers] &&
49
+ @response[:response_headers][:content_type] =~ /json/
50
+
51
+ Sawyer::Agent.serializer.decode(body)
52
+ else
53
+ body
54
+ end
55
+ else
56
+ nil
57
+ end
58
+ end
59
+
60
+ def response_error
61
+ "Error: #{data[:error]}" if data.is_a?(Hash) && data[:error]
62
+ end
63
+ end
64
+
65
+ # Raised on errors in the 400-499 range
66
+ class ClientError < Error; end
67
+
68
+ # Raised when Bugsnag returns a 400 HTTP status code
69
+ class BadRequest < ClientError; end
70
+
71
+ # Raised when Bugsnag returns a 401 HTTP status code
72
+ class Unauthorized < ClientError; end
73
+
74
+ # Raised when Bugsnag returns a 403 HTTP status code
75
+ class Forbidden < ClientError; end
76
+
77
+ # Raised when Bugsnag returns a 404 HTTP status code
78
+ class NotFound < ClientError; end
79
+
80
+ # Raised when Bugsnag returns a 405 HTTP status code
81
+ class MethodNotAllowed < ClientError; end
82
+
83
+ # Raised when Bugsnag returns a 406 HTTP status code
84
+ class NotAcceptable < ClientError; end
85
+
86
+ # Raised when Bugsnag returns a 409 HTTP status code
87
+ class Conflict < ClientError; end
88
+
89
+ # Raised when Bugsnag returns a 414 HTTP status code
90
+ class UnsupportedMediaType < ClientError; end
91
+
92
+ # Raised when Bugsnag returns a 422 HTTP status code
93
+ class UnprocessableEntity < ClientError; end
94
+
95
+ # Raised on errors in the 500-599 range
96
+ class ServerError < Error; end
97
+
98
+ # Raised when Bugsnag returns a 500 HTTP status code
99
+ class InternalServerError < ServerError; end
100
+
101
+ # Raised when Bugsnag returns a 501 HTTP status code
102
+ class NotImplemented < ServerError; end
103
+
104
+ # Raised when Bugsnag returns a 502 HTTP status code
105
+ class BadGateway < ServerError; end
106
+
107
+ # Raised when Bugsnag returns a 503 HTTP status code
108
+ class ServiceUnavailable < ServerError; end
109
+
110
+ # Raised when client fails to provide valid Content-Type
111
+ class MissingContentType < ArgumentError; end
112
+
113
+ # Raised when a method requires account-level credentials
114
+ # but none were provided
115
+ class AccountCredentialsRequired < StandardError; end
116
+
117
+ # Raised when a method requires user-level credentials
118
+ # but none were provided
119
+ class UserCredentialsRequired < StandardError; end
120
+ end
121
+ end
@@ -0,0 +1,22 @@
1
+ require "faraday"
2
+ require "bugsnag/api/error"
3
+
4
+ module Bugsnag
5
+ module Api
6
+ # Faraday response middleware
7
+ module Response
8
+
9
+ # This class raises an Bugsnag-flavored exception based
10
+ # HTTP status codes returned by the API
11
+ class RaiseError < Faraday::Response::Middleware
12
+
13
+ private
14
+ def on_complete(response)
15
+ if error = Bugsnag::Api::Error.from_response(response)
16
+ raise error
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ module Bugsnag
2
+ module Api
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bugsnag-api
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - James Smith
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sawyer
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.5.3
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.5.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Bugsnag API toolkit for ruby
56
+ email:
57
+ - james@bugsnag.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - bugsnag-api.gemspec
68
+ - lib/bugsnag/api.rb
69
+ - lib/bugsnag/api/client.rb
70
+ - lib/bugsnag/api/client/accounts.rb
71
+ - lib/bugsnag/api/client/comments.rb
72
+ - lib/bugsnag/api/client/errors.rb
73
+ - lib/bugsnag/api/client/events.rb
74
+ - lib/bugsnag/api/client/projects.rb
75
+ - lib/bugsnag/api/client/users.rb
76
+ - lib/bugsnag/api/configuration.rb
77
+ - lib/bugsnag/api/error.rb
78
+ - lib/bugsnag/api/response/raise_error.rb
79
+ - lib/bugsnag/api/version.rb
80
+ homepage: https://github.com/bugsnag/bugsnag-api-ruby
81
+ licenses:
82
+ - MIT
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 2.0.14
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: Bugsnag API toolkit for ruby
104
+ test_files: []
105
+ has_rdoc: