Class: Parse::User

Inherits:
Object show all
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

Attributes inherited from Object

#acl, #created_at, #id, #updated_at

Attributes inherited from Pointer

#id, #parse_class

Class Method Summary collapse

Instance Method Summary collapse

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

#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

belongs_to, #key?

Methods included from Associations::HasOne

has_one

Methods included from Core::ParseReference

format, generate_object_id, parse

Methods included from Core::FieldGuards

#apply_field_guards!

Methods included from Core::EnhancedChangeTracking

included

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

#dirty?, find_class

Methods included from Client::Connectable

#client

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_sessionsArray<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.

Returns:

Version:

  • 1.7.1



224
# File 'lib/parse/model/classes/user.rb', line 224

has_many :active_sessions, as: :session

#auth_dataHash

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.

Returns:

  • (Hash)

    Auth data hash object.



189
# File 'lib/parse/model/classes/user.rb', line 189

property :auth_data, :object

#emailString

Emails are optional in Parse, but if set, they must be unique.

Returns:

  • (String)

    The email field.



194
# File 'lib/parse/model/classes/user.rb', line 194

property :email

#email_verifiedBoolean

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).

Returns:

  • (Boolean)


216
# File 'lib/parse/model/classes/user.rb', line 216

property :email_verified, :boolean

#session_tokenString

Returns The session token if this user is logged in.

Returns:

  • (String)

    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

#usernameString

All Parse users have a username and must be globally unique.

Returns:

  • (String)

    The user’s username.



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.

Parameters:

  • service_name (Symbol)

    the name of the service key (ex. :facebook)

  • auth_data (Hash)

    the specific service data to place in the user’s auth-data for this service.

  • body (Hash) (defaults to: {})

    any additional User related fields or properties when signing up this User record.

Returns:

  • (User)

    a logged in user, or nil.

See Also:



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.

Parameters:

  • body (Hash)

    The hash containing the Parse::User fields. The field ‘username` and `password` are required.

  • opts (Hash)

    a customizable set of options

Options Hash (**opts):

  • :master_key (Boolean)

    Whether the master key should be used for this request.

Returns:

  • (User)

    Returns a successfully created Parse::User.

Raises:



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.

Parameters:

  • username (String)

    the user’s username

  • password (String)

    the user’s password

Returns:

  • (User)

    a logged in user for the provided username. Returns nil otherwise.



639
640
641
642
# File 'lib/parse/model/classes/user.rb', line 639

def self.(username, password)
  response = client.(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.

Examples:

user = Parse::User.first

# pass a user object
Parse::User.request_password_reset user
# or email
Parse::User.request_password_reset("user@example.com")

Parameters:

  • email (String)

    The user’s email address.

Returns:

  • (Boolean)

    True/false if successful.



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.

Returns:

  • (User)

    the user matching this active token, otherwise nil.

See Also:

  • #session!


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.

Returns:

  • (User)

    the user matching this active token

Raises:

  • (InvalidSessionTokenError)

    Invalid session token.

See Also:



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.

See Also:



629
630
631
632
633
# File 'lib/parse/model/classes/user.rb', line 629

def self.(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.

Parameters:

  • body (Hash)

    signup request body, with symbol or string keys.

Returns:

  • (Boolean)


844
845
846
847
848
849
850
851
852
853
854
# File 'lib/parse/model/classes/user.rb', line 844

def self.(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.

Examples:

# User reading their own roles (subject to _Role CLP):
permission_set = (["*", user.id] + user.acl_roles.map { |n| "role:#{n}" }).uniq
# Admin/SDK-internal code building ACL filters:
permission_set = (["*", user.id] + user.acl_roles(master: true).map { |n| "role:#{n}" }).uniq

Parameters:

  • max_depth (Integer) (defaults to: 10)

    maximum BFS depth (default: 10).

  • master (Boolean) (defaults to: false)

    when true, bypass ‘_Role` CLP and run the role-graph lookup under master mode. Use for ACL-building code paths inside the SDK or in admin tooling.

  • as (Parse::User, Parse::Pointer, nil) (defaults to: nil)

    caller-scope. When ‘nil`, defaults to `self` (the user-asking-about-their-own-roles case). Pass a different user to ask “what would this caller see when introspecting this user’s roles?”; the scope’s permission set is checked against ‘_Role` CLP.

Returns:

  • (Set<String>)

    role names (no role: prefix). Empty set when the user has no objectId yet or holds no roles.

Raises:



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_countInteger

Get the count of active (non-expired) sessions for this user.

Examples:

count = user.active_session_count
puts "User is logged in on #{count} devices"

Returns:

  • (Integer)

    the number of active sessions



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).

Returns:

  • (Boolean)

    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_idString

Returns the anonymous identifier only if this user is anonymous.

Returns:

  • (String)

    The anonymous identifier for this anonymous user.

See Also:



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.

Returns:

  • (String)

    The session token or nil if no session was found for this 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

Adds the third-party authentication data to for a given service.

Parameters:

  • service_name (Symbol)

    The name of the service (ex. :facebook)

  • data (Hash)

    The body of the OAuth data. Dependent on each service.

Raises:



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.

Returns:

  • (Boolean)

    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.

Parameters:

  • passwd (String) (defaults to: nil)

    The password for this user.

Returns:

  • (Boolean)

    True/false if we received a valid session token.



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.(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

#logoutBoolean

Invalid the current session token for this logged in user.

Returns:

  • (Boolean)

    True/false if successful



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.

Examples:

# Logout from all devices
user.logout_all!

# Logout from all devices except current
user.logout_all!(keep_current: true)

Parameters:

  • keep_current (Boolean) (defaults to: false)

    if true, keeps the current session active (default: false)

Returns:

  • (Integer)

    the number of sessions revoked



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).

Examples:

if user.multi_session?
  puts "User is logged in on multiple devices"
end

Returns:

  • (Boolean)

    true if user has more than one active session



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!)

Returns:

  • (String)

    The password you set.



202
# File 'lib/parse/model/classes/user.rb', line 202

property :password

#request_password_resetBoolean

Request a password reset for this user

Returns:

  • (Boolean)

    true if it was successful requested. false otherwise.

See Also:



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

#sessionSession

Returns the session corresponding to the user’s session token.

Returns:

  • (Session)

    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

#sessionsArray<Parse::Session>

Get all active sessions for this user.

Examples:

user.sessions.each do |session|
  puts "Session created: #{session.created_at}"
end

Returns:



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

Parameters:

  • passwd (defaults to: nil)

    The user’s password to be used for signing up.

Returns:

  • (Boolean)

    True if signup it was successful. If it fails an exception is thrown.

Raises:



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

   = attribute_updates
  # See {#signup_create} for the rationale on the safe-pattern check.
  if self.class.()
    .except!(:createdAt, :updatedAt, "createdAt", "updatedAt")
  else
    .except!(*Parse::Properties::BASE_FIELD_MAP.flatten)
  end
  self.class.strip_server_controlled_keys!()

  # first signup the user, then save any additional attributes
  response = client.create_user 

  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_saveBoolean

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.

Returns:

  • (Boolean)


178
# File 'lib/parse/model/classes/user.rb', line 178

class_attribute :signup_on_save, instance_writer: false

Removes third-party authentication data for this user

Parameters:

  • service_name (Symbol)

    The name of the third-party service (ex. :facebook)

Returns:

  • (Boolean)

    True/false if successful.

Raises:



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