Class: Parse::User
- Includes:
- MFA::UserExtension
- Defined in:
- lib/parse/model/classes/user.rb,
lib/parse/two_factor_auth/user_extension.rb,
lib/parse/stack/generators/templates/model_user.rb
Overview
Reopen User class to include MFA extension
Constant Summary
Constants inherited from Object
Object::BUILTIN_PARSE_CLASS_NAMES, Object::IDENTIFICATION_FIELDS, Object::VALID_ACL_POLICIES
Constants included from Core::Schema
Core::Schema::DEFAULT_PUBLIC_CLP, Core::Schema::SCHEMA_READONLY_CLASSES
Constants included from Core::Describe
Core::Describe::ALL_SECTIONS, Core::Describe::CORE_FIELD_KEYS, Core::Describe::LOCAL_SECTIONS, Core::Describe::NETWORK_SECTIONS
Constants included from Core::Indexing
Core::Indexing::MAX_INDEXES_PER_COLLECTION, Core::Indexing::PARSE_MANAGED_ARRAY_FIELDS, Core::Indexing::SENSITIVE_FIELDS
Constants included from Core::SearchIndexing
Core::SearchIndexing::ALLOWED_INDEX_TYPES, Core::SearchIndexing::INDEX_NAME_PATTERN
Constants included from Core::Fetching
Core::Fetching::NON_SERIALIZABLE_IVARS
Constants included from Core::ParseReference
Core::ParseReference::OBJECT_ID_LENGTH, Core::ParseReference::SEPARATOR
Constants included from Core::FieldGuards
Core::FieldGuards::GUARD_MODES
Constants included from Properties
Properties::BASE, Properties::BASE_FIELD_MAP, Properties::BASE_KEYS, Properties::CORE_FIELDS, Properties::DELETE_OP, Properties::PROTECTED_INITIALIZE_KEYS, Properties::PROTECTED_MASS_ASSIGNMENT_KEYS, Properties::TYPES
Constants inherited from Pointer
Pointer::ATTRIBUTES, Pointer::OBJECT_ID_FORMAT
Constants inherited from Model
Model::CLASS_AUDIENCE, Model::CLASS_INSTALLATION, Model::CLASS_JOB_SCHEDULE, Model::CLASS_JOB_STATUS, Model::CLASS_PRODUCT, Model::CLASS_PUSH_STATUS, Model::CLASS_ROLE, Model::CLASS_SCHEMA, Model::CLASS_SESSION, Model::CLASS_USER, Model::ID, Model::KEY_CLASS_NAME, Model::KEY_CREATED_AT, Model::KEY_OBJECT_ID, Model::KEY_UPDATED_AT, Model::OBJECT_ID, Model::TYPE_ACL, Model::TYPE_BYTES, Model::TYPE_DATE, Model::TYPE_FIELD, Model::TYPE_FILE, Model::TYPE_GEOPOINT, Model::TYPE_NUMBER, Model::TYPE_OBJECT, Model::TYPE_POINTER, Model::TYPE_POLYGON, Model::TYPE_RELATION
Instance Attribute Summary collapse
-
#active_sessions ⇒ Array<Parse::Session>
A has_many relationship to all Session instances for this user.
-
#auth_data ⇒ Hash
The auth data for this Parse::User.
-
#email ⇒ String
Emails are optional in Parse, but if set, they must be unique.
-
#email_verified ⇒ Boolean
Whether this user’s email address has been verified.
-
#session_token ⇒ String
readonly
The session token if this user is logged in.
-
#username ⇒ String
All Parse users have a username and must be globally unique.
Attributes inherited from Object
#acl, #created_at, #id, #updated_at
Attributes inherited from Pointer
Class Method Summary collapse
-
.autologin_service(service_name, auth_data, body: {}) ⇒ User
Automatically and implicitly signup a user if it did not already exists and authenticates them (login) using third-party authentication data.
-
.create(body, **opts) ⇒ User
Creates a new Parse::User given a hash that maps to the fields defined in your Parse::User collection.
-
.login(username, password) ⇒ User
Login and return a Parse::User with this username/password combination.
-
.request_password_reset(email) ⇒ Boolean
Request a password reset for a registered email.
-
.session(token, opts = {}) ⇒ User
Same as ‘session!` but returns nil if a user was not found or sesion token was invalid.
-
.session!(token, opts = {}) ⇒ User
Return a Parse::User for this active session token.
-
.signup(username, password, email = nil, body: {}) ⇒ Object
This method will signup a new user using the parameters below.
-
.signup_body_self_only_acl_safe?(body) ⇒ Boolean
private
True when the signup-body ‘objectId` and `ACL` together describe the safe self-only ownership pattern that Object.acl_policy produces under `owner: :self`: the body has a client-assigned `objectId` matching the Parse-id format, and the ACL has exactly one entry granting read+write to that same objectId.
Instance Method Summary collapse
-
#acl_roles(max_depth: 10, master: false, as: nil) ⇒ Set<String>
Return the transitive upward closure of role names this user inherits permissions from.
-
#active_session_count ⇒ Integer
Get the count of active (non-expired) sessions for this user.
-
#anonymous? ⇒ Boolean
True if this user is anonymous (i.e. created via the
authData.anonymousprovider rather than via signup with a username/password or a real OAuth provider). -
#anonymous_id ⇒ String
Returns the anonymous identifier only if this user is anonymous.
-
#any_session! ⇒ String
If the current session token for this instance is nil, this method finds the most recent active Parse::Session token for this user and applies it to the instance.
-
#link_auth_data!(service_name, **data) ⇒ Object
Adds the third-party authentication data to for a given service.
-
#logged_in? ⇒ Boolean
True if this user has a session token.
-
#login!(passwd = nil) ⇒ Boolean
Login and get a session token for this user.
-
#logout ⇒ Boolean
Invalid the current session token for this logged in user.
-
#logout_all!(keep_current: false) ⇒ Integer
Logout from all sessions, effectively signing out on all devices.
-
#multi_session? ⇒ Boolean
Check if this user has multiple active sessions (logged in on multiple devices).
-
#password=(value) ⇒ String
You may set a password for this user when you are creating them.
-
#request_password_reset ⇒ Boolean
Request a password reset for this user.
-
#session ⇒ Session
The session corresponding to the user’s session token.
-
#sessions ⇒ Array<Parse::Session>
Get all active sessions for this user.
-
#signup!(passwd = nil) ⇒ Boolean
You may set a password for this user when you are creating them.
-
#signup_on_save ⇒ Boolean
When true (default), saving a new User that has a ‘password` value routes through Parse Server’s signup endpoint (‘POST /parse/users`) with the `X-Parse-Revocable-Session` header set, so the signup response returns a session token that is applied to the in-memory user object via the standard `sessionToken_set_attribute!` hydration path.
-
#unlink_auth_data!(service_name) ⇒ Boolean
Removes third-party authentication data for this user.
Methods included from MFA::UserExtension
#confirm_sms_mfa!, #disable_mfa!, #disable_mfa_admin!, #disable_mfa_master_key!, #login_with_mfa!, #mfa_enabled?, #mfa_provisioning_uri, #mfa_qr_code, #mfa_status, #setup_mfa!, #setup_sms_mfa!
Methods inherited from Object
#[], #[]=, #__type, #_resolve_acl_owner_id, #_resolve_default_acl, #acl_changed?, acl_owner_field, acl_policy, acl_policy_setting, #acl_was, #acl_will_change!, #after_create, #after_destroy, #after_save, #after_update, #after_validation, #apply_defaults!, #around_create, #around_destroy, #around_save, #around_update, #around_validation, #as_json, #autofetch_disabled?, #before_create, #before_destroy, #before_save, #before_update, #before_validation, build, #changed, #changed?, class_permissions, #clear_attribute_change!, #clear_changes!, #clear_partial_fetch_state!, default_acls, describe_access, #disable_autofetch!, #enable_autofetch!, #existed?, fetch_clp, #fetched?, #fetched_keys, #fetched_keys=, #field_was_fetched?, #filter_for_user, filter_results_for_user, #fully_fetched?, #has?, #has_selective_keys?, #initialize, #keys, master_only_class!, #nested_fetched_keys, #nested_fetched_keys=, #nested_keys_for, #new?, #parse_class, #partially_fetched?, #persisted?, pointer, #pretty, private_acl!, protect_fields, #reload!, roles_for_user, #rollback!, #run_after_create_callbacks, #run_after_delete_callbacks, #run_after_save_callbacks, #schema, set_class_access, set_clp, set_default_acl, set_default_clp, set_read_user_fields, set_write_user_fields, #twin, unlistable_class!, update_clp!, #updates, #valid?, #validate!, webhook, webhook_function
Methods included from Core::Querying
#all, #count, #count_distinct, #cursor, #distinct, #each, #find, #find_cached, #first, #last_updated, #latest, #literal_where, #newest, #oldest, #query, #scope, #subscribe
Methods included from Core::Schema
#_default_class_level_permissions_for_upgrade, #auto_upgrade!, #create_schema, #fetch_schema, #reset_clp!, #schema, #update_schema
Methods included from Core::Describe
Methods included from Core::Indexing
#apply_indexes!, #indexes_plan, #mongo_geo_index, #mongo_index, #mongo_index_declarations, #mongo_relation_index
Methods included from Core::SearchIndexing
#apply_search_indexes!, #mongo_search_index, #mongo_search_index_declarations, #search_indexes_plan
Methods included from Agent::MetadataDSL
#agent_description, #agent_methods, included, #property_descriptions, #property_enum_descriptions
Methods included from Core::Actions
#_deleted?, #change_requests, #changes_applied!, #changes_payload, #destroy, #destroy_request, #op_add!, #op_add_relation!, #op_add_unique!, #op_destroy!, #op_increment!, #op_remove!, #op_remove_relation!, #operate_field!, #prepare_save!, #relation_change_operations, #save, #save!, #set_attributes!, #update, #update!, #update_relations, #uri_path
Methods included from Core::Fetching
#autofetch!, #fetch, #fetch!, #fetch_cache!, #fetch_json, #fetch_object, #prepare_for_dirty_tracking!
Methods included from Associations::HasMany
has_many, #relation_changes?, #relation_updates, #relations
Methods included from Associations::BelongsTo
Methods included from Associations::HasOne
Methods included from Core::ParseReference
format, generate_object_id, parse
Methods included from Core::FieldGuards
Methods included from Core::EnhancedChangeTracking
Methods included from Properties
#apply_attributes!, #attribute_changes?, #attribute_updates, #attributes, #attributes=, #field_map, #fields, #format_operation, #format_value
Methods inherited from Pointer
#==, #[], #[]=, #__type, #attributes, #className, #fetch, #fetch_cache!, #fetch_json, #fetch_object, #fetched?, #hash, #initialize, #json_hash, #method_missing, #pointer, #pointer?, #present?, #respond_to_missing?, #sig
Methods inherited from Model
Methods included from Client::Connectable
Constructor Details
This class inherits a constructor from Parse::Object
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Parse::Pointer
Instance Attribute Details
#active_sessions ⇒ Array<Parse::Session>
A has_many relationship to all Session instances for this user. This will query the _Session collection for all sessions which have this user in it’s ‘user` column.
224 |
# File 'lib/parse/model/classes/user.rb', line 224 has_many :active_sessions, as: :session |
#auth_data ⇒ Hash
The auth data for this Parse::User. Depending on how this user is authenticated or logged in, the contents may be different, especially if you are using another third-party authentication mechanism like Facebook/Twitter.
189 |
# File 'lib/parse/model/classes/user.rb', line 189 property :auth_data, :object |
#email ⇒ String
Emails are optional in Parse, but if set, they must be unique.
194 |
# File 'lib/parse/model/classes/user.rb', line 194 property :email |
#email_verified ⇒ Boolean
Whether this user’s email address has been verified. Set by Parse Server when the user follows the verification link delivered by the email adapter, and applied to the in-memory object by #signup! / signup-on-save when the server includes it in the signup response (see SIGNUP_RESPONSE_APPLY_KEYS).
216 |
# File 'lib/parse/model/classes/user.rb', line 216 property :email_verified, :boolean |
#session_token ⇒ String
Returns The session token if this user is logged in.
182 183 184 |
# File 'lib/parse/model/classes/user.rb', line 182 def session_token @session_token end |
#username ⇒ String
All Parse users have a username and must be globally unique.
207 |
# File 'lib/parse/model/classes/user.rb', line 207 property :username |
Class Method Details
.autologin_service(service_name, auth_data, body: {}) ⇒ User
Automatically and implicitly signup a user if it did not already exists and authenticates them (login) using third-party authentication data. May raise exceptions similar to ‘create` depending on what you provide the body parameter.
611 612 613 614 615 616 617 618 619 620 621 |
# File 'lib/parse/model/classes/user.rb', line 611 def self.autologin_service(service_name, auth_data, body: {}) # Trust-mark this call so {.assert_create_body_safe!} permits the # +authData+ that we are explicitly responsible for here. The # marker is consumed inside {.create} before forwarding to the # server. body = body.merge({ authData: { service_name => auth_data }, __parse_stack_trusted_authdata: true, }) self.create(body) end |
.create(body, **opts) ⇒ User
Creates a new Parse::User given a hash that maps to the fields defined in your Parse::User collection.
Mass-assignment of authData/auth_data/objectId is refused. If you intend to create-or-login a user via federated identity, use autologin_service or link_or_create_with_auth_data. Passing those keys directly bypasses the SDK’s federated-identity wrapper and risks returning a victim’s sessionToken to whoever submitted the request.
540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 |
# File 'lib/parse/model/classes/user.rb', line 540 def self.create(body, **opts) # Consume and clear the SDK-internal trust marker before validation # or wire transit. This prevents trusted-authdata flag smuggling # through callers that copy hashes from a request parameter. trusted = body.is_a?(Hash) ? (body.delete(:__parse_stack_trusted_authdata) || body.delete("__parse_stack_trusted_authdata")) : false assert_create_body_safe!(body) unless trusted strip_server_controlled_keys!(body) response = client.create_user(body, opts: opts) if response.success? body.delete :password # clear password before merging return Parse::User.build body.merge(response.result) end case response.code when Parse::Response::ERROR_USERNAME_MISSING raise Parse::Error::UsernameMissingError, response when Parse::Response::ERROR_PASSWORD_MISSING raise Parse::Error::PasswordMissingError, response when Parse::Response::ERROR_USERNAME_TAKEN raise Parse::Error::UsernameTakenError, response when Parse::Response::ERROR_EMAIL_TAKEN raise Parse::Error::EmailTakenError, response end raise Parse::Client::ResponseError, response end |
.login(username, password) ⇒ User
Login and return a Parse::User with this username/password combination.
639 640 641 642 |
# File 'lib/parse/model/classes/user.rb', line 639 def self.login(username, password) response = client.login(username.to_s, password.to_s) response.success? ? Parse::User.build(response.result) : nil end |
.request_password_reset(email) ⇒ Boolean
Request a password reset for a registered email.
654 655 656 657 658 659 |
# File 'lib/parse/model/classes/user.rb', line 654 def self.request_password_reset(email) email = email.email if email.is_a?(Parse::User) return false if email.blank? response = client.request_password_reset(email) response.success? end |
.session(token, opts = {}) ⇒ User
Same as ‘session!` but returns nil if a user was not found or sesion token was invalid.
664 665 666 667 668 |
# File 'lib/parse/model/classes/user.rb', line 664 def self.session(token, opts = {}) self.session! token, opts rescue Parse::Error::InvalidSessionTokenError nil end |
.session!(token, opts = {}) ⇒ User
Return a Parse::User for this active session token.
674 675 676 677 678 679 |
# File 'lib/parse/model/classes/user.rb', line 674 def self.session!(token, opts = {}) # support Parse::Session objects token = token.session_token if token.respond_to?(:session_token) response = client.current_user(token, **opts) response.success? ? Parse::User.build(response.result) : nil end |
.signup(username, password, email = nil, body: {}) ⇒ Object
This method will signup a new user using the parameters below. The required fields to create a user in Parse is the username and password fields. The email field is optional. Both username and email (if provided), must be unique. At a minimum, it is recommended you perform a query using the supplied username first to verify do not already have an account with that username. This method will raise all the exceptions from the similar ‘create` method.
629 630 631 632 633 |
# File 'lib/parse/model/classes/user.rb', line 629 def self.signup(username, password, email = nil, body: {}) body = body.merge({ username: username, password: password }) body[:email] = email if email.present? self.create(body) end |
.signup_body_self_only_acl_safe?(body) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
True when the signup-body ‘objectId` and `ACL` together describe the safe self-only ownership pattern that Object.acl_policy produces under `owner: :self`: the body has a client-assigned `objectId` matching the Parse-id format, and the ACL has exactly one entry granting read+write to that same objectId. Any deviation — multiple keys, a non-self key, a `*` (public) entry, a `role:` entry, missing or extra permissions — fails the check and the strip-everything fallback in #signup_create / #signup! runs as before.
844 845 846 847 848 849 850 851 852 853 854 |
# File 'lib/parse/model/classes/user.rb', line 844 def self.signup_body_self_only_acl_safe?(body) return false unless body.is_a?(Hash) oid = body[:objectId] || body["objectId"] acl = body[:ACL] || body["ACL"] return false unless oid.is_a?(String) && oid.match?(PARSE_OBJECT_ID_FORMAT) return false unless acl.is_a?(Hash) && acl.size == 1 perms = acl[oid] || acl[oid.to_s] return false unless perms.is_a?(Hash) normalized = perms.transform_keys(&:to_s) normalized == { "read" => true, "write" => true } end |
Instance Method Details
#acl_roles(max_depth: 10, master: false, as: nil) ⇒ Set<String>
Return the transitive upward closure of role names this user inherits permissions from.
## Authorization
The role graph is privileged data: Parse Server’s ‘_Role` class ships with `acl_policy :private` precisely so anonymous clients cannot enumerate role memberships. This method therefore routes through the mongo-direct fast path under an EXPLICIT authorization scope.
By default, ‘as:` is set to `self` — the user instance itself, meaning “I (this user) am asking about my own roles”. The scope is resolved via ACLScope and CLP is enforced against `_Role`: the call succeeds iff the user’s permission set (‘[“*”, user.id, “role:…”]`) is permitted to `find` on `_Role`. Under Parse Server’s default ‘_Role` CLP (master-only, which Role’s ‘acl_policy :private` does not change), the user’s scope is NOT permitted, so this call raises CLPScope::Denied. Apps that have explicitly opened ‘_Role` CLP for authenticated users (e.g. `find: { requiresAuthentication: true }`) will have the call succeed.
Callers performing privileged work (computing ACL permission sets, e.g. server-side filters) should pass ‘master: true` to bypass the CLP check.
**Breaking change:** Previously this method bypassed the authorization check entirely (callers could construct a ‘Parse::User` with any objectId via `Parse::User.new.tap { |u| u.id = victim_id }` and enumerate the victim’s roles). The new contract is explicit-auth-required; use ‘master: true` for the previous behavior.
800 801 802 803 804 805 806 807 808 809 810 |
# File 'lib/parse/model/classes/user.rb', line 800 def acl_roles(max_depth: 10, master: false, as: nil) return Set.new unless id.is_a?(String) && !id.empty? # Default `as:` to self so the common "user reading their own # roles" case works without ceremony when _Role CLP permits the # user. The CLP check + scope resolution happens inside # Parse::Role.all_for_user → Parse::MongoDB.role_names_for_user. effective_as = as.nil? && master != true ? self : as Parse::Role.all_for_user( self, max_depth: max_depth, master: master, as: effective_as, ) end |
#active_session_count ⇒ Integer
Get the count of active (non-expired) sessions for this user.
722 723 724 725 |
# File 'lib/parse/model/classes/user.rb', line 722 def active_session_count return 0 unless id.present? Parse::Session.active_count_for_user(self) end |
#anonymous? ⇒ Boolean
Returns true if this user is anonymous (i.e. created via the authData.anonymous provider rather than via signup with a username/password or a real OAuth provider).
251 252 253 |
# File 'lib/parse/model/classes/user.rb', line 251 def anonymous? !anonymous_id.nil? end |
#anonymous_id ⇒ String
Returns the anonymous identifier only if this user is anonymous.
258 259 260 |
# File 'lib/parse/model/classes/user.rb', line 258 def anonymous_id auth_data["anonymous"]["id"] if auth_data.present? && auth_data["anonymous"].is_a?(Hash) end |
#any_session! ⇒ String
If the current session token for this instance is nil, this method finds the most recent active Parse::Session token for this user and applies it to the instance. The user instance will now be authenticated and logged in with the selected session token. Useful if you need to call save or destroy methods on behalf of a logged in user.
686 687 688 689 690 691 692 |
# File 'lib/parse/model/classes/user.rb', line 686 def any_session! unless @session_token.present? _active_session = active_sessions(restricted: false, order: :updated_at.desc).first self.session_token = _active_session.session_token if _active_session.present? end @session_token end |
#link_auth_data!(service_name, **data) ⇒ Object
Adds the third-party authentication data to for a given service.
266 267 268 269 270 |
# File 'lib/parse/model/classes/user.rb', line 266 def link_auth_data!(service_name, **data) response = client.set_service_auth_data(id, service_name, data) raise Parse::Client::ResponseError, response if response.error? apply_attributes!(response.result) end |
#logged_in? ⇒ Boolean
Returns true if this user has a session token.
291 292 293 |
# File 'lib/parse/model/classes/user.rb', line 291 def logged_in? self.session_token.present? end |
#login!(passwd = nil) ⇒ Boolean
Login and get a session token for this user.
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 |
# File 'lib/parse/model/classes/user.rb', line 418 def login!(passwd = nil) self.password = passwd || self.password response = client.login(username.to_s, password.to_s) if response.success? # Unlike signup, login's response is the canonical state of an # existing user, including any linked authData. Applying the # full response body here is intentional -- the server is # telling us what the account currently looks like. (Compare # signup, where we narrow to an allow-list because a brand-new # account has no legitimate authData to report.) apply_attributes! response.result # Drop the plaintext password from memory now that the login # has succeeded. Direct ivar assignment so the dirty tracker # doesn't record this clear as a pending change. @password = nil # Clear dirty state so a subsequent user.save! does not re-send # `password` (which Parse Server would treat as a password # change and use to revoke the session this login just issued). # See the matching note in #signup!. changes_applied! clear_partial_fetch_state! end self.session_token.present? end |
#logout ⇒ Boolean
Invalid the current session token for this logged in user.
445 446 447 448 449 450 451 452 |
# File 'lib/parse/model/classes/user.rb', line 445 def logout return true if self.session_token.blank? client.logout session_token self.session_token = nil true rescue false end |
#logout_all!(keep_current: false) ⇒ Integer
Logout from all sessions, effectively signing out on all devices. Optionally keep the current session active.
708 709 710 711 712 713 714 715 |
# File 'lib/parse/model/classes/user.rb', line 708 def logout_all!(keep_current: false) return 0 unless id.present? except_token = keep_current ? @session_token : nil count = Parse::Session.revoke_all_for_user(self, except: except_token) @session_token = nil unless keep_current @session = nil unless keep_current count end |
#multi_session? ⇒ Boolean
Check if this user has multiple active sessions (logged in on multiple devices).
744 745 746 |
# File 'lib/parse/model/classes/user.rb', line 744 def multi_session? active_session_count > 1 end |
#password=(value) ⇒ String
You may set a password for this user when you are creating them. Parse never returns a Parse::User’s password when a record is fetched. Therefore, normally this getter is nil. While this API exists, it is recommended you use either the #login! or #signup! methods. (see #login!)
202 |
# File 'lib/parse/model/classes/user.rb', line 202 property :password |
#request_password_reset ⇒ Boolean
Request a password reset for this user
298 299 300 301 |
# File 'lib/parse/model/classes/user.rb', line 298 def request_password_reset return false if email.nil? Parse::User.request_password_reset(email) end |
#session ⇒ Session
Returns the session corresponding to the user’s session token.
461 462 463 464 465 466 467 468 469 470 471 472 |
# File 'lib/parse/model/classes/user.rb', line 461 def session if @session.blank? && @session_token.present? response = client.fetch_session(@session_token) # Trusted hydration: +response.result+ is the server-side # _Session row, which legitimately includes +sessionToken+, # +createdAt+, +updatedAt+, and other protected keys. Route # through {Parse::Object.build} which handles the trusted-init # signalling. @session ||= Parse::Object.build(response.result, Parse::Model::CLASS_SESSION) end @session end |
#sessions ⇒ Array<Parse::Session>
Get all active sessions for this user.
733 734 735 736 |
# File 'lib/parse/model/classes/user.rb', line 733 def sessions return [] unless id.present? Parse::Session.for_user(self).all end |
#signup!(passwd = nil) ⇒ Boolean
You may set a password for this user when you are creating them. Parse never returns a
312 313 314 315 316 317 318 319 320 321 322 323 324 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 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 |
# File 'lib/parse/model/classes/user.rb', line 312 def signup!(passwd = nil) self.password = passwd || password if username.blank? raise Parse::Error::UsernameMissingError, "Signup requires a username." end if password.blank? raise Parse::Error::PasswordMissingError, "Signup requires a password." end signup_attrs = attribute_updates # See {#signup_create} for the rationale on the safe-pattern check. if self.class.signup_body_self_only_acl_safe?(signup_attrs) signup_attrs.except!(:createdAt, :updatedAt, "createdAt", "updatedAt") else signup_attrs.except!(*Parse::Properties::BASE_FIELD_MAP.flatten) end self.class.strip_server_controlled_keys!(signup_attrs) # first signup the user, then save any additional attributes response = client.create_user signup_attrs if response.success? # Restrict what the server can plant into the in-memory user via # the signup response, matching the defense in {#signup_create}. # `POST /parse/users` legitimately returns objectId, createdAt, # updatedAt (extracted into @-vars directly below), sessionToken, # and emailVerified. Any other key in the response body -- # `authData`, `_rperm`, `_wperm`, `roles`, etc. -- is dropped, so # a compromised or MITM'd Parse Server cannot use this code path # to plant credentials/permissions onto the user we just signed # up. The previous `apply_attributes! response.result` accepted # every key the server returned through the typed property # writers (`authData_set_attribute!` exists because we declare # `property :auth_data, :object`), which was a footgun the # save-as-signup path had already addressed. result = response.result @id = result[Parse::Model::OBJECT_ID] || @id @created_at = result["createdAt"] || @created_at @updated_at = result["updatedAt"] || result["createdAt"] || @updated_at set_attributes!(result.slice(*SIGNUP_RESPONSE_APPLY_KEYS)) # Drop the plaintext password from memory now that the server # has it hashed and we no longer need it. Matches the Parse JS # SDK behavior of clearing the password attribute after a # successful save/signup. Uses direct ivar assignment so the # dirty tracker doesn't record this clear as a pending change # that would be re-sent on the next save. @password = nil # Mirror Parse::Object#save: a successful round-trip means the # locally-set credential fields are now in sync with the server # and must NOT be re-sent on the next save. Without this, a # subsequent user.save! re-transmits `password`, which Parse # Server treats as a password change under # revokeSessionOnPasswordReset and revokes the session just # minted by this signup. changes_applied! clear_partial_fetch_state! return true end case response.code when Parse::Response::ERROR_USERNAME_MISSING raise Parse::Error::UsernameMissingError, response when Parse::Response::ERROR_PASSWORD_MISSING raise Parse::Error::PasswordMissingError, response when Parse::Response::ERROR_USERNAME_TAKEN raise Parse::Error::UsernameTakenError, response when Parse::Response::ERROR_EMAIL_TAKEN raise Parse::Error::EmailTakenError, response when Parse::Response::ERROR_EMAIL_INVALID raise Parse::Error::InvalidEmailAddress, response end raise Parse::Client::ResponseError, response end |
#signup_on_save ⇒ Boolean
When true (default), saving a new Parse::User that has a ‘password` value routes through Parse Server’s signup endpoint (‘POST /parse/users`) with the `X-Parse-Revocable-Session` header set, so the signup response returns a session token that is applied to the in-memory user object via the standard `sessionToken_set_attribute!` hydration path. Without this flag, `Parse::User.new(…).save!` left `session_token` `nil` because the underlying create path did not request a revocable session.
Set to ‘false` to always create users without requesting a revocable session token - for example, when a master-key server-side script is provisioning user rows that will receive credentials later. New users created with no password always fall through to the standard create path regardless of this flag.
‘auth_data` (federated identity / OAuth) signup is deliberately NOT triggered by this flag. `POST /parse/users` treats `auth_data` as a claim against an existing account, so allowing mass-assigned `auth_data` to trigger a revocable-session signup would let attacker-controlled params plant another user’s session token onto the in-memory object. Use autologin_service or signup (the explicit class methods) for OAuth-driven signup; both bypass the mass-assignment filter because the caller is explicitly choosing the federated-identity flow.
Inherited through subclasses via ActiveSupport::Concern‘s `class_attribute`, so an application-specific subclass may override the default without affecting `Parse::User` itself.
178 |
# File 'lib/parse/model/classes/user.rb', line 178 class_attribute :signup_on_save, instance_writer: false |
#unlink_auth_data!(service_name) ⇒ Boolean
Removes third-party authentication data for this user
276 277 278 279 280 |
# File 'lib/parse/model/classes/user.rb', line 276 def unlink_auth_data!(service_name) response = client.set_service_auth_data(id, service_name, nil) raise Parse::Client::ResponseError, response if response.error? apply_attributes!(response.result) end |