feat: add import/export model types (ServiceImport, StreamImport, exports, auth)
This commit is contained in:
25
src/NATS.Server/Imports/ExportAuth.cs
Normal file
25
src/NATS.Server/Imports/ExportAuth.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using NATS.Server.Auth;
|
||||
|
||||
namespace NATS.Server.Imports;
|
||||
|
||||
public sealed class ExportAuth
|
||||
{
|
||||
public bool TokenRequired { get; init; }
|
||||
public uint AccountPosition { get; init; }
|
||||
public HashSet<string>? ApprovedAccounts { get; init; }
|
||||
public Dictionary<string, long>? RevokedAccounts { get; init; }
|
||||
|
||||
public bool IsAuthorized(Account account)
|
||||
{
|
||||
if (RevokedAccounts != null && RevokedAccounts.ContainsKey(account.Name))
|
||||
return false;
|
||||
|
||||
if (ApprovedAccounts == null && !TokenRequired && AccountPosition == 0)
|
||||
return true;
|
||||
|
||||
if (ApprovedAccounts != null)
|
||||
return ApprovedAccounts.Contains(account.Name);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
8
src/NATS.Server/Imports/ExportMap.cs
Normal file
8
src/NATS.Server/Imports/ExportMap.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace NATS.Server.Imports;
|
||||
|
||||
public sealed class ExportMap
|
||||
{
|
||||
public Dictionary<string, StreamExport> Streams { get; } = new(StringComparer.Ordinal);
|
||||
public Dictionary<string, ServiceExport> Services { get; } = new(StringComparer.Ordinal);
|
||||
public Dictionary<string, ServiceImport> Responses { get; } = new(StringComparer.Ordinal);
|
||||
}
|
||||
18
src/NATS.Server/Imports/ImportMap.cs
Normal file
18
src/NATS.Server/Imports/ImportMap.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace NATS.Server.Imports;
|
||||
|
||||
public sealed class ImportMap
|
||||
{
|
||||
public List<StreamImport> Streams { get; } = [];
|
||||
public Dictionary<string, List<ServiceImport>> Services { get; } = new(StringComparer.Ordinal);
|
||||
|
||||
public void AddServiceImport(ServiceImport si)
|
||||
{
|
||||
if (!Services.TryGetValue(si.From, out var list))
|
||||
{
|
||||
list = [];
|
||||
Services[si.From] = list;
|
||||
}
|
||||
|
||||
list.Add(si);
|
||||
}
|
||||
}
|
||||
13
src/NATS.Server/Imports/ServiceExport.cs
Normal file
13
src/NATS.Server/Imports/ServiceExport.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using NATS.Server.Auth;
|
||||
|
||||
namespace NATS.Server.Imports;
|
||||
|
||||
public sealed class ServiceExport
|
||||
{
|
||||
public ExportAuth Auth { get; init; } = new();
|
||||
public Account? Account { get; init; }
|
||||
public ServiceResponseType ResponseType { get; init; } = ServiceResponseType.Singleton;
|
||||
public TimeSpan ResponseThreshold { get; init; } = TimeSpan.FromMinutes(2);
|
||||
public ServiceLatency? Latency { get; init; }
|
||||
public bool AllowTrace { get; init; }
|
||||
}
|
||||
21
src/NATS.Server/Imports/ServiceImport.cs
Normal file
21
src/NATS.Server/Imports/ServiceImport.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using NATS.Server.Auth;
|
||||
using NATS.Server.Subscriptions;
|
||||
|
||||
namespace NATS.Server.Imports;
|
||||
|
||||
public sealed class ServiceImport
|
||||
{
|
||||
public required Account DestinationAccount { get; init; }
|
||||
public required string From { get; init; }
|
||||
public required string To { get; init; }
|
||||
public SubjectTransform? Transform { get; init; }
|
||||
public ServiceExport? Export { get; init; }
|
||||
public ServiceResponseType ResponseType { get; init; } = ServiceResponseType.Singleton;
|
||||
public byte[]? Sid { get; set; }
|
||||
public bool IsResponse { get; init; }
|
||||
public bool UsePub { get; init; }
|
||||
public bool Invalid { get; set; }
|
||||
public bool Share { get; init; }
|
||||
public bool Tracking { get; init; }
|
||||
public long TimestampTicks { get; set; }
|
||||
}
|
||||
7
src/NATS.Server/Imports/ServiceLatency.cs
Normal file
7
src/NATS.Server/Imports/ServiceLatency.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace NATS.Server.Imports;
|
||||
|
||||
public sealed class ServiceLatency
|
||||
{
|
||||
public int SamplingPercentage { get; init; } = 100;
|
||||
public string Subject { get; init; } = string.Empty;
|
||||
}
|
||||
8
src/NATS.Server/Imports/ServiceResponseType.cs
Normal file
8
src/NATS.Server/Imports/ServiceResponseType.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace NATS.Server.Imports;
|
||||
|
||||
public enum ServiceResponseType
|
||||
{
|
||||
Singleton,
|
||||
Streamed,
|
||||
Chunked,
|
||||
}
|
||||
6
src/NATS.Server/Imports/StreamExport.cs
Normal file
6
src/NATS.Server/Imports/StreamExport.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace NATS.Server.Imports;
|
||||
|
||||
public sealed class StreamExport
|
||||
{
|
||||
public ExportAuth Auth { get; init; } = new();
|
||||
}
|
||||
14
src/NATS.Server/Imports/StreamImport.cs
Normal file
14
src/NATS.Server/Imports/StreamImport.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using NATS.Server.Auth;
|
||||
using NATS.Server.Subscriptions;
|
||||
|
||||
namespace NATS.Server.Imports;
|
||||
|
||||
public sealed class StreamImport
|
||||
{
|
||||
public required Account SourceAccount { get; init; }
|
||||
public required string From { get; init; }
|
||||
public required string To { get; init; }
|
||||
public SubjectTransform? Transform { get; init; }
|
||||
public bool UsePub { get; init; }
|
||||
public bool Invalid { get; set; }
|
||||
}
|
||||
75
tests/NATS.Server.Tests/ImportExportTests.cs
Normal file
75
tests/NATS.Server.Tests/ImportExportTests.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using NATS.Server.Auth;
|
||||
using NATS.Server.Imports;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class ImportExportTests
|
||||
{
|
||||
[Fact]
|
||||
public void ExportAuth_public_export_authorizes_any_account()
|
||||
{
|
||||
var auth = new ExportAuth();
|
||||
var account = new Account("test");
|
||||
auth.IsAuthorized(account).ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExportAuth_approved_accounts_restricts_access()
|
||||
{
|
||||
var auth = new ExportAuth { ApprovedAccounts = ["allowed"] };
|
||||
var allowed = new Account("allowed");
|
||||
var denied = new Account("denied");
|
||||
auth.IsAuthorized(allowed).ShouldBeTrue();
|
||||
auth.IsAuthorized(denied).ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExportAuth_revoked_account_denied()
|
||||
{
|
||||
var auth = new ExportAuth
|
||||
{
|
||||
ApprovedAccounts = ["test"],
|
||||
RevokedAccounts = new() { ["test"] = DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
|
||||
};
|
||||
var account = new Account("test");
|
||||
auth.IsAuthorized(account).ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ServiceResponseType_defaults_to_singleton()
|
||||
{
|
||||
var import = new ServiceImport
|
||||
{
|
||||
DestinationAccount = new Account("dest"),
|
||||
From = "requests.>",
|
||||
To = "api.>",
|
||||
};
|
||||
import.ResponseType.ShouldBe(ServiceResponseType.Singleton);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExportMap_stores_and_retrieves_exports()
|
||||
{
|
||||
var map = new ExportMap();
|
||||
map.Services["api.>"] = new ServiceExport { Account = new Account("svc") };
|
||||
map.Streams["events.>"] = new StreamExport();
|
||||
|
||||
map.Services.ShouldContainKey("api.>");
|
||||
map.Streams.ShouldContainKey("events.>");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImportMap_stores_service_imports()
|
||||
{
|
||||
var map = new ImportMap();
|
||||
var si = new ServiceImport
|
||||
{
|
||||
DestinationAccount = new Account("dest"),
|
||||
From = "requests.>",
|
||||
To = "api.>",
|
||||
};
|
||||
map.AddServiceImport(si);
|
||||
map.Services.ShouldContainKey("requests.>");
|
||||
map.Services["requests.>"].Count.ShouldBe(1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user