nearmiss-ruby 1.0.0

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.
@@ -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