nearmiss-ruby 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,76 @@
1
+ module Nearmiss
2
+ class Client
3
+
4
+ # Methods for the Projects API
5
+ #
6
+ module Projects
7
+
8
+ # List projects
9
+ #
10
+ # @note Shows a list of projects for the users organization aka account
11
+ #
12
+ # @return [Array<Sawyer::Resource>] List of projects
13
+ def projects(options = {})
14
+ paginate "projects", options
15
+ end
16
+ alias :list_projects :projects
17
+
18
+ # Get a single project
19
+ #
20
+ # @param project [String] UUID of project to fetch
21
+ # @return [Sawyer::Resource] Project information
22
+ #
23
+ def project(project, options = {})
24
+ get "#{project_path(project)}", options
25
+ end
26
+
27
+ # Create a project
28
+ #
29
+ # @param options [Hash] Project information.
30
+ # @option options [String] :name e.g. Berkeley Art Museum
31
+ # @option options [String] :project_id e.g. 10611.70
32
+ # @return [Sawyer::Resource] Newly created project info
33
+ def create_project(options = {})
34
+ post 'projects', options
35
+ end
36
+
37
+ # Edit a project
38
+ #
39
+ # @param options [Hash] Project information.
40
+ # @option options [String] :name e.g. Berkeley Art Museum
41
+ # @option options [String] :project_id e.g. 10611.70
42
+ #
43
+ # @return
44
+ # [Sawyer::Resource] Newly created project info
45
+ # @example Update a project
46
+ # @client.edit_project('some_id', {
47
+ # name: "New name of project",
48
+ # project_id: "1043.32"
49
+ # })
50
+ #
51
+ def edit_project(project, options = {})
52
+ patch "#{project_path(project)}", options
53
+ end
54
+
55
+ # Delete a project
56
+ #
57
+ # @param project [String] Project ID
58
+ # @return [Boolean] Indicating success of deletion
59
+ #
60
+ def delete_project(project, options = {})
61
+ boolean_from_response :delete, "projects/#{project}", options
62
+ end
63
+ alias :remove_project :delete_project
64
+
65
+ private
66
+
67
+ def project_path(id)
68
+ if uuid?(id)
69
+ "projects/#{id}"
70
+ else
71
+ "project/#{id}"
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,52 @@
1
+ module Nearmiss
2
+ class Client
3
+
4
+ # Methods for API rate limiting info
5
+ #
6
+ # @see https://developer.github.com/v3/#rate-limiting
7
+ module RateLimit
8
+
9
+ # Get rate limit info from last response if available
10
+ # or make a new request to fetch rate limit
11
+ #
12
+ # @see https://developer.github.com/v3/rate_limit/#rate-limit
13
+ # @return [Nearmiss::RateLimit] Rate limit info
14
+ def rate_limit(options = {})
15
+ return rate_limit! if last_response.nil?
16
+
17
+ Nearmiss::RateLimit.from_response(last_response)
18
+ end
19
+ alias ratelimit rate_limit
20
+
21
+ # Get number of rate limted requests remaining
22
+ #
23
+ # @see https://developer.github.com/v3/rate_limit/#rate-limit
24
+ # @return [Fixnum] Number of requests remaining in this period
25
+ def rate_limit_remaining(options = {})
26
+ nearmiss_warn "Deprecated: Please use .rate_limit.remaining"
27
+ rate_limit.remaining
28
+ end
29
+ alias ratelimit_remaining rate_limit_remaining
30
+
31
+ # Refresh rate limit info by making a new request
32
+ #
33
+ # @return [Nearmiss::RateLimit] Rate limit info
34
+ def rate_limit!(options = {})
35
+ get "rate_limit"
36
+ Nearmiss::RateLimit.from_response(last_response)
37
+ end
38
+ alias ratelimit! rate_limit!
39
+
40
+ # Refresh rate limit info and get number of rate limted requests remaining
41
+ #
42
+ # @return [Fixnum] Number of requests remaining in this period
43
+ def rate_limit_remaining!(options = {})
44
+ nearmiss_warn "Deprecated: Please use .rate_limit!.remaining"
45
+ rate_limit!.remaining
46
+ end
47
+ alias ratelimit_remaining! rate_limit_remaining!
48
+
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,81 @@
1
+ module Nearmiss
2
+ class Client
3
+
4
+ # Methods for the Users API
5
+ #
6
+ module Users
7
+
8
+ # List users
9
+ #
10
+ # @note Logged in user must be an admin to see all users
11
+ #
12
+ # @return [Array<Sawyer::Resource>] List of projects
13
+ def users(options = {})
14
+ paginate "users", options
15
+ end
16
+ alias :list_users :users
17
+
18
+ # Get a single user
19
+ #
20
+ # @param user [String] Nearmiss user email or id.
21
+ # @return [Sawyer::Resource]
22
+ # @example
23
+ # Nearmiss.user("31817811-dce4-48c4-aa5f-f49603c5abee") or Nearmiss.user("m4rkuskk+a@gmail.com")
24
+ def user(user=nil, options = {})
25
+ if user.nil?
26
+ get "me", options
27
+ else
28
+ get "users/#{user}", options
29
+ end
30
+ # get User.path(user), options
31
+ end
32
+
33
+ # Edit a user
34
+ #
35
+ # @param options [Hash] User information.
36
+ # @option options [String] :email Email of user
37
+ # @option options [String] :name Name of user
38
+ # @option options [String] :nickname Nickname of user
39
+ # @option options [Integer] :role Set to admin or not
40
+ # @option options [String] :phone_number Phone number of user
41
+ # @option options [String] :image URL of image of user
42
+ # @option options [String] :language Code "en", "de", "es"
43
+ # @return
44
+ # [Sawyer::Resource] Edited user info
45
+ # @example Update a user
46
+ # @client.edit_user('some_id', {
47
+ # email: "mklooth@webcor.com",
48
+ # name: "Markus Klooth"
49
+ # })
50
+ #
51
+ def edit_user(user, options = {})
52
+ patch "update_user/#{user}", options
53
+ end
54
+ alias :update_user :edit_user
55
+
56
+ def update_email(user, options = {})
57
+
58
+ end
59
+
60
+
61
+ def delete_user(user, options = {})
62
+ delete "users/#{user}", options
63
+ end
64
+
65
+ # Validate user username and password
66
+ #
67
+ # @param options [Hash] User credentials
68
+ # @option options [String] :email Nearmiss login email
69
+ # @option options [String] :password Nearmiss password
70
+ # @return [Boolean] True if credentials are valid
71
+ def validate_credentials(options = {})
72
+ !self.class.new(options).user.nil?
73
+ rescue Nearmiss::Unauthorized
74
+ false
75
+ end
76
+
77
+
78
+
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,307 @@
1
+ # require "set"
2
+ require_relative "authentication"
3
+ require_relative "configurable"
4
+ require_relative "arguments"
5
+ require_relative "util"
6
+ require_relative 'rate_limit'
7
+
8
+ require_relative 'client/account'
9
+ require_relative 'client/bookmarks'
10
+ require_relative 'client/categories'
11
+ require_relative 'client/incidents'
12
+ require_relative 'client/notifications'
13
+ require_relative 'client/projects'
14
+ require_relative 'client/rate_limit'
15
+ require_relative 'client/users'
16
+
17
+ module Nearmiss
18
+
19
+ class Client
20
+ include Nearmiss::Util
21
+ include Nearmiss::Authentication
22
+ include Nearmiss::Configurable
23
+
24
+ include Nearmiss::Client::Account
25
+ include Nearmiss::Client::Bookmarks
26
+ include Nearmiss::Client::Categories
27
+ include Nearmiss::Client::Incidents
28
+ include Nearmiss::Client::Notifications
29
+ include Nearmiss::Client::Projects
30
+ include Nearmiss::Client::RateLimit
31
+ include Nearmiss::Client::Users
32
+
33
+ # include Nearmiss::Client::Users
34
+ # include Nearmiss::Client::ProjectLibrary
35
+ # include Nearmiss::Client::Projects
36
+ # include Nearmiss::Client::Templates
37
+ # include Nearmiss::Client::Checklists
38
+ # include Nearmiss::Client::Tasks
39
+ # include Nearmiss::Client::Issues
40
+ # include Nearmiss::Client::Utils
41
+
42
+ attr_accessor :access_token, :client_id, :uid, :expiry, :me
43
+
44
+ CONVENIENCE_HEADERS = Set.new([:accept, :content_type])
45
+
46
+
47
+ def initialize(options = {})
48
+
49
+ # Use options passed in, but fall back to module defaults
50
+ Nearmiss::Configurable.keys.each do |key|
51
+ instance_variable_set(:"@#{key}", options[key] || Nearmiss.instance_variable_get(:"@#{key}"))
52
+ end
53
+
54
+ sign_in if basic_authenticated?
55
+ end
56
+
57
+ # Compares client options to a Hash of requested options
58
+ #
59
+ # @param opts [Hash] Options to compare with current client options
60
+ # @return [Boolean]
61
+ def same_options?(opts)
62
+ opts.hash == options.hash
63
+ end
64
+
65
+
66
+ def inspect # :nodoc:
67
+
68
+ inspected = super
69
+
70
+ # mask password
71
+ inspected = inspected.gsub! @password, "*******" if @password
72
+ # Only show last 4 of token, secret
73
+ if @access_token
74
+ inspected = inspected.gsub! @access_token, "#{'*'*36}#{@access_token[36..-1]}"
75
+ end
76
+ # if @client_secret
77
+ # inspected = inspected.gsub! @client_secret, "#{'*'*36}#{@client_secret[36..-1]}"
78
+ # end
79
+
80
+ inspected
81
+ end
82
+
83
+ # Hypermedia agent for the BIM360-Field API
84
+ #
85
+ # @return [Sawyer::Agent]
86
+ def agent
87
+ @agent ||= Sawyer::Agent.new(api_endpoint, sawyer_options) do |http|
88
+ # http.headers[:accept] = "image/jpg"
89
+ http.headers[:content_type] = "application/json"
90
+ http.headers[:user_agent] = user_agent
91
+ http.headers[:accept] = "application/json"
92
+ http.headers[:api_key] = api_key
93
+ http.headers[:'x-client-platform'] = "api"
94
+
95
+ if @access_token
96
+ http.headers.merge!({
97
+ :'access-token' => @access_token,
98
+ :client => @client_id,
99
+ :expiry => @expiry,
100
+ :'token-type' => "Bearer",
101
+ :uid => @uid
102
+ })
103
+ end
104
+
105
+ # if
106
+ # if basic_authenticated?
107
+ # http.basic_auth(@login, @password)
108
+ # elsif token_authenticated?
109
+ # http.authorization 'token', @access_token
110
+ # end
111
+ end
112
+ end
113
+
114
+
115
+ # Set username for authentication
116
+ #
117
+ # @param value [String] Nearmiss-field username
118
+ def email=(value)
119
+ reset_agent
120
+ @email = value
121
+ end
122
+
123
+ # Set password for authentication
124
+ #
125
+ # @param value [String] Nearmiss-field password
126
+ def password=(value)
127
+ reset_agent
128
+ @password = value
129
+ end
130
+
131
+ # Set OAuth access token for authentication
132
+ #
133
+ # @param value [String] 40 character Nearmiss-field API OAuth access token
134
+ # def access_token=(value)
135
+ # reset_agent
136
+ # @access_token = value
137
+ # end
138
+
139
+
140
+
141
+
142
+
143
+ # Make a HTTP GET request
144
+ #
145
+ # @param url [String] The path, relative to {#api_endpoint}
146
+ # @param options [Hash] Query and header params for request
147
+ # @return [Sawyer::Resource]
148
+ def get(url, options = {})
149
+ request :get, url, options
150
+ end
151
+
152
+ def post(url, options = {})
153
+ request :post, url, options
154
+ end
155
+
156
+ def put(url, options = {})
157
+ request :put, url, options
158
+ end
159
+
160
+ def patch(url, options = {})
161
+ request :patch, url, options
162
+ end
163
+
164
+ def delete(url, options = {})
165
+ request :delete, url, options
166
+ end
167
+
168
+ # Response for last HTTP request
169
+ #
170
+ # @return [Sawyer::Response]
171
+ def last_response
172
+ @last_response if defined? @last_response
173
+ end
174
+
175
+
176
+ # Make one or more HTTP GET requests, optionally fetching
177
+ # the next page of results from URL in Link response header based
178
+ # on value in {#auto_paginate}.
179
+ #
180
+ # @param url [String] The path, relative to {#api_endpoint}
181
+ # @param options [Hash] Query and header params for request
182
+ # @param block [Block] Block to perform the data concatination of the
183
+ # multiple requests. The block is called with two parameters, the first
184
+ # contains the contents of the requests so far and the second parameter
185
+ # contains the latest response.
186
+ # @return [Sawyer::Resource]
187
+ def paginate(url, options = {}, &block)
188
+ opts = parse_query_and_convenience_headers(options.dup)
189
+ if @auto_paginate || @per_page
190
+ opts[:query][:per_page] ||= @per_page || (@auto_paginate ? 100 : nil)
191
+ end
192
+
193
+ data = request(:get, url, opts)
194
+
195
+ if @auto_paginate
196
+ while @last_response.rels[:next] #&& rate_limit.remaining > 0
197
+ @last_response = @last_response.rels[:next].get
198
+ if block_given?
199
+ yield(data, @last_response)
200
+ else
201
+ data.concat(@last_response.data) if @last_response.data.is_a?(Array)
202
+ end
203
+ end
204
+
205
+ end
206
+
207
+ data
208
+ end
209
+
210
+
211
+ # Wrapper around Kernel#warn to print warnings unless
212
+ # OCTOKIT_SILENT is set to true.
213
+ #
214
+ # @return [nil]
215
+ def nearmiss_warn(*message)
216
+ unless ENV['NEARMISS_SILENT']
217
+ warn message
218
+ end
219
+ end
220
+
221
+
222
+
223
+ private
224
+
225
+ def reset_agent
226
+ @agent = nil
227
+ end
228
+
229
+ # Make a HTTP Request
230
+ #
231
+ # @param method [Symbol] Http method
232
+ # @param path [String] path relative to {#api_endpoint}
233
+ # @param options [Hash] Query and header params for request
234
+ # @return [Sawyer::Resource]
235
+
236
+ def request(method, path, data, options = {})
237
+ if data.is_a?(Hash)
238
+ options[:query] = data.delete(:query) || {}
239
+ options[:headers] = data.delete(:headers) || {}
240
+ if accept = data.delete(:accept)
241
+ options[:headers][:accept] = accept
242
+ end
243
+ end
244
+
245
+ if @access_token
246
+ options[:headers].merge!({
247
+ "access-token" => @access_token,
248
+ "client" => @client_id,
249
+ "expiry" => @expiry,
250
+ "token-type" => "Bearer",
251
+ "uid" => @uid
252
+ })
253
+ end
254
+
255
+
256
+ @last_response = response = agent.call(method, URI::Parser.new.escape(path.to_s), data, options)
257
+
258
+ update_headers(response.headers)
259
+
260
+ response.data
261
+
262
+ end
263
+
264
+
265
+ def sawyer_options
266
+ opts = {
267
+ :links_parser => Sawyer::LinkParsers::Simple.new
268
+ }
269
+ conn_opts = @connection_options
270
+ conn_opts[:builder] = @middleware if @middleware
271
+ conn_opts[:proxy] = @proxy if @proxy
272
+ opts[:faraday] = Faraday.new(conn_opts)
273
+
274
+ opts
275
+ end
276
+
277
+ # Executes the request, checking if it was successful
278
+ #
279
+ # @return [Boolean] True on success, false otherwise
280
+ def boolean_from_response(method, path, options = {})
281
+ request(method, path, options)
282
+ @last_response.status == 204
283
+ rescue Nearmiss::NotFound
284
+ false
285
+ end
286
+
287
+
288
+ def parse_query_and_convenience_headers(options)
289
+ headers = options.fetch(:headers, {})
290
+ CONVENIENCE_HEADERS.each do |h|
291
+ if header = options.delete(h)
292
+ headers[h] = header
293
+ end
294
+ end
295
+ query = options.delete(:query)
296
+ opts = {:query => options}
297
+ opts[:query].merge!(query) if query && query.is_a?(Hash)
298
+ opts[:headers] = headers unless headers.empty?
299
+
300
+ opts
301
+ end
302
+
303
+
304
+ end
305
+
306
+
307
+ end
@@ -0,0 +1,53 @@
1
+ module Nearmiss
2
+ module Configurable
3
+
4
+ attr_accessor :middleware, :proxy, :user_agent, :connection_options, :api_key, :auto_paginate, :per_page
5
+ attr_writer :password, :api_endpoint, :email
6
+
7
+ # Define static methods
8
+ class << self
9
+
10
+ def keys
11
+ @keys ||= [
12
+ :middleware,
13
+ :proxy,
14
+ :user_agent,
15
+ :connection_options,
16
+ :password,
17
+ :api_endpoint,
18
+ :api_key,
19
+ :email,
20
+ :auto_paginate,
21
+ :per_page
22
+ ]
23
+ end
24
+ end
25
+
26
+ # Set configuration options using a block
27
+ def configure
28
+ yield self
29
+ end
30
+
31
+ # Reset configuration options to default values
32
+ def reset!
33
+ Nearmiss::Configurable.keys.each do |key|
34
+ instance_variable_set(:"@#{key}", Nearmiss::Default.options[key])
35
+ end
36
+ self
37
+ end
38
+ alias setup reset!
39
+
40
+ def api_endpoint
41
+ File.join(@api_endpoint, "")
42
+ end
43
+
44
+ def options
45
+ Hash[Nearmiss::Configurable.keys.map{|key| [key, instance_variable_get(:"@#{key}")]}]
46
+ end
47
+
48
+ private
49
+
50
+
51
+
52
+ end
53
+ end
@@ -0,0 +1,137 @@
1
+ # require "bim360/version" unless defined?(Nearmiss::VERSION)
2
+ # require 'bim360/response/raise_error'
3
+
4
+ module Nearmiss
5
+
6
+
7
+ # Default configuration options for {Client}
8
+ module Default
9
+
10
+ # config = YAML.load_file(File.join(Rails.root, 'secrets/secrets.yml'))['nearmiss']
11
+
12
+ # Default API endpoint
13
+ API_ENDPOINT = "http://nearmissapp.com".freeze
14
+
15
+ # Default User Agent header string
16
+ USER_AGENT = "Nearmiss Ruby Gem #{Nearmiss::VERSION}".freeze
17
+
18
+ API_KEY = "WEBCOR".freeze
19
+
20
+ # Default Faraday middleware stack
21
+ # MIDDLEWARE =
22
+
23
+
24
+ class << self
25
+
26
+ # Configuration options
27
+ # @return [Hash]
28
+ def options
29
+ Hash[Nearmiss::Configurable.keys.map{|key| [key, send(key)]}]
30
+ end
31
+
32
+ # Default access token from ENV
33
+ # @return [String]
34
+ def access_token
35
+ ENV['NEARMISS_ACCESS_TOKEN']
36
+ end
37
+
38
+ def client_id
39
+
40
+ end
41
+
42
+ def uid
43
+
44
+ end
45
+
46
+ def expiry
47
+
48
+ end
49
+
50
+ def user
51
+
52
+ end
53
+
54
+
55
+ def config
56
+ @config ||= {}
57
+ end
58
+
59
+ # Default API endpoint from ENV or {API_ENDPOINT}
60
+ # @return [String]
61
+ def api_endpoint
62
+ ENV['NEARMISS_API_ENDPOINT'] || API_ENDPOINT
63
+ end
64
+
65
+ # Default BIM360-Field username for Basic Auth from ENV
66
+ # @return [String]
67
+ def email
68
+ ENV['NEARMISS_EMAIL'] || config['email']
69
+ end
70
+
71
+ # Default BIM360-Field password for Basic Auth from ENV
72
+ # @return [String]
73
+ def password
74
+ ENV['NEARMISS_PASSWORD'] || config['password']
75
+ end
76
+
77
+ # def ticket
78
+ # ENV['NEARMISS_TICKET']
79
+ # end
80
+
81
+ # Default proxy server URI for Faraday connection from ENV
82
+ # @return [String]
83
+ def proxy
84
+ ENV['NEARMISS_PROXY']
85
+ end
86
+
87
+ # Default options for Faraday::Connection
88
+ # @return [Hash]
89
+ def connection_options
90
+ {
91
+ :headers => {
92
+ # :accept => default_media_type,
93
+ :user_agent => user_agent
94
+ }
95
+ }
96
+ end
97
+
98
+
99
+ # Default middleware stack for Faraday::Connection
100
+ # from {MIDDLEWARE}
101
+ # @return [String]
102
+ def middleware
103
+ Faraday::RackBuilder.new do |builder|
104
+ builder.use Nearmiss::Response::RaiseError
105
+ builder.adapter Faraday.default_adapter
106
+ end
107
+ end
108
+
109
+ # Default pagination preference from ENV
110
+ # @return [String]
111
+ def auto_paginate
112
+ ENV['NEARMISS_AUTO_PAGINATE'] || true
113
+ end
114
+
115
+ # Default pagination page size from ENV
116
+ # @return [Fixnum] Page size
117
+ def per_page
118
+ page_size = ENV['NEARMISS_PER_PAGE']
119
+
120
+ page_size.to_i if page_size
121
+ end
122
+
123
+
124
+ # Default User-Agent header string from ENV or {USER_AGENT}
125
+ # @return [String]
126
+ def user_agent
127
+ ENV['NEARMISS_USER_AGENT'] || USER_AGENT
128
+ end
129
+
130
+ def api_key
131
+ ENV['NEARMISS_API_KEY'] || API_KEY
132
+ end
133
+
134
+ end
135
+
136
+ end
137
+ end