|
|
|
@@ -1,9 +1,9 @@
|
|
|
|
|
using Microsoft.Extensions.Options;
|
|
|
|
|
using ZB.MOM.WW.Configuration;
|
|
|
|
|
using ZB.MOM.WW.MxGateway.Contracts;
|
|
|
|
|
|
|
|
|
|
namespace ZB.MOM.WW.MxGateway.Server.Configuration;
|
|
|
|
|
|
|
|
|
|
public sealed class GatewayOptionsValidator : IValidateOptions<GatewayOptions>
|
|
|
|
|
public sealed class GatewayOptionsValidator : OptionsValidatorBase<GatewayOptions>
|
|
|
|
|
{
|
|
|
|
|
private const int MinimumMaxMessageBytes = 1024;
|
|
|
|
|
private const int MaximumMaxMessageBytes = 256 * 1024 * 1024;
|
|
|
|
@@ -11,33 +11,26 @@ public sealed class GatewayOptionsValidator : IValidateOptions<GatewayOptions>
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Validates gateway configuration options.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">Options name.</param>
|
|
|
|
|
/// <param name="builder">The accumulator to record failures on.</param>
|
|
|
|
|
/// <param name="options">Gateway options to validate.</param>
|
|
|
|
|
/// <returns>Validation result.</returns>
|
|
|
|
|
public ValidateOptionsResult Validate(string? name, GatewayOptions options)
|
|
|
|
|
protected override void Validate(ValidationBuilder builder, GatewayOptions options)
|
|
|
|
|
{
|
|
|
|
|
List<string> failures = [];
|
|
|
|
|
|
|
|
|
|
ValidateAuthentication(options.Authentication, failures);
|
|
|
|
|
ValidateLdap(options.Ldap, failures);
|
|
|
|
|
ValidateWorker(options.Worker, failures);
|
|
|
|
|
ValidateSessions(options.Sessions, failures);
|
|
|
|
|
ValidateEvents(options.Events, failures);
|
|
|
|
|
ValidateDashboard(options.Dashboard, failures);
|
|
|
|
|
ValidateProtocol(options.Protocol, failures);
|
|
|
|
|
ValidateAlarms(options.Alarms, failures);
|
|
|
|
|
ValidateTls(options.Tls, failures);
|
|
|
|
|
|
|
|
|
|
return failures.Count == 0
|
|
|
|
|
? ValidateOptionsResult.Success
|
|
|
|
|
: ValidateOptionsResult.Fail(failures);
|
|
|
|
|
ValidateAuthentication(options.Authentication, builder);
|
|
|
|
|
ValidateLdap(options.Ldap, builder);
|
|
|
|
|
ValidateWorker(options.Worker, builder);
|
|
|
|
|
ValidateSessions(options.Sessions, builder);
|
|
|
|
|
ValidateEvents(options.Events, builder);
|
|
|
|
|
ValidateDashboard(options.Dashboard, builder);
|
|
|
|
|
ValidateProtocol(options.Protocol, builder);
|
|
|
|
|
ValidateAlarms(options.Alarms, builder);
|
|
|
|
|
ValidateTls(options.Tls, builder);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void ValidateAuthentication(AuthenticationOptions options, List<string> failures)
|
|
|
|
|
private static void ValidateAuthentication(AuthenticationOptions options, ValidationBuilder builder)
|
|
|
|
|
{
|
|
|
|
|
if (!Enum.IsDefined(options.Mode))
|
|
|
|
|
{
|
|
|
|
|
failures.Add("MxGateway:Authentication:Mode must be a supported authentication mode.");
|
|
|
|
|
builder.Add("MxGateway:Authentication:Mode must be a supported authentication mode.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -46,67 +39,67 @@ public sealed class GatewayOptionsValidator : IValidateOptions<GatewayOptions>
|
|
|
|
|
AddIfBlank(
|
|
|
|
|
options.SqlitePath,
|
|
|
|
|
"MxGateway:Authentication:SqlitePath is required when API-key authentication is enabled.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfInvalidPath(
|
|
|
|
|
options.SqlitePath,
|
|
|
|
|
"MxGateway:Authentication:SqlitePath must be a valid filesystem path.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfBlank(
|
|
|
|
|
options.PepperSecretName,
|
|
|
|
|
"MxGateway:Authentication:PepperSecretName is required when API-key authentication is enabled.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void ValidateLdap(LdapOptions options, List<string> failures)
|
|
|
|
|
private static void ValidateLdap(LdapOptions options, ValidationBuilder builder)
|
|
|
|
|
{
|
|
|
|
|
if (!options.Enabled)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AddIfBlank(options.Server, "MxGateway:Ldap:Server is required when LDAP login is enabled.", failures);
|
|
|
|
|
AddIfBlank(options.SearchBase, "MxGateway:Ldap:SearchBase is required when LDAP login is enabled.", failures);
|
|
|
|
|
AddIfBlank(options.Server, "MxGateway:Ldap:Server is required when LDAP login is enabled.", builder);
|
|
|
|
|
AddIfBlank(options.SearchBase, "MxGateway:Ldap:SearchBase is required when LDAP login is enabled.", builder);
|
|
|
|
|
AddIfBlank(
|
|
|
|
|
options.ServiceAccountDn,
|
|
|
|
|
"MxGateway:Ldap:ServiceAccountDn is required when LDAP login is enabled.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfBlank(
|
|
|
|
|
options.ServiceAccountPassword,
|
|
|
|
|
"MxGateway:Ldap:ServiceAccountPassword is required when LDAP login is enabled.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfBlank(
|
|
|
|
|
options.UserNameAttribute,
|
|
|
|
|
"MxGateway:Ldap:UserNameAttribute is required when LDAP login is enabled.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfBlank(
|
|
|
|
|
options.DisplayNameAttribute,
|
|
|
|
|
"MxGateway:Ldap:DisplayNameAttribute is required when LDAP login is enabled.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfBlank(
|
|
|
|
|
options.GroupAttribute,
|
|
|
|
|
"MxGateway:Ldap:GroupAttribute is required when LDAP login is enabled.",
|
|
|
|
|
failures);
|
|
|
|
|
AddIfNotPositive(options.Port, "MxGateway:Ldap:Port must be greater than zero.", failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfNotPositive(options.Port, "MxGateway:Ldap:Port must be greater than zero.", builder);
|
|
|
|
|
|
|
|
|
|
if (!options.UseTls && !options.AllowInsecureLdap)
|
|
|
|
|
{
|
|
|
|
|
failures.Add("MxGateway:Ldap:AllowInsecureLdap must be true when UseTls is false.");
|
|
|
|
|
builder.Add("MxGateway:Ldap:AllowInsecureLdap must be true when UseTls is false.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void ValidateWorker(WorkerOptions options, List<string> failures)
|
|
|
|
|
private static void ValidateWorker(WorkerOptions options, ValidationBuilder builder)
|
|
|
|
|
{
|
|
|
|
|
AddIfBlank(options.ExecutablePath, "MxGateway:Worker:ExecutablePath is required.", failures);
|
|
|
|
|
AddIfBlank(options.ExecutablePath, "MxGateway:Worker:ExecutablePath is required.", builder);
|
|
|
|
|
AddIfInvalidPath(
|
|
|
|
|
options.ExecutablePath,
|
|
|
|
|
"MxGateway:Worker:ExecutablePath must be a valid filesystem path.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(options.ExecutablePath)
|
|
|
|
|
&& !string.Equals(Path.GetExtension(options.ExecutablePath), ".exe", StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
failures.Add("MxGateway:Worker:ExecutablePath must point to a .exe file.");
|
|
|
|
|
builder.Add("MxGateway:Worker:ExecutablePath must point to a .exe file.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(options.WorkingDirectory))
|
|
|
|
@@ -114,94 +107,94 @@ public sealed class GatewayOptionsValidator : IValidateOptions<GatewayOptions>
|
|
|
|
|
AddIfInvalidPath(
|
|
|
|
|
options.WorkingDirectory,
|
|
|
|
|
"MxGateway:Worker:WorkingDirectory must be a valid filesystem path.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!Enum.IsDefined(options.RequiredArchitecture))
|
|
|
|
|
{
|
|
|
|
|
failures.Add("MxGateway:Worker:RequiredArchitecture must be a supported worker architecture.");
|
|
|
|
|
builder.Add("MxGateway:Worker:RequiredArchitecture must be a supported worker architecture.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AddIfNotPositive(
|
|
|
|
|
options.StartupTimeoutSeconds,
|
|
|
|
|
"MxGateway:Worker:StartupTimeoutSeconds must be greater than zero.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfNotPositive(
|
|
|
|
|
options.StartupProbeRetryAttempts,
|
|
|
|
|
"MxGateway:Worker:StartupProbeRetryAttempts must be greater than zero.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfNotPositive(
|
|
|
|
|
options.StartupProbeRetryDelayMilliseconds,
|
|
|
|
|
"MxGateway:Worker:StartupProbeRetryDelayMilliseconds must be greater than zero.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfNotPositive(
|
|
|
|
|
options.PipeConnectAttemptTimeoutMilliseconds,
|
|
|
|
|
"MxGateway:Worker:PipeConnectAttemptTimeoutMilliseconds must be greater than zero.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfNotPositive(
|
|
|
|
|
options.ShutdownTimeoutSeconds,
|
|
|
|
|
"MxGateway:Worker:ShutdownTimeoutSeconds must be greater than zero.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfNotPositive(
|
|
|
|
|
options.HeartbeatIntervalSeconds,
|
|
|
|
|
"MxGateway:Worker:HeartbeatIntervalSeconds must be greater than zero.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfNotPositive(
|
|
|
|
|
options.HeartbeatGraceSeconds,
|
|
|
|
|
"MxGateway:Worker:HeartbeatGraceSeconds must be greater than zero.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
|
|
|
|
|
if (options.HeartbeatGraceSeconds < options.HeartbeatIntervalSeconds)
|
|
|
|
|
{
|
|
|
|
|
failures.Add(
|
|
|
|
|
builder.Add(
|
|
|
|
|
"MxGateway:Worker:HeartbeatGraceSeconds must be greater than or equal to HeartbeatIntervalSeconds.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options.MaxMessageBytes is < MinimumMaxMessageBytes or > MaximumMaxMessageBytes)
|
|
|
|
|
{
|
|
|
|
|
failures.Add(
|
|
|
|
|
builder.Add(
|
|
|
|
|
$"MxGateway:Worker:MaxMessageBytes must be between {MinimumMaxMessageBytes} and {MaximumMaxMessageBytes}.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void ValidateSessions(SessionOptions options, List<string> failures)
|
|
|
|
|
private static void ValidateSessions(SessionOptions options, ValidationBuilder builder)
|
|
|
|
|
{
|
|
|
|
|
AddIfNotPositive(
|
|
|
|
|
options.DefaultCommandTimeoutSeconds,
|
|
|
|
|
"MxGateway:Sessions:DefaultCommandTimeoutSeconds must be greater than zero.",
|
|
|
|
|
failures);
|
|
|
|
|
AddIfNotPositive(options.MaxSessions, "MxGateway:Sessions:MaxSessions must be greater than zero.", failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfNotPositive(options.MaxSessions, "MxGateway:Sessions:MaxSessions must be greater than zero.", builder);
|
|
|
|
|
AddIfNotPositive(
|
|
|
|
|
options.MaxPendingCommandsPerSession,
|
|
|
|
|
"MxGateway:Sessions:MaxPendingCommandsPerSession must be greater than zero.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfNotPositive(
|
|
|
|
|
options.DefaultLeaseSeconds,
|
|
|
|
|
"MxGateway:Sessions:DefaultLeaseSeconds must be greater than zero.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfNotPositive(
|
|
|
|
|
options.LeaseSweepIntervalSeconds,
|
|
|
|
|
"MxGateway:Sessions:LeaseSweepIntervalSeconds must be greater than zero.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
|
|
|
|
|
if (options.AllowMultipleEventSubscribers)
|
|
|
|
|
{
|
|
|
|
|
failures.Add(
|
|
|
|
|
builder.Add(
|
|
|
|
|
"MxGateway:Sessions:AllowMultipleEventSubscribers is not supported until event fan-out is implemented.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void ValidateEvents(EventOptions options, List<string> failures)
|
|
|
|
|
private static void ValidateEvents(EventOptions options, ValidationBuilder builder)
|
|
|
|
|
{
|
|
|
|
|
AddIfNotPositive(options.QueueCapacity, "MxGateway:Events:QueueCapacity must be greater than zero.", failures);
|
|
|
|
|
AddIfNotPositive(options.QueueCapacity, "MxGateway:Events:QueueCapacity must be greater than zero.", builder);
|
|
|
|
|
|
|
|
|
|
if (!Enum.IsDefined(options.BackpressurePolicy))
|
|
|
|
|
{
|
|
|
|
|
failures.Add("MxGateway:Events:BackpressurePolicy must be a supported backpressure policy.");
|
|
|
|
|
builder.Add("MxGateway:Events:BackpressurePolicy must be a supported backpressure policy.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void ValidateDashboard(DashboardOptions options, List<string> failures)
|
|
|
|
|
private static void ValidateDashboard(DashboardOptions options, ValidationBuilder builder)
|
|
|
|
|
{
|
|
|
|
|
// GroupToRole shape is validated even when the dashboard is disabled so
|
|
|
|
|
// misconfiguration surfaces at startup; emptiness is allowed, with the
|
|
|
|
@@ -212,13 +205,13 @@ public sealed class GatewayOptionsValidator : IValidateOptions<GatewayOptions>
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrWhiteSpace(entry.Key))
|
|
|
|
|
{
|
|
|
|
|
failures.Add("MxGateway:Dashboard:GroupToRole keys (LDAP group names) must be non-blank.");
|
|
|
|
|
builder.Add("MxGateway:Dashboard:GroupToRole keys (LDAP group names) must be non-blank.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.Equals(entry.Value, Dashboard.DashboardRoles.Admin, StringComparison.Ordinal)
|
|
|
|
|
&& !string.Equals(entry.Value, Dashboard.DashboardRoles.Viewer, StringComparison.Ordinal))
|
|
|
|
|
{
|
|
|
|
|
failures.Add(
|
|
|
|
|
builder.Add(
|
|
|
|
|
$"MxGateway:Dashboard:GroupToRole['{entry.Key}'] must be '{Dashboard.DashboardRoles.Admin}' or '{Dashboard.DashboardRoles.Viewer}'.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -226,18 +219,18 @@ public sealed class GatewayOptionsValidator : IValidateOptions<GatewayOptions>
|
|
|
|
|
AddIfNotPositive(
|
|
|
|
|
options.SnapshotIntervalMilliseconds,
|
|
|
|
|
"MxGateway:Dashboard:SnapshotIntervalMilliseconds must be greater than zero.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfNegative(
|
|
|
|
|
options.RecentFaultLimit,
|
|
|
|
|
"MxGateway:Dashboard:RecentFaultLimit must be greater than or equal to zero.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfNegative(
|
|
|
|
|
options.RecentSessionLimit,
|
|
|
|
|
"MxGateway:Dashboard:RecentSessionLimit must be greater than or equal to zero.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void ValidateAlarms(AlarmsOptions options, List<string> failures)
|
|
|
|
|
private static void ValidateAlarms(AlarmsOptions options, ValidationBuilder builder)
|
|
|
|
|
{
|
|
|
|
|
if (!options.Enabled)
|
|
|
|
|
{
|
|
|
|
@@ -251,14 +244,14 @@ public sealed class GatewayOptionsValidator : IValidateOptions<GatewayOptions>
|
|
|
|
|
if (string.IsNullOrWhiteSpace(options.SubscriptionExpression)
|
|
|
|
|
&& string.IsNullOrWhiteSpace(options.DefaultArea))
|
|
|
|
|
{
|
|
|
|
|
failures.Add(
|
|
|
|
|
builder.Add(
|
|
|
|
|
"MxGateway:Alarms requires either a non-blank SubscriptionExpression or a non-blank DefaultArea when Enabled is true.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(options.SubscriptionExpression)
|
|
|
|
|
&& !options.SubscriptionExpression.StartsWith(@"\\", StringComparison.Ordinal))
|
|
|
|
|
{
|
|
|
|
|
failures.Add(
|
|
|
|
|
builder.Add(
|
|
|
|
|
@"MxGateway:Alarms:SubscriptionExpression must start with '\\' (canonical \\<host>\Galaxy!<area> shape).");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -266,11 +259,11 @@ public sealed class GatewayOptionsValidator : IValidateOptions<GatewayOptions>
|
|
|
|
|
private const int MinimumCertValidityYears = 1;
|
|
|
|
|
private const int MaximumCertValidityYears = 100;
|
|
|
|
|
|
|
|
|
|
private static void ValidateTls(TlsOptions options, List<string> failures)
|
|
|
|
|
private static void ValidateTls(TlsOptions options, ValidationBuilder builder)
|
|
|
|
|
{
|
|
|
|
|
if (options.ValidityYears is < MinimumCertValidityYears or > MaximumCertValidityYears)
|
|
|
|
|
{
|
|
|
|
|
failures.Add(
|
|
|
|
|
builder.Add(
|
|
|
|
|
$"MxGateway:Tls:ValidityYears must be between {MinimumCertValidityYears} and {MaximumCertValidityYears}.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -278,61 +271,52 @@ public sealed class GatewayOptionsValidator : IValidateOptions<GatewayOptions>
|
|
|
|
|
AddIfBlank(
|
|
|
|
|
options.SelfSignedCertPath,
|
|
|
|
|
"MxGateway:Tls:SelfSignedCertPath must not be blank.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
AddIfInvalidPath(
|
|
|
|
|
options.SelfSignedCertPath,
|
|
|
|
|
"MxGateway:Tls:SelfSignedCertPath must be a valid filesystem path.",
|
|
|
|
|
failures);
|
|
|
|
|
builder);
|
|
|
|
|
|
|
|
|
|
foreach (string dns in options.AdditionalDnsNames)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrWhiteSpace(dns))
|
|
|
|
|
{
|
|
|
|
|
failures.Add("MxGateway:Tls:AdditionalDnsNames entries must be non-blank.");
|
|
|
|
|
builder.Add("MxGateway:Tls:AdditionalDnsNames entries must be non-blank.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void ValidateProtocol(ProtocolOptions options, List<string> failures)
|
|
|
|
|
private static void ValidateProtocol(ProtocolOptions options, ValidationBuilder builder)
|
|
|
|
|
{
|
|
|
|
|
if (options.WorkerProtocolVersion != GatewayContractInfo.WorkerProtocolVersion)
|
|
|
|
|
{
|
|
|
|
|
failures.Add(
|
|
|
|
|
builder.Add(
|
|
|
|
|
$"MxGateway:Protocol:WorkerProtocolVersion must be {GatewayContractInfo.WorkerProtocolVersion}.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options.MaxGrpcMessageBytes is < MinimumMaxMessageBytes or > MaximumMaxMessageBytes)
|
|
|
|
|
{
|
|
|
|
|
failures.Add(
|
|
|
|
|
builder.Add(
|
|
|
|
|
$"MxGateway:Protocol:MaxGrpcMessageBytes must be between {MinimumMaxMessageBytes} and {MaximumMaxMessageBytes}.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void AddIfBlank(string? value, string message, List<string> failures)
|
|
|
|
|
private static void AddIfBlank(string? value, string message, ValidationBuilder builder)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
|
|
|
{
|
|
|
|
|
failures.Add(message);
|
|
|
|
|
}
|
|
|
|
|
builder.RequireThat(!string.IsNullOrWhiteSpace(value), message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void AddIfNotPositive(int value, string message, List<string> failures)
|
|
|
|
|
private static void AddIfNotPositive(int value, string message, ValidationBuilder builder)
|
|
|
|
|
{
|
|
|
|
|
if (value <= 0)
|
|
|
|
|
{
|
|
|
|
|
failures.Add(message);
|
|
|
|
|
}
|
|
|
|
|
builder.RequireThat(value > 0, message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void AddIfNegative(int value, string message, List<string> failures)
|
|
|
|
|
private static void AddIfNegative(int value, string message, ValidationBuilder builder)
|
|
|
|
|
{
|
|
|
|
|
if (value < 0)
|
|
|
|
|
{
|
|
|
|
|
failures.Add(message);
|
|
|
|
|
}
|
|
|
|
|
builder.RequireThat(value >= 0, message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void AddIfInvalidPath(string? value, string message, List<string> failures)
|
|
|
|
|
private static void AddIfInvalidPath(string? value, string message, ValidationBuilder builder)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
|
|
|
{
|
|
|
|
@@ -345,15 +329,15 @@ public sealed class GatewayOptionsValidator : IValidateOptions<GatewayOptions>
|
|
|
|
|
}
|
|
|
|
|
catch (ArgumentException)
|
|
|
|
|
{
|
|
|
|
|
failures.Add(message);
|
|
|
|
|
builder.Add(message);
|
|
|
|
|
}
|
|
|
|
|
catch (NotSupportedException)
|
|
|
|
|
{
|
|
|
|
|
failures.Add(message);
|
|
|
|
|
builder.Add(message);
|
|
|
|
|
}
|
|
|
|
|
catch (PathTooLongException)
|
|
|
|
|
{
|
|
|
|
|
failures.Add(message);
|
|
|
|
|
builder.Add(message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|