module Devise::Models::Invitable
Invitable
is responsible for sending invitation emails. When an invitation is sent to an email address, an account is created for it. Invitation email contains a link allowing the user to accept the invitation by setting a password (as reset password from Devise’s recoverable module).
Configuration:
invite_for: The period the generated invitation token is valid. After this period, the invited resource won't be able to accept the invitation. When invite_for is 0 (the default), the invitation won't expire.
Examples:
User.find(1).invited_to_sign_up? # => true/false User.invite!(email: 'someone@example.com') # => send invitation User.accept_invitation!(invitation_token: '...') # => accept invitation with a token User.find(1).accept_invitation! # => accept invitation User.find(1).invite! # => reset invitation status and send invitation again
Attributes
Public Class Methods
Source
# File lib/devise_invitable/models.rb, line 146 def self.confirmation_required?; false; end
Source
# File lib/devise_invitable/models.rb, line 77 def self.required_fields(klass) fields = [:invitation_token, :invitation_created_at, :invitation_sent_at, :invitation_accepted_at, :invitation_limit, klass.invited_by_foreign_key || :invited_by_id, :invited_by_type] fields << :invitations_count if defined?(ActiveRecord) && self < ActiveRecord::Base fields -= [:invited_by_type] if klass.invited_by_class_name fields end
Public Instance Methods
Source
# File lib/devise_invitable/models.rb, line 86 def accept_invitation self.invitation_accepted_at = Time.now.utc self.invitation_token = nil end
Accept an invitation by clearing invitation token and and setting invitation_accepted_at
Source
# File lib/devise_invitable/models.rb, line 93 def accept_invitation! if self.invited_to_sign_up? @accepting_invitation = true run_callbacks :invitation_accepted do self.accept_invitation self.confirmed_at ||= self.invitation_accepted_at if self.respond_to?(:confirmed_at=) self.save end.tap do |saved| self.rollback_accepted_invitation if !saved @accepting_invitation = false end end end
Accept an invitation by clearing invitation token and and setting invitation_accepted_at Saves the model and confirms it if model is confirmable, running invitation_accepted callbacks
Source
# File lib/devise_invitable/models.rb, line 134 def accepted_or_not_invited? invitation_accepted? || !invited_to_sign_up? end
Verifies whether a user has accepted an invitation (false when user is accepting it), or was never invited
Source
# File lib/devise_invitable/models.rb, line 124 def accepting_invitation? @accepting_invitation end
Returns true if accept_invitation
! was called
Source
# File lib/devise_invitable/models.rb, line 231 def add_taken_error(key) errors.add(key, :taken) end
Source
# File lib/devise_invitable/models.rb, line 201 def clear_errors_on_valid_keys self.class.invite_key.each do |key, value| self.errors.delete(key) if value === self.send(key) end end
Source
# File lib/devise_invitable/models.rb, line 195 def clear_reset_password_token reset_password_token_present = reset_password_token.present? super accept_invitation! if reset_password_token_present && valid_invitation? end
Source
# File lib/devise_invitable/models.rb, line 219 def confirmation_required_for_invited? respond_to?(:confirmation_required?, true) && confirmation_required? end
Source
# File lib/devise_invitable/models.rb, line 114 def created_by_invite? invitation_created_at.present? end
Verify wheather a user is created by invitation, irrespective to invitation status
Source
# File lib/devise_invitable/models.rb, line 208 def deliver_invitation(options = {}) generate_invitation_token! unless @raw_invitation_token self.update_attribute :invitation_sent_at, Time.now.utc unless self.invitation_sent_at send_devise_notification(:invitation_instructions, @raw_invitation_token, options) end
Deliver the invitation email
Source
# File lib/devise_invitable/models.rb, line 215 def encrypted_invitation_token self.invitation_token end
provide alias to the encrypted invitation_token stored by devise
Source
# File lib/devise_invitable/models.rb, line 129 def invitation_accepted? !accepting_invitation? && invitation_accepted_at.present? end
Verifies whether a user accepted an invitation (false when user is accepting it)
Source
# File lib/devise_invitable/models.rb, line 223 def invitation_due_at return nil if (self.class.invite_for == 0 || self.class.invite_for.nil?) return unless (time = self.invitation_created_at || self.invitation_sent_at) time + self.class.invite_for end
Source
# File lib/devise_invitable/models.rb, line 235 def invitation_taken? !invited_to_sign_up? end
Source
# File lib/devise_invitable/models.rb, line 139 def invite!(invited_by = nil, options = {}) # This is an order-dependant assignment, this can't be moved was_invited = invited_to_sign_up? # Required to workaround confirmable model's confirmation_required? method # being implemented to check for non-nil value of confirmed_at if new_record_and_responds_to?(:confirmation_required?) def self.confirmation_required?; false; end end yield self if block_given? generate_invitation_token if no_token_present_or_skip_invitation? run_callbacks :invitation_created do self.invitation_created_at = Time.now.utc self.invitation_sent_at = self.invitation_created_at unless skip_invitation self.invited_by = invited_by if invited_by # Call these before_validate methods since we aren't validating on save self.downcase_keys if new_record_and_responds_to?(:downcase_keys) self.strip_whitespace if new_record_and_responds_to?(:strip_whitespace) validate = options.key?(:validate) ? options[:validate] : self.class.validate_on_invite if save(validate: validate) self.invited_by.decrement_invitation_limit! if !was_invited and self.invited_by.present? deliver_invitation(options) unless skip_invitation end end end
Reset invitation token and send invitation again
Source
# File lib/devise_invitable/models.rb, line 119 def invited_to_sign_up? accepting_invitation? || (persisted? && invitation_token.present?) end
Verifies whether a user has been invited or not
Source
# File lib/devise_invitable/models.rb, line 187 def password_required? (accepting_invitation? && self.class.require_password_on_accepting) || super end
Enforce password when invitation is being accepted
Source
# File lib/devise_invitable/models.rb, line 107 def rollback_accepted_invitation self.invitation_token = self.invitation_token_was self.invitation_accepted_at = nil self.confirmed_at = nil if self.respond_to?(:confirmed_at=) end
Source
# File lib/devise_invitable/models.rb, line 182 def send_password_change_notification? super && !accepting_invitation? end
Prevent password changed email when accepting invitation
Source
# File lib/devise_invitable/models.rb, line 191 def unauthenticated_message block_from_invitation? ? :invited : super end
Source
# File lib/devise_invitable/models.rb, line 172 def valid_invitation? invited_to_sign_up? && invitation_period_valid? end
Verify whether a invitation is active or not. If the user has been invited, we need to calculate if the invitation time has not expired for this user, in other words, if the invitation is still valid.
Source
# File lib/devise_invitable/models.rb, line 177 def valid_password?(password) super unless !accepting_invitation? && block_from_invitation? end
Only verify password when is not invited
Protected Instance Methods
Source
# File lib/devise_invitable/models.rb, line 241 def block_from_invitation? invited_to_sign_up? end
Source
# File lib/devise_invitable/models.rb, line 271 def generate_invitation_token raw, enc = Devise.token_generator.generate(self.class, :invitation_token) @raw_invitation_token = raw self.invitation_token = enc end
Generates a new random token for invitation, and stores the time this token is being generated
Source
# File lib/devise_invitable/models.rb, line 277 def generate_invitation_token! generate_invitation_token && save(validate: false) end
Source
# File lib/devise_invitable/models.rb, line 264 def invitation_period_valid? time = invitation_created_at || invitation_sent_at self.class.invite_for.to_i.zero? || (time && time.utc >= self.class.invite_for.ago) end
Checks if the invitation for the user is within the limit time. We do this by calculating if the difference between today and the invitation sent date does not exceed the invite for time configured. Invite_for is a model configuration, must always be an integer value.
Example:
# invite_for = 1.day and invitation_sent_at = today invitation_period_valid? # returns true # invite_for = 5.days and invitation_sent_at = 4.days.ago invitation_period_valid? # returns true # invite_for = 5.days and invitation_sent_at = 5.days.ago invitation_period_valid? # returns false # invite_for = nil invitation_period_valid? # will always return true
Source
# File lib/devise_invitable/models.rb, line 281 def new_record_and_responds_to?(method) self.new_record? && self.respond_to?(method, true) end
Source
# File lib/devise_invitable/models.rb, line 285 def no_token_present_or_skip_invitation? self.invitation_token.nil? || (!skip_invitation || @raw_invitation_token.nil?) end