Class: Parse::Webhooks::Payload
- Inherits:
-
Object
- Object
- Parse::Webhooks::Payload
- Includes:
- ActiveModel::Serializers::JSON
- Defined in:
- lib/parse/webhooks/payload.rb
Overview
Represents the data structure that Parse server sends to a registered webhook. Parse Parse allows you to receive Cloud Code webhooks on your own hosted server. The ‘Parse::Webhooks` class is a lightweight Rack application that routes incoming Cloud Code webhook requests and payloads to locally registered handlers. The payloads are Payload type of objects that represent that data that Parse sends webhook handlers.
Constant Summary collapse
- ATTRIBUTES =
The set of keys that can be contained in a Parse hash payload for a webhook.
{ master: nil, user: nil, installationId: nil, params: nil, functionName: nil, object: nil, original: nil, update: nil, query: nil, log: nil, objects: nil, triggerName: nil }.freeze
Instance Attribute Summary collapse
-
#function_name ⇒ String
(also: #functionName)
The name of the function.
-
#installation_id ⇒ String
(also: #installationId)
The identifier of the device that submitted the request.
-
#log ⇒ Object
The query request in a beforeFind trigger.
-
#master ⇒ Boolean
Whether the master key was used for this request.
-
#object ⇒ Hash
In a beforeSave, this attribute is the final object that will be persisted.
-
#objects ⇒ Object
The query request in a beforeFind trigger.
-
#original ⇒ Hash
In a beforeSave, for previously saved objects, this attribute is the Parse::Object that was previously in the persistent store.
-
#params ⇒ Hash
The list of function arguments submitted for a function request.
-
#query ⇒ Object
The query request in a beforeFind trigger.
-
#raw ⇒ Hash
The raw payload from Parse server.
-
#trigger_name ⇒ String
(also: #triggerName)
The name of the trigger (ex. beforeSave, afterSave, etc.).
-
#update ⇒ Hash
The update payload in the request.
-
#user ⇒ Parse::User
The user who performed this request or action.
Instance Method Summary collapse
-
#after_delete? ⇒ Boolean
true if this is a afterDelete webhook trigger request.
-
#after_find? ⇒ Boolean
true if this is a afterFind webhook trigger request.
-
#after_save? ⇒ Boolean
true if this is a afterSave webhook trigger request.
-
#after_trigger? ⇒ Boolean
true if this is a afterSave or afterDelete webhook trigger request.
- #attributes ⇒ ATTRIBUTES
-
#before_delete? ⇒ Boolean
true if this is a beforeDelete webhook trigger request.
-
#before_find? ⇒ Boolean
true if this is a beforeFind webhook trigger request.
-
#before_save? ⇒ Boolean
true if this is a beforeSave webhook trigger request.
-
#before_trigger? ⇒ Boolean
true if this is a beforeSave or beforeDelete webhook trigger request.
-
#client_initiated? ⇒ Boolean
Returns true if this webhook was triggered by a client request (JavaScript, iOS, Android, etc.) This is the inverse of ruby_initiated? and is useful for callback logic that should only run for client-initiated operations.
-
#error!(msg = "") ⇒ Parse::Webhooks::ResponseError
This method will intentionally raise a ResponseError with a specific message.
-
#function? ⇒ Boolean
true if this is a webhook function request.
-
#initialize(hash = {}) ⇒ Payload
constructor
You would normally never create a Payload object since it is automatically provided to you when using Parse::Webhooks.
-
#master? ⇒ Boolean
true if the master key was used for this request.
-
#object? ⇒ Boolean
true if this request is a trigger that contains an object.
-
#original_parse_object ⇒ Parse::Object
A Parse::Object from the original object.
-
#parse_class ⇒ String
The name of the Parse class for this request.
-
#parse_id ⇒ String
(also: #objectId)
The objectId in this request.
-
#parse_object(pristine = false) ⇒ Parse::Object
This method returns a Parse::Object by combining the original object, if was provided, with the final object.
-
#parse_query ⇒ Parse::Query
The Parse query for a beforeFind trigger.
-
#ruby_initiated? ⇒ Boolean
Returns true if this webhook was triggered by a Ruby Parse Stack request.
-
#trigger? ⇒ Boolean
true if this is a webhook trigger request.
-
#wlog(s) ⇒ Object
Method to print to standard that utilizes the an internal id to make it easier to trace incoming requests.
Constructor Details
#initialize(hash = {}) ⇒ Payload
You would normally never create a Parse::Webhooks::Payload object since it is automatically provided to you when using Parse::Webhooks.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/parse/webhooks/payload.rb', line 76 def initialize(hash = {}) hash = JSON.parse(hash, max_nesting: 20) if hash.is_a?(String) hash = Hash[hash.map { |k, v| [k.to_s.underscore.to_sym, v] }] @raw = hash @master = hash[:master] # Strip protected mass-assignment keys (sessionToken, _rperm, _wperm, # _hashed_password, authData, roles, etc.) BEFORE constructing the # user object. Without this, an attacker reaching the webhook # endpoint with a valid key (or with the optional unauthenticated # mode enabled) can forge any of these fields on +payload.user+ # via the +objectId+-present hydration branch that bypasses the # +Parse::Object#apply_attributes!+ protected-key filter. if hash[:user].present? @user = Parse::User.new(self.class.scrub_protected_keys(hash[:user])) end @installation_id = hash[:installation_id] @params = hash[:params] @params = @params.with_indifferent_access if @params.is_a?(Hash) @function_name = hash[:function_name] @object = self.class.scrub_protected_keys(hash[:object]) @trigger_name = hash[:trigger_name] @original = self.class.scrub_protected_keys(hash[:original]) @update = self.class.scrub_protected_keys(hash[:update]) || {} # Added for beforeFind and afterFind triggers @query = hash[:query] @objects = hash[:objects] || [] @log = hash[:log] end |
Instance Attribute Details
#function_name ⇒ String Also known as: functionName
Returns the name of the function.
64 |
# File 'lib/parse/webhooks/payload.rb', line 64 attr_accessor :master, :user, :installation_id, :params, :function_name, :object, :trigger_name |
#installation_id ⇒ String Also known as: installationId
Returns The identifier of the device that submitted the request.
64 |
# File 'lib/parse/webhooks/payload.rb', line 64 attr_accessor :master, :user, :installation_id, :params, :function_name, :object, :trigger_name |
#log ⇒ Object
The query request in a beforeFind trigger. Available in Parse Server 2.3.1 or later.
@return [Parse::Query]
The set of matching objects in an afterFind trigger. Available in Parse Server 2.3.1 or later.
@return [<Parse::Object>]
Logging information if available. Available in Parse Server 2.3.1 or later.
@return [Hash] the set of matching objects in an afterFind trigger.
64 |
# File 'lib/parse/webhooks/payload.rb', line 64 attr_accessor :master, :user, :installation_id, :params, :function_name, :object, :trigger_name |
#master ⇒ Boolean
Returns whether the master key was used for this request.
64 65 66 |
# File 'lib/parse/webhooks/payload.rb', line 64 def master @master end |
#object ⇒ Hash
In a beforeSave, this attribute is the final object that will be persisted.
64 |
# File 'lib/parse/webhooks/payload.rb', line 64 attr_accessor :master, :user, :installation_id, :params, :function_name, :object, :trigger_name |
#objects ⇒ Object
The query request in a beforeFind trigger. Available in Parse Server 2.3.1 or later.
@return [Parse::Query]
The set of matching objects in an afterFind trigger. Available in Parse Server 2.3.1 or later.
@return [<Parse::Object>]
Logging information if available. Available in Parse Server 2.3.1 or later.
@return [Hash] the set of matching objects in an afterFind trigger.
64 |
# File 'lib/parse/webhooks/payload.rb', line 64 attr_accessor :master, :user, :installation_id, :params, :function_name, :object, :trigger_name |
#original ⇒ Hash
In a beforeSave, for previously saved objects, this attribute is the Parse::Object that was previously in the persistent store.
64 |
# File 'lib/parse/webhooks/payload.rb', line 64 attr_accessor :master, :user, :installation_id, :params, :function_name, :object, :trigger_name |
#params ⇒ Hash
Returns The list of function arguments submitted for a function request.
64 |
# File 'lib/parse/webhooks/payload.rb', line 64 attr_accessor :master, :user, :installation_id, :params, :function_name, :object, :trigger_name |
#query ⇒ Object
The query request in a beforeFind trigger. Available in Parse Server 2.3.1 or later.
@return [Parse::Query]
The set of matching objects in an afterFind trigger. Available in Parse Server 2.3.1 or later.
@return [<Parse::Object>]
Logging information if available. Available in Parse Server 2.3.1 or later.
@return [Hash] the set of matching objects in an afterFind trigger.
64 |
# File 'lib/parse/webhooks/payload.rb', line 64 attr_accessor :master, :user, :installation_id, :params, :function_name, :object, :trigger_name |
#raw ⇒ Hash
Returns the raw payload from Parse server.
64 |
# File 'lib/parse/webhooks/payload.rb', line 64 attr_accessor :master, :user, :installation_id, :params, :function_name, :object, :trigger_name |
#trigger_name ⇒ String Also known as: triggerName
Returns the name of the trigger (ex. beforeSave, afterSave, etc.).
64 |
# File 'lib/parse/webhooks/payload.rb', line 64 attr_accessor :master, :user, :installation_id, :params, :function_name, :object, :trigger_name |
#update ⇒ Hash
Returns the update payload in the request.
64 |
# File 'lib/parse/webhooks/payload.rb', line 64 attr_accessor :master, :user, :installation_id, :params, :function_name, :object, :trigger_name |
#user ⇒ Parse::User
Returns the user who performed this request or action.
64 |
# File 'lib/parse/webhooks/payload.rb', line 64 attr_accessor :master, :user, :installation_id, :params, :function_name, :object, :trigger_name |
Instance Method Details
#after_delete? ⇒ Boolean
true if this is a afterDelete webhook trigger request.
201 202 203 |
# File 'lib/parse/webhooks/payload.rb', line 201 def after_delete? trigger? && @trigger_name.to_sym == :afterDelete end |
#after_find? ⇒ Boolean
true if this is a afterFind webhook trigger request.
211 212 213 |
# File 'lib/parse/webhooks/payload.rb', line 211 def after_find? trigger? && @trigger_name.to_sym == :afterFind end |
#after_save? ⇒ Boolean
true if this is a afterSave webhook trigger request.
191 192 193 |
# File 'lib/parse/webhooks/payload.rb', line 191 def after_save? trigger? && @trigger_name.to_sym == :afterSave end |
#after_trigger? ⇒ Boolean
true if this is a afterSave or afterDelete webhook trigger request.
181 182 183 |
# File 'lib/parse/webhooks/payload.rb', line 181 def after_trigger? after_save? || after_delete? || after_find? end |
#attributes ⇒ ATTRIBUTES
130 131 132 |
# File 'lib/parse/webhooks/payload.rb', line 130 def attributes ATTRIBUTES end |
#before_delete? ⇒ Boolean
true if this is a beforeDelete webhook trigger request.
196 197 198 |
# File 'lib/parse/webhooks/payload.rb', line 196 def before_delete? trigger? && @trigger_name.to_sym == :beforeDelete end |
#before_find? ⇒ Boolean
true if this is a beforeFind webhook trigger request.
206 207 208 |
# File 'lib/parse/webhooks/payload.rb', line 206 def before_find? trigger? && @trigger_name.to_sym == :beforeFind end |
#before_save? ⇒ Boolean
true if this is a beforeSave webhook trigger request.
186 187 188 |
# File 'lib/parse/webhooks/payload.rb', line 186 def before_save? trigger? && @trigger_name.to_sym == :beforeSave end |
#before_trigger? ⇒ Boolean
true if this is a beforeSave or beforeDelete webhook trigger request.
176 177 178 |
# File 'lib/parse/webhooks/payload.rb', line 176 def before_trigger? before_save? || before_delete? || before_find? end |
#client_initiated? ⇒ Boolean
Returns true if this webhook was triggered by a client request (JavaScript, iOS, Android, etc.) This is the inverse of ruby_initiated? and is useful for callback logic that should only run for client-initiated operations.
355 356 357 |
# File 'lib/parse/webhooks/payload.rb', line 355 def client_initiated? !ruby_initiated? end |
#error!(msg = "") ⇒ Parse::Webhooks::ResponseError
This method will intentionally raise a ResponseError with a specific message. When used inside of a registered cloud code webhook function or trigger, will halt processing and return the proper error response code back to the Parse server.
310 311 312 |
# File 'lib/parse/webhooks/payload.rb', line 310 def error!(msg = "") raise Parse::Webhooks::ResponseError, msg end |
#function? ⇒ Boolean
true if this is a webhook function request.
146 147 148 |
# File 'lib/parse/webhooks/payload.rb', line 146 def function? @function_name.present? end |
#master? ⇒ Boolean
true if the master key was used for this request.
151 152 153 |
# File 'lib/parse/webhooks/payload.rb', line 151 def master? @master.present? end |
#object? ⇒ Boolean
true if this request is a trigger that contains an object.
216 217 218 |
# File 'lib/parse/webhooks/payload.rb', line 216 def object? trigger? && @object.present? end |
#original_parse_object ⇒ Parse::Object
Returns a Parse::Object from the original object.
221 222 223 224 225 226 227 |
# File 'lib/parse/webhooks/payload.rb', line 221 def original_parse_object return nil unless @original.is_a?(Hash) # Always pass the trigger's expected class explicitly so the # className inside the payload cannot redirect this hydration to a # different class. Parse::Object.build(@original, parse_class) end |
#parse_class ⇒ String
Returns the name of the Parse class for this request.
156 157 158 159 160 |
# File 'lib/parse/webhooks/payload.rb', line 156 def parse_class return @webhook_class if @webhook_class.present? return nil unless @object.present? @object[Parse::Model::KEY_CLASS_NAME] || @object[:className] end |
#parse_id ⇒ String Also known as: objectId
Returns the objectId in this request.
163 164 165 166 |
# File 'lib/parse/webhooks/payload.rb', line 163 def parse_id return nil unless @object.present? @object[Parse::Model::OBJECT_ID] || @object[:objectId] end |
#parse_object(pristine = false) ⇒ Parse::Object
This method returns a Parse::Object by combining the original object, if was provided, with the final object. This will return a dirty tracked Parse::Object subclass, that will have information on which fields have changed between the previous state in the persistent store and the one about to be saved.
235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/parse/webhooks/payload.rb', line 235 def parse_object(pristine = false) return nil unless object? return Parse::Object.build(@object, parse_class) if pristine # Memoize so pre-block guard application and the user webhook handler # observe the same instance. Otherwise field_guards applied on the # framework's pre-built object would be invisible to the block's # later parse_object call (which would construct a fresh dirty-tracked # object from @object/@original). return @parse_object if defined?(@parse_object) && !@parse_object.nil? @parse_object = build_parse_object end |
#parse_query ⇒ Parse::Query
Returns the Parse query for a beforeFind trigger.
315 316 317 318 |
# File 'lib/parse/webhooks/payload.rb', line 315 def parse_query return nil unless parse_class.present? && @query.is_a?(Hash) Parse::Query.new parse_class, @query end |
#ruby_initiated? ⇒ Boolean
Returns true if this webhook was triggered by a Ruby Parse Stack request. This is determined by checking for the ‘RB’ prefix in the request ID header. This flag is useful for preventing callback loops and implementing intelligent callback handling based on the request origin.
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 |
# File 'lib/parse/webhooks/payload.rb', line 325 def ruby_initiated? @ruby_initiated ||= begin request_id = nil if @raw.respond_to?(:[]) # Check for headers at the top level first request_id = @raw["x-parse-request-id"] || @raw["X-Parse-Request-Id"] || @raw[:x_parse_request_id] || @raw[:'X-Parse-Request-Id'] # If not found at top level, check nested headers if request_id.nil? headers_sym = @raw[:headers] if @raw[:headers].is_a?(Hash) headers_str = @raw["headers"] if @raw["headers"].is_a?(Hash) if headers_sym request_id = headers_sym["x-parse-request-id"] || headers_sym["X-Parse-Request-Id"] elsif headers_str request_id = headers_str["x-parse-request-id"] || headers_str["X-Parse-Request-Id"] end end end request_id&.start_with?("_RB_") || false end end |
#trigger? ⇒ Boolean
true if this is a webhook trigger request.
171 172 173 |
# File 'lib/parse/webhooks/payload.rb', line 171 def trigger? @trigger_name.present? end |
#wlog(s) ⇒ Object
Method to print to standard that utilizes the an internal id to make it easier to trace incoming requests.
136 137 138 139 140 141 142 143 |
# File 'lib/parse/webhooks/payload.rb', line 136 def wlog(s) # generates a unique random number in order to be used in logging. This # is useful when debugging issues in production where one server instance # may be running multiple threads and you want to trace the incoming call. @rid ||= rand(999).to_s.rjust(3) puts "[> #{@rid}] #{s}" @rid end |