diff --git a/app/models/concerns/session_manageable.rb b/app/models/concerns/session_manageable.rb index 4e61252ab..b7143084e 100644 --- a/app/models/concerns/session_manageable.rb +++ b/app/models/concerns/session_manageable.rb @@ -1,26 +1,33 @@ +# Provides session management functionality for Devise Token Auth tokens. +# Handles logout operations, session limits, and token cleanup. module SessionManageable extend ActiveSupport::Concern + # Clears all active sessions for the user. + # @return [void] def logout_all_sessions! - # Clear all devise token auth tokens self.tokens = {} save! end + # Logs out a specific session by client ID. + # @param client_id [String] the client identifier to logout + # @return [Boolean] true if session was found and removed def logout_session!(client_id) return false unless client_id.present? && tokens.present? - # Remove specific client token removed = tokens.delete(client_id) save! if removed removed.present? end + # Removes tokens that expired before the given timestamp. + # @param timestamp [Time, Integer] cutoff time for token cleanup + # @return [void] def reset_tokens_before!(timestamp) return unless tokens.present? - # Remove tokens that expired before the given timestamp self.tokens = tokens.select do |_client_id, token_data| (token_data['expiry'] || 0) >= timestamp.to_i end @@ -28,18 +35,23 @@ module SessionManageable save! end + # Returns count of non-expired active sessions. + # @return [Integer] number of active sessions def active_session_count return 0 unless tokens.present? - # Count only non-expired tokens current_time = Time.current.to_i tokens.count { |_client_id, token_data| (token_data['expiry'] || 0) > current_time } end + # Checks if user has exceeded configured session limit. + # @return [Boolean] true if session limit is exceeded def session_limit_exceeded? active_session_count >= session_limit end + # Returns session information for all active tokens. + # @return [Array] array of session info, sorted by expiry (newest first) def session_info return [] unless tokens.present? @@ -53,6 +65,9 @@ module SessionManageable private + # Returns configured session limit from GlobalConfig. + # Defaults to infinity if not configured. + # @return [Integer, Float] session limit or Float::INFINITY def session_limit @session_limit ||= GlobalConfig.get( 'USER_SESSION_LIMIT',