diff --git a/src/NATS.Server/Auth/Account.cs b/src/NATS.Server/Auth/Account.cs new file mode 100644 index 0000000..6e8ac3f --- /dev/null +++ b/src/NATS.Server/Auth/Account.cs @@ -0,0 +1,28 @@ +using System.Collections.Concurrent; +using NATS.Server.Subscriptions; + +namespace NATS.Server.Auth; + +public sealed class Account : IDisposable +{ + public const string GlobalAccountName = "$G"; + + public string Name { get; } + public SubList SubList { get; } = new(); + public Permissions? DefaultPermissions { get; set; } + + private readonly ConcurrentDictionary _clients = new(); + + public Account(string name) + { + Name = name; + } + + public int ClientCount => _clients.Count; + + public void AddClient(ulong clientId) => _clients[clientId] = 0; + + public void RemoveClient(ulong clientId) => _clients.TryRemove(clientId, out _); + + public void Dispose() => SubList.Dispose(); +} diff --git a/tests/NATS.Server.Tests/AccountTests.cs b/tests/NATS.Server.Tests/AccountTests.cs new file mode 100644 index 0000000..304a498 --- /dev/null +++ b/tests/NATS.Server.Tests/AccountTests.cs @@ -0,0 +1,35 @@ +using NATS.Server.Auth; +using NATS.Server.Subscriptions; + +namespace NATS.Server.Tests; + +public class AccountTests +{ + [Fact] + public void Account_has_name_and_own_sublist() + { + var account = new Account("test-account"); + + account.Name.ShouldBe("test-account"); + account.SubList.ShouldNotBeNull(); + account.SubList.Count.ShouldBe(0u); + } + + [Fact] + public void Account_tracks_clients() + { + var account = new Account("test"); + + account.ClientCount.ShouldBe(0); + account.AddClient(1); + account.ClientCount.ShouldBe(1); + account.RemoveClient(1); + account.ClientCount.ShouldBe(0); + } + + [Fact] + public void GlobalAccount_has_default_name() + { + Account.GlobalAccountName.ShouldBe("$G"); + } +}