Refactor VPN configuration handling to remove device limit management
- Updated the VPN configuration commands and handlers to eliminate the device limit parameter, simplifying the configuration process. - Adjusted related API documentation to reflect the removal of device limit management, clarifying that this setting is now handled directly in the 3x-ui by node administrators. - Enhanced the overall codebase by removing unnecessary device limit references across various components, ensuring a cleaner and more maintainable code structure.
This commit is contained in:
+7
-7
@@ -36,7 +36,7 @@ public class BlockUserCommandHandlerTests
|
||||
Assert.Equal(failure, result.Error);
|
||||
await _gateway.DidNotReceive().UpdateClientAsync(
|
||||
Arg.Any<Node>(), Arg.Any<string>(), Arg.Any<string>(), Arg.Any<VpnProtocol>(),
|
||||
Arg.Any<string>(), Arg.Any<int>(), Arg.Any<bool>(), Arg.Any<CancellationToken>());
|
||||
Arg.Any<string>(), Arg.Any<bool>(), Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -48,7 +48,7 @@ public class BlockUserCommandHandlerTests
|
||||
|
||||
var node = Node.Register("node-1", new Uri("https://node1.example.com"), new NodeCredentials("admin", "protected"), null);
|
||||
var inbound = Inbound.FromRemote(node.Id, "1", VpnProtocol.Vless, "remark", 443);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, "my-config", 0);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, "my-config");
|
||||
|
||||
dbContext.Nodes.Add(node);
|
||||
dbContext.Inbounds.Add(inbound);
|
||||
@@ -59,7 +59,7 @@ public class BlockUserCommandHandlerTests
|
||||
_currentUser.UserId.Returns(adminId);
|
||||
_gateway.UpdateClientAsync(
|
||||
Arg.Any<Node>(), Arg.Any<string>(), Arg.Any<string>(), Arg.Any<VpnProtocol>(),
|
||||
Arg.Any<string>(), Arg.Any<int>(), Arg.Any<bool>(), Arg.Any<CancellationToken>())
|
||||
Arg.Any<string>(), Arg.Any<bool>(), Arg.Any<CancellationToken>())
|
||||
.Returns(Result.Success());
|
||||
|
||||
var handler = new BlockUserCommandHandler(dbContext, _identityService, _gateway, _notifier, _telegramNotifier, _currentUser, _logger);
|
||||
@@ -71,7 +71,7 @@ public class BlockUserCommandHandlerTests
|
||||
|
||||
await _gateway.Received(1).UpdateClientAsync(
|
||||
Arg.Is<Node>(n => n.Id == node.Id), inbound.RemoteInboundId, config.ClientExternalId, config.Protocol,
|
||||
"my-config", config.DeviceLimit, enable: false, Arg.Any<CancellationToken>());
|
||||
"my-config", enable: false, Arg.Any<CancellationToken>());
|
||||
await _notifier.Received(1).NotifyConfigStatusChangedAsync(userId, config.Id, ConfigStatus.Disabled, Arg.Any<CancellationToken>());
|
||||
|
||||
var audit = Assert.Single(dbContext.AuditLogs.Local);
|
||||
@@ -95,7 +95,7 @@ public class BlockUserCommandHandlerTests
|
||||
Assert.True(result.IsSuccess);
|
||||
await _gateway.DidNotReceive().UpdateClientAsync(
|
||||
Arg.Any<Node>(), Arg.Any<string>(), Arg.Any<string>(), Arg.Any<VpnProtocol>(),
|
||||
Arg.Any<string>(), Arg.Any<int>(), Arg.Any<bool>(), Arg.Any<CancellationToken>());
|
||||
Arg.Any<string>(), Arg.Any<bool>(), Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -107,7 +107,7 @@ public class BlockUserCommandHandlerTests
|
||||
|
||||
var node = Node.Register("node-1", new Uri("https://node1.example.com"), new NodeCredentials("admin", "protected"), null);
|
||||
var inbound = Inbound.FromRemote(node.Id, "1", VpnProtocol.Vless, "remark", 443);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, "my-config", 0);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, "my-config");
|
||||
|
||||
dbContext.Nodes.Add(node);
|
||||
dbContext.Inbounds.Add(inbound);
|
||||
@@ -118,7 +118,7 @@ public class BlockUserCommandHandlerTests
|
||||
_currentUser.UserId.Returns(adminId);
|
||||
_gateway.UpdateClientAsync(
|
||||
Arg.Any<Node>(), Arg.Any<string>(), Arg.Any<string>(), Arg.Any<VpnProtocol>(),
|
||||
Arg.Any<string>(), Arg.Any<int>(), Arg.Any<bool>(), Arg.Any<CancellationToken>())
|
||||
Arg.Any<string>(), Arg.Any<bool>(), Arg.Any<CancellationToken>())
|
||||
.Returns(Result.Failure(Error.Failure("Xui.UpdateClientFailed", "Нода недоступна.")));
|
||||
|
||||
var handler = new BlockUserCommandHandler(dbContext, _identityService, _gateway, _notifier, _telegramNotifier, _currentUser, _logger);
|
||||
|
||||
+5
-5
@@ -28,7 +28,7 @@ public class UnblockUserCommandHandlerTests
|
||||
|
||||
var node = Node.Register("node-1", new Uri("https://node1.example.com"), new NodeCredentials("admin", "protected"), null);
|
||||
var inbound = Inbound.FromRemote(node.Id, "1", VpnProtocol.Vless, "remark", 443);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, "my-config", 0);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, "my-config");
|
||||
config.Disable();
|
||||
|
||||
dbContext.Nodes.Add(node);
|
||||
@@ -40,7 +40,7 @@ public class UnblockUserCommandHandlerTests
|
||||
_identityService.UnblockUserAsync(userId, Arg.Any<CancellationToken>()).Returns(Result.Success());
|
||||
_gateway.UpdateClientAsync(
|
||||
Arg.Any<Node>(), Arg.Any<string>(), Arg.Any<string>(), Arg.Any<VpnProtocol>(),
|
||||
Arg.Any<string>(), Arg.Any<int>(), Arg.Any<bool>(), Arg.Any<CancellationToken>())
|
||||
Arg.Any<string>(), Arg.Any<bool>(), Arg.Any<CancellationToken>())
|
||||
.Returns(Result.Success());
|
||||
|
||||
var handler = new UnblockUserCommandHandler(dbContext, _identityService, _gateway, _notifier, _currentUser, _logger);
|
||||
@@ -51,7 +51,7 @@ public class UnblockUserCommandHandlerTests
|
||||
Assert.Equal(ConfigStatus.Active, config.Status);
|
||||
await _gateway.Received(1).UpdateClientAsync(
|
||||
node, inbound.RemoteInboundId, config.ClientExternalId, config.Protocol,
|
||||
Arg.Any<string>(), config.DeviceLimit, true, Arg.Any<CancellationToken>());
|
||||
Arg.Any<string>(), true, Arg.Any<CancellationToken>());
|
||||
await _notifier.Received(1).NotifyConfigStatusChangedAsync(userId, config.Id, ConfigStatus.Active, Arg.Any<CancellationToken>());
|
||||
Assert.Single(dbContext.AuditLogs.Local);
|
||||
Assert.Equal("UserUnblocked", dbContext.AuditLogs.Local.Single().Action);
|
||||
@@ -84,7 +84,7 @@ public class UnblockUserCommandHandlerTests
|
||||
|
||||
var node = Node.Register("node-1", new Uri("https://node1.example.com"), new NodeCredentials("admin", "protected"), null);
|
||||
var inbound = Inbound.FromRemote(node.Id, "1", VpnProtocol.Vless, "remark", 443);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, "my-config", 0);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, "my-config");
|
||||
config.Disable();
|
||||
|
||||
dbContext.Nodes.Add(node);
|
||||
@@ -96,7 +96,7 @@ public class UnblockUserCommandHandlerTests
|
||||
_identityService.UnblockUserAsync(userId, Arg.Any<CancellationToken>()).Returns(Result.Success());
|
||||
_gateway.UpdateClientAsync(
|
||||
Arg.Any<Node>(), Arg.Any<string>(), Arg.Any<string>(), Arg.Any<VpnProtocol>(),
|
||||
Arg.Any<string>(), Arg.Any<int>(), Arg.Any<bool>(), Arg.Any<CancellationToken>())
|
||||
Arg.Any<string>(), Arg.Any<bool>(), Arg.Any<CancellationToken>())
|
||||
.Returns(Result.Failure(Error.Failure("Xui.UpdateClientFailed", "Нода недоступна.")));
|
||||
|
||||
var handler = new UnblockUserCommandHandler(dbContext, _identityService, _gateway, _notifier, _currentUser, _logger);
|
||||
|
||||
+3
-3
@@ -23,10 +23,10 @@ public class GetMyConfigsQueryHandlerTests
|
||||
var inbound = Inbound.FromRemote(Guid.NewGuid(), "1", VpnProtocol.Vless, "remark", 443);
|
||||
inbound.Publish("My inbound", [], null);
|
||||
|
||||
var activeConfig = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, "Active", 0);
|
||||
var revokedConfig = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, "Revoked", 0);
|
||||
var activeConfig = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, "Active");
|
||||
var revokedConfig = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, "Revoked");
|
||||
revokedConfig.Revoke();
|
||||
var otherUsersConfig = VpnConfig.Create(otherUserId, inbound.Id, VpnProtocol.Vless, "Other", 0);
|
||||
var otherUsersConfig = VpnConfig.Create(otherUserId, inbound.Id, VpnProtocol.Vless, "Other");
|
||||
|
||||
dbContext.Inbounds.Add(inbound);
|
||||
dbContext.VpnConfigs.AddRange(activeConfig, revokedConfig, otherUsersConfig);
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ public class RevokeVpnConfigCommandHandlerTests
|
||||
|
||||
var node = Node.Register("node-1", new Uri("https://node1.example.com"), new NodeCredentials("admin", "protected"), null);
|
||||
var inbound = Inbound.FromRemote(node.Id, "1", VpnProtocol.Vless, "remark", 443);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, null, 0);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, null);
|
||||
config.AssignRemoteClient("external-id");
|
||||
|
||||
dbContext.Nodes.Add(node);
|
||||
@@ -49,7 +49,7 @@ public class RevokeVpnConfigCommandHandlerTests
|
||||
var userId = Guid.NewGuid();
|
||||
|
||||
var inbound = Inbound.FromRemote(Guid.NewGuid(), "1", VpnProtocol.Vless, "remark", 443);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, null, 0);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, null);
|
||||
config.Revoke();
|
||||
|
||||
dbContext.Inbounds.Add(inbound);
|
||||
|
||||
+6
-6
@@ -24,7 +24,7 @@ public class RotateVpnConfigCommandHandlerTests
|
||||
|
||||
var node = Node.Register("node-1", new Uri("https://node1.example.com"), new NodeCredentials("admin", "protected"), null);
|
||||
var inbound = Inbound.FromRemote(node.Id, "1", VpnProtocol.Vless, "remark", 443);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, "my-config", 0);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, "my-config");
|
||||
config.AssignRemoteClient("old-external-id");
|
||||
|
||||
dbContext.Nodes.Add(node);
|
||||
@@ -34,7 +34,7 @@ public class RotateVpnConfigCommandHandlerTests
|
||||
|
||||
_gateway.AddClientAsync(
|
||||
Arg.Any<Node>(), inbound.RemoteInboundId, config.Protocol, Arg.Any<string>(),
|
||||
Arg.Any<string>(), config.DeviceLimit, Arg.Any<CancellationToken>())
|
||||
Arg.Any<string>(), Arg.Any<CancellationToken>())
|
||||
.Returns(Result.Success("new-external-id"));
|
||||
|
||||
var handler = new RotateVpnConfigCommandHandler(dbContext, _gateway, FakeCurrentUser.Authenticated(userId));
|
||||
@@ -69,7 +69,7 @@ public class RotateVpnConfigCommandHandlerTests
|
||||
var otherUserId = Guid.NewGuid();
|
||||
|
||||
var inbound = Inbound.FromRemote(Guid.NewGuid(), "1", VpnProtocol.Vless, "remark", 443);
|
||||
var config = VpnConfig.Create(ownerId, inbound.Id, VpnProtocol.Vless, null, 0);
|
||||
var config = VpnConfig.Create(ownerId, inbound.Id, VpnProtocol.Vless, null);
|
||||
|
||||
dbContext.Inbounds.Add(inbound);
|
||||
dbContext.VpnConfigs.Add(config);
|
||||
@@ -90,7 +90,7 @@ public class RotateVpnConfigCommandHandlerTests
|
||||
var userId = Guid.NewGuid();
|
||||
|
||||
var inbound = Inbound.FromRemote(Guid.NewGuid(), "1", VpnProtocol.Vless, "remark", 443);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, null, 0);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, null);
|
||||
config.Revoke();
|
||||
|
||||
dbContext.Inbounds.Add(inbound);
|
||||
@@ -113,7 +113,7 @@ public class RotateVpnConfigCommandHandlerTests
|
||||
|
||||
var node = Node.Register("node-1", new Uri("https://node1.example.com"), new NodeCredentials("admin", "protected"), null);
|
||||
var inbound = Inbound.FromRemote(node.Id, "1", VpnProtocol.Vless, "remark", 443);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, null, 0);
|
||||
var config = VpnConfig.Create(userId, inbound.Id, VpnProtocol.Vless, null);
|
||||
config.AssignRemoteClient("old-external-id");
|
||||
|
||||
dbContext.Nodes.Add(node);
|
||||
@@ -124,7 +124,7 @@ public class RotateVpnConfigCommandHandlerTests
|
||||
var gatewayError = Error.Failure("Xui.Unreachable", "Панель недоступна.");
|
||||
_gateway.AddClientAsync(
|
||||
Arg.Any<Node>(), inbound.RemoteInboundId, config.Protocol, Arg.Any<string>(),
|
||||
Arg.Any<string>(), config.DeviceLimit, Arg.Any<CancellationToken>())
|
||||
Arg.Any<string>(), Arg.Any<CancellationToken>())
|
||||
.Returns(Result.Failure<string>(gatewayError));
|
||||
|
||||
var handler = new RotateVpnConfigCommandHandler(dbContext, _gateway, FakeCurrentUser.Authenticated(userId));
|
||||
|
||||
@@ -13,13 +13,12 @@ public class VpnConfigTests
|
||||
var userId = Guid.NewGuid();
|
||||
var inboundId = Guid.NewGuid();
|
||||
|
||||
var config = VpnConfig.Create(userId, inboundId, VpnProtocol.Vless, "My device", deviceLimit: 3);
|
||||
var config = VpnConfig.Create(userId, inboundId, VpnProtocol.Vless, "My device");
|
||||
|
||||
Assert.Equal(userId, config.UserId);
|
||||
Assert.Equal(inboundId, config.InboundId);
|
||||
Assert.Equal(VpnProtocol.Vless, config.Protocol);
|
||||
Assert.Equal("My device", config.Label);
|
||||
Assert.Equal(3, config.DeviceLimit);
|
||||
Assert.Equal(ConfigStatus.Active, config.Status);
|
||||
Assert.Equal(string.Empty, config.ClientExternalId);
|
||||
Assert.False(string.IsNullOrWhiteSpace(config.ClientEmail));
|
||||
@@ -32,8 +31,8 @@ public class VpnConfigTests
|
||||
public void Create_GeneratesUniqueSubscriptionTokensAndClientEmails()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var a = VpnConfig.Create(userId, Guid.NewGuid(), VpnProtocol.Vless, null, 1);
|
||||
var b = VpnConfig.Create(userId, Guid.NewGuid(), VpnProtocol.Vless, null, 1);
|
||||
var a = VpnConfig.Create(userId, Guid.NewGuid(), VpnProtocol.Vless, null);
|
||||
var b = VpnConfig.Create(userId, Guid.NewGuid(), VpnProtocol.Vless, null);
|
||||
|
||||
Assert.NotEqual(a.SubscriptionToken, b.SubscriptionToken);
|
||||
Assert.NotEqual(a.ClientEmail, b.ClientEmail);
|
||||
@@ -42,7 +41,7 @@ public class VpnConfigTests
|
||||
[Fact]
|
||||
public void AssignRemoteClient_SetsClientExternalId()
|
||||
{
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Trojan, null, 1);
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Trojan, null);
|
||||
|
||||
config.AssignRemoteClient("some-remote-password");
|
||||
|
||||
@@ -52,7 +51,7 @@ public class VpnConfigTests
|
||||
[Fact]
|
||||
public void Rotate_WhenActive_ChangesEmailExternalIdAndToken()
|
||||
{
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null, 1);
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null);
|
||||
config.AssignRemoteClient("old-id");
|
||||
var oldToken = config.SubscriptionToken;
|
||||
var oldEmail = config.ClientEmail;
|
||||
@@ -70,7 +69,7 @@ public class VpnConfigTests
|
||||
[InlineData(ConfigStatus.Disabled)]
|
||||
public void Rotate_WhenNotActive_Throws(ConfigStatus status)
|
||||
{
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null, 1);
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null);
|
||||
MoveToStatus(config, status);
|
||||
|
||||
Assert.Throws<DomainException>(() => config.Rotate("e", "i"));
|
||||
@@ -79,7 +78,7 @@ public class VpnConfigTests
|
||||
[Fact]
|
||||
public void Revoke_WhenActive_SetsRevokedStatus()
|
||||
{
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null, 1);
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null);
|
||||
|
||||
config.Revoke();
|
||||
|
||||
@@ -89,7 +88,7 @@ public class VpnConfigTests
|
||||
[Fact]
|
||||
public void Revoke_WhenAlreadyRevoked_Throws()
|
||||
{
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null, 1);
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null);
|
||||
config.Revoke();
|
||||
|
||||
Assert.Throws<DomainException>(() => config.Revoke());
|
||||
@@ -98,7 +97,7 @@ public class VpnConfigTests
|
||||
[Fact]
|
||||
public void Disable_WhenActive_SetsDisabled()
|
||||
{
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null, 1);
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null);
|
||||
|
||||
config.Disable();
|
||||
|
||||
@@ -108,7 +107,7 @@ public class VpnConfigTests
|
||||
[Fact]
|
||||
public void Disable_WhenRevoked_DoesNotChangeStatus()
|
||||
{
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null, 1);
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null);
|
||||
config.Revoke();
|
||||
|
||||
config.Disable();
|
||||
@@ -119,7 +118,7 @@ public class VpnConfigTests
|
||||
[Fact]
|
||||
public void Enable_WhenDisabled_ReturnsToActive()
|
||||
{
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null, 1);
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null);
|
||||
config.Disable();
|
||||
|
||||
config.Enable();
|
||||
@@ -130,7 +129,7 @@ public class VpnConfigTests
|
||||
[Fact]
|
||||
public void Enable_WhenRevoked_DoesNotResurrect()
|
||||
{
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null, 1);
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null);
|
||||
config.Revoke();
|
||||
|
||||
config.Enable();
|
||||
@@ -141,7 +140,7 @@ public class VpnConfigTests
|
||||
[Fact]
|
||||
public void UpdateTraffic_SetsBytesAndLastSyncAt()
|
||||
{
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null, 1);
|
||||
var config = VpnConfig.Create(Guid.NewGuid(), Guid.NewGuid(), VpnProtocol.Vless, null);
|
||||
|
||||
config.UpdateTraffic(100, 200);
|
||||
|
||||
|
||||
@@ -87,7 +87,6 @@ public class ConfigQuotaTests(PnvPanelWebApplicationFactory factory)
|
||||
{
|
||||
inboundId = inbound.Id,
|
||||
label = $"device-{i}",
|
||||
deviceLimit = (int?)null,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ public sealed class FakeXuiPanelGateway : IXuiPanelGateway
|
||||
|
||||
public Task<Result<string>> AddClientAsync(
|
||||
Node node, string inboundRemoteId, VpnProtocol protocol, string clientEmail, string clientName,
|
||||
int deviceLimit, CancellationToken cancellationToken)
|
||||
CancellationToken cancellationToken)
|
||||
=> Task.FromResult(Result.Success(Guid.NewGuid().ToString()));
|
||||
|
||||
public Task<Result> RemoveClientAsync(
|
||||
@@ -41,7 +41,7 @@ public sealed class FakeXuiPanelGateway : IXuiPanelGateway
|
||||
|
||||
public Task<Result> UpdateClientAsync(
|
||||
Node node, string inboundRemoteId, string clientExternalId, VpnProtocol protocol,
|
||||
string name, int deviceLimit, bool enable, CancellationToken cancellationToken)
|
||||
string name, bool enable, CancellationToken cancellationToken)
|
||||
=> Task.FromResult(Result.Success());
|
||||
|
||||
public Task<Result<string>> BuildConnectionStringAsync(
|
||||
|
||||
Reference in New Issue
Block a user