parse-stack 1.6.13 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1be0d0741ab2d2b2c1fb6113f3b4763dfd6d6b1d
4
- data.tar.gz: 83ebaed1bfae4f8a86291bdc23eda363a852f29b
3
+ metadata.gz: 48e731586682a18f7800110c166f20536c46b717
4
+ data.tar.gz: e5cd663b12a7935acb772ff881ca471709de076b
5
5
  SHA512:
6
- metadata.gz: 2a54f519b4aa5561cfa10b6d514024f664652c0614c2291e6e57c9921bb9356e8038618e17fbbe22bc7c5c258d83cad3ff4d3ca5cafe79adb24c804bc7442cb7
7
- data.tar.gz: c398da3567d2b00d506823cb9edc4a2ee064d6f685db654b460655358bf7ade01d4f5b9364ebae4869b0eed9171096832750ef9f70829fe41ae4dec0aa7d2b6f
6
+ metadata.gz: 79a487df290f8e3f7efc843b8f7b079fccd5dee56e52f3821a20f75f3b391675da33ce03e23a01ed9c442305017d2cee5e1d6dcfb52074bca218ee5f8f986044
7
+ data.tar.gz: b54958ad9b82dd8fddc10b6c1701e20eea11701482d27403cc92c41e4db883573feb77a9ab17915738092b940ee319a6b6c394f7afa6d7360790d1b916d524b9
data/Changes.md CHANGED
@@ -1,5 +1,12 @@
1
1
  ## Parse-Stack Changelog
2
2
 
3
+ ### 1.7.0
4
+ - NEW: You can use `set_default_acl` to set default ACLs for your subclasses.
5
+ - NEW: Support for `withinPolygon` query constraint.
6
+ - Refactoring of the default ACL system and deprecation of `Parse::Object.acl`
7
+ - Parse::ACL.everyone returns an ACL instance with public read and writes.
8
+ - Documentation updates.
9
+
3
10
  ### 1.6.12
4
11
  - NEW: Parse.use_shortnames! to utilize shorter class methods. (optional)
5
12
  - NEW: parse-console supports `--url` option to load config from JSON url.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- parse-stack (1.6.13)
4
+ parse-stack (1.7.0)
5
5
  active_model_serializers (>= 0.9, < 1)
6
6
  activemodel (>= 4.2.1, < 6)
7
7
  activesupport (>= 4.2.1, < 6)
data/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  # Parse Stack - The Parse Server Ruby Client SDK
4
4
 
5
- [Parse Stack](https://github.com/modernistik/parse-stack) is the [Parse Server](https://github.com/ParsePlatform/parse-server) SDK, REST Client and ORM framework for [Ruby](https://www.ruby-lang.org/en/). It provides a client adapter, a query engine, an object relational mapper (ORM) and a Cloud Code Webhooks rack application.
5
+ [Parse Stack](https://github.com/modernistik/parse-stack) is the [Parse Server](http://parseplatform.org/) SDK, REST Client and ORM framework for [Ruby](https://www.ruby-lang.org/en/). It provides a client adapter, a query engine, an object relational mapper (ORM) and a Cloud Code Webhooks rack application.
6
6
 
7
- Below is a [quick start guide](https://github.com/modernistik/parse-stack#overview), but you can also check out the full *[API Reference](https://www.modernistik.com/gems/parse-stack/)* for more detailed information about our Parse Server SDK.
7
+ Below is a [quick start guide](https://github.com/modernistik/parse-stack#overview), but you can also check out the full *[API Reference](https://www.modernistik.com/gems/parse-stack/index.html)* for more detailed information about our Parse Server SDK.
8
8
 
9
9
  #### Tutorial Videos
10
10
  1. Getting Started: https://youtu.be/zoYSGmciDlQ
@@ -15,7 +15,7 @@ Below is a [quick start guide](https://github.com/modernistik/parse-stack#overvi
15
15
  [![Gem Version](https://img.shields.io/gem/v/parse-stack.svg)](https://github.com/modernistik/parse-stack)
16
16
  [![Downloads](https://img.shields.io/gem/dt/parse-stack.svg)](https://rubygems.org/gems/parse-stack)
17
17
  [![Build Status](https://travis-ci.org/modernistik/parse-stack.svg?branch=master)](https://travis-ci.org/modernistik/parse-stack)
18
- [![API Reference](http://img.shields.io/badge/api-docs-blue.svg)](https://www.modernistik.com/gems/parse-stack/)
18
+ [![API Reference](http://img.shields.io/badge/api-docs-blue.svg)](https://www.modernistik.com/gems/parse-stack/index.html)
19
19
 
20
20
  ### Questions?
21
21
  [![Gitter](https://badges.gitter.im/modernistik/parse-stack.svg)](https://gitter.im/modernistik/parse-stack?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
@@ -57,12 +57,12 @@ Master : true
57
57
  ```
58
58
 
59
59
  ## Overview
60
- Parse-Stack is a full stack framework that utilizes several ideas behind [DataMapper](http://datamapper.org/docs/find.html) and [ActiveModel](https://github.com/rails/rails/tree/master/activemodel) to manage and maintain larger scale ruby applications and tools that utilize the [Parse Server Platform](https://github.com/ParsePlatform/parse-server). If you are familiar with these technologies, the framework should feel familiar to you.
60
+ Parse-Stack is a full stack framework that utilizes several ideas behind [DataMapper](http://datamapper.org/docs/find.html) and [ActiveModel](https://github.com/rails/rails/tree/master/activemodel) to manage and maintain larger scale ruby applications and tools that utilize the [Parse Server Platform](http://parseplatform.org/). If you are familiar with these technologies, the framework should feel familiar to you.
61
61
 
62
62
  ```ruby
63
63
  require 'parse/stack'
64
64
 
65
- Parse.setup server_url: 'https://localhost:1337/parse',
65
+ Parse.setup server_url: 'http://localhost:1337/parse',
66
66
  app_id: APP_ID,
67
67
  api_key: REST_API_KEY,
68
68
  master_key: YOUR_MASTER_KEY # optional
@@ -80,6 +80,9 @@ class Song < Parse::Object
80
80
  belongs_to :artist
81
81
  # `like` is a Parse Relation to User class
82
82
  has_many :likes, as: :user, through: :relation
83
+
84
+ # deny public write to Song records by default
85
+ set_default_acl :public, read: true, write: false
83
86
  end
84
87
 
85
88
  class Artist < Parse::Object
@@ -153,6 +156,7 @@ result = Parse.call_function :myFunctionName, {param: value}
153
156
  - [Parse::ACL](#parseacl)
154
157
  - [Parse::Session](#parsesession)
155
158
  - [Parse::Installation](#parseinstallation)
159
+ - [Parse::Product](#parseproduct)
156
160
  - [Parse::Role](#parserole)
157
161
  - [Parse::User](#parseuser)
158
162
  - [Signup](#signup)
@@ -188,6 +192,7 @@ result = Parse.call_function :myFunctionName, {param: value}
188
192
  - [Creating, Saving and Deleting Records](#creating-saving-and-deleting-records)
189
193
  - [Create](#create)
190
194
  - [Saving](#saving)
195
+ - [Saving applying User ACLs](#saving-applying-user-acls)
191
196
  - [Raising an exception when save fails](#raising-an-exception-when-save-fails)
192
197
  - [Modifying Associations](#modifying-associations)
193
198
  - [Batch Requests](#batch-requests)
@@ -229,6 +234,7 @@ result = Parse.call_function :myFunctionName, {param: value}
229
234
  - [Geo Queries](#geo-queries)
230
235
  - [Max Distance Constraint](#max-distance-constraint)
231
236
  - [Bounding Box Constraint](#bounding-box-constraint)
237
+ - [Polygon Area Constraint](#polygon-area-constraint)
232
238
  - [Relational Queries](#relational-queries)
233
239
  - [Compound Queries](#compound-queries)
234
240
  - [Query Scopes](#query-scopes)
@@ -244,7 +250,8 @@ result = Parse.call_function :myFunctionName, {param: value}
244
250
  - [Register Webhooks](#register-webhooks)
245
251
  - [Parse REST API Client](#parse-rest-api-client)
246
252
  - [Request Caching](#request-caching)
247
- - [Development](#development)
253
+ - [Contributing](#contributing)
254
+ - [License](#license)
248
255
 
249
256
  <!-- END doctoc generated TOC please keep comment here to allow auto update -->
250
257
 
@@ -590,11 +597,27 @@ All `Parse::Object` subclasses have an `acl` property by default. With this prop
590
597
 
591
598
  artist.save
592
599
  ```
600
+ You may also set default ACLs for newly created insatnces of your subclasses using `set_default_acl`:
601
+
602
+ ```ruby
603
+ class AdminData < Parse::Object
604
+
605
+ # Disable public read and write
606
+ set_default_acl :public, read: false, write: false
607
+
608
+ # but allow members of the Admin role to read and write
609
+ set_default_acl 'Admin', role: true, read: true, write: true
610
+
611
+ end
612
+
613
+ data = AdminData.new
614
+ data.acl # => ACL({"role:Admin"=>{"read"=>true, "write"=>true}})
615
+ ```
593
616
 
594
617
  For more information about Parse record ACLs, see the documentation at [Security](http://docs.parseplatform.org/rest/guide/#security)
595
618
 
596
619
  ### [Parse::Session](https://www.modernistik.com/gems/parse-stack/Parse/Session.html)
597
- This class represents the data and columns contained in the standard Parse `_Session` collection. You may add additional properties and methods to this class. See [Session API Reference](https://www.modernistik.com/gems/parse-stack/Parse/Session). You may call `Parse.use_shortnames!` to use `Session` in addition to `Parse::Session`.
620
+ This class represents the data and columns contained in the standard Parse `_Session` collection. You may add additional properties and methods to this class. See [Session API Reference](https://www.modernistik.com/gems/parse-stack/Parse/Session.html). You may call `Parse.use_shortnames!` to use `Session` in addition to `Parse::Session`.
598
621
 
599
622
  You can get a specific `Parse::Session` given a session_token by using the `session` method. You can also find the user tied to a specific Parse session or session token with `Parse::User.session`.
600
623
 
@@ -606,25 +629,25 @@ session.user # the Parse user for this session
606
629
  # or fetch user with a session token
607
630
  user = Parse::User.session(token)
608
631
 
609
- # save an object with the priviledges (ACLs) of this user
632
+ # save an object with the privileges (ACLs) of this user
610
633
  some_object.save( session: user.session_token )
611
634
 
612
- # delete an object with the priviledges of this user
635
+ # delete an object with the privileges of this user
613
636
  some_object.destroy( session: user.session_token )
614
637
 
615
638
  ```
616
639
 
617
- ### [Parse::Installation](https://www.modernistik.com/gems/parse-stack/Parse/Installation)
618
- This class represents the data and columns contained in the standard Parse `_Installation` collection. You may add additional properties and methods to this class. See [Installation API Reference](https://www.modernistik.com/gems/parse-stack/Parse/Installation). You may call `Parse.use_shortnames!` to use `Installation` in addition to `Parse::Installation`.
640
+ ### [Parse::Installation](https://www.modernistik.com/gems/parse-stack/Parse/Installation.html)
641
+ This class represents the data and columns contained in the standard Parse `_Installation` collection. You may add additional properties and methods to this class. See [Installation API Reference](https://www.modernistik.com/gems/parse-stack/Parse/Installation.html). You may call `Parse.use_shortnames!` to use `Installation` in addition to `Parse::Installation`.
619
642
 
620
- ### [Parse::Product](https://www.modernistik.com/gems/parse-stack/Parse/Product)
621
- This class represents the data and columns contained in the standard Parse `_Product` collection. You may add additional properties and methods to this class. See [Product API Reference](https://www.modernistik.com/gems/parse-stack/Parse/Product). You may call `Parse.use_shortnames!` to use `Product` in addition to `Parse::Product`.
643
+ ### [Parse::Product](https://www.modernistik.com/gems/parse-stack/Parse/Product.html)
644
+ This class represents the data and columns contained in the standard Parse `_Product` collection. You may add additional properties and methods to this class. See [Product API Reference](https://www.modernistik.com/gems/parse-stack/Parse/Product.html). You may call `Parse.use_shortnames!` to use `Product` in addition to `Parse::Product`.
622
645
 
623
- ### [Parse::Role](https://www.modernistik.com/gems/parse-stack/Parse/Role)
624
- This class represents the data and columns contained in the standard Parse `_Role` collection. You may add additional properties and methods to this class. See [Roles API Reference](https://www.modernistik.com/gems/parse-stack/Parse/Role). You may call `Parse.use_shortnames!` to use `Role` in addition to `Parse::Role`.
646
+ ### [Parse::Role](https://www.modernistik.com/gems/parse-stack/Parse/Role.html)
647
+ This class represents the data and columns contained in the standard Parse `_Role` collection. You may add additional properties and methods to this class. See [Roles API Reference](https://www.modernistik.com/gems/parse-stack/Parse/Role.html). You may call `Parse.use_shortnames!` to use `Role` in addition to `Parse::Role`.
625
648
 
626
- ### [Parse::User](https://www.modernistik.com/gems/parse-stack/Parse/User)
627
- This class represents the data and columns contained in the standard Parse `_User` collection. You may add additional properties and methods to this class. See [User API Reference](https://www.modernistik.com/gems/parse-stack/Parse/User). You may call `Parse.use_shortnames!` to use `User` in addition to `Parse::User`.
649
+ ### [Parse::User](https://www.modernistik.com/gems/parse-stack/Parse/User.html)
650
+ This class represents the data and columns contained in the standard Parse `_User` collection. You may add additional properties and methods to this class. See [User API Reference](https://www.modernistik.com/gems/parse-stack/Parse/User.html). You may call `Parse.use_shortnames!` to use `User` in addition to `Parse::User`.
628
651
 
629
652
  #### Signup
630
653
  You can signup new users in two ways. You can either use a class method `Parse::User.signup` to create a new user with the minimum fields of username, password and email, or create a `Parse::User` object can call the `signup!` method. If signup fails, it will raise the corresponding exception.
@@ -638,7 +661,7 @@ user.signup!
638
661
  ```
639
662
 
640
663
  ##### Third-Party Services
641
- You can signup users using third-party services like Facebook and Twitter as described in: [Signing Up and Logging In](http://docs.parseplatform.org/rest/guide/#signing-up). To do this with Parse-Stack, you can call the `Parse::User.autologin_service` method by passing the service name and the corresponding authentication hash data. For a listing of supported third-party authentication services, see [OAuth](https://github.com/ParsePlatform/parse-server/wiki/OAuth).
664
+ You can signup users using third-party services like Facebook and Twitter as described in: [Signing Up and Logging In](http://docs.parseplatform.org/rest/guide/#signing-up). To do this with Parse-Stack, you can call the `Parse::User.autologin_service` method by passing the service name and the corresponding authentication hash data. For a listing of supported third-party authentication services, see [OAuth](http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication).
642
665
 
643
666
  ```ruby
644
667
  fb_auth = {}
@@ -1374,7 +1397,7 @@ To commit a new record or changes to an existing record to Parse, use the `#save
1374
1397
  The save operation can handle both creating and updating existing objects. If you do not want to update the association data of a changed object, you may use the `#update` method to only save the changed property values. In the case where you want to force update an object even though it has not changed, to possibly trigger your `before_save` hooks, you can use the `#update!` method. In addition, just like with other ActiveModel objects, you may call `reload!` to fetch the current record again from the data store.
1375
1398
 
1376
1399
  ### Saving applying User ACLs
1377
- You may save and delete objects from Parse on behalf of a logged in user by passing the session token to the call to `save` or `destroy`. Doing so will allow Parse to apply the ACLs of this user against the record to see if the user is authorized to read or write the record. See [Parse::Actions](https://www.modernistik.com/gems/parse-stack/Parse/Actions).
1400
+ You may save and delete objects from Parse on behalf of a logged in user by passing the session token to the call to `save` or `destroy`. Doing so will allow Parse to apply the ACLs of this user against the record to see if the user is authorized to read or write the record. See [Parse::Actions](https://www.modernistik.com/gems/parse-stack/Parse/Core/Actions.html).
1378
1401
 
1379
1402
  ```ruby
1380
1403
  user = Parse::User.login('myuser','pass')
@@ -1745,7 +1768,7 @@ The `where` clause is based on utilizing a set of constraints on the defined col
1745
1768
  { :column.constraint => value }
1746
1769
  ```
1747
1770
 
1748
- ## Query Constraints
1771
+ ## [Query Constraints](https://www.modernistik.com/gems/parse-stack/Parse/Constraint.html)
1749
1772
  Most of the constraints supported by Parse are available to `Parse::Query`. Assuming you have a column named `field`, here are some examples. For an explanation of the constraints, please see [Parse Query Constraints documentation](http://docs.parseplatform.org/rest/guide/#queries). You can build your own custom query constraints by creating a `Parse::Constraint` subclass. For all these `where` clauses assume `q` is a `Parse::Query` object.
1750
1773
 
1751
1774
  #### Equals
@@ -1958,7 +1981,7 @@ Song.all :artist => Artist.pointer(artist_id)
1958
1981
  Song.all :artist => Parse::Pointer.new("Artist", artist_id)
1959
1982
  ```
1960
1983
 
1961
- ### Geo Queries
1984
+ ### [Geo Queries](https://www.modernistik.com/gems/parse-stack/Parse/Constraint/NearSphereQueryConstraint.html)
1962
1985
  Equivalent to the `$nearSphere` Parse query operation. This is only applicable if the field is of type `GeoPoint`. This will query Parse and return a list of results ordered by distance with the nearest object being first.
1963
1986
 
1964
1987
  ```ruby
@@ -1984,7 +2007,7 @@ PlaceObject.all :location.near => geopoint.max_miles(10)
1984
2007
 
1985
2008
  We will support `$maxDistanceInKilometers` (for kms) and `$maxDistanceInRadians` (for radian angle) in the future.
1986
2009
 
1987
- #### Bounding Box Constraint
2010
+ #### [Bounding Box Constraint](https://www.modernistik.com/gems/parse-stack/Parse/Constraint/WithinGeoBoxQueryConstraint.html)
1988
2011
  Equivalent to the `$within` Parse query operation and `$box` geopoint constraint. The rectangular bounding box is defined by a southwest point as the first parameter, followed by the a northeast point. Please note that Geo box queries that cross the international date lines are not currently supported by Parse.
1989
2012
 
1990
2013
  ```ruby
@@ -1999,6 +2022,22 @@ ne = Parse::GeoPoint.new 36.12, -115.31 # Las Vegas
1999
2022
  PlaceObject.all :location.within_box => [sw,ne]
2000
2023
  ```
2001
2024
 
2025
+ #### [Polygon Area Constraint](https://www.modernistik.com/gems/parse-stack/Parse/Constraint/WithinPolygonQueryConstraint.html)
2026
+ Equivalent to the `$geoWithin` Parse query operation and `$polygon` geopoint constraint. The polygon area is described by a list of `Parse::GeoPoint` objects and should contain 3 or more points. This feature is only available in Parse-Server version 2.4.2 and later.
2027
+
2028
+ ```ruby
2029
+ # As many points as you want, minimum 3
2030
+ q.where :field.within_polygon => [geopoint1, geopoint2, geopoint3]
2031
+
2032
+ # Polygon for the Bermuda Triangle
2033
+ bermuda = Parse::GeoPoint.new 32.3078000,-64.7504999 # Bermuda
2034
+ miami = Parse::GeoPoint.new 25.7823198,-80.2660226 # Miami, FL
2035
+ san_juan = Parse::GeoPoint.new 18.3848232,-66.0933608 # San Juan, PR
2036
+
2037
+ # get all sunken ships inside the Bermuda Triangle
2038
+ SunkenShip.all :location.within_polygon => [bermuda, san_juan, miami]
2039
+ ```
2040
+
2002
2041
  ### Relational Queries
2003
2042
  Equivalent to the `$relatedTo` Parse query operation. If you want to retrieve objects that are members of a `Relation` field in your Parse class.
2004
2043
 
data/Rakefile CHANGED
@@ -29,6 +29,6 @@ end
29
29
 
30
30
  YARD::Rake::YardocTask.new do |t|
31
31
  t.files = ['lib/**/*.rb'] # optional
32
- # t.options = ['--any', '--extra', '--opts'] # optional
32
+ t.options = ['-o', 'doc/parse-stack' ] # optional
33
33
  t.stats_options = ['--list-undoc'] # optional
34
34
  end
data/bin/console CHANGED
@@ -6,16 +6,24 @@ require 'dotenv'
6
6
  require 'byebug'
7
7
  Dotenv.load
8
8
 
9
- Parse.setup # cache: 'redis://localhost:6379'
9
+ def setup
10
+ Parse.setup # cache: 'redis://localhost:6379'
10
11
 
11
- puts "[ParseServerURL] #{Parse.client.server_url}"
12
- puts "[ParseAppID] #{Parse.client.app_id}"
12
+ puts "[ParseServerURL] #{Parse.client.server_url}"
13
+ puts "[ParseAppID] #{Parse.client.app_id}"
13
14
 
14
- if Parse.client.master_key.present?
15
- Parse.auto_generate_models!.each do |model|
16
- puts "Generated #{model}"
15
+ if Parse.client.master_key.present?
16
+ Parse.auto_generate_models!.each do |model|
17
+ puts "Generated #{model}"
18
+ end
17
19
  end
20
+
18
21
  end
22
+ puts "Type 'setup' to connect to Parse-Server"
23
+
24
+ # Create shortnames
25
+ Parse.use_shortnames!
26
+
19
27
  # You can add fixtures and/or initialization code here to make experimenting
20
28
  # with your gem easier. You can also use a different console, if you like.
21
29
 
data/bin/parse-console CHANGED
@@ -3,7 +3,8 @@
3
3
  require 'optparse'
4
4
  require 'json'
5
5
  require 'open-uri'
6
- require 'active_support/all'
6
+ require 'active_support'
7
+ require 'active_support/core_ext'
7
8
 
8
9
  DEFAULT_CONFIG_FILE = 'config.json'
9
10
  DEFAULT_CONFIG_CONTENTS = {
@@ -10,7 +10,7 @@ module Parse
10
10
  # Send analytics data.
11
11
  # @param event_name [String] the name of the event.
12
12
  # @param metrics [Hash] the metrics to attach to event.
13
- # @see https://parseplatform.github.io/docs/rest/guide/#analytics-app-open-analytics Parse Analytics
13
+ # @see http://docs.parseplatform.org/rest/guide/#analytics Parse Analytics
14
14
  def send_analytics(event_name, metrics = {})
15
15
  request :post, "events/#{event_name}", body: metrics
16
16
  end
@@ -12,7 +12,7 @@ module Parse
12
12
  # Update the schema for a collection.
13
13
  # @param payload [Hash] the paylod for the Push notification.
14
14
  # @return [Parse::Response]
15
- # @see https://parseplatform.github.io/docs/rest/guide/#sending-pushes Sending Pushes
15
+ # @see http://docs.parseplatform.org/rest/guide/#sending-pushes Sending Pushes
16
16
  def push(payload = {})
17
17
  request :post, PUSH_PATH, body: payload.as_json
18
18
  end
@@ -39,10 +39,10 @@ module Parse
39
39
  # An ACL represents the dirty-trackable Parse Permissions object used for
40
40
  # each record. In Parse, it is composed a hash-like object that represent
41
41
  # {Parse::User} objectIds and/or a set of {Parse::Role} names. For each entity
42
- # (ex. User/Role/Public), you can define read/write priviledges on a particular
42
+ # (ex. User/Role/Public), you can define read/write privileges on a particular
43
43
  # record through a {Parse::ACL::Permission} instance.
44
44
  #
45
- # If you want to give priviledges for an action (ex. read/write),
45
+ # If you want to give privileges for an action (ex. read/write),
46
46
  # you set that particular permission it to true. If you want to deny a
47
47
  # permission, then you set it to false. Any denied permissions will not be
48
48
  # part of the final hash structure that is sent to parse, as omission of a permission
@@ -82,8 +82,26 @@ module Parse
82
82
  # artist.acl.apply_role "Admins", true, true
83
83
  #
84
84
  # artist.save
85
+ #
86
+ # You may also set default ACLs for your subclasses by using {Parse::Object.set_default_acl}.
87
+ # These will be get applied for newly created instances. All subclasses have
88
+ # public read and write enabled by default.
89
+ #
90
+ # class AdminData < Parse::Object
91
+ #
92
+ # # Disable public read and write
93
+ # set_default_acl :public, read: true, write: false
94
+ #
95
+ # # Allow Admin roles to read/write
96
+ # set_default_acl 'Admin', role: true, read: true, write: true
97
+ #
98
+ # end
99
+ #
100
+ # data = AdminData.new
101
+ # data.acl # => ACL({"role:Admin"=>{"read"=>true, "write"=>true}})
102
+ #
85
103
  # For more information about Parse record ACLs, see the documentation on
86
- # {https://parseplatform.github.io/docs/rest/guide/#security Security}.
104
+ # {http://docs.parseplatform.org/rest/guide/#security Security}.
87
105
  class ACL < DataType
88
106
 
89
107
  # @!attribute permissions
@@ -101,20 +119,28 @@ module Parse
101
119
  @permissions ||= {}
102
120
  end
103
121
  # The key field value for public permissions.
104
- PUBLIC = "*"
122
+ PUBLIC = "*".freeze
105
123
 
106
124
  # Create a new ACL with default Public read/write permissions and any
107
125
  # overrides from the input hash format.
108
126
  # @param acls [Hash] a Parse-compatible hash acl format.
109
127
  # @param owner [Parse::Object] a delegate to receive notifications of acl changes.
110
128
  # This delegate must support receiving `acl_will_change!` method.
111
- def initialize(acls = {}, owner: nil)
112
- everyone(true, true) # sets Public read/write
129
+ def initialize(acls = nil, owner: nil)
130
+ acls = acls.as_json if acls.is_a?(ACL)
131
+ self.attributes = acls if acls.is_a?(Hash)
113
132
  @delegate = owner
114
- if acls.is_a?(Hash)
115
- self.attributes = acls
116
- end
133
+ end
117
134
 
135
+ # Create a new ACL with default Public read/write permissions and any
136
+ # overrides from the input hash format.
137
+ # @param read [Boolean] the read permissions for PUBLIC (default: true)
138
+ # @param write [Boolean] the write permissions for PUBLIC (default: true)
139
+ # @version 1.7.0
140
+ def self.everyone(read = true, write = true)
141
+ acl = Parse::ACL.new
142
+ acl.everyone(read, write)
143
+ acl
118
144
  end
119
145
 
120
146
  # Create a new ACL::Permission instance with the supplied read and write values.
@@ -125,12 +151,27 @@ module Parse
125
151
  def self.permission(read, write = nil)
126
152
  ACL::Permission.new(read, write)
127
153
  end
128
-
129
- # @return [Boolean] whether two ACLs have the same set of priviledges.
154
+ # Determines whether two ACLs or a Parse-ACL hash is equivalent to this object.
155
+ # @example
156
+ # acl = Parse::ACL.new
157
+ # # create a public read-only ACL
158
+ # acl.apply :public, true, false
159
+ # acl.as_json # => {'*' => { "read" => true }}
160
+ #
161
+ # create a second instance with similar privileges
162
+ # acl2 = Parse::ACL.everyone(true, false)
163
+ # acl2.as_json # => {'*' => { "read" => true }}
164
+ #
165
+ # acl == acl2 # => true
166
+ # acl == {'*' => { "read" => true }} # hash ok too
167
+ #
168
+ # acl2.apply_role 'Admin', true, true # rw for Admins
169
+ # acl == acl2 # => false
170
+ #
171
+ # @return [Boolean] whether two ACLs have the same set of privileges.
130
172
  def ==(other_acl)
131
- return false unless other_acl.is_a?(self.class)
132
- return false if permissions.keys != other_acl.permissions.keys
133
- permissions.keys.all? { |per| permissions[per] == other_acl.permissions[per] }
173
+ return false unless other_acl.is_a?(self.class) || other_acl.is_a?(Hash)
174
+ as_json == other_acl.as_json
134
175
  end
135
176
 
136
177
  # Set the public read and write permissions.
@@ -162,7 +203,7 @@ module Parse
162
203
  end
163
204
  end
164
205
 
165
- # Apply a new permission with a given objectId (or tag)
206
+ # Apply a new permission with a given objectId, tag or :public.
166
207
  # @overload apply(user, read = nil, write = nil)
167
208
  # Set the read and write permissions for this user on this ACL.
168
209
  # @param user [Parse::User] the user object.
@@ -175,7 +216,8 @@ module Parse
175
216
  # @param write [Boolean] the write permission.
176
217
  # @overload apply(id, read = nil, write = nil)
177
218
  # Set the read and write permissions for this objectId on this ACL.
178
- # @param id [String] the objectId for a {Parse::User}.
219
+ # @param id [String|:public] the objectId for a {Parse::User}. If :public is passed,
220
+ # then the {Parse::ACL::PUBLIC} read and write permissions will be modified.
179
221
  # @param read [Boolean] the read permission.
180
222
  # @param write [Boolean] the write permission.
181
223
  # @return [Hash] the current set of permissions.
@@ -183,12 +225,14 @@ module Parse
183
225
  def apply(id, read = nil, write = nil)
184
226
  return apply_role(id,read,write) if id.is_a?(Parse::Role)
185
227
  id = id.id if id.is_a?(Parse::Pointer)
186
- return unless id.present?
228
+ unless id.present?
229
+ raise ArgumentError, "Invalid argument applying ACLs: must be either objectId, role or :public"
230
+ end
231
+ id = PUBLIC if id.to_sym == :public
187
232
  # create a new Permissions
188
233
  permission = ACL.permission(read, write)
189
234
  # if the input is already an Permission object, then set it directly
190
235
  permission = read if read.is_a?(Parse::ACL::Permission)
191
-
192
236
  if permission.is_a?(ACL::Permission)
193
237
  if permissions[id.to_s] != permission
194
238
  will_change! # dirty track
@@ -215,6 +259,8 @@ module Parse
215
259
 
216
260
  # Used for object conversion when formatting the input/output value in
217
261
  # Parse::Object properties
262
+ # @param value [Hash] a Parse ACL hash to construct a Parse::ACL instance.
263
+ # @param delegate [Object] any object that would need to be notified of changes.
218
264
  # @return [ACL]
219
265
  # @see Parse::DataType
220
266
  def self.typecast(value, delegate = nil)
@@ -224,8 +270,7 @@ module Parse
224
270
  # Used for JSON serialization. Only if an attribute is non-nil, do we allow it
225
271
  # in the Permissions hash, since omission means denial of priviledge. If the
226
272
  # permission value has neither read or write, then the entire record has been denied
227
- # all priviledges
228
-
273
+ # all privileges
229
274
  # @return [Hash]
230
275
  def attributes
231
276
  permissions.select {|k,v| v.present? }.as_json
@@ -280,7 +325,7 @@ module Parse
280
325
  # @return [Boolean] whether this permission is allowed.
281
326
  attr_reader :write
282
327
 
283
- # Create a new permission with the given read and write priviledges.
328
+ # Create a new permission with the given read and write privileges.
284
329
  # @overload new(read = nil, write = nil)
285
330
  # @param read [Boolean] whether reading is allowed.
286
331
  # @param write [Boolean] whether writing is allowed.
@@ -293,7 +338,7 @@ module Parse
293
338
  #
294
339
  def initialize(r_perm = nil, w_perm = nil)
295
340
  if r_perm.is_a?(Hash)
296
- r_perm.symbolize_keys!
341
+ r_perm = r_perm.symbolize_keys
297
342
  @read = r_perm[:read].present?
298
343
  @write = r_perm[:write].present?
299
344
  else
@@ -15,7 +15,7 @@ module Parse
15
15
  # to implement your associations, will affect how `has_many` works in
16
16
  # Parse-Stack. Parse natively supports one-to-many and many-to-many
17
17
  # relationships using `Array` and `Relations`, as described in
18
- # {https://parseplatform.github.io/docs/js/guide/#relational-data Parse Relational Data}.
18
+ # {http://docs.parseplatform.org/js/guide/#relations Parse Relational Data}.
19
19
  # Both of these methods require you define a specific column type in your
20
20
  # Parse table that will be used to store information about the association.
21
21
  #
@@ -169,7 +169,7 @@ module Parse
169
169
  # *ParseRelation-Approach*
170
170
  #
171
171
  # Other than the use of arrays, Parse supports native one-to-many and many-to-many
172
- # associations through what is referred to as a {https://parseplatform.github.io/docs/js/guide/#many-to-many-relationships Parse Relation}.
172
+ # associations through what is referred to as a {http://docs.parseplatform.org/js/guide/#many-to-many Parse Relation}.
173
173
  # This is implemented by defining a column to be of type `Relation` which
174
174
  # refers to a foreign class. Parse-Stack supports this by passing the
175
175
  # `through: :relation` option to the `has_many` method. Designating a column
@@ -183,7 +183,7 @@ module Parse
183
183
  #
184
184
  # *3*. Applying query constraints for a set of records within a relation is performed against the foreign table class, not the class having the relational column.
185
185
  #
186
- # The Parse documentation provides more details on associations, see {http://parseplatform.github.io/docs/ios/guide/#relations Parse Relations Guide}.
186
+ # The Parse documentation provides more details on associations, see {http://docs.parseplatform.org/ios/guide/#relations Parse Relations Guide}.
187
187
  # Parse-Stack will handle the work for (2) and (3) automatically.
188
188
  #
189
189
  # In the example below, a `Band` can have thousands of `Fans`. We setup a
@@ -74,11 +74,11 @@ module Parse
74
74
  # *OAuth-Login*
75
75
  #
76
76
  # You can signup users using third-party services like Facebook and Twitter as
77
- # described in {https://parseplatform.github.io/docs/rest/guide/#signing-up-and-logging-in
77
+ # described in {http://docs.parseplatform.org/rest/guide/#signing-up
78
78
  # Signing Up and Logging In}. To do this with Parse-Stack, you can call the
79
79
  # {Parse::User.autologin_service} method by passing the service name and the
80
80
  # corresponding authentication hash data. For a listing of supported third-party
81
- # authentication services, see {https://github.com/ParsePlatform/parse-server/wiki/OAuth OAuth}.
81
+ # authentication services, see {http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication OAuth}.
82
82
  #
83
83
  # fb_auth = {}
84
84
  # fb_auth[:id] = "123456789"
@@ -105,12 +105,12 @@ module Parse
105
105
  #
106
106
  # You can link or unlink user accounts with third-party services like
107
107
  # Facebook and Twitter as described in:
108
- # {https://parseplatform.github.io/docs/rest/guide/#linking Linking and Unlinking Users}.
108
+ # {http://docs.parseplatform.org/rest/guide/#linking-users Linking and Unlinking Users}.
109
109
  # To do this, you must first get the corresponding authentication data for the
110
110
  # specific service, and then apply it to the user using the linking and
111
111
  # unlinking methods. Each method returns true or false if the action was
112
112
  # successful. For a listing of supported third-party authentication services,
113
- # see {https://github.com/ParsePlatform/parse-server/wiki/OAuth OAuth}.
113
+ # see {http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication OAuth}.
114
114
  #
115
115
  # user = Parse::User.first
116
116
  #
@@ -157,8 +157,8 @@ module Parse
157
157
  # @see Parse::Model.autosave_on_create
158
158
  def first_or_create(query_attrs = {}, resource_attrs = {})
159
159
 
160
- query_attrs.symbolize_keys!
161
- resource_attrs.symbolize_keys!
160
+ query_attrs = query_attrs.symbolize_keys
161
+ resource_attrs = resource_attrs.symbolize_keys
162
162
  obj = query(query_attrs).first
163
163
 
164
164
  if obj.blank?
@@ -511,7 +511,7 @@ module Parse
511
511
  # we will create the object. If the object has an id, we will update the record.
512
512
  #
513
513
  # You may pass a session token to the `session` argument to perform this actions
514
- # with the priviledges of a certain user.
514
+ # with the privileges of a certain user.
515
515
  #
516
516
  # You can define before and after :save callbacks
517
517
  # autoraise: set to true will automatically raise an exception if the save fails
@@ -116,7 +116,7 @@ module Parse
116
116
  # or with an array of two items where the first is the lat and the second is the lng (ex. [32.22,-118.81])
117
117
  def attributes=(h)
118
118
  if h.is_a?(Hash)
119
- h.symbolize_keys!
119
+ h = h.symbolize_keys
120
120
  @latitude = h[:latitude].to_f || h[:lat].to_f || @latitude
121
121
  @longitude = h[:longitude].to_f || h[:lng].to_f || @longitude
122
122
  elsif h.is_a?(Array) && h.count == 2
@@ -165,12 +165,12 @@ module Parse
165
165
  # to set it to something different.
166
166
  class << self
167
167
 
168
- attr_accessor :disable_serialized_string_date, :parse_class, :acl
169
-
168
+ attr_accessor :disable_serialized_string_date, :parse_class
169
+ attr_reader :default_acls
170
170
  # @!attribute disable_serialized_string_date
171
171
  # Disables returning a serialized string date properties when encoding to JSON.
172
172
  # This affects created_at and updated_at fields in order to be backwards compatible with old SDKs.
173
- # @return [Boolean]
173
+ # @return [Boolean] the disabled status of whether string dates should be serialized.
174
174
 
175
175
  # The class method to override the implicitly assumed Parse collection name
176
176
  # in your Parse database. The default Parse collection name is the singular form
@@ -195,16 +195,51 @@ module Parse
195
195
  @parse_class
196
196
  end
197
197
 
198
- # A method to override the default ACLs for new objects for this particular
199
- # subclass.
200
- # @param acls [Hash] a hash with key value pairs of ACLs permissions.
201
- # @return [ACL] the default ACLs for this class.
202
- def acl(acls = {}, owner: nil)
203
- acls = {"*" => {read: true, write: false} }.merge( acls ).symbolize_keys
204
- @acl ||= Parse::ACL.new(acls, owner: owner)
198
+ # The set of default ACLs to be applied on newly created instances of this class.
199
+ # By default, public read and write are enabled.
200
+ # @see Parse::ACL.everyone
201
+ # @return [Parse::ACL] the current default ACLs for this class.
202
+ def default_acls
203
+ @default_acls ||= Parse::ACL.everyone # default public read/write
205
204
  end
206
205
 
207
- end
206
+ # A method to set default ACLs to be applied for newly created
207
+ # instances of this class. All subclasses have public read and write enabled
208
+ # by default.
209
+ # @example
210
+ # class AdminData < Parse::Object
211
+ #
212
+ # # Disable public read and write
213
+ # set_default_acl :public, read: false, write: false
214
+ #
215
+ # # but allow members of the Admin role to read and write
216
+ # set_default_acl 'Admin', role: true, read: true, write: true
217
+ #
218
+ # end
219
+ #
220
+ # data = AdminData.new
221
+ # data.acl # => ACL({"role:Admin"=>{"read"=>true, "write"=>true}})
222
+ #
223
+ # @param id [String|:public] The name for ACL entry. This can be an objectId, a role name or :public.
224
+ # @param read [Boolean] Whether to allow read permissions (default: false).
225
+ # @param write [Boolean] Whether to allow write permissions (default: false).
226
+ # @param role [Boolean] Whether the `id` argument should be applied as a role name.
227
+ # @see Parse::ACL#apply_role
228
+ # @see Parse::ACL#apply
229
+ # @version 1.7.0
230
+ def set_default_acl(id, read: false, write: false, role: false)
231
+ unless id.present?
232
+ raise ArgumentError, "Invalid argument applying #{self}.default_acls : must be either objectId, role or :public"
233
+ end
234
+ role ? default_acls.apply_role(id, read, write) : default_acls.apply(id, read, write)
235
+ end
236
+
237
+ # @!visibility private
238
+ def acl(acls, owner: nil)
239
+ raise "[#{self}.acl DEPRECATED] - Use `#{self}.default_acl` instead."
240
+ end
241
+
242
+ end # << self
208
243
 
209
244
  # @return [String] the Parse class for this object.
210
245
  # @see Parse::Object.parse_class
@@ -255,9 +290,10 @@ module Parse
255
290
  apply_attributes!(opts, dirty_track: !dirty_track)
256
291
  end
257
292
 
258
- if self.acl.blank?
259
- self.acl = self.class.acl({}, owner: self) || Parse::ACL.new(owner: self)
260
- end
293
+ # if no ACLs, then apply the class default acls
294
+ # ACL.typecast will auto convert of Parse::ACL
295
+ self.acl = self.class.default_acls.as_json if self.acl.nil?
296
+
261
297
  clear_changes! if @id.present? #then it was an import
262
298
 
263
299
  # do not apply defaults on a pointer because it will stop it from being
data/lib/parse/query.rb CHANGED
@@ -13,7 +13,7 @@ require 'active_support/core_ext'
13
13
 
14
14
  module Parse
15
15
  # The {Parse::Query} class provides the lower-level querying interface for
16
- # your Parse collections by utilizing the {http://parseplatform.github.io/docs/rest/guide/#queries
16
+ # your Parse collections by utilizing the {http://docs.parseplatform.org/rest/guide/#queries
17
17
  # REST Querying interface}. This is the main engine behind making Parse queries
18
18
  # on remote collections. It takes a set of constraints and generates the
19
19
  # proper hash parameters that are passed to an API request in order to retrive
@@ -58,7 +58,7 @@ module Parse
58
58
  # Most of the constraints supported by Parse are available to `Parse::Query`.
59
59
  # Assuming you have a column named `field`, here are some examples. For an
60
60
  # explanation of the constraints, please see
61
- # {http://parseplatform.github.io/docs/rest/guide/#queries Parse Query Constraints documentation}.
61
+ # {http://docs.parseplatform.org/rest/guide/#queries Parse Query Constraints documentation}.
62
62
  # You can build your own custom query constraints by creating a `Parse::Constraint`
63
63
  # subclass. For all these `where` clauses assume `q` is a `Parse::Query` object.
64
64
  class Query
@@ -131,7 +131,7 @@ module Parse
131
131
  # @!attribute [rw] session_token
132
132
  # Set the session token to send with this API request. A session token is tied to
133
133
  # a logged in {Parse::User}. When sending a session_token in the request,
134
- # this performs the query on behalf of the user (with their allowed priviledges).
134
+ # this performs the query on behalf of the user (with their allowed privileges).
135
135
  # Using the short hand (inline) form, you can also pass an authenticated {Parse::User} instance
136
136
  # or a {Parse::Session} instance.
137
137
  # @example
@@ -107,7 +107,7 @@ module Parse
107
107
  d = { __type: Parse::Model::TYPE_DATE, iso: d.iso8601(3) } if d.respond_to?(:iso8601)
108
108
  d = d.pointer if d.respond_to?(:pointer) #simplified query object
109
109
  d = d.to_s if d.is_a?(Regexp)
110
- #d = d.pointer if d.is_a?(Parse::Object) #simplified query object
110
+ # d = d.pointer if d.is_a?(Parse::Object) #simplified query object
111
111
  # d = d.compile
112
112
  if d.is_a?(Parse::Query)
113
113
  compiled = d.compile(encode: false, includeClassName: true)
@@ -663,6 +663,50 @@ module Parse
663
663
  end
664
664
  end
665
665
 
666
+ # Equivalent to the `$geoWithin` Parse query operation and `$polygon` geopoints
667
+ # constraint. The polygon area is defined by a list of {Parse::GeoPoint}
668
+ # objects that make up the enclosed area. A polygon query should have 3 or more geopoints.
669
+ # Please note that some Geo queries that cross the international date lines are not currently
670
+ # supported by Parse.
671
+ #
672
+ # # As many points as you want, minimum 3
673
+ # q.where :field.within_polygon => [geopoint1, geopoint2, geopoint3]
674
+ #
675
+ # # Polygon for the Bermuda Triangle
676
+ # bermuda = Parse::GeoPoint.new 32.3078000,-64.7504999 # Bermuda
677
+ # miami = Parse::GeoPoint.new 25.7823198,-80.2660226 # Miami, FL
678
+ # san_juan = Parse::GeoPoint.new 18.3848232,-66.0933608 # San Juan, PR
679
+ #
680
+ # # get all sunken ships inside the Bermuda Triangle
681
+ # SunkenShip.all :location.within_polygon => [bermuda, san_juan, miami]
682
+ #
683
+ class WithinPolygonQueryConstraint < Constraint
684
+ # @!method within_polygon
685
+ # A registered method on a symbol to create the constraint. Maps to Parse
686
+ # operator "$geoWithin" with "$polygon" subconstraint. Takes an array of {Parse::GeoPoint} objects.
687
+ # @example
688
+ # # As many points as you want
689
+ # q.where :field.within_polygon => [geopoint1, geopoint2, geopoint3]
690
+ # @return [WithinPolygonQueryConstraint]
691
+ # @version 1.7.0 (requires Server v2.4.2 or later)
692
+ contraint_keyword :$geoWithin
693
+ register :within_polygon
694
+
695
+ # @return [Hash] the compiled constraint.
696
+ def build
697
+ geopoint_values = formatted_value
698
+ unless geopoint_values.is_a?(Array) &&
699
+ geopoint_values.all? {|point| point.is_a?(Parse::GeoPoint) } &&
700
+ geopoint_values.count > 2
701
+ raise ArgumentError, '[Parse::Query] Invalid query value parameter passed to'\
702
+ ' `within_polygon` constraint: Value must be an array with 3'\
703
+ ' or more `Parse::GeoPoint` objects'
704
+ end
705
+
706
+ { @operation.operand => { :$geoWithin => { :$polygon => geopoint_values } } }
707
+ end
708
+ end
709
+
666
710
  end
667
711
 
668
712
  end
@@ -6,6 +6,6 @@ module Parse
6
6
  # The Parse Server SDK for Ruby
7
7
  module Stack
8
8
  # The current version.
9
- VERSION = "1.6.13"
9
+ VERSION = "1.7.0"
10
10
  end
11
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parse-stack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.13
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony Persaud
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-09 00:00:00.000000000 Z
11
+ date: 2017-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel