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