mirror of
https://github.com/snltty/linker.git
synced 2025-09-27 05:25:57 +08:00
白名单
This commit is contained in:
@@ -16,7 +16,6 @@ namespace linker.messenger.api
|
|||||||
serviceCollection.AddSingleton<ActionTransfer>();
|
serviceCollection.AddSingleton<ActionTransfer>();
|
||||||
serviceCollection.AddSingleton<SignInArgsAction>();
|
serviceCollection.AddSingleton<SignInArgsAction>();
|
||||||
|
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ActionClientMessenger>();
|
serviceCollection.AddSingleton<ActionClientMessenger>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ActionSync>();
|
serviceCollection.AddSingleton<ActionSync>();
|
||||||
@@ -28,7 +27,7 @@ namespace linker.messenger.api
|
|||||||
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<ActionApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<ActionApiController>() });
|
||||||
|
|
||||||
SignInArgsTransfer signInArgsTransfer = serviceProvider.GetService<SignInArgsTransfer>();
|
SignInArgsTransfer signInArgsTransfer = serviceProvider.GetService<SignInArgsTransfer>();
|
||||||
signInArgsTransfer.AddArgs(new List<ISignInArgs> { serviceProvider.GetService<SignInArgsAction>() });
|
signInArgsTransfer.AddArgs(new List<ISignInArgsClient> { serviceProvider.GetService<SignInArgsAction>() });
|
||||||
|
|
||||||
IMessengerResolver messengerResolver = serviceProvider.GetService<IMessengerResolver>();
|
IMessengerResolver messengerResolver = serviceProvider.GetService<IMessengerResolver>();
|
||||||
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<ActionClientMessenger>() });
|
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<ActionClientMessenger>() });
|
||||||
@@ -52,7 +51,8 @@ namespace linker.messenger.api
|
|||||||
public static ServiceProvider UseActionServer(this ServiceProvider serviceProvider)
|
public static ServiceProvider UseActionServer(this ServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
SignInArgsTransfer signInArgsTransfer = serviceProvider.GetService<SignInArgsTransfer>();
|
SignInArgsTransfer signInArgsTransfer = serviceProvider.GetService<SignInArgsTransfer>();
|
||||||
signInArgsTransfer.AddArgs(new List<ISignInArgs> { serviceProvider.GetService<SignInArgsAction>() });
|
signInArgsTransfer.AddArgs(new List<ISignInArgsClient> { serviceProvider.GetService<SignInArgsAction>() });
|
||||||
|
signInArgsTransfer.AddArgs(new List<ISignInArgsServer> { serviceProvider.GetService<SignInArgsAction>() });
|
||||||
|
|
||||||
RelayServerValidatorTransfer relayServerValidatorTransfer = serviceProvider.GetService<RelayServerValidatorTransfer>();
|
RelayServerValidatorTransfer relayServerValidatorTransfer = serviceProvider.GetService<RelayServerValidatorTransfer>();
|
||||||
relayServerValidatorTransfer.AddValidators(new List<IRelayServerValidator> { serviceProvider.GetService<RelayValidatorAction>() });
|
relayServerValidatorTransfer.AddValidators(new List<IRelayServerValidator> { serviceProvider.GetService<RelayValidatorAction>() });
|
||||||
|
@@ -101,9 +101,12 @@ namespace linker.messenger.action
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class SignInArgsAction : JsonArgReplace, ISignInArgs
|
|
||||||
|
public sealed class SignInArgsAction : JsonArgReplace, ISignInArgsClient, ISignInArgsServer
|
||||||
{
|
{
|
||||||
public string Name => "action";
|
public string Name => "action";
|
||||||
|
public SignInArgsLevel Level => SignInArgsLevel.Default;
|
||||||
|
|
||||||
private readonly ActionTransfer actionTransfer;
|
private readonly ActionTransfer actionTransfer;
|
||||||
private readonly IActionClientStore actionStore;
|
private readonly IActionClientStore actionStore;
|
||||||
private readonly IActionServerStore actionServerStore;
|
private readonly IActionServerStore actionServerStore;
|
||||||
@@ -153,7 +156,7 @@ namespace linker.messenger.action
|
|||||||
public string Name => "action";
|
public string Name => "action";
|
||||||
private readonly ActionTransfer actionTransfer;
|
private readonly ActionTransfer actionTransfer;
|
||||||
private readonly IActionServerStore actionServerStore;
|
private readonly IActionServerStore actionServerStore;
|
||||||
public RelayValidatorAction(ActionTransfer actionTransfer, IActionServerStore actionServerStore)
|
public RelayValidatorAction(ActionTransfer actionTransfer, IActionServerStore actionServerStore)
|
||||||
{
|
{
|
||||||
this.actionTransfer = actionTransfer;
|
this.actionTransfer = actionTransfer;
|
||||||
this.actionServerStore = actionServerStore;
|
this.actionServerStore = actionServerStore;
|
||||||
|
@@ -152,6 +152,9 @@ namespace linker.messenger.api
|
|||||||
|
|
||||||
[AccessDisplay("修改所有验证参数")]
|
[AccessDisplay("修改所有验证参数")]
|
||||||
ActionOther = 48,
|
ActionOther = 48,
|
||||||
|
|
||||||
|
[AccessDisplay("中继白名单")]
|
||||||
|
User2Node = 49,
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class AccessTextInfo
|
public sealed class AccessTextInfo
|
||||||
|
@@ -95,6 +95,11 @@ namespace linker.messenger.relay
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新节点
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task<bool> UpdateNode(ApiControllerParamsInfo param)
|
public async Task<bool> UpdateNode(ApiControllerParamsInfo param)
|
||||||
{
|
{
|
||||||
RelayServerNodeUpdateInfo info = param.Content.DeJson<RelayServerNodeUpdateInfo>();
|
RelayServerNodeUpdateInfo info = param.Content.DeJson<RelayServerNodeUpdateInfo>();
|
||||||
@@ -111,6 +116,11 @@ namespace linker.messenger.relay
|
|||||||
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
|
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查密钥
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task<bool> CheckKey(ApiControllerParamsInfo param)
|
public async Task<bool> CheckKey(ApiControllerParamsInfo param)
|
||||||
{
|
{
|
||||||
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
@@ -121,6 +131,71 @@ namespace linker.messenger.relay
|
|||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
|
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加用户到节点
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<bool> AddUser2Node(ApiControllerParamsInfo param)
|
||||||
|
{
|
||||||
|
RelayServerUser2NodeInfo info = param.Content.DeJson<RelayServerUser2NodeInfo>();
|
||||||
|
var resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = signInClientState.Connection,
|
||||||
|
MessengerId = (ushort)RelayMessengerIds.AddUser2Node,
|
||||||
|
Payload = serializer.Serialize(new RelayServerUser2NodeAddInfo
|
||||||
|
{
|
||||||
|
Data = info,
|
||||||
|
SecretKey = relayClientStore.Server.SecretKey
|
||||||
|
})
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除用户到节点
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<bool> DelUser2Node(ApiControllerParamsInfo param)
|
||||||
|
{
|
||||||
|
var resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = signInClientState.Connection,
|
||||||
|
MessengerId = (ushort)RelayMessengerIds.DelUser2Node,
|
||||||
|
Payload = serializer.Serialize(new RelayServerUser2NodeDelInfo
|
||||||
|
{
|
||||||
|
Id = int.Parse(param.Content),
|
||||||
|
SecretKey = relayClientStore.Server.SecretKey
|
||||||
|
})
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 用户到节点分页查询
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<RelayServerUser2NodePageResultInfo> PageUser2Node(ApiControllerParamsInfo param)
|
||||||
|
{
|
||||||
|
RelayServerUser2NodePageRequestInfo info = param.Content.DeJson<RelayServerUser2NodePageRequestInfo>();
|
||||||
|
info.SecretKey = relayClientStore.Server.SecretKey;
|
||||||
|
var resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = signInClientState.Connection,
|
||||||
|
MessengerId = (ushort)RelayMessengerIds.PageUser2Node,
|
||||||
|
Payload = serializer.Serialize(info)
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
if (resp.Code == MessageResponeCodes.OK)
|
||||||
|
{
|
||||||
|
return serializer.Deserialize<RelayServerUser2NodePageResultInfo>(resp.Data.Span);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RelayServerUser2NodePageResultInfo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class SyncInfo
|
public sealed class SyncInfo
|
||||||
|
@@ -46,20 +46,20 @@ namespace linker.messenger.relay.messenger
|
|||||||
private readonly RelayServerMasterTransfer relayServerTransfer;
|
private readonly RelayServerMasterTransfer relayServerTransfer;
|
||||||
private readonly RelayServerValidatorTransfer relayValidatorTransfer;
|
private readonly RelayServerValidatorTransfer relayValidatorTransfer;
|
||||||
private readonly ISerializer serializer;
|
private readonly ISerializer serializer;
|
||||||
private readonly ICdkeyServerStore cdkeyStore;
|
|
||||||
private readonly IRelayServerStore relayServerStore;
|
private readonly IRelayServerStore relayServerStore;
|
||||||
private readonly RelayServerNodeTransfer relayServerNodeTransfer;
|
private readonly RelayServerNodeTransfer relayServerNodeTransfer;
|
||||||
|
private readonly IRelayServerUser2NodeStore relayServerUser2NodeStore;
|
||||||
|
|
||||||
public RelayServerMessenger(IMessengerSender messengerSender, SignInServerCaching signCaching, ISerializer serializer, RelayServerMasterTransfer relayServerTransfer, RelayServerValidatorTransfer relayValidatorTransfer, ICdkeyServerStore cdkeyStore, IRelayServerStore relayServerStore, RelayServerNodeTransfer relayServerNodeTransfer)
|
public RelayServerMessenger(IMessengerSender messengerSender, SignInServerCaching signCaching, ISerializer serializer, RelayServerMasterTransfer relayServerTransfer, RelayServerValidatorTransfer relayValidatorTransfer, IRelayServerStore relayServerStore, RelayServerNodeTransfer relayServerNodeTransfer, IRelayServerUser2NodeStore relayServerUser2NodeStore)
|
||||||
{
|
{
|
||||||
this.messengerSender = messengerSender;
|
this.messengerSender = messengerSender;
|
||||||
this.signCaching = signCaching;
|
this.signCaching = signCaching;
|
||||||
this.relayServerTransfer = relayServerTransfer;
|
this.relayServerTransfer = relayServerTransfer;
|
||||||
this.relayValidatorTransfer = relayValidatorTransfer;
|
this.relayValidatorTransfer = relayValidatorTransfer;
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
this.cdkeyStore = cdkeyStore;
|
|
||||||
this.relayServerStore = relayServerStore;
|
this.relayServerStore = relayServerStore;
|
||||||
this.relayServerNodeTransfer = relayServerNodeTransfer;
|
this.relayServerNodeTransfer = relayServerNodeTransfer;
|
||||||
|
this.relayServerUser2NodeStore = relayServerUser2NodeStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -70,39 +70,40 @@ namespace linker.messenger.relay.messenger
|
|||||||
public async Task RelayTest(IConnection connection)
|
public async Task RelayTest(IConnection connection)
|
||||||
{
|
{
|
||||||
RelayTestInfo info = serializer.Deserialize<RelayTestInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
RelayTestInfo info = serializer.Deserialize<RelayTestInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
await RelayTest(connection, info, (validated) =>
|
|
||||||
{
|
|
||||||
List<RelayServerNodeReportInfo> list = relayServerTransfer.GetNodes(validated).Select(c => (RelayServerNodeReportInfo)c).ToList();
|
|
||||||
|
|
||||||
return serializer.Serialize(list);
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
[MessengerId((ushort)RelayMessengerIds.RelayTest170)]
|
|
||||||
public async Task RelayTest170(IConnection connection)
|
|
||||||
{
|
|
||||||
RelayTestInfo170 info = serializer.Deserialize<RelayTestInfo170>(connection.ReceiveRequestWrap.Payload.Span);
|
|
||||||
await RelayTest(connection, info, (validated) =>
|
|
||||||
{
|
|
||||||
return serializer.Serialize(relayServerTransfer.GetNodes(validated));
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
private async Task RelayTest(IConnection connection, RelayTestInfo info, Func<bool, byte[]> data)
|
|
||||||
{
|
|
||||||
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache) == false)
|
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache) == false)
|
||||||
{
|
{
|
||||||
connection.Write(Helper.FalseArray);
|
connection.Write(serializer.Serialize(new List<RelayServerNodeReportInfo> { }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
string result = await relayValidatorTransfer.Validate(new client.transport.RelayInfo
|
(List<RelayServerNodeReportInfo170> nodes, bool validated) = await GetNodes(new client.transport.RelayInfo170
|
||||||
{
|
{
|
||||||
SecretKey = info.SecretKey,
|
SecretKey = info.SecretKey,
|
||||||
FromMachineId = info.MachineId,
|
FromMachineId = info.MachineId,
|
||||||
FromMachineName = cache.MachineName,
|
FromMachineName = cache.MachineName,
|
||||||
TransactionId = "test",
|
TransactionId = "test",
|
||||||
TransportName = "test",
|
TransportName = "test",
|
||||||
}, cache, null).ConfigureAwait(false);
|
}, cache, null);
|
||||||
|
connection.Write(serializer.Serialize(nodes.Select(c => (RelayServerNodeReportInfo)c).ToList()));
|
||||||
connection.Write(data(string.IsNullOrWhiteSpace(result)));
|
}
|
||||||
|
[MessengerId((ushort)RelayMessengerIds.RelayTest170)]
|
||||||
|
public async Task RelayTest170(IConnection connection)
|
||||||
|
{
|
||||||
|
RelayTestInfo170 info = serializer.Deserialize<RelayTestInfo170>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache) == false)
|
||||||
|
{
|
||||||
|
connection.Write(serializer.Serialize(new List<RelayServerNodeReportInfo170> { }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(List<RelayServerNodeReportInfo170> nodes, bool validated) = await GetNodes(new client.transport.RelayInfo170
|
||||||
|
{
|
||||||
|
SecretKey = info.SecretKey,
|
||||||
|
FromMachineId = info.MachineId,
|
||||||
|
FromMachineName = cache.MachineName,
|
||||||
|
UserId = info.UserId,
|
||||||
|
TransactionId = "test",
|
||||||
|
TransportName = "test",
|
||||||
|
}, cache, null);
|
||||||
|
connection.Write(serializer.Serialize(nodes));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -125,15 +126,12 @@ namespace linker.messenger.relay.messenger
|
|||||||
info.FromMachineName = from.MachineName;
|
info.FromMachineName = from.MachineName;
|
||||||
|
|
||||||
RelayAskResultInfo result = new RelayAskResultInfo();
|
RelayAskResultInfo result = new RelayAskResultInfo();
|
||||||
string error = await relayValidatorTransfer.Validate(info, from, to).ConfigureAwait(false);
|
(List<RelayServerNodeReportInfo170> nodes, bool validated) = await GetNodes(info, from, to);
|
||||||
bool validated = string.IsNullOrWhiteSpace(error);
|
result.Nodes = nodes.Select(c => (RelayServerNodeReportInfo)c).ToList();
|
||||||
result.Nodes = relayServerTransfer.GetNodes(validated).Select(c => (RelayServerNodeReportInfo)c).ToList();
|
|
||||||
|
|
||||||
if (result.Nodes.Count > 0)
|
if (result.Nodes.Count > 0)
|
||||||
{
|
{
|
||||||
result.FlowingId = relayServerTransfer.AddRelay(from.MachineId, from.MachineName, to.MachineId, to.MachineName, from.GroupId, validated, []);
|
result.FlowingId = relayServerTransfer.AddRelay(from.MachineId, from.MachineName, to.MachineId, to.MachineName, from.GroupId, string.Empty, validated, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
connection.Write(serializer.Serialize(result));
|
connection.Write(serializer.Serialize(result));
|
||||||
}
|
}
|
||||||
[MessengerId((ushort)RelayMessengerIds.RelayAsk170)]
|
[MessengerId((ushort)RelayMessengerIds.RelayAsk170)]
|
||||||
@@ -152,22 +150,29 @@ namespace linker.messenger.relay.messenger
|
|||||||
info.FromMachineName = from.MachineName;
|
info.FromMachineName = from.MachineName;
|
||||||
|
|
||||||
RelayAskResultInfo170 result = new RelayAskResultInfo170();
|
RelayAskResultInfo170 result = new RelayAskResultInfo170();
|
||||||
string error = await relayValidatorTransfer.Validate(info, from, to).ConfigureAwait(false);
|
(result.Nodes, bool validated) = await GetNodes(info, from, to).ConfigureAwait(false);
|
||||||
bool validated = string.IsNullOrWhiteSpace(error);
|
|
||||||
result.Nodes = relayServerTransfer.GetNodes(validated);
|
|
||||||
|
|
||||||
if (result.Nodes.Count > 0)
|
if (result.Nodes.Count > 0)
|
||||||
{
|
{
|
||||||
List<CdkeyInfo> cdkeys = info.UseCdkey
|
result.FlowingId = relayServerTransfer.AddRelay(from.MachineId, from.MachineName, to.MachineId, to.MachineName, from.GroupId, info.UserId, validated, info.UseCdkey);
|
||||||
? (await cdkeyStore.GetAvailable(info.UserId, "Relay").ConfigureAwait(false)).Select(c => new CdkeyInfo { Bandwidth = c.Bandwidth, Id = c.Id, LastBytes = c.LastBytes }).ToList()
|
|
||||||
: [];
|
|
||||||
|
|
||||||
result.FlowingId = relayServerTransfer.AddRelay(from.MachineId, from.MachineName, to.MachineId, to.MachineName, from.GroupId, validated, cdkeys);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connection.Write(serializer.Serialize(result));
|
connection.Write(serializer.Serialize(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<(List<RelayServerNodeReportInfo170>, bool)> GetNodes(RelayInfo relayInfo, SignCacheInfo from, SignCacheInfo to)
|
||||||
|
{
|
||||||
|
string error = await relayValidatorTransfer.Validate(relayInfo, from, to).ConfigureAwait(false);
|
||||||
|
bool validated = string.IsNullOrWhiteSpace(error);
|
||||||
|
return (await relayServerTransfer.GetNodes(validated, string.Empty), validated);
|
||||||
|
}
|
||||||
|
private async Task<(List<RelayServerNodeReportInfo170>, bool)> GetNodes(RelayInfo170 relayInfo, SignCacheInfo from, SignCacheInfo to)
|
||||||
|
{
|
||||||
|
string error = await relayValidatorTransfer.Validate(relayInfo, from, to).ConfigureAwait(false);
|
||||||
|
bool validated = string.IsNullOrWhiteSpace(error);
|
||||||
|
return (await relayServerTransfer.GetNodes(validated, relayInfo.UserId), validated);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 收到中继请求
|
/// 收到中继请求
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -242,17 +247,31 @@ namespace linker.messenger.relay.messenger
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取缓存
|
/// 获取缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="connection"></param>
|
/// <param name="connection"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[MessengerId((ushort)RelayMessengerIds.NodeGetCache)]
|
[MessengerId((ushort)RelayMessengerIds.NodeGetCache)]
|
||||||
public void NodeGetCache(IConnection connection)
|
public async Task NodeGetCache(IConnection connection)
|
||||||
{
|
{
|
||||||
string key = serializer.Deserialize<string>(connection.ReceiveRequestWrap.Payload.Span);
|
string key = serializer.Deserialize<string>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
if (relayServerTransfer.TryGetRelayCache(key, out RelayCacheInfo cache))
|
RelayCacheInfo cache = await relayServerTransfer.TryGetRelayCache(key, string.Empty);
|
||||||
|
if (cache != null)
|
||||||
|
{
|
||||||
|
connection.Write(serializer.Serialize(cache));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connection.Write(Helper.EmptyArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[MessengerId((ushort)RelayMessengerIds.NodeGetCache186)]
|
||||||
|
public async Task NodeGetCache186(IConnection connection)
|
||||||
|
{
|
||||||
|
ValueTuple<string, string> key = serializer.Deserialize<ValueTuple<string, string>>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
RelayCacheInfo cache = await relayServerTransfer.TryGetRelayCache(key.Item1, key.Item2);
|
||||||
|
if (cache != null)
|
||||||
{
|
{
|
||||||
connection.Write(serializer.Serialize(cache));
|
connection.Write(serializer.Serialize(cache));
|
||||||
}
|
}
|
||||||
@@ -262,7 +281,7 @@ namespace linker.messenger.relay.messenger
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取缓存
|
/// 节点报告
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="connection"></param>
|
/// <param name="connection"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
@@ -326,11 +345,89 @@ namespace linker.messenger.relay.messenger
|
|||||||
relayServerNodeTransfer.UpdateLastBytes(info);
|
relayServerNodeTransfer.UpdateLastBytes(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查密钥
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connection"></param>
|
||||||
[MessengerId((ushort)RelayMessengerIds.CheckKey)]
|
[MessengerId((ushort)RelayMessengerIds.CheckKey)]
|
||||||
public void CheckKey(IConnection connection)
|
public void CheckKey(IConnection connection)
|
||||||
{
|
{
|
||||||
string key = serializer.Deserialize<string>(connection.ReceiveRequestWrap.Payload.Span);
|
string key = serializer.Deserialize<string>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
connection.Write(relayServerStore.ValidateSecretKey(key) ? Helper.TrueArray : Helper.FalseArray);
|
connection.Write(relayServerStore.ValidateSecretKey(key) ? Helper.TrueArray : Helper.FalseArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加CDKEY
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connection"></param>
|
||||||
|
[MessengerId((ushort)RelayMessengerIds.AddUser2Node)]
|
||||||
|
public async Task AddUser2Node(IConnection connection)
|
||||||
|
{
|
||||||
|
RelayServerUser2NodeAddInfo info = serializer.Deserialize<RelayServerUser2NodeAddInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache) == false)
|
||||||
|
{
|
||||||
|
connection.Write(Helper.FalseArray);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (relayServerStore.ValidateSecretKey(info.SecretKey) == false)
|
||||||
|
{
|
||||||
|
connection.Write(Helper.FalseArray);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await relayServerUser2NodeStore.Add(info.Data).ConfigureAwait(false);
|
||||||
|
connection.Write(Helper.TrueArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除Cdkey
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connection"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[MessengerId((ushort)RelayMessengerIds.DelUser2Node)]
|
||||||
|
public async Task DelUser2Node(IConnection connection)
|
||||||
|
{
|
||||||
|
RelayServerUser2NodeDelInfo info = serializer.Deserialize<RelayServerUser2NodeDelInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache) == false)
|
||||||
|
{
|
||||||
|
connection.Write(Helper.FalseArray);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (relayServerStore.ValidateSecretKey(info.SecretKey) == false)
|
||||||
|
{
|
||||||
|
connection.Write(Helper.FalseArray);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await relayServerUser2NodeStore.Del(info.Id).ConfigureAwait(false);
|
||||||
|
connection.Write(Helper.TrueArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查询CDKEY
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connection"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[MessengerId((ushort)RelayMessengerIds.PageUser2Node)]
|
||||||
|
public async Task PageUser2Node(IConnection connection)
|
||||||
|
{
|
||||||
|
RelayServerUser2NodePageRequestInfo info = serializer.Deserialize<RelayServerUser2NodePageRequestInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache) == false)
|
||||||
|
{
|
||||||
|
connection.Write(serializer.Serialize(new RelayServerUser2NodePageResultInfo { }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (relayServerStore.ValidateSecretKey(info.SecretKey) == false && string.IsNullOrWhiteSpace(info.UserId))
|
||||||
|
{
|
||||||
|
connection.Write(serializer.Serialize(new RelayServerUser2NodePageResultInfo { }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var page = await relayServerUser2NodeStore.Page(info).ConfigureAwait(false);
|
||||||
|
|
||||||
|
connection.Write(serializer.Serialize(page));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -31,6 +31,12 @@
|
|||||||
|
|
||||||
CheckKey = 2123,
|
CheckKey = 2123,
|
||||||
|
|
||||||
|
AddUser2Node = 2124,
|
||||||
|
DelUser2Node = 2125,
|
||||||
|
PageUser2Node = 2126,
|
||||||
|
|
||||||
|
NodeGetCache186 = 2127,
|
||||||
|
|
||||||
Max = 2199
|
Max = 2199
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -130,7 +130,7 @@ namespace linker.messenger.relay.server
|
|||||||
|
|
||||||
public long LastTicks { get; set; }
|
public long LastTicks { get; set; }
|
||||||
}
|
}
|
||||||
public sealed partial class RelayServerNodeReportInfo170 : RelayServerNodeReportInfo
|
public partial class RelayServerNodeReportInfo170 : RelayServerNodeReportInfo
|
||||||
{
|
{
|
||||||
public string Url { get; set; } = "https://linker-doc.snltty.com";
|
public string Url { get; set; } = "https://linker-doc.snltty.com";
|
||||||
public TunnelProtocolType AllowProtocol { get; set; } = TunnelProtocolType.Tcp;
|
public TunnelProtocolType AllowProtocol { get; set; } = TunnelProtocolType.Tcp;
|
||||||
|
@@ -0,0 +1,47 @@
|
|||||||
|
namespace linker.messenger.relay.server
|
||||||
|
{
|
||||||
|
public interface IRelayServerUser2NodeStore
|
||||||
|
{
|
||||||
|
public Task<RelayServerUser2NodePageResultInfo> Page(RelayServerUser2NodePageRequestInfo request);
|
||||||
|
public Task<bool> Add(RelayServerUser2NodeInfo info);
|
||||||
|
public Task<bool> Del(int id);
|
||||||
|
|
||||||
|
public Task<List<string>> Get(string userid);
|
||||||
|
}
|
||||||
|
public sealed partial class RelayServerUser2NodeDelInfo
|
||||||
|
{
|
||||||
|
public string SecretKey { get; set; }
|
||||||
|
public int Id { get; set; }
|
||||||
|
}
|
||||||
|
public sealed partial class RelayServerUser2NodeAddInfo
|
||||||
|
{
|
||||||
|
public string SecretKey { get; set; }
|
||||||
|
public RelayServerUser2NodeInfo Data { get; set; }
|
||||||
|
}
|
||||||
|
public sealed partial class RelayServerUser2NodePageRequestInfo
|
||||||
|
{
|
||||||
|
public int Page { get; set; }
|
||||||
|
public int Size { get; set; }
|
||||||
|
public string UserId { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Remark { get; set; }
|
||||||
|
public string SecretKey { get; set; }
|
||||||
|
}
|
||||||
|
public sealed partial class RelayServerUser2NodePageResultInfo
|
||||||
|
{
|
||||||
|
public int Page { get; set; }
|
||||||
|
public int Size { get; set; }
|
||||||
|
public int Count { get; set; }
|
||||||
|
public List<RelayServerUser2NodeInfo> List { get; set; }
|
||||||
|
}
|
||||||
|
public sealed partial class RelayServerUser2NodeInfo
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string UserId { get; set; } = string.Empty;
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public string Remark { get; set; } = string.Empty;
|
||||||
|
public DateTime AddTime { get; set; } = DateTime.Now;
|
||||||
|
|
||||||
|
public string[] Nodes { get; set; } = [];
|
||||||
|
}
|
||||||
|
}
|
@@ -1,5 +1,6 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.timer;
|
using linker.libs.timer;
|
||||||
|
using linker.libs.winapis;
|
||||||
using linker.messenger.cdkey;
|
using linker.messenger.cdkey;
|
||||||
using linker.messenger.relay.messenger;
|
using linker.messenger.relay.messenger;
|
||||||
using linker.messenger.relay.server.caching;
|
using linker.messenger.relay.server.caching;
|
||||||
@@ -24,20 +25,23 @@ namespace linker.messenger.relay.server
|
|||||||
private readonly IRelayServerMasterStore relayServerMasterStore;
|
private readonly IRelayServerMasterStore relayServerMasterStore;
|
||||||
private readonly ICdkeyServerStore relayServerCdkeyStore;
|
private readonly ICdkeyServerStore relayServerCdkeyStore;
|
||||||
private readonly IMessengerSender messengerSender;
|
private readonly IMessengerSender messengerSender;
|
||||||
|
private readonly IRelayServerUser2NodeStore relayServerUser2NodeStore;
|
||||||
|
private readonly ICdkeyServerStore cdkeyServerStore;
|
||||||
|
|
||||||
|
public RelayServerMasterTransfer(IRelayServerCaching relayCaching, ISerializer serializer, IRelayServerMasterStore relayServerMasterStore, ICdkeyServerStore relayServerCdkeyStore, IMessengerSender messengerSender, IRelayServerUser2NodeStore relayServerUser2NodeStore, ICdkeyServerStore cdkeyServerStore)
|
||||||
public RelayServerMasterTransfer(IRelayServerCaching relayCaching, ISerializer serializer, IRelayServerMasterStore relayServerMasterStore, ICdkeyServerStore relayServerCdkeyStore, IMessengerSender messengerSender)
|
|
||||||
{
|
{
|
||||||
this.relayCaching = relayCaching;
|
this.relayCaching = relayCaching;
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
this.relayServerMasterStore = relayServerMasterStore;
|
this.relayServerMasterStore = relayServerMasterStore;
|
||||||
this.relayServerCdkeyStore = relayServerCdkeyStore;
|
this.relayServerCdkeyStore = relayServerCdkeyStore;
|
||||||
this.messengerSender = messengerSender;
|
this.messengerSender = messengerSender;
|
||||||
|
this.relayServerUser2NodeStore = relayServerUser2NodeStore;
|
||||||
|
this.cdkeyServerStore = cdkeyServerStore;
|
||||||
TrafficTask();
|
TrafficTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ulong AddRelay(string fromid, string fromName, string toid, string toName, string groupid, bool validated, List<CdkeyInfo> cdkeys)
|
public ulong AddRelay(string fromid, string fromName, string toid, string toName, string groupid, string userid, bool validated, bool useCdkey)
|
||||||
{
|
{
|
||||||
ulong flowingId = Interlocked.Increment(ref relayFlowingId);
|
ulong flowingId = Interlocked.Increment(ref relayFlowingId);
|
||||||
|
|
||||||
@@ -49,8 +53,9 @@ namespace linker.messenger.relay.server
|
|||||||
ToId = toid,
|
ToId = toid,
|
||||||
ToName = toName,
|
ToName = toName,
|
||||||
GroupId = groupid,
|
GroupId = groupid,
|
||||||
|
UserId = userid,
|
||||||
Validated = validated,
|
Validated = validated,
|
||||||
Cdkey = cdkeys
|
UseCdkey = useCdkey,
|
||||||
};
|
};
|
||||||
bool added = relayCaching.TryAdd($"{fromid}->{toid}->{flowingId}", cache, 15000);
|
bool added = relayCaching.TryAdd($"{fromid}->{toid}->{flowingId}", cache, 15000);
|
||||||
if (added == false) return 0;
|
if (added == false) return 0;
|
||||||
@@ -58,9 +63,16 @@ namespace linker.messenger.relay.server
|
|||||||
return flowingId;
|
return flowingId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetRelayCache(string key, out RelayCacheInfo value)
|
public async Task<RelayCacheInfo> TryGetRelayCache(string key, string nodeid)
|
||||||
{
|
{
|
||||||
return relayCaching.TryGetValue(key, out value);
|
if (relayCaching.TryGetValue(key, out RelayCacheInfo value))
|
||||||
|
{
|
||||||
|
value.Validated = value.Validated || (await relayServerUser2NodeStore.Get(value.UserId)).Contains(nodeid);
|
||||||
|
value.Cdkey = value.UseCdkey
|
||||||
|
? (await cdkeyServerStore.GetAvailable(value.UserId, "Relay").ConfigureAwait(false)).Select(c => new CdkeyInfo { Bandwidth = c.Bandwidth, Id = c.Id, LastBytes = c.LastBytes }).ToList()
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置节点
|
/// 设置节点
|
||||||
@@ -113,12 +125,17 @@ namespace linker.messenger.relay.server
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="validated">是否已认证</param>
|
/// <param name="validated">是否已认证</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public List<RelayServerNodeReportInfo170> GetNodes(bool validated)
|
public async Task<List<RelayServerNodeReportInfo170>> GetNodes(bool validated, string userid)
|
||||||
{
|
{
|
||||||
|
var nodes = await relayServerUser2NodeStore.Get(userid);
|
||||||
|
|
||||||
var result = reports.Values
|
var result = reports.Values
|
||||||
.Where(c => c.Public || validated)
|
|
||||||
.Where(c => Environment.TickCount64 - c.LastTicks < 15000)
|
.Where(c => Environment.TickCount64 - c.LastTicks < 15000)
|
||||||
.Where(c => validated || (c.ConnectionRatio < c.MaxConnection && (c.MaxGbTotal == 0 || (c.MaxGbTotal > 0 && c.MaxGbTotalLastBytes > 0))))
|
.Where(c =>
|
||||||
|
{
|
||||||
|
return validated || nodes.Contains(c.Id)
|
||||||
|
|| (c.Public && (c.ConnectionRatio < c.MaxConnection && (c.MaxGbTotal == 0 || (c.MaxGbTotal > 0 && c.MaxGbTotalLastBytes > 0))));
|
||||||
|
})
|
||||||
.OrderByDescending(c => c.LastTicks);
|
.OrderByDescending(c => c.LastTicks);
|
||||||
|
|
||||||
return result.OrderByDescending(x => x.MaxConnection == 0 ? int.MaxValue : x.MaxConnection)
|
return result.OrderByDescending(x => x.MaxConnection == 0 ? int.MaxValue : x.MaxConnection)
|
||||||
@@ -148,7 +165,6 @@ namespace linker.messenger.relay.server
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public void AddTraffic(RelayTrafficUpdateInfo info)
|
public void AddTraffic(RelayTrafficUpdateInfo info)
|
||||||
{
|
{
|
||||||
if (info.SecretKey != relayServerMasterStore.Master.SecretKey) return;
|
|
||||||
if (info.Dic.Count == 0) return;
|
if (info.Dic.Count == 0) return;
|
||||||
|
|
||||||
trafficQueue.Enqueue(info.Dic);
|
trafficQueue.Enqueue(info.Dic);
|
||||||
|
@@ -60,17 +60,15 @@ namespace linker.messenger.relay.server
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<RelayCacheInfo> TryGetRelayCache(string key)
|
||||||
|
|
||||||
public async ValueTask<RelayCacheInfo> TryGetRelayCache(string key)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
{
|
{
|
||||||
Connection = connection,
|
Connection = connection,
|
||||||
MessengerId = (ushort)RelayMessengerIds.NodeGetCache,
|
MessengerId = (ushort)RelayMessengerIds.NodeGetCache186,
|
||||||
Payload = serializer.Serialize(key)
|
Payload = serializer.Serialize(new ValueTuple<string, string>(key, node.Id))
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
if (resp.Code == MessageResponeCodes.OK && resp.Data.Length > 0)
|
if (resp.Code == MessageResponeCodes.OK && resp.Data.Length > 0)
|
||||||
{
|
{
|
||||||
@@ -94,7 +92,6 @@ namespace linker.messenger.relay.server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public bool Validate(TunnelProtocolType tunnelProtocolType)
|
public bool Validate(TunnelProtocolType tunnelProtocolType)
|
||||||
{
|
{
|
||||||
if (tunnelProtocolType == TunnelProtocolType.Udp && node.AllowUdp == false) return false;
|
if (tunnelProtocolType == TunnelProtocolType.Udp && node.AllowUdp == false) return false;
|
||||||
@@ -362,7 +359,7 @@ namespace linker.messenger.relay.server
|
|||||||
ConnectionRatio = connectionNum,
|
ConnectionRatio = connectionNum,
|
||||||
EndPoint = endPoint,
|
EndPoint = endPoint,
|
||||||
Url = node.Url,
|
Url = node.Url,
|
||||||
AllowProtocol = (node.AllowTcp ? TunnelProtocolType.Tcp :TunnelProtocolType.None)
|
AllowProtocol = (node.AllowTcp ? TunnelProtocolType.Tcp : TunnelProtocolType.None)
|
||||||
| (node.AllowUdp ? TunnelProtocolType.Udp : TunnelProtocolType.None)
|
| (node.AllowUdp ? TunnelProtocolType.Udp : TunnelProtocolType.None)
|
||||||
};
|
};
|
||||||
await messengerSender.SendOnly(new MessageRequestWrap
|
await messengerSender.SendOnly(new MessageRequestWrap
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Buffers;
|
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using System;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using linker.libs.timer;
|
using linker.libs.timer;
|
||||||
using linker.messenger.cdkey;
|
using linker.messenger.cdkey;
|
||||||
@@ -417,9 +415,11 @@ namespace linker.messenger.relay.server
|
|||||||
public string ToId { get; set; }
|
public string ToId { get; set; }
|
||||||
public string ToName { get; set; }
|
public string ToName { get; set; }
|
||||||
public string GroupId { get; set; }
|
public string GroupId { get; set; }
|
||||||
|
public string UserId { get; set; }
|
||||||
public bool Validated { get; set; }
|
public bool Validated { get; set; }
|
||||||
|
|
||||||
public List<CdkeyInfo> Cdkey { get; set; }
|
public bool UseCdkey { get; set; }
|
||||||
|
public List<CdkeyInfo> Cdkey { get; set; } = [];
|
||||||
}
|
}
|
||||||
public sealed class RelayTrafficCacheInfo
|
public sealed class RelayTrafficCacheInfo
|
||||||
{
|
{
|
||||||
|
@@ -19,9 +19,7 @@ namespace linker.messenger.relay.server.validator
|
|||||||
{
|
{
|
||||||
return $"SecretKey validate fail";
|
return $"SecretKey validate fail";
|
||||||
}
|
}
|
||||||
|
return await Task.FromResult(string.Empty);
|
||||||
await Task.CompletedTask.ConfigureAwait(false);
|
|
||||||
return string.Empty;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -73,6 +73,12 @@ namespace linker.messenger.serializer.memorypack
|
|||||||
MemoryPackFormatterProvider.Register(new RelayServerNodeUpdateInfoFormatter());
|
MemoryPackFormatterProvider.Register(new RelayServerNodeUpdateInfoFormatter());
|
||||||
MemoryPackFormatterProvider.Register(new RelayServerNodeUpdateWrapInfoFormatter());
|
MemoryPackFormatterProvider.Register(new RelayServerNodeUpdateWrapInfoFormatter());
|
||||||
|
|
||||||
|
MemoryPackFormatterProvider.Register(new RelayServerUser2NodeInfoFormatter());
|
||||||
|
MemoryPackFormatterProvider.Register(new RelayServerUser2NodeAddInfoFormatter());
|
||||||
|
MemoryPackFormatterProvider.Register(new RelayServerUser2NodeDelInfoFormatter());
|
||||||
|
MemoryPackFormatterProvider.Register(new RelayServerUser2NodePageRequestInfoFormatter());
|
||||||
|
MemoryPackFormatterProvider.Register(new RelayServerUser2NodePageResultInfoFormatter());
|
||||||
|
|
||||||
MemoryPackFormatterProvider.Register(new CdkeyInfoFormatter());
|
MemoryPackFormatterProvider.Register(new CdkeyInfoFormatter());
|
||||||
MemoryPackFormatterProvider.Register(new CdkeyStoreInfoFormatter());
|
MemoryPackFormatterProvider.Register(new CdkeyStoreInfoFormatter());
|
||||||
MemoryPackFormatterProvider.Register(new CdkeyPageRequestInfoFormatter());
|
MemoryPackFormatterProvider.Register(new CdkeyPageRequestInfoFormatter());
|
||||||
|
@@ -934,4 +934,309 @@ namespace linker.messenger.serializer.memorypack
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public readonly partial struct SerializableRelayServerUser2NodeInfo
|
||||||
|
{
|
||||||
|
[MemoryPackIgnore]
|
||||||
|
public readonly RelayServerUser2NodeInfo info;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
int Id => info.Id;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string UserId => info.UserId;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string Name => info.Name;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string Remark => info.Remark;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
DateTime AddTime => info.AddTime;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string[] Nodes => info.Nodes;
|
||||||
|
|
||||||
|
[MemoryPackConstructor]
|
||||||
|
SerializableRelayServerUser2NodeInfo(int id, string userid, string name, string remark, DateTime addTime, string[] nodes)
|
||||||
|
{
|
||||||
|
var info = new RelayServerUser2NodeInfo
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
UserId = userid,
|
||||||
|
AddTime = addTime,
|
||||||
|
Remark = remark,
|
||||||
|
Nodes = nodes,
|
||||||
|
Name = name
|
||||||
|
};
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SerializableRelayServerUser2NodeInfo(RelayServerUser2NodeInfo info)
|
||||||
|
{
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class RelayServerUser2NodeInfoFormatter : MemoryPackFormatter<RelayServerUser2NodeInfo>
|
||||||
|
{
|
||||||
|
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref RelayServerUser2NodeInfo value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
writer.WriteNullObjectHeader();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WritePackable(new SerializableRelayServerUser2NodeInfo(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Deserialize(ref MemoryPackReader reader, scoped ref RelayServerUser2NodeInfo value)
|
||||||
|
{
|
||||||
|
if (reader.PeekIsNull())
|
||||||
|
{
|
||||||
|
reader.Advance(1); // skip null block
|
||||||
|
value = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrapped = reader.ReadPackable<SerializableRelayServerUser2NodeInfo>();
|
||||||
|
value = wrapped.info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public readonly partial struct SerializableRelayServerUser2NodeAddInfo
|
||||||
|
{
|
||||||
|
[MemoryPackIgnore]
|
||||||
|
public readonly RelayServerUser2NodeAddInfo info;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string SecretKey => info.SecretKey;
|
||||||
|
[MemoryPackInclude, MemoryPackAllowSerialize]
|
||||||
|
RelayServerUser2NodeInfo Data => info.Data;
|
||||||
|
|
||||||
|
[MemoryPackConstructor]
|
||||||
|
SerializableRelayServerUser2NodeAddInfo(string secretKey, RelayServerUser2NodeInfo data)
|
||||||
|
{
|
||||||
|
var info = new RelayServerUser2NodeAddInfo
|
||||||
|
{
|
||||||
|
SecretKey = secretKey,
|
||||||
|
Data = data
|
||||||
|
};
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SerializableRelayServerUser2NodeAddInfo(RelayServerUser2NodeAddInfo info)
|
||||||
|
{
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class RelayServerUser2NodeAddInfoFormatter : MemoryPackFormatter<RelayServerUser2NodeAddInfo>
|
||||||
|
{
|
||||||
|
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref RelayServerUser2NodeAddInfo value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
writer.WriteNullObjectHeader();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WritePackable(new SerializableRelayServerUser2NodeAddInfo(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Deserialize(ref MemoryPackReader reader, scoped ref RelayServerUser2NodeAddInfo value)
|
||||||
|
{
|
||||||
|
if (reader.PeekIsNull())
|
||||||
|
{
|
||||||
|
reader.Advance(1); // skip null block
|
||||||
|
value = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrapped = reader.ReadPackable<SerializableRelayServerUser2NodeAddInfo>();
|
||||||
|
value = wrapped.info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public readonly partial struct SerializableRelayServerUser2NodeDelInfo
|
||||||
|
{
|
||||||
|
[MemoryPackIgnore]
|
||||||
|
public readonly RelayServerUser2NodeDelInfo info;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string SecretKey => info.SecretKey;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
int Id => info.Id;
|
||||||
|
|
||||||
|
[MemoryPackConstructor]
|
||||||
|
SerializableRelayServerUser2NodeDelInfo(string secretKey, int id)
|
||||||
|
{
|
||||||
|
var info = new RelayServerUser2NodeDelInfo
|
||||||
|
{
|
||||||
|
SecretKey = secretKey,
|
||||||
|
Id = id
|
||||||
|
};
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SerializableRelayServerUser2NodeDelInfo(RelayServerUser2NodeDelInfo info)
|
||||||
|
{
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class RelayServerUser2NodeDelInfoFormatter : MemoryPackFormatter<RelayServerUser2NodeDelInfo>
|
||||||
|
{
|
||||||
|
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref RelayServerUser2NodeDelInfo value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
writer.WriteNullObjectHeader();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WritePackable(new SerializableRelayServerUser2NodeDelInfo(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Deserialize(ref MemoryPackReader reader, scoped ref RelayServerUser2NodeDelInfo value)
|
||||||
|
{
|
||||||
|
if (reader.PeekIsNull())
|
||||||
|
{
|
||||||
|
reader.Advance(1); // skip null block
|
||||||
|
value = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrapped = reader.ReadPackable<SerializableRelayServerUser2NodeDelInfo>();
|
||||||
|
value = wrapped.info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public readonly partial struct SerializableRelayServerUser2NodePageRequestInfo
|
||||||
|
{
|
||||||
|
[MemoryPackIgnore]
|
||||||
|
public readonly RelayServerUser2NodePageRequestInfo info;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
int Page => info.Page;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
int Size => info.Size;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string UserId => info.UserId;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string Name => info.Name;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string Remark => info.Remark;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string SecretKey => info.SecretKey;
|
||||||
|
|
||||||
|
[MemoryPackConstructor]
|
||||||
|
SerializableRelayServerUser2NodePageRequestInfo(int page, int size, string userid, string name, string remark, string secretKey)
|
||||||
|
{
|
||||||
|
var info = new RelayServerUser2NodePageRequestInfo
|
||||||
|
{
|
||||||
|
Size = size,
|
||||||
|
Page = page,
|
||||||
|
UserId = userid,
|
||||||
|
Remark = remark,
|
||||||
|
SecretKey = secretKey,
|
||||||
|
Name = name,
|
||||||
|
};
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SerializableRelayServerUser2NodePageRequestInfo(RelayServerUser2NodePageRequestInfo info)
|
||||||
|
{
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class RelayServerUser2NodePageRequestInfoFormatter : MemoryPackFormatter<RelayServerUser2NodePageRequestInfo>
|
||||||
|
{
|
||||||
|
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref RelayServerUser2NodePageRequestInfo value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
writer.WriteNullObjectHeader();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WritePackable(new SerializableRelayServerUser2NodePageRequestInfo(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Deserialize(ref MemoryPackReader reader, scoped ref RelayServerUser2NodePageRequestInfo value)
|
||||||
|
{
|
||||||
|
if (reader.PeekIsNull())
|
||||||
|
{
|
||||||
|
reader.Advance(1); // skip null block
|
||||||
|
value = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrapped = reader.ReadPackable<SerializableRelayServerUser2NodePageRequestInfo>();
|
||||||
|
value = wrapped.info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public readonly partial struct SerializableRelayServerUser2NodePageResultInfo
|
||||||
|
{
|
||||||
|
[MemoryPackIgnore]
|
||||||
|
public readonly RelayServerUser2NodePageResultInfo info;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
int Page => info.Page;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
int Size => info.Size;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
int Count => info.Count;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
List<RelayServerUser2NodeInfo> List => info.List;
|
||||||
|
|
||||||
|
[MemoryPackConstructor]
|
||||||
|
SerializableRelayServerUser2NodePageResultInfo(int page, int size, int count, List<RelayServerUser2NodeInfo> list)
|
||||||
|
{
|
||||||
|
var info = new RelayServerUser2NodePageResultInfo
|
||||||
|
{
|
||||||
|
Count = count,
|
||||||
|
List = list,
|
||||||
|
Size = size,
|
||||||
|
Page = page
|
||||||
|
};
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SerializableRelayServerUser2NodePageResultInfo(RelayServerUser2NodePageResultInfo info)
|
||||||
|
{
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class RelayServerUser2NodePageResultInfoFormatter : MemoryPackFormatter<RelayServerUser2NodePageResultInfo>
|
||||||
|
{
|
||||||
|
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref RelayServerUser2NodePageResultInfo value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
writer.WriteNullObjectHeader();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WritePackable(new SerializableRelayServerUser2NodePageResultInfo(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Deserialize(ref MemoryPackReader reader, scoped ref RelayServerUser2NodePageResultInfo value)
|
||||||
|
{
|
||||||
|
if (reader.PeekIsNull())
|
||||||
|
{
|
||||||
|
reader.Advance(1); // skip null block
|
||||||
|
value = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrapped = reader.ReadPackable<SerializableRelayServerUser2NodePageResultInfo>();
|
||||||
|
value = wrapped.info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@ namespace linker.messenger.signin
|
|||||||
public static ServiceProvider UseSignInClient(this ServiceProvider serviceProvider)
|
public static ServiceProvider UseSignInClient(this ServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
SignInArgsTransfer signInArgsTransfer = serviceProvider.GetService<SignInArgsTransfer>();
|
SignInArgsTransfer signInArgsTransfer = serviceProvider.GetService<SignInArgsTransfer>();
|
||||||
signInArgsTransfer.AddArgs(new List<ISignInArgs> {
|
signInArgsTransfer.AddArgs(new List<ISignInArgsClient> {
|
||||||
serviceProvider.GetService<SignInArgsGroupPasswordClient>(),
|
serviceProvider.GetService<SignInArgsGroupPasswordClient>(),
|
||||||
serviceProvider.GetService<SignInArgsSecretKeyClient>(),
|
serviceProvider.GetService<SignInArgsSecretKeyClient>(),
|
||||||
serviceProvider.GetService<SignInArgsMachineKeyClient>(),
|
serviceProvider.GetService<SignInArgsMachineKeyClient>(),
|
||||||
@@ -44,7 +44,7 @@ namespace linker.messenger.signin
|
|||||||
IMessengerResolver messengerResolver = serviceProvider.GetService<IMessengerResolver>();
|
IMessengerResolver messengerResolver = serviceProvider.GetService<IMessengerResolver>();
|
||||||
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<SignInClientMessenger>() });
|
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<SignInClientMessenger>() });
|
||||||
|
|
||||||
ExRouteTransfer exRouteTransfer= serviceProvider.GetService<ExRouteTransfer>();
|
ExRouteTransfer exRouteTransfer = serviceProvider.GetService<ExRouteTransfer>();
|
||||||
exRouteTransfer.AddExRoutes(new List<IExRoute> { serviceProvider.GetService<SignInExRoute>() });
|
exRouteTransfer.AddExRoutes(new List<IExRoute> { serviceProvider.GetService<SignInExRoute>() });
|
||||||
|
|
||||||
LoggerHelper.Instance.Info($"start signin");
|
LoggerHelper.Instance.Info($"start signin");
|
||||||
@@ -76,7 +76,7 @@ namespace linker.messenger.signin
|
|||||||
SignInServerCaching signInServerCaching = serviceProvider.GetService<SignInServerCaching>();
|
SignInServerCaching signInServerCaching = serviceProvider.GetService<SignInServerCaching>();
|
||||||
|
|
||||||
SignInArgsTransfer signInArgsTransfer = serviceProvider.GetService<SignInArgsTransfer>();
|
SignInArgsTransfer signInArgsTransfer = serviceProvider.GetService<SignInArgsTransfer>();
|
||||||
signInArgsTransfer.AddArgs(new List<ISignInArgs> {
|
signInArgsTransfer.AddArgs(new List<ISignInArgsServer> {
|
||||||
serviceProvider.GetService<SignInArgsGroupPasswordServer>(),
|
serviceProvider.GetService<SignInArgsGroupPasswordServer>(),
|
||||||
serviceProvider.GetService<SignInArgsSecretKeyServer>(),
|
serviceProvider.GetService<SignInArgsSecretKeyServer>(),
|
||||||
serviceProvider.GetService<SignInArgsMachineKeyServer>(),
|
serviceProvider.GetService<SignInArgsMachineKeyServer>(),
|
||||||
|
@@ -1,11 +1,19 @@
|
|||||||
namespace linker.messenger.signin.args
|
namespace linker.messenger.signin.args
|
||||||
{
|
{
|
||||||
|
public enum SignInArgsLevel
|
||||||
|
{
|
||||||
|
Low = -99,
|
||||||
|
Default = 0,
|
||||||
|
Hight = 99
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 登录参数处理
|
/// 登录参数处理
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISignInArgs
|
public interface ISignInArgsClient
|
||||||
{
|
{
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
public SignInArgsLevel Level { get; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加参数,客户端调用
|
/// 添加参数,客户端调用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -13,6 +21,11 @@
|
|||||||
/// <param name="args"></param>
|
/// <param name="args"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task<string> Invoke(string host, Dictionary<string, string> args);
|
public Task<string> Invoke(string host, Dictionary<string, string> args);
|
||||||
|
}
|
||||||
|
public interface ISignInArgsServer
|
||||||
|
{
|
||||||
|
public string Name { get; }
|
||||||
|
public SignInArgsLevel Level { get; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 验证参数,服务端调用
|
/// 验证参数,服务端调用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -21,5 +34,4 @@
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task<string> Validate(SignInfo signInfo, SignCacheInfo cache);
|
public Task<string> Validate(SignInfo signInfo, SignCacheInfo cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -3,47 +3,34 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加分组密码
|
/// 添加分组密码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SignInArgsGroupPasswordClient : ISignInArgs
|
public sealed class SignInArgsGroupPasswordClient : ISignInArgsClient
|
||||||
{
|
{
|
||||||
public string Name => "group";
|
public string Name => "group";
|
||||||
|
public SignInArgsLevel Level => SignInArgsLevel.Default;
|
||||||
|
|
||||||
private readonly ISignInClientStore signInClientStore;
|
private readonly ISignInClientStore signInClientStore;
|
||||||
public SignInArgsGroupPasswordClient(ISignInClientStore signInClientStore)
|
public SignInArgsGroupPasswordClient(ISignInClientStore signInClientStore)
|
||||||
{
|
{
|
||||||
this.signInClientStore = signInClientStore;
|
this.signInClientStore = signInClientStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public async Task<string> Invoke(string host, Dictionary<string, string> args)
|
public async Task<string> Invoke(string host, Dictionary<string, string> args)
|
||||||
{
|
{
|
||||||
args.TryAdd("signin-gpwd", signInClientStore.Group.Password);
|
args.TryAdd("signin-gpwd", signInClientStore.Group.Password);
|
||||||
await Task.CompletedTask.ConfigureAwait(false);
|
await Task.CompletedTask.ConfigureAwait(false);
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> Validate(SignInfo signInfo, SignCacheInfo cache)
|
|
||||||
{
|
|
||||||
await Task.CompletedTask.ConfigureAwait(false);
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 验证分组密码
|
/// 验证分组密码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SignInArgsGroupPasswordServer : ISignInArgs
|
public sealed class SignInArgsGroupPasswordServer : ISignInArgsServer
|
||||||
{
|
{
|
||||||
public string Name => "group";
|
public string Name => "group";
|
||||||
|
public SignInArgsLevel Level => SignInArgsLevel.Hight;
|
||||||
public SignInArgsGroupPasswordServer()
|
public SignInArgsGroupPasswordServer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
public async Task<string> Invoke(string host, Dictionary<string, string> args)
|
|
||||||
{
|
|
||||||
await Task.CompletedTask.ConfigureAwait(false);
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 验证参数
|
/// 验证参数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
12
src/linker.messenger.signin/args/SignInArgsLimit.cs
Normal file
12
src/linker.messenger.signin/args/SignInArgsLimit.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
namespace linker.messenger.signin.args
|
||||||
|
{
|
||||||
|
public sealed class SignInArgsLimitServer : ISignInArgsServer
|
||||||
|
{
|
||||||
|
public string Name => "limit";
|
||||||
|
public SignInArgsLevel Level => SignInArgsLevel.Low;
|
||||||
|
public async Task<string> Validate(SignInfo signInfo, SignCacheInfo cache)
|
||||||
|
{
|
||||||
|
return await Task.FromResult(string.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -5,9 +5,10 @@ namespace linker.messenger.signin.args
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 给登录加一个唯一ID的参数
|
/// 给登录加一个唯一ID的参数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SignInArgsMachineKeyClient : ISignInArgs
|
public sealed class SignInArgsMachineKeyClient : ISignInArgsClient
|
||||||
{
|
{
|
||||||
public string Name => "machineId";
|
public string Name => "machineId";
|
||||||
|
public SignInArgsLevel Level => SignInArgsLevel.Default;
|
||||||
public async Task<string> Invoke(string host, Dictionary<string, string> args)
|
public async Task<string> Invoke(string host, Dictionary<string, string> args)
|
||||||
{
|
{
|
||||||
string machineKey = SystemIdHelper.GetSystemId();
|
string machineKey = SystemIdHelper.GetSystemId();
|
||||||
@@ -19,30 +20,17 @@ namespace linker.messenger.signin.args
|
|||||||
}
|
}
|
||||||
|
|
||||||
args.TryAdd("machineKey", machineKey);
|
args.TryAdd("machineKey", machineKey);
|
||||||
|
return await Task.FromResult(string.Empty);
|
||||||
await Task.CompletedTask.ConfigureAwait(false);
|
|
||||||
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> Validate(SignInfo signInfo, SignCacheInfo cache)
|
|
||||||
{
|
|
||||||
await Task.CompletedTask.ConfigureAwait(false);
|
|
||||||
return string.Empty;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 验证登录唯一参数
|
/// 验证登录唯一参数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SignInArgsMachineKeyServer : ISignInArgs
|
public sealed class SignInArgsMachineKeyServer : ISignInArgsServer
|
||||||
{
|
{
|
||||||
public string Name => "machineId";
|
public string Name => "machineId";
|
||||||
public async Task<string> Invoke(string host, Dictionary<string, string> args)
|
public SignInArgsLevel Level => SignInArgsLevel.Default;
|
||||||
{
|
|
||||||
await Task.CompletedTask.ConfigureAwait(false);
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 验证参数
|
/// 验证参数
|
||||||
|
@@ -3,10 +3,12 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 给登录加一个唯一ID的参数
|
/// 给登录加一个唯一ID的参数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SignInArgsSecretKeyClient : ISignInArgs
|
public sealed class SignInArgsSecretKeyClient : ISignInArgsClient
|
||||||
{
|
{
|
||||||
public string Name => "secretKey";
|
public string Name => "secretKey";
|
||||||
|
|
||||||
|
public SignInArgsLevel Level => SignInArgsLevel.Default;
|
||||||
|
|
||||||
private readonly ISignInClientStore signInClientStore;
|
private readonly ISignInClientStore signInClientStore;
|
||||||
public SignInArgsSecretKeyClient(ISignInClientStore signInClientStore)
|
public SignInArgsSecretKeyClient(ISignInClientStore signInClientStore)
|
||||||
{
|
{
|
||||||
@@ -18,31 +20,21 @@
|
|||||||
await Task.CompletedTask.ConfigureAwait(false);
|
await Task.CompletedTask.ConfigureAwait(false);
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> Validate(SignInfo signInfo, SignCacheInfo cache)
|
|
||||||
{
|
|
||||||
await Task.CompletedTask.ConfigureAwait(false);
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 验证登录唯一参数
|
/// 验证登录唯一参数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SignInArgsSecretKeyServer : ISignInArgs
|
public sealed class SignInArgsSecretKeyServer : ISignInArgsServer
|
||||||
{
|
{
|
||||||
public string Name => "secretKey";
|
public string Name => "secretKey";
|
||||||
|
public SignInArgsLevel Level => SignInArgsLevel.Default;
|
||||||
|
|
||||||
private readonly ISignInServerStore signInServerStore;
|
private readonly ISignInServerStore signInServerStore;
|
||||||
public SignInArgsSecretKeyServer(ISignInServerStore signInServerStore)
|
public SignInArgsSecretKeyServer(ISignInServerStore signInServerStore)
|
||||||
{
|
{
|
||||||
this.signInServerStore = signInServerStore;
|
this.signInServerStore = signInServerStore;
|
||||||
}
|
}
|
||||||
public async Task<string> Invoke(string host, Dictionary<string, string> args)
|
|
||||||
{
|
|
||||||
await Task.CompletedTask.ConfigureAwait(false);
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 验证参数
|
/// 验证参数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -5,7 +5,8 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class SignInArgsTransfer
|
public sealed partial class SignInArgsTransfer
|
||||||
{
|
{
|
||||||
private List<ISignInArgs> startups = new List<ISignInArgs>();
|
private List<ISignInArgsClient> clients = new List<ISignInArgsClient>();
|
||||||
|
private List<ISignInArgsServer> servers = new List<ISignInArgsServer>();
|
||||||
|
|
||||||
public SignInArgsTransfer()
|
public SignInArgsTransfer()
|
||||||
{
|
{
|
||||||
@@ -15,23 +16,18 @@
|
|||||||
/// 加载所有登录参数实现类
|
/// 加载所有登录参数实现类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="list"></param>
|
/// <param name="list"></param>
|
||||||
public void AddArgs(List<ISignInArgs> list)
|
public void AddArgs(List<ISignInArgsClient> list)
|
||||||
{
|
{
|
||||||
startups = startups.Concat(list).Distinct().ToList();
|
clients = clients.Concat(list).Distinct().OrderByDescending(c=>c.Level).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除实现类
|
/// 加载所有登录参数实现类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="names"></param>
|
/// <param name="list"></param>
|
||||||
public void RemoveArgs(List<string> names)
|
public void AddArgs(List<ISignInArgsServer> list)
|
||||||
{
|
{
|
||||||
foreach (string name in names)
|
servers = servers.Concat(list).Distinct().OrderByDescending(c => c.Level).ToList();
|
||||||
{
|
|
||||||
ISignInArgs item = startups.FirstOrDefault(c => c.Name == name);
|
|
||||||
if (item != null)
|
|
||||||
startups.Remove(item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -42,7 +38,7 @@
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<string> Invoke(string host, Dictionary<string, string> args)
|
public async Task<string> Invoke(string host, Dictionary<string, string> args)
|
||||||
{
|
{
|
||||||
foreach (var item in startups)
|
foreach (var item in clients)
|
||||||
{
|
{
|
||||||
string result = await item.Invoke(host, args).ConfigureAwait(false);
|
string result = await item.Invoke(host, args).ConfigureAwait(false);
|
||||||
if (string.IsNullOrWhiteSpace(result) == false)
|
if (string.IsNullOrWhiteSpace(result) == false)
|
||||||
@@ -60,7 +56,7 @@
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<string> Validate(SignInfo signInfo, SignCacheInfo cache)
|
public async Task<string> Validate(SignInfo signInfo, SignCacheInfo cache)
|
||||||
{
|
{
|
||||||
foreach (var item in startups)
|
foreach (var item in servers)
|
||||||
{
|
{
|
||||||
string result = await item.Validate(signInfo, cache).ConfigureAwait(false);
|
string result = await item.Validate(signInfo, cache).ConfigureAwait(false);
|
||||||
if (string.IsNullOrWhiteSpace(result) == false)
|
if (string.IsNullOrWhiteSpace(result) == false)
|
||||||
|
@@ -5,42 +5,25 @@ namespace linker.messenger.signin.args
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 版本限制
|
/// 版本限制
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SignInArgsVersionClient : ISignInArgs
|
public sealed class SignInArgsVersionClient : ISignInArgsClient
|
||||||
{
|
{
|
||||||
public string Name => "version";
|
public string Name => "version";
|
||||||
|
public SignInArgsLevel Level => SignInArgsLevel.Default;
|
||||||
|
|
||||||
public async Task<string> Invoke(string host, Dictionary<string, string> args)
|
public async Task<string> Invoke(string host, Dictionary<string, string> args)
|
||||||
{
|
{
|
||||||
args.TryAdd("version", VersionHelper.Version);
|
args.TryAdd("version", VersionHelper.Version);
|
||||||
|
return await Task.FromResult(string.Empty);
|
||||||
await Task.CompletedTask.ConfigureAwait(false);
|
|
||||||
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> Validate(SignInfo signInfo, SignCacheInfo cache)
|
|
||||||
{
|
|
||||||
await Task.CompletedTask.ConfigureAwait(false);
|
|
||||||
return string.Empty;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 版本限制
|
/// 版本限制
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SignInArgsVersionServer : ISignInArgs
|
public sealed class SignInArgsVersionServer : ISignInArgsServer
|
||||||
{
|
{
|
||||||
public string Name => "version";
|
public string Name => "version";
|
||||||
/// <summary>
|
public SignInArgsLevel Level => SignInArgsLevel.Default;
|
||||||
/// 客户端调用
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="host"></param>
|
|
||||||
/// <param name="args"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<string> Invoke(string host, Dictionary<string, string> args)
|
|
||||||
{
|
|
||||||
await Task.CompletedTask.ConfigureAwait(false);
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 服务端调用
|
/// 服务端调用
|
||||||
@@ -54,11 +37,7 @@ namespace linker.messenger.signin.args
|
|||||||
{
|
{
|
||||||
return "need v1.5.0+";
|
return "need v1.5.0+";
|
||||||
}
|
}
|
||||||
|
return await Task.FromResult(string.Empty);
|
||||||
await Task.CompletedTask.ConfigureAwait(false);
|
|
||||||
return string.Empty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -70,6 +70,7 @@ namespace linker.messenger.store.file
|
|||||||
serviceCollection.AddSingleton<IRelayServerStore, RelayServerStore>();
|
serviceCollection.AddSingleton<IRelayServerStore, RelayServerStore>();
|
||||||
serviceCollection.AddSingleton<IRelayServerNodeStore, RelayServerNodeStore>();
|
serviceCollection.AddSingleton<IRelayServerNodeStore, RelayServerNodeStore>();
|
||||||
serviceCollection.AddSingleton<IRelayServerMasterStore, RelayServerMasterStore>();
|
serviceCollection.AddSingleton<IRelayServerMasterStore, RelayServerMasterStore>();
|
||||||
|
serviceCollection.AddSingleton<IRelayServerUser2NodeStore, RelayServerUser2NodeStore>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ICdkeyServerStore, CdkeyServerStore>();
|
serviceCollection.AddSingleton<ICdkeyServerStore, CdkeyServerStore>();
|
||||||
serviceCollection.AddSingleton<ICdkeyClientStore, CdkeyClientStore>();
|
serviceCollection.AddSingleton<ICdkeyClientStore, CdkeyClientStore>();
|
||||||
|
@@ -189,6 +189,8 @@ namespace linker.messenger.store.file.relay
|
|||||||
|
|
||||||
public async Task<List<CdkeyStoreInfo>> GetAvailable(string userid, string type)
|
public async Task<List<CdkeyStoreInfo>> GetAvailable(string userid, string type)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(userid) || string.IsNullOrWhiteSpace(type)) return [];
|
||||||
|
|
||||||
return await Task.FromResult(liteCollection.Find(x => x.UserId == userid && x.Type == type && x.LastBytes > 0 && x.StartTime <= DateTime.Now && x.EndTime >= DateTime.Now && x.Deleted == false).ToList()).ConfigureAwait(false);
|
return await Task.FromResult(liteCollection.Find(x => x.UserId == userid && x.Type == type && x.LastBytes > 0 && x.StartTime <= DateTime.Now && x.EndTime >= DateTime.Now && x.Deleted == false).ToList()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
public async Task<List<CdkeyStoreInfo>> Get(List<int> ids)
|
public async Task<List<CdkeyStoreInfo>> Get(List<int> ids)
|
||||||
|
@@ -0,0 +1,72 @@
|
|||||||
|
using linker.messenger.relay.server;
|
||||||
|
using LiteDB;
|
||||||
|
|
||||||
|
namespace linker.messenger.store.file.relay
|
||||||
|
{
|
||||||
|
public sealed class RelayServerUser2NodeStore : IRelayServerUser2NodeStore
|
||||||
|
{
|
||||||
|
private readonly ILiteCollection<RelayServerUser2NodeInfo> liteCollection;
|
||||||
|
public RelayServerUser2NodeStore(Storefactory dBfactory)
|
||||||
|
{
|
||||||
|
liteCollection = dBfactory.GetCollection<RelayServerUser2NodeInfo>("relayUser2Node");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> Add(RelayServerUser2NodeInfo info)
|
||||||
|
{
|
||||||
|
if (info.Id == 0)
|
||||||
|
{
|
||||||
|
info.AddTime = DateTime.Now;
|
||||||
|
liteCollection.Insert(info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
liteCollection.UpdateMany(p => new RelayServerUser2NodeInfo
|
||||||
|
{
|
||||||
|
Name = info.Name,
|
||||||
|
Remark = info.Remark,
|
||||||
|
Nodes = info.Nodes,
|
||||||
|
}, c => c.Id == info.Id);
|
||||||
|
}
|
||||||
|
return await Task.FromResult(true).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
public async Task<bool> Del(int id)
|
||||||
|
{
|
||||||
|
return await Task.FromResult(liteCollection.Delete(id)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<string>> Get(string userid)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(userid)) return [];
|
||||||
|
return await Task.FromResult(liteCollection.Find(c => c.UserId == userid).SelectMany(c => c.Nodes).ToList()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RelayServerUser2NodePageResultInfo> Page(RelayServerUser2NodePageRequestInfo info)
|
||||||
|
{
|
||||||
|
ILiteQueryable<RelayServerUser2NodeInfo> query = liteCollection.Query();
|
||||||
|
if (string.IsNullOrWhiteSpace(info.UserId) == false)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.UserId == info.UserId);
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(info.Name) == false)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.Name.Contains(info.Name));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(info.Remark) == false)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.Remark.Contains(info.Remark));
|
||||||
|
}
|
||||||
|
|
||||||
|
query = query.OrderBy(c => c.Id, Query.Descending);
|
||||||
|
|
||||||
|
return await Task.FromResult(new RelayServerUser2NodePageResultInfo
|
||||||
|
{
|
||||||
|
Page = info.Page,
|
||||||
|
Size = info.Size,
|
||||||
|
Count = query.Count(),
|
||||||
|
List = query.Skip((info.Page - 1) * info.Size).Limit(info.Size).ToList()
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -42,7 +42,7 @@ namespace linker.messenger.tunnel
|
|||||||
public static ServiceProvider UseTunnelClient(this ServiceProvider serviceProvider)
|
public static ServiceProvider UseTunnelClient(this ServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
SignInArgsTransfer signInArgsTransfer = serviceProvider.GetService<SignInArgsTransfer>();
|
SignInArgsTransfer signInArgsTransfer = serviceProvider.GetService<SignInArgsTransfer>();
|
||||||
signInArgsTransfer.AddArgs(new List<ISignInArgs> { serviceProvider.GetService<SignInArgsNet>() });
|
signInArgsTransfer.AddArgs(new List<ISignInArgsClient> { serviceProvider.GetService<SignInArgsNet>() });
|
||||||
|
|
||||||
TunnelNetworkTransfer tunnelNetworkTransfer = serviceProvider.GetService<TunnelNetworkTransfer>();
|
TunnelNetworkTransfer tunnelNetworkTransfer = serviceProvider.GetService<TunnelNetworkTransfer>();
|
||||||
|
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
using linker.messenger.signin.args;
|
using linker.messenger.signin.args;
|
||||||
using linker.messenger.signin;
|
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
|
|
||||||
namespace linker.messenger.tunnel
|
namespace linker.messenger.tunnel
|
||||||
{
|
{
|
||||||
public sealed class SignInArgsNet : ISignInArgs
|
public sealed class SignInArgsNet : ISignInArgsClient
|
||||||
{
|
{
|
||||||
public string Name => "tunnelNet";
|
public string Name => "tunnelNet";
|
||||||
|
public SignInArgsLevel Level => SignInArgsLevel.Default;
|
||||||
|
|
||||||
private readonly ITunnelClientStore tunnelClientStore;
|
private readonly ITunnelClientStore tunnelClientStore;
|
||||||
public SignInArgsNet(ITunnelClientStore tunnelClientStore)
|
public SignInArgsNet(ITunnelClientStore tunnelClientStore)
|
||||||
{
|
{
|
||||||
@@ -15,16 +16,7 @@ namespace linker.messenger.tunnel
|
|||||||
public async Task<string> Invoke(string host, Dictionary<string, string> args)
|
public async Task<string> Invoke(string host, Dictionary<string, string> args)
|
||||||
{
|
{
|
||||||
args.TryAdd("tunnelNet", new SignInArgsNetInfo { Lat = tunnelClientStore.Network.Net.Lat, Lon = tunnelClientStore.Network.Net.Lon, City = tunnelClientStore.Network.Net.City }.ToJson());
|
args.TryAdd("tunnelNet", new SignInArgsNetInfo { Lat = tunnelClientStore.Network.Net.Lat, Lon = tunnelClientStore.Network.Net.Lon, City = tunnelClientStore.Network.Net.City }.ToJson());
|
||||||
|
return await Task.FromResult(string.Empty);
|
||||||
await Task.CompletedTask.ConfigureAwait(false);
|
|
||||||
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> Validate(SignInfo signInfo, SignCacheInfo cache)
|
|
||||||
{
|
|
||||||
await Task.CompletedTask.ConfigureAwait(false);
|
|
||||||
return string.Empty;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public sealed class SignInArgsNetInfo
|
public sealed class SignInArgsNetInfo
|
||||||
|
@@ -54,6 +54,8 @@ namespace linker.messenger.tuntap.cidr
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (File.Exists(Path.Join(path, file)) == false) return;
|
||||||
|
|
||||||
maps = File.ReadAllText(Path.Join(path, file)).Split(Environment.NewLine)
|
maps = File.ReadAllText(Path.Join(path, file)).Split(Environment.NewLine)
|
||||||
.Where(c => string.IsNullOrWhiteSpace(c) == false)
|
.Where(c => string.IsNullOrWhiteSpace(c) == false)
|
||||||
.Select(c => c.Split(','))
|
.Select(c => c.Split(','))
|
||||||
|
@@ -23,4 +23,14 @@ export const relayUpdateNode = (data) => {
|
|||||||
}
|
}
|
||||||
export const checkRelayKey = (key) => {
|
export const checkRelayKey = (key) => {
|
||||||
return sendWebsocketMsg('relay/checkkey',key);
|
return sendWebsocketMsg('relay/checkkey',key);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const user2NodePage = (data) => {
|
||||||
|
return sendWebsocketMsg('relay/PageUser2Node', data);
|
||||||
|
}
|
||||||
|
export const user2NodeAdd = (data) => {
|
||||||
|
return sendWebsocketMsg('relay/AddUser2Node', data);
|
||||||
|
}
|
||||||
|
export const user2NodeDel = (data) => {
|
||||||
|
return sendWebsocketMsg('relay/DelUser2Node', data);
|
||||||
}
|
}
|
@@ -254,6 +254,17 @@ export default {
|
|||||||
'server.relayDefault': '默认',
|
'server.relayDefault': '默认',
|
||||||
'server.relaySetDefault': '设置默认中继节点',
|
'server.relaySetDefault': '设置默认中继节点',
|
||||||
'server.relaySetDefaultText': '不选择则所有客户端',
|
'server.relaySetDefaultText': '不选择则所有客户端',
|
||||||
|
'server.relayUser2Node': '中继白名单',
|
||||||
|
'server.relayUser2NodeUserId': '用户编号',
|
||||||
|
'server.relayUser2NodeName': '名称',
|
||||||
|
'server.relayUser2NodeRemark': '备注',
|
||||||
|
'server.relayUser2NodeAddTime': '添加时间',
|
||||||
|
'server.relayUser2NodeNodes': '节点',
|
||||||
|
'server.relayUser2NodeOper': '操作',
|
||||||
|
'server.relayUser2NodeDelConfirm': '确认删除吗?',
|
||||||
|
'server.relayUser2NodeAdd': '添加白名单',
|
||||||
|
'server.relayUser2NodeUnselect': '未选择',
|
||||||
|
'server.relayUser2NodeSelected': '已选择',
|
||||||
|
|
||||||
'server.cdkeySecretKey': 'Cdkey密钥',
|
'server.cdkeySecretKey': 'Cdkey密钥',
|
||||||
'server.cdkeyText': '密钥正确时可管理cdkey',
|
'server.cdkeyText': '密钥正确时可管理cdkey',
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form-item :label="$t('server.cdkeySecretKey')">
|
<el-form-item :label="$t('server.cdkeySecretKey')">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<el-input :class="{success:state.keyState,error:state.keyState==false}" class="flex-1" type="password" show-password v-model="state.secretKey" maxlength="36" @blur="handleChange"/>
|
<el-input :class="{success:state.keyState,error:state.keyState==false}" style="width:20rem;" type="password" show-password v-model="state.secretKey" maxlength="36" @blur="handleChange"/>
|
||||||
<Sync class="mgl-1" name="CdkeySecretKey"></Sync>
|
<Sync class="mgl-1" name="CdkeySecretKey"></Sync>
|
||||||
<span class="mgl-1" v-if="globalData.isPc">{{$t('server.cdkeyText')}}</span>
|
<span class="mgl-1" v-if="globalData.isPc">{{$t('server.cdkeyText')}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
<el-form-item :label="$t('server.relaySecretKey')">
|
<el-form-item :label="$t('server.relaySecretKey')">
|
||||||
<div >
|
<div >
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<el-input :class="{success:state.keyState,error:state.keyState==false}" class="flex-1" type="password" show-password v-model="state.list.SecretKey" maxlength="36" @change="handleSave" />
|
<el-input :class="{success:state.keyState,error:state.keyState==false}" style="width:20rem;" type="password" show-password v-model="state.list.SecretKey" maxlength="36" @blur="handleSave" />
|
||||||
<Sync class="mgl-1" name="RelaySecretKey"></Sync>
|
<Sync class="mgl-1" name="RelaySecretKey"></Sync>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
@@ -10,142 +10,42 @@
|
|||||||
<el-checkbox class="mgr-1" v-model="state.list.SSL" :label="$t('server.relaySSL')" @change="handleSave" />
|
<el-checkbox class="mgr-1" v-model="state.list.SSL" :label="$t('server.relaySSL')" @change="handleSave" />
|
||||||
<el-checkbox v-model="state.list.Disabled" :label="$t('server.relayDisable')" @change="handleSave" />
|
<el-checkbox v-model="state.list.Disabled" :label="$t('server.relayDisable')" @change="handleSave" />
|
||||||
</div>
|
</div>
|
||||||
<a href="javascript:;" @click="state.show=true" class="mgr-1 delay a-line" :class="{red:state.nodes.length==0,green:state.nodes.length>0}">
|
<a href="javascript:;" @click="state.showModes=true" class="mgr-1 delay a-line" :class="{red:state.nodes.length==0,green:state.nodes.length>0}">
|
||||||
{{$t('server.relayNodes')}} : {{state.nodes.length}}
|
{{$t('server.relayNodes')}} : {{state.nodes.length}}
|
||||||
</a>
|
</a>
|
||||||
|
<User2Node :keyState="state.keyState"></User2Node>
|
||||||
<div class="mgr-1" :title="$t('server.relayUseCdkeyTitle')">
|
<div class="mgr-1" :title="$t('server.relayUseCdkeyTitle')">
|
||||||
<el-checkbox v-model="state.list.UseCdkey" :label="$t('server.relayUseCdkey')" @change="handleSave" />
|
<el-checkbox v-model="state.list.UseCdkey" :label="$t('server.relayUseCdkey')" @change="handleSave" />
|
||||||
</div>
|
</div>
|
||||||
<Cdkey type="Relay"></Cdkey>
|
<Cdkey type="Relay"></Cdkey>
|
||||||
|
<Nodes v-if="state.showModes" v-model="state.showModes" :data="state.nodes" :keyState="state.keyState"></Nodes>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</el-form-item>
|
||||||
</el-form-item>
|
|
||||||
<el-dialog v-model="state.show" :title="$t('server.relayTitle')" width="98%" top="2vh">
|
|
||||||
<div>
|
|
||||||
<el-table :data="state.nodes" size="small" border height="500">
|
|
||||||
<el-table-column property="Name" :label="$t('server.relayName')">
|
|
||||||
<template #default="scope">
|
|
||||||
<div>
|
|
||||||
<a :href="scope.row.Url" class="a-line" :class="{green:scope.row.Public}" target="_blank" :title="scope.row.Public?$t('server.public'):''">{{ scope.row.Name }}</a>
|
|
||||||
<a v-if="state.keyState" href="javascript:;" class="a-line a-edit" @click="handleEdit(scope.row)">
|
|
||||||
<span><el-icon><Edit /></el-icon></span>
|
|
||||||
<span :class="{green:state.syncData.Value == 1 && scope.row.Id==state.syncData.Key}"
|
|
||||||
:title="state.syncData.Value == 1 && scope.row.Id==state.syncData.Key ? `${$t('server.relayDefault')}TCP`:''"
|
|
||||||
v-if="(scope.row.AllowProtocol & 1) == 1">,tcp</span>
|
|
||||||
<span
|
|
||||||
:class="{green:state.syncData.Value == 2 && scope.row.Id==state.syncData.Key}"
|
|
||||||
:title="state.syncData.Value == 2 && scope.row.Id==state.syncData.Key ? `${$t('server.relayDefault')}UDP`:''"
|
|
||||||
v-if="(scope.row.AllowProtocol & 2) == 2">,udp</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column property="MaxGbTotal" :label="$t('server.relayFlow')" width="160">
|
|
||||||
<template #default="scope">
|
|
||||||
<span v-if="scope.row.MaxGbTotal == 0">--</span>
|
|
||||||
<span v-else>{{ (scope.row.MaxGbTotalLastBytes/1024/1024/1024).toFixed(2) }}GB / {{ scope.row.MaxGbTotal }}GB</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column property="MaxBandwidth" :label="$t('server.relaySpeed')" width="80">
|
|
||||||
<template #default="scope">
|
|
||||||
<span v-if="scope.row.MaxBandwidth == 0">--</span>
|
|
||||||
<span v-else>{{ scope.row.MaxBandwidth }}Mbps</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column property="MaxBandwidthTotal" :label="`${$t('server.relaySpeed2')}/${$t('server.relaySpeed1')}`" width="120">
|
|
||||||
<template #default="scope">
|
|
||||||
<span>
|
|
||||||
<span>{{scope.row.BandwidthRatio}}</span>
|
|
||||||
<span>/</span>
|
|
||||||
<span v-if="scope.row.MaxBandwidthTotal == 0">--</span>
|
|
||||||
<span v-else>{{ scope.row.MaxBandwidthTotal }}Mbps</span>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column property="ConnectionRatio" :label="$t('server.relayConnection')" width="100">
|
|
||||||
<template #default="scope">
|
|
||||||
<span><strong>{{scope.row.ConnectionRatio}}</strong>/{{scope.row.MaxConnection}}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column property="Delay" :label="$t('server.relayDelay')" width="60">
|
|
||||||
<template #default="scope">
|
|
||||||
<span>{{ scope.row.Delay }}ms</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column property="Public" :label="$t('server.relayDefault')" width="60">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-dropdown size="small">
|
|
||||||
<div class="dropdown">
|
|
||||||
<span style="font-size: 1.2rem;">{{ $t('server.relayDefault') }}</span>
|
|
||||||
<el-icon class="el-icon--right">
|
|
||||||
<ArrowDown />
|
|
||||||
</el-icon>
|
|
||||||
</div>
|
|
||||||
<template #dropdown>
|
|
||||||
<el-dropdown-menu>
|
|
||||||
<el-dropdown-item v-if="(scope.row.AllowProtocol & 1) == 1" @click="handleShowSync(scope.row.Id, 1)">{{$t('common.relay')}}TCP</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="(scope.row.AllowProtocol & 2) == 2" @click="handleShowSync(scope.row.Id, 2)">{{$t('common.relay')}}UDP</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</template>
|
|
||||||
</el-dropdown>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
<EditNode v-if="state.showEdit" v-model="state.showEdit" :data="state.current"></EditNode>
|
|
||||||
<el-dialog class="options-center" :title="$t('server.relaySetDefault')" destroy-on-close v-model="state.showSync" width="54rem" top="2vh">
|
|
||||||
<div>
|
|
||||||
<div class="t-c">{{ $t('server.relaySetDefaultText') }}</div>
|
|
||||||
<Ids ref="domIds"></Ids>
|
|
||||||
<div class="t-c w-100 mgt-1">
|
|
||||||
<el-button @click="state.showSync = false">{{$t('common.cancel')}}</el-button>
|
|
||||||
<el-button type="primary" @click="handleSync">{{$t('common.confirm')}}</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { checkRelayKey, getDefault, setRelayServers, setRelaySubscribe, syncDefault } from '@/apis/relay';
|
import { checkRelayKey, setRelayServers, setRelaySubscribe } from '@/apis/relay';
|
||||||
import { injectGlobalData } from '@/provide';
|
import { injectGlobalData } from '@/provide';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { onMounted, onUnmounted, reactive, ref, watch } from 'vue'
|
import { onMounted, onUnmounted, provide, reactive, ref } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import Sync from '../sync/Index.vue'
|
import Sync from '../sync/Index.vue'
|
||||||
import Ids from '../sync/Ids.vue';
|
|
||||||
import Cdkey from './cdkey/Index.vue'
|
import Cdkey from './cdkey/Index.vue'
|
||||||
import EditNode from './EditNode.vue';
|
import Nodes from './relay/Nodes.vue';
|
||||||
import { Edit,ArrowDown } from '@element-plus/icons-vue';
|
import User2Node from './user2node/Index.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components:{Sync,Ids,Cdkey,EditNode,Edit,ArrowDown},
|
components:{Sync,Cdkey,Nodes,User2Node},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const {t} = useI18n();
|
const {t} = useI18n();
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
list:globalData.value.config.Client.Relay.Server,
|
list:globalData.value.config.Client.Relay.Server,
|
||||||
show:false,
|
showModes:false,
|
||||||
nodes:[],
|
nodes:[],
|
||||||
timer:0,
|
timer:0,
|
||||||
showEdit:false,
|
|
||||||
current:{},
|
|
||||||
keyState:false,
|
keyState:false,
|
||||||
|
|
||||||
showSync:false,
|
|
||||||
syncData:{
|
|
||||||
Key:'',
|
|
||||||
Value:0
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
watch(()=>globalData.value.config.Client.Relay.Server,()=>{
|
|
||||||
state.list.Delay = globalData.value.config.Client.Relay.Server.Delay;
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleEdit = (row)=>{
|
|
||||||
state.current = row;
|
|
||||||
state.showEdit = true;
|
|
||||||
}
|
|
||||||
const handleSave = ()=>{
|
const handleSave = ()=>{
|
||||||
setRelayServers(state.list).then(()=>{
|
setRelayServers(state.list).then(()=>{
|
||||||
ElMessage.success(t('common.oper'));
|
ElMessage.success(t('common.oper'));
|
||||||
@@ -155,10 +55,14 @@ export default {
|
|||||||
});
|
});
|
||||||
handleCheckKey();
|
handleCheckKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nodes = ref([]);
|
||||||
|
provide('nodes',nodes);
|
||||||
const _setRelaySubscribe = ()=>{
|
const _setRelaySubscribe = ()=>{
|
||||||
clearTimeout(state.timer);
|
clearTimeout(state.timer);
|
||||||
setRelaySubscribe().then((res)=>{
|
setRelaySubscribe().then((res)=>{
|
||||||
state.nodes = res;
|
state.nodes = res;
|
||||||
|
nodes.value = res;
|
||||||
state.timer = setTimeout(_setRelaySubscribe,1000);
|
state.timer = setTimeout(_setRelaySubscribe,1000);
|
||||||
}).catch(()=>{
|
}).catch(()=>{
|
||||||
state.timer = setTimeout(_setRelaySubscribe,1000);
|
state.timer = setTimeout(_setRelaySubscribe,1000);
|
||||||
@@ -170,37 +74,15 @@ export default {
|
|||||||
}).catch(()=>{});
|
}).catch(()=>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
const domIds = ref(null);
|
|
||||||
const handleShowSync = (id,proto)=>{
|
|
||||||
state.syncData.Key = id;
|
|
||||||
state.syncData.Value = proto;
|
|
||||||
state.showSync = true;
|
|
||||||
}
|
|
||||||
const handleSync = ()=>{
|
|
||||||
syncDefault({
|
|
||||||
Ids:domIds.value.getIds(),
|
|
||||||
Data:state.syncData
|
|
||||||
}).then((res)=>{
|
|
||||||
state.showSync = false;
|
|
||||||
ElMessage.success(t('common.oper'));
|
|
||||||
}).catch(()=>{
|
|
||||||
ElMessage.error(t('common.operFail'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(()=>{
|
onMounted(()=>{
|
||||||
_setRelaySubscribe();
|
_setRelaySubscribe();
|
||||||
handleCheckKey();
|
handleCheckKey();
|
||||||
getDefault().then((res)=>{
|
|
||||||
state.syncData.Key = res.Key || '';
|
|
||||||
state.syncData.Value = res.Value || 0;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
onUnmounted(()=>{
|
onUnmounted(()=>{
|
||||||
clearTimeout(state.timer);
|
clearTimeout(state.timer);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {globalData,state,handleSave,handleEdit,domIds,handleShowSync,handleSync}
|
return {globalData,state,handleSave}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
<el-form-item :label="$t('server.sforwardSecretKey')">
|
<el-form-item :label="$t('server.sforwardSecretKey')">
|
||||||
<div>
|
<div>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<el-input :class="{success:state.keyState,error:state.keyState==false}" class="flex-1" type="password" show-password v-model="state.SForwardSecretKey" maxlength="36" @blur="handleChange" />
|
<el-input :class="{success:state.keyState,error:state.keyState==false}" style="width:20rem;" type="password" show-password v-model="state.SForwardSecretKey" maxlength="36" @blur="handleChange" />
|
||||||
<Sync class="mgl-1" name="SForwardSecretKey"></Sync>
|
<Sync class="mgl-1" name="SForwardSecretKey"></Sync>
|
||||||
<span class="mgl-1" v-if="globalData.isPc">{{$t('server.sforwardText')}}</span>
|
<span class="mgl-1" v-if="globalData.isPc">{{$t('server.sforwardText')}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -6,26 +6,26 @@
|
|||||||
<el-form label-width="auto" :label-position="state.position">
|
<el-form label-width="auto" :label-position="state.position">
|
||||||
<el-form-item :label="$t('server.messengerAddr')">
|
<el-form-item :label="$t('server.messengerAddr')">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<el-input class="flex-1" v-model="state.list.Host" @change="handleSave" />
|
<el-input style="width:20rem;" v-model="state.list.Host" @blur="handleSave" />
|
||||||
<Sync class="mgl-1" name="SignInServer"></Sync>
|
<Sync class="mgl-1" name="SignInServer"></Sync>
|
||||||
<span class="mgl-1" v-if="globalData.isPc">{{$t('server.messengerText')}}</span>
|
<span class="mgl-1" v-if="globalData.isPc">{{$t('server.messengerText')}}</span>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="`${$t('server.messengerAddr')}1`">
|
<el-form-item :label="`${$t('server.messengerAddr')}1`">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<el-input class="flex-1" v-model="state.list.Host1" @change="handleSave" />
|
<el-input style="width:20rem;" v-model="state.list.Host1" @blur="handleSave" />
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('server.messengerSecretKey')">
|
<el-form-item :label="$t('server.messengerSecretKey')">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<el-input :class="{success:state.keyState,error:state.keyState==false}" class="flex-1" type="password" show-password maxlength="36" v-model="state.list.SecretKey" @change="handleSave" />
|
<el-input :class="{success:state.keyState,error:state.keyState==false}" style="width:20rem;" type="password" show-password maxlength="36" v-model="state.list.SecretKey" @blur="handleSave" />
|
||||||
<Sync class="mgl-1" name="SignInSecretKey"></Sync>
|
<Sync class="mgl-1" name="SignInSecretKey"></Sync>
|
||||||
<span class="mgl-1" v-if="globalData.isPc">{{$t('server.messengerSecretKeyText')}}</span>
|
<span class="mgl-1" v-if="globalData.isPc">{{$t('server.messengerSecretKeyText')}}</span>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('server.messengerUserId')">
|
<el-form-item :label="$t('server.messengerUserId')">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<el-input class="flex-1" type="password" show-password maxlength="36" v-model="state.list.UserId" @change="handleSave" />
|
<el-input style="width:20rem;" type="password" show-password maxlength="36" v-model="state.list.UserId" @blur="handleSave" />
|
||||||
<Sync class="mgl-1" name="SignInUserId"></Sync>
|
<Sync class="mgl-1" name="SignInUserId"></Sync>
|
||||||
<span class="mgl-1" v-if="globalData.isPc">{{$t('server.messengerUserIdText')}}</span>
|
<span class="mgl-1" v-if="globalData.isPc">{{$t('server.messengerUserIdText')}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
<el-form-item :label="$t('server.updaterSecretKey')">
|
<el-form-item :label="$t('server.updaterSecretKey')">
|
||||||
<div >
|
<div >
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<el-input :class="{success:state.keyState,error:state.keyState==false}" class="flex-1" type="password" show-password v-model="state.secretKey" maxlength="36" @blur="handleChange"/>
|
<el-input :class="{success:state.keyState,error:state.keyState==false}" style="width:20rem;" type="password" show-password v-model="state.secretKey" maxlength="36" @blur="handleChange"/>
|
||||||
<Sync class="mgl-1" name="UpdaterSecretKey"></Sync>
|
<Sync class="mgl-1" name="UpdaterSecretKey"></Sync>
|
||||||
<span class="mgl-1" v-if="globalData.isPc">{{$t('server.updaterText')}}</span>
|
<span class="mgl-1" v-if="globalData.isPc">{{$t('server.updaterText')}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
173
src/linker.web/src/views/full/server/relay/Nodes.vue
Normal file
173
src/linker.web/src/views/full/server/relay/Nodes.vue
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-dialog v-model="state.show" :title="$t('server.relayTitle')" width="98%" top="2vh">
|
||||||
|
<div>
|
||||||
|
<el-table :data="state.nodes" size="small" border height="500">
|
||||||
|
<el-table-column property="Name" :label="$t('server.relayName')">
|
||||||
|
<template #default="scope">
|
||||||
|
<div>
|
||||||
|
<a :href="scope.row.Url" class="a-line" :class="{green:scope.row.Public}" target="_blank" :title="scope.row.Public?$t('server.public'):''">{{ scope.row.Name }}</a>
|
||||||
|
<a v-if="state.keyState" href="javascript:;" class="a-line a-edit" @click="handleEdit(scope.row)">
|
||||||
|
<span><el-icon><Edit /></el-icon></span>
|
||||||
|
<span :class="{green:state.syncData.Value == 1 && scope.row.Id==state.syncData.Key}"
|
||||||
|
:title="state.syncData.Value == 1 && scope.row.Id==state.syncData.Key ? `${$t('server.relayDefault')}TCP`:''"
|
||||||
|
v-if="(scope.row.AllowProtocol & 1) == 1">,tcp</span>
|
||||||
|
<span
|
||||||
|
:class="{green:state.syncData.Value == 2 && scope.row.Id==state.syncData.Key}"
|
||||||
|
:title="state.syncData.Value == 2 && scope.row.Id==state.syncData.Key ? `${$t('server.relayDefault')}UDP`:''"
|
||||||
|
v-if="(scope.row.AllowProtocol & 2) == 2">,udp</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column property="MaxGbTotal" :label="$t('server.relayFlow')" width="160">
|
||||||
|
<template #default="scope">
|
||||||
|
<span v-if="scope.row.MaxGbTotal == 0">--</span>
|
||||||
|
<span v-else>{{ (scope.row.MaxGbTotalLastBytes/1024/1024/1024).toFixed(2) }}GB / {{ scope.row.MaxGbTotal }}GB</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column property="MaxBandwidth" :label="$t('server.relaySpeed')" width="80">
|
||||||
|
<template #default="scope">
|
||||||
|
<span v-if="scope.row.MaxBandwidth == 0">--</span>
|
||||||
|
<span v-else>{{ scope.row.MaxBandwidth }}Mbps</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column property="MaxBandwidthTotal" :label="`${$t('server.relaySpeed2')}/${$t('server.relaySpeed1')}`" width="120">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>
|
||||||
|
<span>{{scope.row.BandwidthRatio}}</span>
|
||||||
|
<span>/</span>
|
||||||
|
<span v-if="scope.row.MaxBandwidthTotal == 0">--</span>
|
||||||
|
<span v-else>{{ scope.row.MaxBandwidthTotal }}Mbps</span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column property="ConnectionRatio" :label="$t('server.relayConnection')" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<span><strong>{{scope.row.ConnectionRatio}}</strong>/{{scope.row.MaxConnection}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column property="Delay" :label="$t('server.relayDelay')" width="60">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ scope.row.Delay }}ms</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column property="Public" :label="$t('server.relayDefault')" width="60">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-dropdown size="small">
|
||||||
|
<div class="dropdown">
|
||||||
|
<span style="font-size: 1.2rem;">{{ $t('server.relayDefault') }}</span>
|
||||||
|
<el-icon class="el-icon--right">
|
||||||
|
<ArrowDown />
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item v-if="(scope.row.AllowProtocol & 1) == 1" @click="handleShowSync(scope.row.Id, 1)">{{$t('common.relay')}}TCP</el-dropdown-item>
|
||||||
|
<el-dropdown-item v-if="(scope.row.AllowProtocol & 2) == 2" @click="handleShowSync(scope.row.Id, 2)">{{$t('common.relay')}}UDP</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
<EditNode v-if="state.showEdit" v-model="state.showEdit" :data="state.current"></EditNode>
|
||||||
|
<el-dialog class="options-center" :title="$t('server.relaySetDefault')" destroy-on-close v-model="state.showSync" width="54rem" top="2vh">
|
||||||
|
<div>
|
||||||
|
<div class="t-c">{{ $t('server.relaySetDefaultText') }}</div>
|
||||||
|
<Ids ref="domIds"></Ids>
|
||||||
|
<div class="t-c w-100 mgt-1">
|
||||||
|
<el-button @click="state.showSync = false">{{$t('common.cancel')}}</el-button>
|
||||||
|
<el-button type="primary" @click="handleSync">{{$t('common.confirm')}}</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { getDefault,syncDefault } from '@/apis/relay';
|
||||||
|
import { injectGlobalData } from '@/provide';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { onMounted, onUnmounted, reactive, ref, watch } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import Ids from '../../sync/Ids.vue';
|
||||||
|
import EditNode from './EditNode.vue';
|
||||||
|
import { Edit,ArrowDown } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ['modelValue','data','keyState'],
|
||||||
|
emits: ['update:modelValue','success'],
|
||||||
|
components:{Ids,EditNode,Edit,ArrowDown},
|
||||||
|
setup(props,{emit}) {
|
||||||
|
const {t} = useI18n();
|
||||||
|
const globalData = injectGlobalData();
|
||||||
|
const state = reactive({
|
||||||
|
show:true,
|
||||||
|
nodes:props.data,
|
||||||
|
showEdit:false,
|
||||||
|
current:{},
|
||||||
|
keyState:props.keyState,
|
||||||
|
|
||||||
|
showSync:false,
|
||||||
|
syncData:{
|
||||||
|
Key:'',
|
||||||
|
Value:0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
watch(() => state.show, (val) => {
|
||||||
|
if (!val) {
|
||||||
|
setTimeout(() => {
|
||||||
|
emit('update:modelValue', val);
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleEdit = (row)=>{
|
||||||
|
state.current = row;
|
||||||
|
state.showEdit = true;
|
||||||
|
}
|
||||||
|
const domIds = ref(null);
|
||||||
|
const handleShowSync = (id,proto)=>{
|
||||||
|
state.syncData.Key = id;
|
||||||
|
state.syncData.Value = proto;
|
||||||
|
state.showSync = true;
|
||||||
|
}
|
||||||
|
const handleSync = ()=>{
|
||||||
|
syncDefault({
|
||||||
|
Ids:domIds.value.getIds(),
|
||||||
|
Data:state.syncData
|
||||||
|
}).then((res)=>{
|
||||||
|
state.showSync = false;
|
||||||
|
ElMessage.success(t('common.oper'));
|
||||||
|
}).catch(()=>{
|
||||||
|
ElMessage.error(t('common.operFail'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(()=>{
|
||||||
|
getDefault().then((res)=>{
|
||||||
|
state.syncData.Key = res.Key || '';
|
||||||
|
state.syncData.Value = res.Value || 0;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
onUnmounted(()=>{
|
||||||
|
clearTimeout(state.timer);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {globalData,state,handleEdit,domIds,handleShowSync,handleSync}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.blue {
|
||||||
|
color: #409EFF;
|
||||||
|
}
|
||||||
|
a.a-edit{
|
||||||
|
margin-left:1rem;
|
||||||
|
.el-icon {
|
||||||
|
vertical-align middle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
124
src/linker.web/src/views/full/server/user2node/Add.vue
Normal file
124
src/linker.web/src/views/full/server/user2node/Add.vue
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog class="options-center" :title="$t('server.relayUser2Node')" destroy-on-close v-model="state.show" width="36rem" top="2vh">
|
||||||
|
<div>
|
||||||
|
<el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="auto">
|
||||||
|
<el-form-item :label="$t('server.relayUser2NodeUserId')" prop="UserId">
|
||||||
|
<el-input maxlength="36" show-word-limit v-model="state.ruleForm.UserId" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('server.relayUser2NodeName')" prop="Name">
|
||||||
|
<el-input v-model="state.ruleForm.Name" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('server.relayUser2NodeNodes')" prop="Nodes">
|
||||||
|
<el-input type="textarea" :value="state.nodes" @click="handleShowNodes" readonly resize="none" rows="4"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('server.relayUser2NodeRemark')" prop="Remark">
|
||||||
|
<el-input v-model="state.ruleForm.Remark" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item></el-form-item>
|
||||||
|
<el-form-item label="" prop="Btns">
|
||||||
|
<div class="t-c w-100">
|
||||||
|
<el-button @click="state.show = false">{{$t('common.cancel')}}</el-button>
|
||||||
|
<el-button type="primary" @click="handleSave">{{$t('common.confirm')}}</el-button>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
<el-dialog class="options-center" :title="$t('server.relayUser2NodeNodes')" destroy-on-close v-model="state.showNodes" width="54rem" top="2vh">
|
||||||
|
<div>
|
||||||
|
<el-transfer class="src-tranfer"
|
||||||
|
v-model="state.nodeIds"
|
||||||
|
filterable
|
||||||
|
:filter-method="srcFilterMethod"
|
||||||
|
:data="nodes"
|
||||||
|
:titles="[$t('server.relayUser2NodeUnselect'), $t('server.relayUser2NodeSelected')]"
|
||||||
|
:props="{
|
||||||
|
key: 'Id',
|
||||||
|
label: 'Name',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<div class="t-c w-100 mgt-1">
|
||||||
|
<el-button @click="state.showNodes = false">{{$t('common.cancel')}}</el-button>
|
||||||
|
<el-button type="primary" @click="handleNodes">{{$t('common.confirm')}}</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { computed, inject, reactive, ref, watch } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { user2NodeAdd } from '@/apis/relay';
|
||||||
|
export default {
|
||||||
|
props: ['modelValue'],
|
||||||
|
emits: ['update:modelValue','success'],
|
||||||
|
setup(props,{emit}) {
|
||||||
|
const {t} = useI18n();
|
||||||
|
const nodes = inject('nodes');
|
||||||
|
const editState = inject('edit');
|
||||||
|
const state = reactive({
|
||||||
|
show:true,
|
||||||
|
|
||||||
|
ruleForm:{
|
||||||
|
Id:editState.value.Id || 0,
|
||||||
|
UserId:editState.value.UserId || '',
|
||||||
|
Name:editState.value.Name || '',
|
||||||
|
Remark:editState.value.Remark || '',
|
||||||
|
Nodes:editState.value.Nodes || [],
|
||||||
|
},
|
||||||
|
nodes:computed(()=>{
|
||||||
|
const json = nodes.value.reduce((json,item,index)=>{ json[item.Id] = item.Name; return json; },{});
|
||||||
|
return state.ruleForm.Nodes.map(c=>json[c]).join(',');
|
||||||
|
}),
|
||||||
|
rules:{
|
||||||
|
UserId: [{ required: true, message: "required", trigger: "blur" }],
|
||||||
|
Name: [{ required: true, message: "required", trigger: "blur" }],
|
||||||
|
Nodes: [{ required: true, message: "required", trigger: "blur" }],
|
||||||
|
},
|
||||||
|
showNodes:false,
|
||||||
|
nodeIds: []
|
||||||
|
});
|
||||||
|
watch(() => state.show, (val) => {
|
||||||
|
if (!val) {
|
||||||
|
setTimeout(() => {
|
||||||
|
emit('update:modelValue', val);
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleShowNodes = ()=>{
|
||||||
|
state.nodeIds = state.ruleForm.Nodes;
|
||||||
|
state.showNodes = true;
|
||||||
|
}
|
||||||
|
const srcFilterMethod = (query, item) => {
|
||||||
|
return item.Name.toLowerCase().includes(query.toLowerCase())
|
||||||
|
}
|
||||||
|
const handleNodes = ()=>{
|
||||||
|
state.ruleForm.Nodes = state.nodeIds;
|
||||||
|
state.showNodes = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ruleFormRef = ref(null);
|
||||||
|
const handleSave = ()=>{
|
||||||
|
ruleFormRef.value.validate((valid) => {
|
||||||
|
if (!valid) return;
|
||||||
|
|
||||||
|
const json = JSON.parse(JSON.stringify(state.ruleForm));
|
||||||
|
user2NodeAdd(json).then(()=>{
|
||||||
|
ElMessage.success(t('common.oper'));
|
||||||
|
state.show = false;
|
||||||
|
emit('success');
|
||||||
|
}).catch(()=>{
|
||||||
|
ElMessage.error(t('common.operFail'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return {state,nodes,handleShowNodes,srcFilterMethod,handleNodes,ruleFormRef,handleSave}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.el-form-item{margin-bottom:1rem}
|
||||||
|
.el-input-number--small{width:10rem !important}
|
||||||
|
</style>
|
29
src/linker.web/src/views/full/server/user2node/Index.vue
Normal file
29
src/linker.web/src/views/full/server/user2node/Index.vue
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<template>
|
||||||
|
<a v-if="state.hasUser2Node && hasUser2Node" @click="state.showManager = true" href="javascript:;" class="mgr-1 a-line">{{$t('server.relayUser2Node')}}</a>
|
||||||
|
<Manager v-if="state.showManager" v-model="state.showManager" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { injectGlobalData } from '@/provide';
|
||||||
|
import { computed, reactive } from 'vue';
|
||||||
|
import Manager from './Manager.vue'
|
||||||
|
export default {
|
||||||
|
props:['keyState'],
|
||||||
|
components:{Manager},
|
||||||
|
setup (props) {
|
||||||
|
|
||||||
|
const globalData = injectGlobalData();
|
||||||
|
const hasUser2Node = computed(()=>globalData.value.hasAccess('User2Node'));
|
||||||
|
const state = reactive({
|
||||||
|
hasUser2Node:computed(()=>props.keyState),
|
||||||
|
showManager:false
|
||||||
|
});
|
||||||
|
|
||||||
|
return {state,hasUser2Node}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
|
||||||
|
</style>
|
150
src/linker.web/src/views/full/server/user2node/Manager.vue
Normal file
150
src/linker.web/src/views/full/server/user2node/Manager.vue
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog class="options-center" :title="$t('server.relayUser2Node')" destroy-on-close v-model="state.show" width="77rem" top="2vh">
|
||||||
|
<div class="group-wrap">
|
||||||
|
<div class="head">
|
||||||
|
<div class="search flex">
|
||||||
|
<div><span>{{$t('server.relayUser2NodeUserId')}}</span> <el-input v-model="state.page.UserId" style="width:8rem" size="small" clearable @change="handleSearch" /></div>
|
||||||
|
<div><span>{{$t('server.relayUser2NodeName')}}</span> <el-input v-model="state.page.Name" style="width:8rem" size="small" clearable @change="handleSearch" /></div>
|
||||||
|
<div><span>{{$t('server.relayUser2NodeRemark')}}</span> <el-input v-model="state.page.Remark" style="width:8rem" size="small" clearable @change="handleSearch" /></div>
|
||||||
|
<div>
|
||||||
|
<el-button size="small" @click="handleSearch()">
|
||||||
|
<el-icon><Search /></el-icon>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-button size="small" type="success" @click="handleAdd">
|
||||||
|
<el-icon><Plus /></el-icon>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-table stripe :data="state.list.List" border size="small" width="100%">
|
||||||
|
|
||||||
|
<el-table-column prop="Name" :label="$t('server.relayUser2NodeName')"></el-table-column>
|
||||||
|
<el-table-column prop="Nodes" :label="$t('server.relayUser2NodeNodes')">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ scope.row.Nodes.map(c=>state.nodes[c]).join(',') }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="Remark" :label="$t('server.relayUser2NodeRemark')"></el-table-column>
|
||||||
|
<el-table-column prop="AddTime" :label="`${$t('server.relayUser2NodeAddTime')}`" width="140" sortable="custom">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column fixed="right" prop="Oper" :label="$t('server.relayUser2NodeOper')" width="110">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button size="small" @click="handleEdit(scope.row)">
|
||||||
|
<el-icon><EditPen /></el-icon>
|
||||||
|
</el-button>
|
||||||
|
<el-popconfirm :title="$t('server.relayUser2NodeDelConfirm')" @confirm="handleDel(scope.row)">
|
||||||
|
<template #reference>
|
||||||
|
<el-button type="danger" size="small">
|
||||||
|
<el-icon><Delete /></el-icon>
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-popconfirm>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div class="t-c">
|
||||||
|
<div class="page">
|
||||||
|
<el-pagination small background layout="prev, pager, next"
|
||||||
|
:page-size="state.page.Size"
|
||||||
|
:total="state.list.Count"
|
||||||
|
:pager-count="5"
|
||||||
|
:current-page="state.page.Page" @current-change="handlePageChange" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
<Add v-if="state.showAdd" v-model="state.showAdd" @success="handleSearch"></Add>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { computed, inject, onMounted, provide, reactive, ref, watch } from 'vue'
|
||||||
|
import { Delete,Plus,Search,Warning,EditPen } from '@element-plus/icons-vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import Add from './Add.vue';
|
||||||
|
import { user2NodeDel, user2NodePage } from '@/apis/relay';
|
||||||
|
export default {
|
||||||
|
props: ['modelValue'],
|
||||||
|
emits: ['update:modelValue'],
|
||||||
|
components:{Delete,Plus,Search ,EditPen,Add,Warning},
|
||||||
|
setup(props,{emit}) {
|
||||||
|
const {t} = useI18n();
|
||||||
|
const nodes = inject('nodes');
|
||||||
|
const state = reactive({
|
||||||
|
nodes:computed(()=>nodes.value.reduce((json,item,index)=>{ json[item.Id] = item.Name; return json; },{})),
|
||||||
|
page:{
|
||||||
|
Page:1,
|
||||||
|
Size:10,
|
||||||
|
UserId:'',
|
||||||
|
Name:'',
|
||||||
|
Remark:''
|
||||||
|
},
|
||||||
|
list:{
|
||||||
|
Page:1,
|
||||||
|
Size:15,
|
||||||
|
Count:0,
|
||||||
|
List:[]
|
||||||
|
},
|
||||||
|
show:true,
|
||||||
|
showAdd:false
|
||||||
|
});
|
||||||
|
watch(() => state.show, (val) => {
|
||||||
|
if (!val) {
|
||||||
|
setTimeout(() => {
|
||||||
|
emit('update:modelValue', val);
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const editState = ref({
|
||||||
|
});
|
||||||
|
provide('edit',editState);
|
||||||
|
|
||||||
|
const handleAdd = ()=>{
|
||||||
|
editState.value = {Id:0,Name:'',Nodes:[],Remark:'',UserId:''};
|
||||||
|
state.showAdd = true;
|
||||||
|
}
|
||||||
|
const handleEdit = (row)=>{
|
||||||
|
editState.value = row
|
||||||
|
state.showAdd = true;
|
||||||
|
}
|
||||||
|
const handleSearch = ()=>{
|
||||||
|
user2NodePage(state.page).then((res)=>{
|
||||||
|
state.list = res;
|
||||||
|
}).catch(()=>{})
|
||||||
|
}
|
||||||
|
const handlePageChange = (p)=>{
|
||||||
|
state.page.Page = p;
|
||||||
|
handleSearch();
|
||||||
|
}
|
||||||
|
const handleDel = (row)=>{
|
||||||
|
user2NodeDel(row.Id).then((res)=>{
|
||||||
|
handleSearch();
|
||||||
|
}).catch(()=>{})
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(()=>{
|
||||||
|
handleSearch();
|
||||||
|
})
|
||||||
|
|
||||||
|
return {state,handleSearch,handlePageChange,handleDel,handleAdd,handleEdit}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.head{
|
||||||
|
.search{
|
||||||
|
&>div{
|
||||||
|
margin-right:1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.page{
|
||||||
|
padding:2rem 0;
|
||||||
|
display:inline-block;
|
||||||
|
}
|
||||||
|
.el-form-item{margin-bottom:1rem}
|
||||||
|
.el-input-number--small{width:10rem !important}
|
||||||
|
</style>
|
@@ -1,5 +1,5 @@
|
|||||||
v1.8.5
|
v1.8.5
|
||||||
2025-06-25 16:12:07
|
2025-06-26 17:46:49
|
||||||
1. 一些累计更新
|
1. 一些累计更新
|
||||||
2. 备用信标服务器
|
2. 备用信标服务器
|
||||||
3. 设置默认中继节点
|
3. 设置默认中继节点
|
||||||
|
Reference in New Issue
Block a user