mirror of
https://github.com/we-promise/sure.git
synced 2026-04-07 14:31:25 +00:00
* First cut of a simplified "intro" UI layout * Linter * Add guest role and intro-only access * Fix guest role UI defaults (#940) Use enum predicate to avoid missing role helper. * Remove legacy user role mapping (#941) Drop the unused user role references in role normalization and SSO role mapping forms to avoid implying a role that never existed. Refs: #0 * Remove role normalization (#942) Remove role normalization Roles are now stored directly without legacy mappings. * Revert role mapping logic * Remove `normalize_role_settings` * Remove unnecessary migration * Make `member` the default * Broken `.erb` --------- Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
64 lines
1.7 KiB
Ruby
64 lines
1.7 KiB
Ruby
class Invitation < ApplicationRecord
|
|
include Encryptable
|
|
|
|
belongs_to :family
|
|
belongs_to :inviter, class_name: "User"
|
|
|
|
# Encrypt sensitive fields if ActiveRecord encryption is configured
|
|
if encryption_ready?
|
|
encrypts :token, deterministic: true
|
|
encrypts :email, deterministic: true, downcase: true
|
|
end
|
|
|
|
validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
|
|
validates :role, presence: true, inclusion: { in: %w[admin member guest] }
|
|
validates :token, presence: true, uniqueness: true
|
|
validates_uniqueness_of :email, scope: :family_id, message: "has already been invited to this family"
|
|
validate :inviter_is_admin
|
|
|
|
before_validation :generate_token, on: :create
|
|
before_create :set_expiration
|
|
|
|
scope :pending, -> { where(accepted_at: nil).where("expires_at > ?", Time.current) }
|
|
scope :accepted, -> { where.not(accepted_at: nil) }
|
|
|
|
def pending?
|
|
accepted_at.nil? && expires_at > Time.current
|
|
end
|
|
|
|
def accept_for(user)
|
|
return false if user.blank?
|
|
return false unless pending?
|
|
return false unless emails_match?(user)
|
|
|
|
transaction do
|
|
user.update!(family_id: family_id, role: role.to_s)
|
|
update!(accepted_at: Time.current)
|
|
end
|
|
true
|
|
end
|
|
|
|
private
|
|
|
|
def emails_match?(user)
|
|
inv_email = email.to_s.strip.downcase
|
|
usr_email = user.email.to_s.strip.downcase
|
|
inv_email.present? && usr_email.present? && inv_email == usr_email
|
|
end
|
|
|
|
def generate_token
|
|
loop do
|
|
self.token = SecureRandom.hex(32)
|
|
break unless self.class.exists?(token: token)
|
|
end
|
|
end
|
|
|
|
def set_expiration
|
|
self.expires_at = 3.days.from_now
|
|
end
|
|
|
|
def inviter_is_admin
|
|
inviter.admin?
|
|
end
|
|
end
|