using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Text.Json; using DysonNetwork.Common.Models; using NodaTime; using Account = DysonNetwork.Common.Models.Account; namespace DysonNetwork.Pass.Features.Auth.Models; public class AuthSession : ModelBase { [Required] public Guid AccountId { get; set; } [ForeignKey(nameof(AccountId))] public virtual Account Account { get; set; } = null!; [Required] [MaxLength(500)] public string Label { get; set; } = string.Empty; [Required] public Instant LastGrantedAt { get; set; } = SystemClock.Instance.GetCurrentInstant(); [Required] public Instant ExpiredAt { get; set; } [MaxLength(1000)] public string? AccessToken { get; set; } [MaxLength(1000)] public string? RefreshToken { get; set; } public bool IsRevoked { get; set; } public string? IpAddress { get; set; } [MaxLength(500)] public string? UserAgent { get; set; } [Column(TypeName = "jsonb")] public Dictionary? Metadata { get; set; } public Guid? ChallengeId { get; set; } [ForeignKey(nameof(ChallengeId))] public virtual AuthChallenge? Challenge { get; set; } // Helper methods public bool IsExpired() => SystemClock.Instance.GetCurrentInstant() >= ExpiredAt; public bool IsActive() => !IsExpired() && !IsRevoked; public void UpdateLastActivity() { LastGrantedAt = SystemClock.Instance.GetCurrentInstant(); } public void SetChallenge(AuthChallenge challenge) { Challenge = challenge; ChallengeId = challenge.Id; } public void ClearChallenge() { Challenge = null; ChallengeId = null; } public void UpdateTokens(string accessToken, string refreshToken, Duration accessTokenLifetime) { AccessToken = accessToken; RefreshToken = refreshToken; ExpiredAt = SystemClock.Instance.GetCurrentInstant().Plus(accessTokenLifetime); UpdateLastActivity(); } public void Revoke() { IsRevoked = true; AccessToken = null; RefreshToken = null; ExpiredAt = SystemClock.Instance.GetCurrentInstant(); } }