DeutschLernen/GermanApp/Domain/Entities/RefreshToken.cs
Lasse Rune Hansen 6bcf592918 feat(backend): complete unit tests for User Authentication feature
- Fix MSTest compatibility with .NET 9.0 by upgrading to MSTest.TestFramework 4.2.3
- Move Tests directory to solution level (Tests/) to prevent test files from being compiled with GermanApp
- Update test project references to point to GermanApp/GermanApp.csproj
- Add InternalsVisibleTo attributes for test assemblies
- Make RefreshToken properties internal for testability
- Fix User.ChangeEmail null handling
- Add 46 comprehensive unit tests for User and RefreshToken domain entities
- All tests passing successfully

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-05 17:07:15 +02:00

53 lines
1.5 KiB
C#

namespace GermanApp.Domain.Entities;
/// <summary>
/// Represents a refresh token for JWT authentication.
/// </summary>
public class RefreshToken
{
public int Id { get; internal set; }
public int UserId { get; internal set; }
public string Token { get; internal set; } = string.Empty;
public DateTime ExpiresAt { get; internal set; }
public bool IsActive { get; internal set; } = true;
public DateTime CreatedAt { get; internal set; }
public DateTime? RevokedAt { get; internal set; }
/// <summary>
/// Constructor for EF Core deserialization.
/// </summary>
private RefreshToken() { }
/// <summary>
/// Factory method to create a new refresh token.
/// </summary>
public static RefreshToken Create(int userId, string token, int expireDays = 7)
{
return new RefreshToken
{
UserId = userId,
Token = token,
ExpiresAt = DateTime.UtcNow.AddDays(expireDays),
CreatedAt = DateTime.UtcNow
};
}
/// <summary>
/// Revokes the refresh token.
/// </summary>
public void Revoke()
{
IsActive = false;
RevokedAt = DateTime.UtcNow;
}
/// <summary>
/// Checks if the token is expired.
/// </summary>
public bool IsExpired() => DateTime.UtcNow >= ExpiresAt;
/// <summary>
/// Checks if the token is valid (not revoked and not expired).
/// </summary>
public bool IsValid() => IsActive && !IsExpired();
}