parse-stack 1.3.1 → 1.3.7
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +2 -1
- data/Changes.md +25 -1
- data/Gemfile +10 -0
- data/Gemfile.lock +10 -9
- data/README.md +593 -254
- data/Rakefile +1 -0
- data/bin/console +5 -0
- data/lib/parse-stack.rb +2 -0
- data/lib/parse/api/batch.rb +2 -1
- data/lib/parse/api/files.rb +2 -0
- data/lib/parse/api/objects.rb +2 -0
- data/lib/parse/client.rb +31 -2
- data/lib/parse/client/authentication.rb +10 -0
- data/lib/parse/client/body_builder.rb +3 -0
- data/lib/parse/client/request.rb +1 -1
- data/lib/parse/client/response.rb +1 -0
- data/lib/parse/model/associations/pointer_collection_proxy.rb +2 -2
- data/lib/parse/model/associations/relation_collection_proxy.rb +1 -0
- data/lib/parse/model/core/actions.rb +8 -8
- data/lib/parse/model/core/properties.rb +9 -0
- data/lib/parse/model/core/schema.rb +9 -0
- data/lib/parse/model/date.rb +4 -0
- data/lib/parse/model/file.rb +17 -2
- data/lib/parse/model/geopoint.rb +39 -2
- data/lib/parse/model/object.rb +2 -1
- data/lib/parse/model/pointer.rb +3 -0
- data/lib/parse/model/push.rb +2 -2
- data/lib/parse/query.rb +33 -17
- data/lib/parse/query/constraint.rb +2 -2
- data/lib/parse/query/constraints.rb +62 -6
- data/lib/parse/query/operation.rb +1 -0
- data/lib/parse/stack.rb +1 -0
- data/lib/parse/stack/tasks.rb +107 -0
- data/lib/parse/stack/version.rb +1 -1
- data/lib/parse/webhooks.rb +2 -2
- data/lib/parse/webhooks/payload.rb +2 -0
- data/lib/parse/webhooks/registration.rb +15 -10
- data/parse-stack.gemspec +8 -15
- metadata +20 -118
data/lib/parse/model/pointer.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
require 'active_model'
|
2
|
+
require 'active_support'
|
2
3
|
require 'active_support/inflector'
|
4
|
+
require 'active_support/core_ext'
|
3
5
|
require 'active_model_serializers'
|
4
6
|
require_relative 'model'
|
7
|
+
require 'active_model_serializers'
|
5
8
|
module Parse
|
6
9
|
|
7
10
|
# A Parse Pointer is the superclass of Parse::Object types. A pointer can be considered
|
data/lib/parse/model/push.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require_relative '../query.rb'
|
2
2
|
require_relative '../client.rb'
|
3
|
-
|
3
|
+
require 'active_model_serializers'
|
4
4
|
module Parse
|
5
5
|
|
6
6
|
class Push
|
@@ -10,7 +10,7 @@ module Parse
|
|
10
10
|
|
11
11
|
alias_method :message, :alert
|
12
12
|
alias_method :message=, :alert=
|
13
|
-
|
13
|
+
|
14
14
|
def self.send(payload)
|
15
15
|
client.push payload.as_json
|
16
16
|
end
|
data/lib/parse/query.rb
CHANGED
@@ -2,7 +2,10 @@ require_relative "client"
|
|
2
2
|
require_relative "query/operation"
|
3
3
|
require_relative "query/constraints"
|
4
4
|
require_relative "query/ordering"
|
5
|
-
|
5
|
+
require 'active_model_serializers'
|
6
|
+
require 'active_support'
|
7
|
+
require 'active_support/inflector'
|
8
|
+
require 'active_support/core_ext'
|
6
9
|
|
7
10
|
module Parse
|
8
11
|
# This is the main engine behind making Parse queries on tables. It takes
|
@@ -23,7 +26,7 @@ module Parse
|
|
23
26
|
# You can modify the default client being used by all Parse::Query objects by setting
|
24
27
|
# Parse::Query.client. You can override individual Parse::Query object clients
|
25
28
|
# by changing their client variable to a different Parse::Client object.
|
26
|
-
attr_accessor :table, :client, :key, :cache, :use_master_key
|
29
|
+
attr_accessor :table, :client, :key, :cache, :use_master_key, :session_token
|
27
30
|
|
28
31
|
# We have a special class method to handle field formatting. This turns
|
29
32
|
# the symbol keys in an operand from one key to another. For example, we can
|
@@ -34,23 +37,17 @@ module Parse
|
|
34
37
|
# in lower case). You can specify a different method to call by setting the Parse::Query.field_formatter
|
35
38
|
# variable with the symbol name of the method to call on the object. You can set this to nil
|
36
39
|
# if you do not want any field formatting to be performed.
|
40
|
+
@field_formatter = :columnize
|
37
41
|
class << self
|
38
42
|
#field formatter getters and setters.
|
39
43
|
attr_accessor :field_formatter
|
40
44
|
|
41
|
-
def field_formatter
|
42
|
-
#default
|
43
|
-
@field_formatter ||= :columnize
|
44
|
-
end
|
45
|
-
|
46
45
|
def format_field(str)
|
47
|
-
res = str.to_s
|
48
|
-
if field_formatter.present?
|
49
|
-
|
50
|
-
# don't format if object d
|
51
|
-
res = res.send(formatter) if res.respond_to?(formatter)
|
46
|
+
res = str.to_s.strip
|
47
|
+
if field_formatter.present? && res.respond_to?(field_formatter)
|
48
|
+
res = res.send(field_formatter)
|
52
49
|
end
|
53
|
-
res
|
50
|
+
res
|
54
51
|
end
|
55
52
|
|
56
53
|
# Simple way to create a query.
|
@@ -78,7 +75,7 @@ module Parse
|
|
78
75
|
when :skip
|
79
76
|
@skip = 0
|
80
77
|
when :limit
|
81
|
-
@limit =
|
78
|
+
@limit = nil
|
82
79
|
when :count
|
83
80
|
@count = 0
|
84
81
|
when :keys
|
@@ -96,7 +93,7 @@ module Parse
|
|
96
93
|
@order = []
|
97
94
|
@keys = []
|
98
95
|
@includes = []
|
99
|
-
@limit =
|
96
|
+
@limit = nil
|
100
97
|
@skip = 0
|
101
98
|
@table = table
|
102
99
|
@cache = true
|
@@ -123,6 +120,10 @@ module Parse
|
|
123
120
|
self.cache = value
|
124
121
|
elsif expression == :use_master_key
|
125
122
|
self.cache = value
|
123
|
+
elsif expression == :session
|
124
|
+
# you can pass a session token or a Parse::Session
|
125
|
+
value = value.is_a?(Parse::Session) ? value.session_token : value
|
126
|
+
self.session_token = value
|
126
127
|
else
|
127
128
|
add_constraint(expression, value)
|
128
129
|
end
|
@@ -176,6 +177,8 @@ module Parse
|
|
176
177
|
@limit = 11_000
|
177
178
|
elsif count.is_a?(Numeric)
|
178
179
|
@limit = [ 0, count.to_i, 11_000].sort[1]
|
180
|
+
else
|
181
|
+
@limit = nil
|
179
182
|
end
|
180
183
|
|
181
184
|
@results = nil
|
@@ -314,6 +317,12 @@ module Parse
|
|
314
317
|
opts = {}
|
315
318
|
opts[:cache] = false unless self.cache
|
316
319
|
opts[:use_mster_key] = self.use_master_key
|
320
|
+
opts[:session_token] = self.session_token
|
321
|
+
# for now, don't cache requests where we disable master_key or provide session token
|
322
|
+
if opts[:use_mster_key] == false || opts[:session_token].present?
|
323
|
+
opts[:cache] = false
|
324
|
+
end
|
325
|
+
|
317
326
|
response = client.find_objects(@table, compiled_query.as_json, opts )
|
318
327
|
if response.error?
|
319
328
|
puts "[ParseQuery] #{response.error}"
|
@@ -323,7 +332,7 @@ module Parse
|
|
323
332
|
|
324
333
|
def results(raw: false)
|
325
334
|
if @results.nil?
|
326
|
-
if @limit <= 1_000
|
335
|
+
if @limit.nil? || @limit.to_i <= 1_000
|
327
336
|
response = fetch!( compile )
|
328
337
|
return [] if response.error?
|
329
338
|
items = raw ? response.results : decode(response.results)
|
@@ -347,7 +356,11 @@ module Parse
|
|
347
356
|
compile.as_json
|
348
357
|
end
|
349
358
|
|
350
|
-
def
|
359
|
+
def prepared(includeClassName: false)
|
360
|
+
compile(encode: false, includeClassName: includeClassName)
|
361
|
+
end
|
362
|
+
|
363
|
+
def compile(encode: true, includeClassName: false)
|
351
364
|
q = {} #query
|
352
365
|
q[:limit] = 11_000 if @limit == :max || @limit == :all
|
353
366
|
q[:limit] = @limit if @limit.is_a?(Numeric) && @limit > 0
|
@@ -366,6 +379,9 @@ module Parse
|
|
366
379
|
q[:limit] = 0
|
367
380
|
q[:count] = 1
|
368
381
|
end
|
382
|
+
if includeClassName
|
383
|
+
q[:className] = @table
|
384
|
+
end
|
369
385
|
q
|
370
386
|
end
|
371
387
|
|
@@ -123,8 +123,8 @@ module Parse
|
|
123
123
|
#d = d.pointer if d.is_a?(Parse::Object) #simplified query object
|
124
124
|
# d = d.compile
|
125
125
|
if d.is_a?(Parse::Query)
|
126
|
-
compiled = d.compile(false)
|
127
|
-
compiled["className"] = d.table
|
126
|
+
compiled = d.compile(encode: false, includeClassName: true)
|
127
|
+
# compiled["className"] = d.table
|
128
128
|
d = compiled
|
129
129
|
end
|
130
130
|
d
|
@@ -24,29 +24,34 @@ module Parse
|
|
24
24
|
class LessOrEqualConstraint < Constraint
|
25
25
|
contraint_keyword :$lte
|
26
26
|
register :lte
|
27
|
+
register :less_than_or_equal
|
27
28
|
register :on_or_before
|
28
29
|
end
|
29
30
|
|
30
31
|
class LessThanConstraint < Constraint
|
31
32
|
contraint_keyword :$lt
|
32
33
|
register :lt
|
34
|
+
register :less_than
|
33
35
|
register :before
|
34
36
|
end
|
35
37
|
|
36
38
|
class GreaterThanConstraint < Constraint
|
37
39
|
contraint_keyword :$gt
|
38
40
|
register :gt
|
41
|
+
register :greater_than
|
39
42
|
register :after
|
40
43
|
end
|
41
44
|
|
42
45
|
class GreaterOrEqualConstraint < Constraint
|
43
46
|
contraint_keyword :$gte
|
44
47
|
register :gte
|
48
|
+
register :greater_than_or_equal
|
45
49
|
register :on_or_after
|
46
50
|
end
|
47
51
|
|
48
52
|
class NotEqualConstraint < Constraint
|
49
53
|
contraint_keyword :$ne
|
54
|
+
register :ne
|
50
55
|
register :not
|
51
56
|
end
|
52
57
|
|
@@ -98,6 +103,7 @@ module Parse
|
|
98
103
|
|
99
104
|
class NotContainedInConstraint < Constraint
|
100
105
|
contraint_keyword :$nin
|
106
|
+
register :nin
|
101
107
|
register :not_in
|
102
108
|
register :not_contained_in
|
103
109
|
end
|
@@ -115,20 +121,53 @@ module Parse
|
|
115
121
|
register :select
|
116
122
|
|
117
123
|
def build
|
118
|
-
|
119
|
-
|
120
|
-
|
124
|
+
|
125
|
+
# if it's a hash, then it should be {:key=>"objectId", :query=>[]}
|
126
|
+
remote_field_name = @operation.operand
|
127
|
+
query = nil
|
128
|
+
if @value.is_a?(Hash)
|
129
|
+
res = @value.symbolize_keys
|
130
|
+
remote_field_name = res[:key] || remote_field_name
|
131
|
+
query = res[:query]
|
132
|
+
unless query.is_a?(Parse::Query)
|
133
|
+
raise "Invalid Parse::Query object provided in :query field of value: #{@operation.operand}.#{$dontSelect} => #{@value}"
|
134
|
+
end
|
135
|
+
query = query.compile(encode: false, includeClassName: true)
|
136
|
+
elsif @value.is_a?(Parse::Query)
|
137
|
+
# if its a query, then assume dontSelect key is the same name as operand.
|
138
|
+
query = @value.compile(encode: false, includeClassName: true)
|
139
|
+
else
|
140
|
+
raise "Invalid `:select` query constraint. It should follow the format: :field.select => { key: 'key', query: '<Parse::Query>' }"
|
141
|
+
end
|
142
|
+
{ @operation.operand => { :$select => { key: remote_field_name, query: query } } }
|
121
143
|
end
|
122
144
|
end
|
123
145
|
|
124
146
|
class RejectionConstraint < Constraint
|
125
147
|
#requires that a key's value not match a value for a key in the result of a different query
|
126
148
|
contraint_keyword :$dontSelect
|
149
|
+
register :dont_select
|
127
150
|
register :reject
|
128
151
|
def build
|
129
|
-
|
130
|
-
|
131
|
-
|
152
|
+
|
153
|
+
# if it's a hash, then it should be {:key=>"objectId", :query=>[]}
|
154
|
+
remote_field_name = @operation.operand
|
155
|
+
query = nil
|
156
|
+
if @value.is_a?(Hash)
|
157
|
+
res = @value.symbolize_keys
|
158
|
+
remote_field_name = res[:key] || remote_field_name
|
159
|
+
query = res[:query]
|
160
|
+
unless query.is_a?(Parse::Query)
|
161
|
+
raise "Invalid Parse::Query object provided in :query field of value: #{@operation.operand}.#{$dontSelect} => #{@value}"
|
162
|
+
end
|
163
|
+
query = query.compile(encode: false, includeClassName: true)
|
164
|
+
elsif @value.is_a?(Parse::Query)
|
165
|
+
# if its a query, then assume dontSelect key is the same name as operand.
|
166
|
+
query = @value.compile(encode: false, includeClassName: true)
|
167
|
+
else
|
168
|
+
raise "Invalid `:reject` query constraint. It should follow the format: :field.reject => { key: 'key', query: '<Parse::Query>' }"
|
169
|
+
end
|
170
|
+
{ @operation.operand => { :$dontSelect => { key: remote_field_name, query: query } } }
|
132
171
|
end
|
133
172
|
end
|
134
173
|
|
@@ -186,4 +225,21 @@ module Parse
|
|
186
225
|
|
187
226
|
end
|
188
227
|
|
228
|
+
class WithinGeoBoxQueryConstraint < Constraint
|
229
|
+
contraint_keyword :$within
|
230
|
+
register :within_box
|
231
|
+
|
232
|
+
def build
|
233
|
+
geopoint_values = formatted_value
|
234
|
+
unless geopoint_values.is_a?(Array) && geopoint_values.count == 2 &&
|
235
|
+
geopoint_values.first.is_a?(Parse::GeoPoint) && geopoint_values.last.is_a?(Parse::GeoPoint)
|
236
|
+
raise( '[Parse::Query] Invalid query value parameter passed to `within_box` constraint. ' +
|
237
|
+
'Values in array must be `Parse::GeoPoint` objects and ' +
|
238
|
+
'it should be in an array format: [southwestPoint, northeastPoint]' )
|
239
|
+
end
|
240
|
+
{ @operation.operand => { :$within => { :$box => geopoint_values } } }
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
244
|
+
|
189
245
|
end
|
data/lib/parse/stack.rb
CHANGED
@@ -0,0 +1,107 @@
|
|
1
|
+
require_relative '../stack.rb'
|
2
|
+
require 'active_support'
|
3
|
+
require 'active_support/inflector'
|
4
|
+
require 'active_support/core_ext'
|
5
|
+
require 'rake'
|
6
|
+
require 'rake/dsl_definition'
|
7
|
+
|
8
|
+
module Parse
|
9
|
+
|
10
|
+
module Stack
|
11
|
+
|
12
|
+
def self.load_tasks
|
13
|
+
Parse::Stack::Tasks.new.install_tasks
|
14
|
+
end
|
15
|
+
|
16
|
+
class Tasks
|
17
|
+
include Rake::DSL if defined? Rake::DSL
|
18
|
+
|
19
|
+
def install_tasks
|
20
|
+
|
21
|
+
namespace :parse do
|
22
|
+
|
23
|
+
task :env do
|
24
|
+
if Rake::Task.task_defined?('environment')
|
25
|
+
Rake::Task['environment'].invoke
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
task :verify_env => :env do
|
30
|
+
|
31
|
+
unless Parse::Client.session?
|
32
|
+
raise "Please make sure you have setup the Parse.setup configuration before invoking task. Usually done in the :environment task."
|
33
|
+
end
|
34
|
+
|
35
|
+
endpoint = ENV['HOOKS_URL']
|
36
|
+
unless endpoint.empty? || endpoint.starts_with?('https://')
|
37
|
+
raise "The ENV variable HOOKS_URL must be a <https> url : '#{endpoint}'. Ex. https://12345678.ngrok.io/webhooks"
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
desc "Run auto_upgrade on all of your Parse models."
|
43
|
+
task :upgrade => :env do
|
44
|
+
puts "Auto Upgrading Parse schemas..."
|
45
|
+
Parse.auto_upgrade! do |k|
|
46
|
+
puts "[+] #{k}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
namespace :webhooks do
|
51
|
+
|
52
|
+
desc "Register local webhooks with Parse server"
|
53
|
+
task :register => :verify_env do
|
54
|
+
endpoint = ENV['HOOKS_URL']
|
55
|
+
puts "Registering Parse Webhooks @ #{endpoint}"
|
56
|
+
Rake::Task['parse:webhooks:register:functions'].invoke
|
57
|
+
Rake::Task['parse:webhooks:register:triggers'].invoke
|
58
|
+
end
|
59
|
+
|
60
|
+
desc "Remove all locally registered webhooks from the Parse Application"
|
61
|
+
task :remove => :verify_env do
|
62
|
+
Rake::Task['parse:webhooks:remove:functions'].invoke
|
63
|
+
Rake::Task['parse:webhooks:remove:triggers'].invoke
|
64
|
+
end
|
65
|
+
|
66
|
+
namespace :register do
|
67
|
+
|
68
|
+
task :functions => :verify_env do
|
69
|
+
endpoint = ENV['HOOKS_URL']
|
70
|
+
Parse::Webhooks.register_functions!(endpoint) do |name|
|
71
|
+
puts "[+] function - #{name}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
task :triggers => :verify_env do
|
76
|
+
endpoint = ENV['HOOKS_URL']
|
77
|
+
Parse::Webhooks.register_triggers!(endpoint, {include_wildcard: true}) do |trigger,name|
|
78
|
+
puts "[+] #{trigger.to_s.ljust(12, ' ')} - #{name}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
namespace :remove do
|
85
|
+
|
86
|
+
task :functions => :verify_env do
|
87
|
+
Parse::Webhooks.remove_all_functions! do |name|
|
88
|
+
puts "[-] function - #{name}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
task :triggers => :verify_env do
|
93
|
+
Parse::Webhooks.remove_all_triggers! do |trigger,name|
|
94
|
+
puts "[-] #{trigger.to_s.ljust(12, ' ')} - #{name}"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end # webhooks
|
101
|
+
|
102
|
+
end # webhooks namespace
|
103
|
+
end
|
104
|
+
end # Tasks
|
105
|
+
end # Webhooks
|
106
|
+
|
107
|
+
end # Parse
|
data/lib/parse/stack/version.rb
CHANGED
data/lib/parse/webhooks.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
|
2
1
|
require 'active_model'
|
3
2
|
require 'active_support'
|
4
3
|
require 'active_support/inflector'
|
5
4
|
require 'active_support/core_ext/object'
|
5
|
+
require 'active_support/core_ext'
|
6
6
|
require 'active_model_serializers'
|
7
7
|
require 'rack'
|
8
8
|
require_relative 'client'
|
@@ -90,7 +90,7 @@ module Parse
|
|
90
90
|
class Webhooks
|
91
91
|
|
92
92
|
def self.reload!(args = {})
|
93
|
-
|
93
|
+
|
94
94
|
end
|
95
95
|
|
96
96
|
include Client::Connectable
|