Add ActivationClaim and ActivationCheckResult types plus five methods on Account (RegisterActivation, CheckActivationExpiry, IsActivationExpired, GetExpiredActivations, RemoveExpiredActivations) and an ActiveActivationCount property, mirroring Go accounts.go checkActivation / activationExpired logic. Adds 10 targeted tests in Auth/ActivationExpirationTests.cs (all pass).
174 lines
5.9 KiB
C#
174 lines
5.9 KiB
C#
// Tests for account claim hot-reload with diff-based update detection.
|
|
// Go reference: accounts_test.go TestUpdateAccountClaims, updateAccountClaimsWithRefresh (~line 3374).
|
|
|
|
using NATS.Server.Auth;
|
|
|
|
namespace NATS.Server.Tests.Auth;
|
|
|
|
public class AccountClaimReloadTests
|
|
{
|
|
// 1. First update: all provided fields are reported as changed.
|
|
[Fact]
|
|
public void UpdateAccountClaims_FirstUpdate_AllFieldsChanged()
|
|
{
|
|
var account = new Account("test");
|
|
var claims = new AccountClaimData
|
|
{
|
|
MaxConnections = 10,
|
|
MaxSubscriptions = 100,
|
|
Nkey = "NKEY123",
|
|
Issuer = "ISSUER_OP",
|
|
ExpiresAt = new DateTime(2030, 1, 1, 0, 0, 0, DateTimeKind.Utc),
|
|
};
|
|
|
|
var result = account.UpdateAccountClaims(claims);
|
|
|
|
result.Changed.ShouldBeTrue();
|
|
result.ChangedFields.ShouldContain(nameof(AccountClaimData.MaxConnections));
|
|
result.ChangedFields.ShouldContain(nameof(AccountClaimData.MaxSubscriptions));
|
|
result.ChangedFields.ShouldContain(nameof(AccountClaimData.Nkey));
|
|
result.ChangedFields.ShouldContain(nameof(AccountClaimData.Issuer));
|
|
result.ChangedFields.ShouldContain(nameof(AccountClaimData.ExpiresAt));
|
|
result.ChangedFields.Count.ShouldBe(5);
|
|
}
|
|
|
|
// 2. Applying the exact same claims a second time returns Changed=false.
|
|
[Fact]
|
|
public void UpdateAccountClaims_NoChange_ReturnsFalse()
|
|
{
|
|
var account = new Account("test");
|
|
var claims = new AccountClaimData
|
|
{
|
|
MaxConnections = 5,
|
|
MaxSubscriptions = 50,
|
|
Nkey = "NKEY_A",
|
|
Issuer = "OP",
|
|
};
|
|
|
|
account.UpdateAccountClaims(claims);
|
|
var result = account.UpdateAccountClaims(claims);
|
|
|
|
result.Changed.ShouldBeFalse();
|
|
result.ChangedFields.Count.ShouldBe(0);
|
|
}
|
|
|
|
// 3. Changing MaxConnections is detected.
|
|
[Fact]
|
|
public void UpdateAccountClaims_MaxConnectionsChanged_Detected()
|
|
{
|
|
var account = new Account("test");
|
|
var initial = new AccountClaimData { MaxConnections = 10 };
|
|
account.UpdateAccountClaims(initial);
|
|
|
|
var updated = new AccountClaimData { MaxConnections = 20 };
|
|
var result = account.UpdateAccountClaims(updated);
|
|
|
|
result.Changed.ShouldBeTrue();
|
|
result.ChangedFields.ShouldContain(nameof(AccountClaimData.MaxConnections));
|
|
account.MaxConnections.ShouldBe(20);
|
|
}
|
|
|
|
// 4. Changing MaxSubscriptions is detected.
|
|
[Fact]
|
|
public void UpdateAccountClaims_MaxSubscriptionsChanged_Detected()
|
|
{
|
|
var account = new Account("test");
|
|
var initial = new AccountClaimData { MaxSubscriptions = 100 };
|
|
account.UpdateAccountClaims(initial);
|
|
|
|
var updated = new AccountClaimData { MaxSubscriptions = 200 };
|
|
var result = account.UpdateAccountClaims(updated);
|
|
|
|
result.Changed.ShouldBeTrue();
|
|
result.ChangedFields.ShouldContain(nameof(AccountClaimData.MaxSubscriptions));
|
|
account.MaxSubscriptions.ShouldBe(200);
|
|
}
|
|
|
|
// 5. Changing Nkey is detected.
|
|
[Fact]
|
|
public void UpdateAccountClaims_NkeyChanged_Detected()
|
|
{
|
|
var account = new Account("test");
|
|
var initial = new AccountClaimData { Nkey = "OLD_NKEY" };
|
|
account.UpdateAccountClaims(initial);
|
|
|
|
var updated = new AccountClaimData { Nkey = "NEW_NKEY" };
|
|
var result = account.UpdateAccountClaims(updated);
|
|
|
|
result.Changed.ShouldBeTrue();
|
|
result.ChangedFields.ShouldContain(nameof(AccountClaimData.Nkey));
|
|
account.Nkey.ShouldBe("NEW_NKEY");
|
|
}
|
|
|
|
// 6. Changing Issuer is detected.
|
|
[Fact]
|
|
public void UpdateAccountClaims_IssuerChanged_Detected()
|
|
{
|
|
var account = new Account("test");
|
|
var initial = new AccountClaimData { Issuer = "ISSUER_A" };
|
|
account.UpdateAccountClaims(initial);
|
|
|
|
var updated = new AccountClaimData { Issuer = "ISSUER_B" };
|
|
var result = account.UpdateAccountClaims(updated);
|
|
|
|
result.Changed.ShouldBeTrue();
|
|
result.ChangedFields.ShouldContain(nameof(AccountClaimData.Issuer));
|
|
account.Issuer.ShouldBe("ISSUER_B");
|
|
}
|
|
|
|
// 7. A successful claim update increments the generation counter.
|
|
[Fact]
|
|
public void UpdateAccountClaims_IncrementsGeneration()
|
|
{
|
|
var account = new Account("test");
|
|
var before = account.GenerationId;
|
|
|
|
var claims = new AccountClaimData { MaxConnections = 5 };
|
|
account.UpdateAccountClaims(claims);
|
|
|
|
account.GenerationId.ShouldBe(before + 1);
|
|
}
|
|
|
|
// 8. HasClaims is false on a fresh account.
|
|
[Fact]
|
|
public void HasClaims_BeforeUpdate_ReturnsFalse()
|
|
{
|
|
var account = new Account("test");
|
|
account.HasClaims.ShouldBeFalse();
|
|
}
|
|
|
|
// 9. HasClaims is true after the first update.
|
|
[Fact]
|
|
public void HasClaims_AfterUpdate_ReturnsTrue()
|
|
{
|
|
var account = new Account("test");
|
|
var claims = new AccountClaimData { MaxConnections = 1 };
|
|
account.UpdateAccountClaims(claims);
|
|
|
|
account.HasClaims.ShouldBeTrue();
|
|
account.CurrentClaims.ShouldNotBeNull();
|
|
account.CurrentClaims!.MaxConnections.ShouldBe(1);
|
|
}
|
|
|
|
// 10. ClaimUpdateCount increments only when claims actually change.
|
|
[Fact]
|
|
public void ClaimUpdateCount_IncrementsOnChange()
|
|
{
|
|
var account = new Account("test");
|
|
account.ClaimUpdateCount.ShouldBe(0);
|
|
|
|
var claimsA = new AccountClaimData { MaxConnections = 5 };
|
|
account.UpdateAccountClaims(claimsA);
|
|
account.ClaimUpdateCount.ShouldBe(1);
|
|
|
|
// Reapplying same claims does NOT increment count.
|
|
account.UpdateAccountClaims(claimsA);
|
|
account.ClaimUpdateCount.ShouldBe(1);
|
|
|
|
// Applying different claims does increment.
|
|
var claimsB = new AccountClaimData { MaxConnections = 10 };
|
|
account.UpdateAccountClaims(claimsB);
|
|
account.ClaimUpdateCount.ShouldBe(2);
|
|
}
|
|
}
|