# frozen_string_literal: true module Maquina ## # A class representing the ActiveSession model in the Maquina module. # Manages active user sessions and their expiration. # # == Attributes # # - +maquina_user_id+:: Foreign key reference to the associated User. # - +expires_at+:: Timestamp when the session expires. # - +user_agent+:: The user agent string from the client browser. # - +remote_addr+:: The remote IP address of the client. # - +return_url+:: URL to return to after session activities. # # == Associations # # - +user+:: Belongs to a User. # # == Validations # # - +expires_at+:: Must be present and in the future if session expiration is configured. # - +user+:: Must not be blocked. # # == Callbacks # # - After initialize: Sets initial expiration time for new sessions based on configuration. # # == Delegations # # - +blocked?+:: Delegated to the associated user. # class ActiveSession < ApplicationRecord belongs_to :user, class_name: "Maquina::User", foreign_key: :maquina_user_id delegate :blocked?, to: :user after_initialize :configure_expiration validates :expires_at, presence: true, comparison: {greater_than: Time.zone.now}, if: ->(session) { (session.new_record? || session.changed.includes?("expires_at")) && Maquina.configuration.session_expiration.present? } validate :non_blocked_user # Checks if the session has expired # # Returns: # - true -> if expires_at is set and in the past # - false -> if expires_at is not set or is in the future def expired? return false if expires_at.blank? !expires_at.future? end private # Validates that the associated user is not blocked # # Adds an error if the user is blocked def non_blocked_user return if user.blank? || !blocked? errors.add(:user, :blocked) end # Sets the initial expiration time for new sessions # # Uses the configured session expiration duration if available def configure_expiration if new_record? && expires_at.blank? && Maquina.configuration.session_expiration.present? self.expires_at = Time.zone.now.since(Maquina.configuration.session_expiration) end end end end