parse-stack 1.5.2 → 1.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +5 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +40 -80
  5. data/lib/parse/api/all.rb +7 -0
  6. data/lib/parse/api/analytics.rb +8 -3
  7. data/lib/parse/api/apps.rb +29 -1
  8. data/lib/parse/api/batch.rb +14 -129
  9. data/lib/parse/api/cloud_functions.rb +9 -0
  10. data/lib/parse/api/config.rb +10 -1
  11. data/lib/parse/api/files.rb +7 -2
  12. data/lib/parse/api/hooks.rb +45 -2
  13. data/lib/parse/api/objects.rb +43 -6
  14. data/lib/parse/api/push.rb +6 -1
  15. data/lib/parse/api/schemas.rb +15 -1
  16. data/lib/parse/api/sessions.rb +5 -0
  17. data/lib/parse/api/users.rb +64 -5
  18. data/lib/parse/client/authentication.rb +25 -8
  19. data/lib/parse/client/batch.rb +206 -0
  20. data/lib/parse/client/body_builder.rb +12 -6
  21. data/lib/parse/client/caching.rb +42 -10
  22. data/lib/parse/client/protocol.rb +51 -46
  23. data/lib/parse/client/response.rb +1 -47
  24. data/lib/parse/client.rb +171 -42
  25. data/lib/parse/model/acl.rb +184 -39
  26. data/lib/parse/model/associations/belongs_to.rb +1 -0
  27. data/lib/parse/model/classes/role.rb +7 -1
  28. data/lib/parse/model/classes/session.rb +7 -3
  29. data/lib/parse/model/classes/user.rb +107 -0
  30. data/lib/parse/model/core/actions.rb +166 -115
  31. data/lib/parse/model/core/fetching.rb +105 -0
  32. data/lib/parse/model/core/properties.rb +40 -13
  33. data/lib/parse/model/core/querying.rb +123 -39
  34. data/lib/parse/model/core/schema.rb +22 -32
  35. data/lib/parse/model/object.rb +26 -20
  36. data/lib/parse/model/pointer.rb +1 -0
  37. data/lib/parse/query/constraint.rb +65 -27
  38. data/lib/parse/query/constraints.rb +0 -3
  39. data/lib/parse/query/operation.rb +33 -22
  40. data/lib/parse/query/ordering.rb +10 -5
  41. data/lib/parse/stack/generators/rails.rb +5 -1
  42. data/lib/parse/stack/generators/templates/model_installation.rb +1 -1
  43. data/lib/parse/stack/generators/templates/model_role.rb +1 -1
  44. data/lib/parse/stack/generators/templates/model_session.rb +2 -2
  45. data/lib/parse/stack/generators/templates/model_user.rb +1 -1
  46. data/lib/parse/stack/generators/templates/parse.rb +0 -1
  47. data/lib/parse/stack/railtie.rb +1 -0
  48. data/lib/parse/stack/tasks.rb +3 -1
  49. data/lib/parse/stack/version.rb +3 -1
  50. data/lib/parse/webhooks/registration.rb +3 -3
  51. data/lib/parse/webhooks.rb +88 -7
  52. metadata +5 -3
data/lib/parse/client.rb CHANGED
@@ -11,6 +11,7 @@ require 'active_support/core_ext/time/calculations'
11
11
  require 'active_support/core_ext'
12
12
  require_relative "client/request"
13
13
  require_relative "client/response"
14
+ require_relative "client/batch"
14
15
  require_relative "client/body_builder"
15
16
  require_relative "client/authentication"
16
17
  require_relative "client/caching"
@@ -30,6 +31,9 @@ module Parse
30
31
  # Retrieve the App specific Parse configuration parameters. The configuration
31
32
  # for a connection is cached after the first request. Use the bang version to
32
33
  # force update from the Parse backend.
34
+ # @example
35
+ # val = Parse.config["myKey"]
36
+ # val = Parse.config["myKey"] # cached
33
37
  # @see Parse.config!
34
38
  # @param conn [Symbol] the name of the client connection to use.
35
39
  # @return [Hash] the Parse config hash for the session.
@@ -38,6 +42,9 @@ module Parse
38
42
  end
39
43
 
40
44
  # Set a parameter in the Parse configuration for an application.
45
+ # @example
46
+ # # update a config with Parse
47
+ # Parse.set_config "myKey", "someValue"
41
48
  # @param field [String] the name configuration variable.
42
49
  # @param value [Object] the value configuration variable. Only Parse types are supported.
43
50
  # @param conn [Symbol] the name of the client connection to use.
@@ -47,6 +54,9 @@ module Parse
47
54
  end
48
55
 
49
56
  # Set a key value pairs in the Parse configuration for an application.
57
+ # @example
58
+ # # batch update several
59
+ # Parse.update_config({fieldEnabled: true, searchMiles: 50})
50
60
  # @param params [Hash] a set of key value pairs to set in the Parse configuration.
51
61
  # @param conn [Symbol] the name of the client connection to use.
52
62
  # @return [Hash] the Parse config hash for the session.
@@ -134,31 +144,68 @@ module Parse
134
144
  @clients[conn] ||= self.new
135
145
  end
136
146
 
137
- # Setup the Parse-Stack framework with the appropriate Parse app keys and middleware.
138
- # @yield a block for additional configuration
139
- # @param opts [Hash] the set of options to configure the :default Parse::Client connection.
140
- # @return [Parse::Client]
141
- # @see Parse::Client#initialize
147
+ # Setup the a new client with the appropriate Parse app keys, middleware and
148
+ # options.
149
+ # @example
150
+ # Parse.setup app_id: "YOUR_APP_ID",
151
+ # api_key: "YOUR_API_KEY",
152
+ # master_key: "YOUR_MASTER_KEY", # optional
153
+ # server_url: 'https://api.parse.com/1/' #default
154
+ # @param opts (see Parse::Client#initialize)
155
+ # @option opts (see Parse::Client#initialize)
156
+ # @yield the block for additional configuration with Faraday middleware.
157
+ # @return (see Parse::Client#initialize)
158
+ # @see Parse::Middleware::BodyBuilder
159
+ # @see Parse::Middleware::Caching
160
+ # @see Parse::Middleware::Authentication
161
+ # @see Parse::Protocol
142
162
  def setup(opts = {})
143
163
  @clients[:default] = self.new(opts, &Proc.new)
144
164
  end
145
165
 
146
166
  end
147
167
 
148
- # This builds a new Parse::Client stack. The options are:
149
- # required
150
- # :application_id - Parse Application ID. If not set it will be read from the
151
- # PARSE_APP_ID environment variable
152
- # :api_key - the Parse REST API Key. If not set it will be
153
- # read from PARSE_API_KEY environment variable
154
- # :master_key - the Parse Master Key (optional). If PARSE_MASTER_KEY env is set
155
- # it will be used.
156
- # optional
157
- # :logger - boolean - whether to print the requests and responses.
158
- # :cache - Moneta::Transformer - if set, it should be a Moneta store instance
159
- # :expires - Integer - if set, it should be a Moneta store instance
160
- # :adapter - the HTTP adapter to use with Faraday, defaults to Faraday.default_adapter
161
- # :host - defaults to Parse::Protocol::SERVER_URL (https://api.parse.com/1/)
168
+ # Create a new client connected to the Parse Server REST API endpoint.
169
+ # @param opts [Hash] a set of connection options to configure the client.
170
+ # @option opts [String] :server_url The server url of your Parse Server if you
171
+ # are not using the hosted Parse service. By default it will use
172
+ # PARSE_SERVER_URL environment variable available or fall back to
173
+ # https://api.parse.com/1/ if not specified.
174
+ # @option opts [String] :app_id The Parse application id. By default it will
175
+ # use PARSE_APP_ID environment variable if not specified.
176
+ # @option opts [String] :api_key The Parse REST API Key. By default it will
177
+ # use PARSE_API_KEY environment variable if not specified.
178
+ # @option opts [String] :master_key The Parse application master key (optional).
179
+ # If this key is set, it will be sent on every request sent by the client
180
+ # and your models. By default it will use PARSE_MASTER_KEY environment
181
+ # variable if not specified.
182
+ # @option opts [Boolean] :logging It provides you additional logging information
183
+ # of requests and responses. If set to the special symbol of *:debug*, it
184
+ # will provide additional payload data in the log messages. This option affects
185
+ # the logging performed by {Parse::Middleware::BodyBuilder}.
186
+ # @option opts [Object] :adapter The connection adapter. By default it uses
187
+ # the `Faraday.default_adapter` which is Net/HTTP.
188
+ # @option opts [Moneta::Transformer] :cache A caching adapter of type
189
+ # {https://github.com/minad/moneta Moneta::Transformer} that will be used
190
+ # by the caching middleware {Parse::Middleware::Caching}.
191
+ # Caching queries and object fetches can help improve the performance of
192
+ # your application, even if it is for a few seconds. Only successful GET
193
+ # object fetches and non-empty result queries will be cached by default.
194
+ # You may set the default expiration time with the expires option.
195
+ # At any point in time you may clear the cache by calling the {Parse::Client#clear_cache!}
196
+ # method on the client connection. See {https://github.com/minad/moneta Moneta}.
197
+ # @option opts [Integer] :expires Sets the default cache expiration time
198
+ # (in seconds) for successful non-empty GET requests when using the caching
199
+ # middleware. The default value is 3 seconds. If :expires is set to 0,
200
+ # caching will be disabled. You can always clear the current state of the
201
+ # cache using the clear_cache! method on your Parse::Client instance.
202
+ # @option opts [Hash] :faraday You may pass a hash of options that will be
203
+ # passed to the Faraday constructor.
204
+ # @raise ArgumentError if the cache instance passed to the :cache option is not of Moneta::Transformer.
205
+ # @see Parse::Middleware::BodyBuilder
206
+ # @see Parse::Middleware::Caching
207
+ # @see Parse::Middleware::Authentication
208
+ # @see Parse::Protocol
162
209
  def initialize(opts = {})
163
210
  @server_url = opts[:server_url] || ENV["PARSE_SERVER_URL"] || Parse::Protocol::SERVER_URL
164
211
  @application_id = opts[:application_id] || opts[:app_id] || ENV["PARSE_APP_ID"] || ENV['PARSE_SERVER_APPLICATION_ID']
@@ -211,7 +258,6 @@ module Parse
211
258
 
212
259
  end
213
260
  Parse::Client.clients[:default] ||= self
214
- self
215
261
  end
216
262
 
217
263
  # @return [String] the url prefix of the Parse Server url.
@@ -224,17 +270,62 @@ module Parse
224
270
  self.cache.clear if self.cache.present?
225
271
  end
226
272
 
227
- # This is the base method to make raw requests. The first parameter is a symbol
228
- # of the type of request - either :get, :put, :post, :delete. The second parameter
229
- # is the path api to use. For example, to make a request for objects, you would pass the "/1/classes/<ClassName>".
230
- # After the first two parameters, the rest are named parameters. If the request is of type :get, you can pass
231
- # any query string parameters in hash form with query:. If it is any other request, the body of the request should be sent
232
- # with the body: parameter. Note that the middleware will handle turning the hash sent into the body: parameter into JSON.
233
- # If you need to override or add additional headers to a specific request (ex. when uploading a Parse File), you can do so
234
- # with the header: paramter (also a hash).
235
- # This method also takes in a Parse::Request object instead of the arguments listed above.
273
+ # Send a REST API request to the server. This is the low-level API used for all requests
274
+ # to the Parse server with the provided options. Every request sent to Parse through
275
+ # the client goes through the configured set of middleware that can be modified by applying
276
+ # different headers or specific options.
277
+ # This method supports retrying requests a few times when a {Parse::ServiceUnavailableError}
278
+ # is raised.
279
+ # @param method [Symbol] The method type of the HTTP request (ex. :get, :post).
280
+ # - This parameter can also be a {Parse::Request} object.
281
+ # @param uri [String] the url path. It should not be an absolute url.
282
+ # @param body [Hash] the body of the request.
283
+ # @param query [Hash] the set of url query parameters to use in a GET request.
284
+ # @param headers [Hash] additional headers to apply to this request.
285
+ # @param opts [Hash] a set of options to pass through the middleware stack.
286
+ # - *:cache* [Integer] the number of seconds to cache this specific request.
287
+ # If set to `false`, caching will be disabled completely all together, which means even if
288
+ # a cached response exists, it will not be used.
289
+ # - *:use_master_key* [Boolean] whether this request should send the master key, if
290
+ # it was configured with {Parse.setup}. By default, if a master key was configured,
291
+ # all outgoing requests will contain it in the request header. Default `true`.
292
+ # - *:session_token* [String] The session token to send in this request. This disables
293
+ # sending the master key in the request, and sends this request with the credentials provided by
294
+ # the session_token.
295
+ # - *:retry* [Integer] The number of retrties to perform if the service is unavailable.
296
+ # Set to false to disable the retry mechanism. When performing request retries, the
297
+ # client will sleep for a number of seconds ({Parse::Client::RETRY_DELAY}) between requests.
298
+ # The default value is {Parse::Client::RETRY_COUNT}.
299
+ # @raise Parse::AuthenticationError when HTTP response status is 401 or 403
300
+ # @raise Parse::TimeoutError when HTTP response status is 400 or
301
+ # 408, and the Parse code is 143 or {Parse::Response::ERROR_TIMEOUT}.
302
+ # @raise Parse::ConnectionError when HTTP response status is 404 is not an object not found error.
303
+ # - This will also be raised if after retrying a request a number of times has finally failed.
304
+ # @raise Parse::ProtocolError when HTTP response status is 405 or 406
305
+ # @raise Parse::ServiceUnavailableError when HTTP response status is 500 or 503.
306
+ # - This may also happen when the Parse Server response code is any
307
+ # number less than {Parse::Response::ERROR_SERVICE_UNAVAILABLE}.
308
+ # @raise Parse::ServerError when the Parse response code is less than 100
309
+ # @raise Parse::RequestLimitExceededError when the Parse response code is {Parse::Response::ERROR_EXCEEDED_BURST_LIMIT}.
310
+ # - This usually means you have exceeded the burst limit on requests, which will mean you will be throttled for the
311
+ # next 60 seconds.
312
+ # @raise Parse::InvalidSessionTokenError when the Parse response code is 209.
313
+ # - This means the session token that was sent in the request seems to be invalid.
314
+ # @return [Parse::Response] the response for this request.
315
+ # @see Parse::Middleware::BodyBuilder
316
+ # @see Parse::Middleware::Caching
317
+ # @see Parse::Middleware::Authentication
318
+ # @see Parse::Protocol
319
+ # @see Parse::Request
236
320
  def request(method, uri = nil, body: nil, query: nil, headers: nil, opts: {})
237
321
  retry_count ||= RETRY_COUNT
322
+
323
+ if opts[:retry] == false
324
+ retry_count = 0
325
+ elsif opts[:retry].to_i > 0
326
+ retry_count = opts[:retry]
327
+ end
328
+
238
329
  headers ||= {}
239
330
  # if the first argument is a Parse::Request object, then construct it
240
331
  _request = nil
@@ -297,16 +388,13 @@ module Parse
297
388
  when 405, 406
298
389
  puts "[Parse:ProtocolError] #{response}"
299
390
  raise Parse::ProtocolError, response
300
- when 500
301
- puts "[Parse:ServiceUnavailableError] #{response}"
302
- raise Parse::ServiceUnavailableError, response
303
- when 503
391
+ when 500, 503
304
392
  puts "[Parse:ServiceUnavailableError] #{response}"
305
393
  raise Parse::ServiceUnavailableError, response
306
394
  end
307
395
 
308
396
  if response.error?
309
- if response.code <= Parse::Response::ERROR_SERVICE_UNAVAILALBE
397
+ if response.code <= Parse::Response::ERROR_SERVICE_UNAVAILABLE
310
398
  puts "[Parse:ServiceUnavailableError] #{response}"
311
399
  raise Parse::ServiceUnavailableError, response
312
400
  elsif response.code <= 100
@@ -315,7 +403,7 @@ module Parse
315
403
  elsif response.code == Parse::Response::ERROR_EXCEEDED_BURST_LIMIT
316
404
  puts "[Parse:RequestLimitExceededError] #{response}"
317
405
  raise Parse::RequestLimitExceededError, response
318
- elsif response.code == 209 #Error 209: invalid session token
406
+ elsif response.code == 209 # Error 209: invalid session token
319
407
  puts "[Parse:InvalidSessionTokenError] #{response}"
320
408
  raise Parse::InvalidSessionTokenError, response
321
409
  end
@@ -329,7 +417,7 @@ module Parse
329
417
  retry_count -= 1
330
418
  retry
331
419
  end
332
- raise e
420
+ raise
333
421
  rescue Faraday::Error::ClientError, Net::OpenTimeout => e
334
422
  if retry_count > 0
335
423
  puts "[Parse:Retry] Retries remaining #{retry_count} : #{_request}"
@@ -340,26 +428,46 @@ module Parse
340
428
  raise Parse::ConnectionError, "#{_request} : #{e.class} - #{e.message}"
341
429
  end
342
430
 
343
- # shorthand for request(:get, uri, query: {})
431
+ # Send a GET request.
432
+ # @param uri [String] the uri path for this request.
433
+ # @param query [Hash] the set of url query parameters.
434
+ # @param headers [Hash] additional headers to send in this request.
435
+ # @return (see #request)
344
436
  def get(uri, query = nil, headers = {})
345
437
  request :get, uri, query: query, headers: headers
346
438
  end
347
439
 
348
- # shorthand for request(:post, uri, body: {})
440
+ # Send a POST request.
441
+ # @param uri (see #get)
442
+ # @param body [Hash] a hash that will be JSON encoded for the body of this request.
443
+ # @param headers (see #get)
444
+ # @return (see #request)
349
445
  def post(uri, body = nil, headers = {} )
350
446
  request :post, uri, body: body, headers: headers
351
447
  end
352
448
 
353
- # shorthand for request(:put, uri, body: {})
449
+ # Send a PUT request.
450
+ # @param uri (see #post)
451
+ # @param body (see #post)
452
+ # @param headers (see #post)
453
+ # @return (see #request)
354
454
  def put(uri, body = nil, headers = {})
355
455
  request :put, uri, body: body, headers: headers
356
456
  end
357
457
 
358
- # shorthand for request(:delete, uri, body: {}, headers: {})
458
+ # Send a DELETE request.
459
+ # @param uri (see #post)
460
+ # @param body (see #post)
461
+ # @param headers (see #post)
462
+ # @return (see #request)
359
463
  def delete(uri, body = nil, headers = {})
360
464
  request :delete, uri, body: body, headers: headers
361
465
  end
362
466
 
467
+ # Send a {Parse::Request} object.
468
+ # @param req [Parse::Request] the request to send
469
+ # @raise ArgumentError if req is not of type Parse::Request.
470
+ # @return (see #request)
363
471
  def send_request(req) #Parse::Request object
364
472
  raise ArgumentError, "Object not of Parse::Request type." unless req.is_a?(Parse::Request)
365
473
  request req.method, req.path, req.body, req.headers
@@ -376,12 +484,15 @@ module Parse
376
484
  end
377
485
 
378
486
  module ClassMethods
487
+
488
+ # @return [Parse::Client] the current client for :default.
379
489
  attr_accessor :client
380
490
  def client
381
491
  @client ||= Parse::Client.client #defaults to :default tag
382
492
  end
383
493
  end
384
494
 
495
+ # @return [Parse::Client] the current client defined for the class.
385
496
  def client
386
497
  self.class.client
387
498
  end
@@ -391,6 +502,16 @@ module Parse
391
502
 
392
503
  # Helper method that users should call to setup the client stack.
393
504
  # A block can be passed in order to do additional client configuration.
505
+ # To connect to a Parse server, you will need a minimum of an application_id,
506
+ # an api_key and a server_url. To connect to the server endpoint, you use the
507
+ # {Parse.setup} method below.
508
+ #
509
+ # @example (see Parse::Client.setup)
510
+ # @param opts (see Parse::Client.setup)
511
+ # @option opts (see Parse::Client.setup)
512
+ # @yield (see Parse::Client.setup)
513
+ # @return (see Parse::Client.setup)
514
+ # @see Parse::Client.setup
394
515
  def self.setup(opts = {})
395
516
  if block_given?
396
517
  Parse::Client.new(opts, &Proc.new)
@@ -399,7 +520,11 @@ module Parse
399
520
  end
400
521
  end
401
522
 
402
- # Helper method to call cloud functions and get results
523
+ # Helper method to trigger cloud jobs and get results.
524
+ # @param name [String] the name of the cloud code job to trigger.
525
+ # @param body [Hash] the set of parameters to pass to the job.
526
+ # @param opts (see Parse.call_function)
527
+ # @return (see Parse.call_function)
403
528
  def self.trigger_job(name, body = {}, **opts)
404
529
  conn = opts[:session] || opts[:client] || :default
405
530
  response = Parse::Client.client(conn).trigger_job(name, body)
@@ -407,7 +532,11 @@ module Parse
407
532
  response.error? ? nil : response.result["result"]
408
533
  end
409
534
 
410
- # Helper method to call cloud functions and get results
535
+ # Helper method to call cloud functions and get results.
536
+ # @param name [String] the name of the cloud code function to call.
537
+ # @param body [Hash] the set of parameters to pass to the function.
538
+ # @param opts [Hash] additional options.
539
+ # @return [Object] the result data of the response. nil if there was an error.
411
540
  def self.call_function(name, body = {}, **opts)
412
541
  conn = opts[:session] || opts[:client] || :default
413
542
  response = Parse::Client.client(conn).call_function(name, body)