mirror of
https://github.com/snltty/linker.git
synced 2025-09-26 21:15:57 +08:00
186
This commit is contained in:
@@ -6,7 +6,7 @@ sidebar_position: 10
|
||||
|
||||
:::tip[说明]
|
||||
1. 首次运行手动初始化的客户端拥有完全管理权限,可导出配置,用以作为组网其它设备运行
|
||||
2. 可以指定导出的设备名,管理端口,管理密码,和本客户端的其它配置信息,比如设定好的中继密钥什么的
|
||||
2. 可以指定导出的设备名,管理端口,管理密码,和本客户端的其它配置信息
|
||||
3. 可以指定导出的配置拥有什么权限
|
||||
4. `下载`则导出压缩包,可以复制到其它电脑上直接运行
|
||||
5. `复制`导出的配置复制到剪贴板,对应初始化配置时的`粘贴配置`
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 84 KiB |
Binary file not shown.
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 126 KiB |
@@ -18,6 +18,7 @@ sidebar_position: 96
|
||||
- 仰望 * 2
|
||||
- 李氏の天下
|
||||
- 小猪
|
||||
- 菜菜(木子)
|
||||
|
||||
</div>
|
||||
</details>
|
@@ -1,5 +1,4 @@
|
||||
using linker.libs.extends;
|
||||
using linker.messenger.relay.client.transport;
|
||||
using linker.messenger.relay.server;
|
||||
using linker.messenger.relay.server.validator;
|
||||
using linker.messenger.sforward;
|
||||
@@ -53,6 +52,10 @@ namespace linker.messenger.action
|
||||
/// </summary>
|
||||
public string GroupId { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// 用户id
|
||||
/// </summary>
|
||||
public string UserId { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// 超级管理
|
||||
/// </summary>
|
||||
public bool Super { get; set; }
|
||||
@@ -169,7 +172,8 @@ namespace linker.messenger.action
|
||||
MachineName = signInfo.MachineName,
|
||||
MachineKey = machineKey,
|
||||
IPAddress = signInfo.Connection.Address.Address,
|
||||
Super = signInfo.Super
|
||||
Super = signInfo.Super,
|
||||
UserId = signInfo.UserId
|
||||
}
|
||||
};
|
||||
return await actionTransfer.ExcuteActions(Replace(replace, str), actionServerStore.SignInActionUrl).ConfigureAwait(false);
|
||||
@@ -221,7 +225,8 @@ namespace linker.messenger.action
|
||||
MachineName = fromMachine.MachineName,
|
||||
MachineKey = machineKey,
|
||||
IPAddress = fromMachine.Connection.Address.Address,
|
||||
Super = fromMachine.Super
|
||||
Super = fromMachine.Super,
|
||||
UserId = fromMachine.UserId
|
||||
}
|
||||
};
|
||||
return await actionTransfer.ExcuteActions(Replace(replace, str), actionServerStore.RelayActionUrl).ConfigureAwait(false);
|
||||
@@ -256,7 +261,8 @@ namespace linker.messenger.action
|
||||
MachineName = fromMachine.MachineName,
|
||||
MachineKey = machineKey,
|
||||
IPAddress = fromMachine.Connection.Address.Address,
|
||||
Super = fromMachine.Super
|
||||
Super = fromMachine.Super,
|
||||
UserId = fromMachine.UserId
|
||||
}
|
||||
};
|
||||
string ids = await actionTransfer.ExcuteActions(Replace(replace, str), actionServerStore.RelayNodeUrl).ConfigureAwait(false);
|
||||
@@ -302,7 +308,8 @@ namespace linker.messenger.action
|
||||
MachineName = cache.MachineName,
|
||||
MachineKey = machineKey,
|
||||
IPAddress = cache.Connection.Address.Address,
|
||||
Super = cache.Super
|
||||
Super = cache.Super,
|
||||
UserId = cache.UserId
|
||||
}
|
||||
};
|
||||
return await actionTransfer.ExcuteActions(Replace(replace, str), actionServerStore.SForwardActionUrl).ConfigureAwait(false);
|
||||
|
@@ -54,6 +54,7 @@ namespace linker.messenger.flow
|
||||
{
|
||||
Connection = signInClientState.Connection,
|
||||
MessengerId = messengerId,
|
||||
Payload = serializer.Serialize(param.Content)
|
||||
}).ConfigureAwait(false);
|
||||
if (resp.Code == MessageResponeCodes.OK && resp.Data.Length > 0)
|
||||
{
|
||||
@@ -87,6 +88,7 @@ namespace linker.messenger.flow
|
||||
{
|
||||
Connection = signInClientState.Connection,
|
||||
MessengerId = messengerId,
|
||||
Payload = serializer.Serialize(param.Content)
|
||||
}).ConfigureAwait(false);
|
||||
if (resp.Code == MessageResponeCodes.OK && resp.Data.Length > 0)
|
||||
{
|
||||
|
@@ -24,6 +24,8 @@ namespace linker.messenger.serializer.memorypack
|
||||
MemoryPackFormatterProvider.Register(new SignInResponseInfoFormatter());
|
||||
MemoryPackFormatterProvider.Register(new SignInConfigSetNameInfoFormatter());
|
||||
MemoryPackFormatterProvider.Register(new SignInNamesResponseItemInfoFormatter());
|
||||
MemoryPackFormatterProvider.Register(new SignInUserIdsResponseItemInfoFormatter());
|
||||
|
||||
MemoryPackFormatterProvider.Register(new SignInPushArgInfoFormatter());
|
||||
|
||||
|
||||
|
@@ -493,7 +493,59 @@ namespace linker.messenger.serializer.memorypack
|
||||
value = wrapped.info;
|
||||
}
|
||||
}
|
||||
[MemoryPackable]
|
||||
public readonly partial struct SerializableSignInUserIdsResponseItemInfo
|
||||
{
|
||||
[MemoryPackIgnore]
|
||||
public readonly SignInUserIdsResponseItemInfo info;
|
||||
|
||||
[MemoryPackInclude]
|
||||
string UserId => info.UserId;
|
||||
|
||||
[MemoryPackInclude]
|
||||
string MachineName => info.MachineName;
|
||||
|
||||
[MemoryPackInclude]
|
||||
bool Online => info.Online;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableSignInUserIdsResponseItemInfo(string userId, string machineName, bool online)
|
||||
{
|
||||
var info = new SignInUserIdsResponseItemInfo { UserId = userId, MachineName = machineName, Online = online };
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public SerializableSignInUserIdsResponseItemInfo(SignInUserIdsResponseItemInfo signInfo)
|
||||
{
|
||||
this.info = signInfo;
|
||||
}
|
||||
}
|
||||
public class SignInUserIdsResponseItemInfoFormatter : MemoryPackFormatter<SignInUserIdsResponseItemInfo>
|
||||
{
|
||||
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref SignInUserIdsResponseItemInfo value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WritePackable(new SerializableSignInUserIdsResponseItemInfo(value));
|
||||
}
|
||||
|
||||
public override void Deserialize(ref MemoryPackReader reader, scoped ref SignInUserIdsResponseItemInfo value)
|
||||
{
|
||||
if (reader.PeekIsNull())
|
||||
{
|
||||
reader.Advance(1); // skip null block
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var wrapped = reader.ReadPackable<SerializableSignInUserIdsResponseItemInfo>();
|
||||
value = wrapped.info;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[MemoryPackable]
|
||||
|
@@ -42,6 +42,7 @@
|
||||
<ProjectReference Include="..\linker.messenger.plan\linker.messenger.plan.csproj" />
|
||||
<ProjectReference Include="..\linker.messenger.signin\linker.messenger.signin.csproj" />
|
||||
<ProjectReference Include="..\linker.messenger.sync\linker.messenger.sync.csproj" />
|
||||
<ProjectReference Include="..\linker.messenger.wlist\linker.messenger.wlist.csproj" />
|
||||
<ProjectReference Include="..\linker.messenger\linker.messenger.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using linker.messenger.signin;
|
||||
using linker.messenger.wlist;
|
||||
|
||||
namespace linker.messenger.sforward.server.validator
|
||||
{
|
||||
@@ -10,14 +11,19 @@ namespace linker.messenger.sforward.server.validator
|
||||
public string Name => "default";
|
||||
|
||||
private readonly ISForwardServerStore sForwardServerStore;
|
||||
public SForwardValidator(ISForwardServerStore sForwardServerStore)
|
||||
private readonly IWhiteListServerStore whiteListServerStore;
|
||||
public SForwardValidator(ISForwardServerStore sForwardServerStore, IWhiteListServerStore whiteListServerStore)
|
||||
{
|
||||
this.sForwardServerStore = sForwardServerStore;
|
||||
this.whiteListServerStore = whiteListServerStore;
|
||||
}
|
||||
|
||||
public async Task<string> Validate(SignCacheInfo signCacheInfo, SForwardAddInfo sForwardAddInfo)
|
||||
{
|
||||
if (signCacheInfo.Super == false)
|
||||
List<string> sforward = await whiteListServerStore.Get("SForward", signCacheInfo.UserId);
|
||||
string target = string.IsNullOrWhiteSpace(sForwardAddInfo.Domain) ? sForwardAddInfo.RemotePort.ToString() : sForwardAddInfo.Domain;
|
||||
|
||||
if (signCacheInfo.Super == false && sforward.Contains(target) == false)
|
||||
{
|
||||
return $"need super key and password";
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ namespace linker.messenger.signin
|
||||
serviceCollection.AddSingleton<SignInArgsSuperClient>();
|
||||
serviceCollection.AddSingleton<SignInArgsMachineKeyClient>();
|
||||
serviceCollection.AddSingleton<SignInArgsVersionClient>();
|
||||
serviceCollection.AddSingleton<SignInArgsUserIdClient>();
|
||||
|
||||
serviceCollection.AddSingleton<SignInClientState>();
|
||||
serviceCollection.AddSingleton<SignInClientTransfer>();
|
||||
@@ -34,6 +35,7 @@ namespace linker.messenger.signin
|
||||
serviceProvider.GetService<SignInArgsSuperClient>(),
|
||||
serviceProvider.GetService<SignInArgsMachineKeyClient>(),
|
||||
serviceProvider.GetService<SignInArgsVersionClient>(),
|
||||
serviceProvider.GetService<SignInArgsUserIdClient>(),
|
||||
});
|
||||
|
||||
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||
@@ -63,6 +65,7 @@ namespace linker.messenger.signin
|
||||
serviceCollection.AddSingleton<SignInArgsSuperServer>();
|
||||
serviceCollection.AddSingleton<SignInArgsMachineKeyServer>();
|
||||
serviceCollection.AddSingleton<SignInArgsVersionServer>();
|
||||
serviceCollection.AddSingleton<SignInArgsUserIdServer>();
|
||||
|
||||
serviceCollection.AddSingleton<SignInServerMessenger>();
|
||||
serviceCollection.AddSingleton<SignInServerCaching>();
|
||||
@@ -81,6 +84,7 @@ namespace linker.messenger.signin
|
||||
serviceProvider.GetService<SignInArgsSuperServer>(),
|
||||
serviceProvider.GetService<SignInArgsMachineKeyServer>(),
|
||||
serviceProvider.GetService<SignInArgsVersionServer>(),
|
||||
serviceProvider.GetService<SignInArgsUserIdServer>(),
|
||||
});
|
||||
|
||||
return serviceProvider;
|
||||
|
@@ -137,6 +137,20 @@ namespace linker.messenger.signin
|
||||
return new List<SignInNamesResponseItemInfo>();
|
||||
}
|
||||
|
||||
public async Task<List<SignInUserIdsResponseItemInfo>> UserIds(ApiControllerParamsInfo param)
|
||||
{
|
||||
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||
{
|
||||
Connection = signInClientState.Connection,
|
||||
MessengerId = (ushort)SignInMessengerIds.UserIds,
|
||||
Payload = serializer.Serialize(param.Content)
|
||||
}).ConfigureAwait(false);
|
||||
if (resp.Code == MessageResponeCodes.OK)
|
||||
{
|
||||
return serializer.Deserialize<List<SignInUserIdsResponseItemInfo>>(resp.Data.Span);
|
||||
}
|
||||
return new List<SignInUserIdsResponseItemInfo>();
|
||||
}
|
||||
|
||||
public async Task CheckSuper(ApiControllerParamsInfo param)
|
||||
{
|
||||
|
@@ -212,6 +212,19 @@ namespace linker.messenger.signin
|
||||
connection.Write(serializer.Serialize(list));
|
||||
}
|
||||
}
|
||||
[MessengerId((ushort)SignInMessengerIds.UserIds)]
|
||||
public void UserIds(IConnection connection)
|
||||
{
|
||||
string name = serializer.Deserialize<string>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache) == false || cache.Super == false)
|
||||
{
|
||||
connection.Write(serializer.Serialize(new List<SignInUserIdsResponseItemInfo>()));
|
||||
return;
|
||||
}
|
||||
|
||||
List<SignInUserIdsResponseItemInfo> list = signCaching.Get(name, 10).Select(c => new SignInUserIdsResponseItemInfo { UserId = c.UserId, MachineName = c.MachineName, Online = c.Connected }).ToList();
|
||||
connection.Write(serializer.Serialize(list));
|
||||
}
|
||||
|
||||
|
||||
[MessengerId((ushort)SignInMessengerIds.Exists)]
|
||||
@@ -374,7 +387,6 @@ namespace linker.messenger.signin
|
||||
public int Count { get; set; }
|
||||
public List<SignInIdsResponseItemInfo> List { get; set; } = new List<SignInIdsResponseItemInfo>();
|
||||
}
|
||||
|
||||
public sealed class SignInIdsResponseItemInfo
|
||||
{
|
||||
public string MachineId { get; set; }
|
||||
@@ -387,6 +399,12 @@ namespace linker.messenger.signin
|
||||
public string MachineName { get; set; }
|
||||
public bool Online { get; set; }
|
||||
}
|
||||
public sealed class SignInUserIdsResponseItemInfo
|
||||
{
|
||||
public string UserId { get; set; }
|
||||
public string MachineName { get; set; }
|
||||
public bool Online { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 登录返回
|
||||
|
@@ -32,6 +32,8 @@
|
||||
|
||||
CheckSuper = 19,
|
||||
|
||||
UserIds = 20,
|
||||
|
||||
None = 99
|
||||
}
|
||||
}
|
||||
|
@@ -72,6 +72,8 @@ namespace linker.messenger.signin
|
||||
cache.Args = signInfo.Args;
|
||||
cache.GroupId = signInfo.GroupId;
|
||||
cache.Super = signInfo.Super;
|
||||
cache.UserId = signInfo.UserId;
|
||||
|
||||
signInStore.Update(cache);
|
||||
signInStore.Confirm();
|
||||
return string.Empty;
|
||||
@@ -101,6 +103,10 @@ namespace linker.messenger.signin
|
||||
{
|
||||
return Clients.Values.ToList();
|
||||
}
|
||||
public List<SignCacheInfo> Get(string name,int count)
|
||||
{
|
||||
return Clients.Values.Where(c=>c.MachineName.Contains(name) || c.UserId.Contains(name)).Take(count).ToList();
|
||||
}
|
||||
public List<SignCacheInfo> Get(SignCacheInfo other)
|
||||
{
|
||||
return Clients.Values.Where(c => c.GroupId == other.GroupId).ToList();
|
||||
@@ -176,7 +182,7 @@ namespace linker.messenger.signin
|
||||
/// <summary>
|
||||
/// 登录缓存对象
|
||||
/// </summary>
|
||||
public sealed class SignCacheInfo
|
||||
public partial class SignCacheInfo
|
||||
{
|
||||
public string Id { get; set; }
|
||||
/// <summary>
|
||||
@@ -240,6 +246,7 @@ namespace linker.messenger.signin
|
||||
|
||||
|
||||
public bool Super { get; set; }
|
||||
public string UserId { get; set; } = string.Empty;
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -258,15 +265,13 @@ namespace linker.messenger.signin
|
||||
/// <summary>
|
||||
/// 登录参数
|
||||
/// </summary>
|
||||
public sealed class SignInfo
|
||||
public partial class SignInfo
|
||||
{
|
||||
public string MachineId { get; set; } = string.Empty;
|
||||
public string MachineName { get; set; } = string.Empty;
|
||||
public string GroupId { get; set; } = string.Empty;
|
||||
public string Version { get; set; } = string.Empty;
|
||||
|
||||
public bool Super { get; set; } = false;
|
||||
|
||||
public Dictionary<string, string> Args { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
public IConnection Connection { get; set; }
|
||||
|
@@ -56,3 +56,13 @@
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace linker.messenger.signin
|
||||
{
|
||||
public partial class SignInfo
|
||||
{
|
||||
public bool Super { get; set; } = false;
|
||||
}
|
||||
|
||||
}
|
54
src/linker.messenger.signin/args/SignInArgsUserId.cs
Normal file
54
src/linker.messenger.signin/args/SignInArgsUserId.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using linker.libs;
|
||||
using linker.messenger;
|
||||
|
||||
namespace linker.messenger.signin.args
|
||||
{
|
||||
/// <summary>
|
||||
/// 版本限制
|
||||
/// </summary>
|
||||
public sealed class SignInArgsUserIdClient : ISignInArgsClient
|
||||
{
|
||||
public string Name => "userid";
|
||||
public SignInArgsLevel Level => SignInArgsLevel.Default;
|
||||
|
||||
private readonly ISignInClientStore signInClientStore;
|
||||
public SignInArgsUserIdClient(ISignInClientStore signInClientStore)
|
||||
{
|
||||
this.signInClientStore = signInClientStore;
|
||||
}
|
||||
public async Task<string> Invoke(string host, Dictionary<string, string> args)
|
||||
{
|
||||
args.TryAdd("userid", signInClientStore.Server.UserId);
|
||||
return await Task.FromResult(string.Empty);
|
||||
}
|
||||
}
|
||||
public sealed class SignInArgsUserIdServer : ISignInArgsServer
|
||||
{
|
||||
public string Name => "userid";
|
||||
public SignInArgsLevel Level => SignInArgsLevel.Default;
|
||||
|
||||
/// <summary>
|
||||
/// 服务端调用
|
||||
/// </summary>
|
||||
/// <param name="signInfo">新登录参数</param>
|
||||
/// <param name="cache">之前的登录信息</param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> Validate(SignInfo signInfo, SignCacheInfo cache)
|
||||
{
|
||||
if (signInfo.Args.TryGetValue("userid", out string userid))
|
||||
{
|
||||
signInfo.UserId = userid;
|
||||
}
|
||||
return await Task.FromResult(string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace linker.messenger.signin
|
||||
{
|
||||
public partial class SignInfo
|
||||
{
|
||||
public string UserId { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
}
|
@@ -9,7 +9,7 @@ namespace linker.messenger.store.file.cdkey
|
||||
{
|
||||
public sealed class CdkeyServerStore : ICdkeyServerStore
|
||||
{
|
||||
private string regex = @"([0-9]+|\?)-([0-9]+|\?)-([0-9]+|\?)\s+([0-9]+|\?):([0-9]+|\?):([0-9]+|\?)";
|
||||
private readonly string regex = @"([0-9]+|\?)-([0-9]+|\?)-([0-9]+|\?)\s+([0-9]+|\?):([0-9]+|\?):([0-9]+|\?)";
|
||||
private int index = 0;
|
||||
|
||||
private readonly Storefactory dBfactory;
|
||||
|
@@ -78,7 +78,7 @@ namespace linker.messenger.tuntap.cidr
|
||||
{
|
||||
try
|
||||
{
|
||||
Dictionary<IPAddress, string> ip2machine = tuntapDecenter.Infos.Values.ToDictionary(c => c.IP, c => c.MachineId);
|
||||
Dictionary<IPAddress, string> ip2machine = tuntapDecenter.Infos.Values.Where(c=>c.Available).DistinctBy(c=>c.IP).ToDictionary(c => c.IP, c => c.MachineId);
|
||||
CidrAddInfo<string>[] cidrs = maps.Select(c =>
|
||||
{
|
||||
ip2machine.TryGetValue(c.Dst, out string machineId);
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import { sendWebsocketMsg } from './request'
|
||||
|
||||
export const getFlows = (machineId) => {
|
||||
export const getFlows = (machineId = '') => {
|
||||
return sendWebsocketMsg('flow/GetFlows',machineId);
|
||||
}
|
||||
export const getMessengerFlows = (machineId) => {
|
||||
export const getMessengerFlows = (machineId = '') => {
|
||||
return sendWebsocketMsg('flow/GetMessengerFlows',machineId);
|
||||
}
|
||||
export const getSForwardFlows = (data) => {
|
||||
@@ -15,7 +15,7 @@ export const getRelayFlows = (data) => {
|
||||
export const getCitys = () => {
|
||||
return sendWebsocketMsg('flow/GetCitys');
|
||||
}
|
||||
export const getStopwatch = (machineId) => {
|
||||
export const getStopwatch = (machineId = '') => {
|
||||
return sendWebsocketMsg('flow/GetStopwatch',machineId);
|
||||
}
|
||||
export const getForwardFlows = (data) => {
|
||||
|
@@ -37,4 +37,7 @@ export const getSignInNames = () => {
|
||||
}
|
||||
export const checkSignInKey = () => {
|
||||
return sendWebsocketMsg('signIn/CheckSuper');
|
||||
}
|
||||
export const getSignInUserIds = (name) => {
|
||||
return sendWebsocketMsg('signIn/UserIds',name);
|
||||
}
|
@@ -246,6 +246,7 @@ export default {
|
||||
'server.wlistAddTime': 'Add time',
|
||||
'server.wlistNodes': 'Value',
|
||||
'server.wlistNodesRelay': 'Nodes',
|
||||
'server.wlistNodesSForward': 'Port/Domain',
|
||||
'server.wlistOper': 'Oper',
|
||||
'server.wlistDelConfirm': 'Are you sure to delete?',
|
||||
'server.wlistAdd': 'Add',
|
||||
@@ -253,7 +254,7 @@ export default {
|
||||
'server.wlistSelected': 'Selected',
|
||||
|
||||
|
||||
'server.sforwardSecretKey': 'Server forward secretKey',
|
||||
'server.sforward': 'Server forward',
|
||||
'server.sforwardText': 'The server forward can be used when the key is correct',
|
||||
|
||||
'server.updater':'Updater',
|
||||
|
@@ -337,13 +337,14 @@ export default {
|
||||
'server.wlistAddTime': '添加时间',
|
||||
'server.wlistNodes': '内容',
|
||||
'server.wlistNodesRelay': '节点',
|
||||
'server.wlistNodesSForward': '端口/域名',
|
||||
'server.wlistOper': '操作',
|
||||
'server.wlistDelConfirm': '确认删除吗?',
|
||||
'server.wlistAdd': '添加白名单',
|
||||
'server.wlistUnselect': '未选择',
|
||||
'server.wlistSelected': '已选择',
|
||||
|
||||
'server.sforwardSecretKey': '服务器穿透密钥',
|
||||
'server.sforward': '服务器穿透',
|
||||
'server.sforwardText': '密钥正确时可使用服务器穿透',
|
||||
|
||||
'server.updater': '更新',
|
||||
|
@@ -1,21 +1,23 @@
|
||||
<template>
|
||||
<el-form-item :label="$t('server.relay')">
|
||||
<div >
|
||||
<div>
|
||||
<div class="flex">
|
||||
<div class="mgr-1">
|
||||
<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 class="mgr-1" v-model="state.list.Disabled" :label="$t('server.relayDisable')" @change="handleSave" />
|
||||
<el-checkbox v-model="state.list.SSL" :label="$t('server.relaySSL')" @change="handleSave" />
|
||||
</div>
|
||||
<div class="mgr-1" :title="$t('server.relayUseCdkeyTitle')">
|
||||
<el-checkbox v-model="state.list.UseCdkey" :label="$t('server.relayUseCdkey')" @change="handleSave" />
|
||||
</div>
|
||||
<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}}
|
||||
</a>
|
||||
<Sync class="mgl-1" name="RelaySecretKey"></Sync>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<WhiteList type="Relay"></WhiteList>
|
||||
<div class="mgr-1" :title="$t('server.relayUseCdkeyTitle')">
|
||||
<el-checkbox v-model="state.list.UseCdkey" :label="$t('server.relayUseCdkey')" @change="handleSave" />
|
||||
</div>
|
||||
<Cdkey type="Relay"></Cdkey>
|
||||
<Nodes v-if="state.showModes" v-model="state.showModes" :data="state.nodes"></Nodes>
|
||||
<Sync class="mgl-1" name="RelaySecretKey"></Sync>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
39
src/linker.web/src/views/full/server/SForwardServers.vue
Normal file
39
src/linker.web/src/views/full/server/SForwardServers.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<el-form-item :label="$t('server.sforward')">
|
||||
<div>
|
||||
<div class="flex">
|
||||
<!-- <Cdkey type="SForward"></Cdkey> -->
|
||||
<WhiteList type="SForward"></WhiteList>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<script>
|
||||
import { injectGlobalData } from '@/provide';
|
||||
import { onUnmounted, provide, reactive, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import Cdkey from './cdkey/Index.vue'
|
||||
import WhiteList from './wlist/Index.vue';
|
||||
|
||||
export default {
|
||||
components:{Cdkey,WhiteList},
|
||||
setup(props) {
|
||||
const {t} = useI18n();
|
||||
const globalData = injectGlobalData();
|
||||
const state = reactive({
|
||||
});
|
||||
|
||||
const nodes = ref([]);
|
||||
provide('nodes',nodes);
|
||||
const handleSave = ()=>{
|
||||
}
|
||||
onUnmounted(()=>{
|
||||
clearTimeout(state.timer);
|
||||
});
|
||||
|
||||
return {globalData,state,handleSave}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="stylus" scoped>
|
||||
</style>
|
@@ -38,6 +38,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item></el-form-item>
|
||||
<RelayServers class="mgt-2"></RelayServers>
|
||||
<SForwardServers class="mgt-2"></SForwardServers>
|
||||
<Updater></Updater>
|
||||
</el-form>
|
||||
</div>
|
||||
@@ -56,10 +57,11 @@ import { ElMessage } from 'element-plus';
|
||||
import { computed, onMounted, reactive } from 'vue'
|
||||
import Updater from './Updater.vue';
|
||||
import RelayServers from './RelayServers.vue';
|
||||
import SForwardServers from './SForwardServers.vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import Sync from '../sync/Index.vue'
|
||||
export default {
|
||||
components:{Updater,RelayServers,Sync},
|
||||
components:{Updater,RelayServers,SForwardServers,Sync},
|
||||
setup(props) {
|
||||
const {t} = useI18n();
|
||||
const globalData = injectGlobalData();
|
||||
|
@@ -3,14 +3,20 @@
|
||||
<div>
|
||||
<el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="auto">
|
||||
<el-form-item :label="$t('server.wlistUserId')" prop="UserId">
|
||||
<el-input maxlength="36" show-word-limit v-model="state.ruleForm.UserId" />
|
||||
<el-select v-model="state.ruleForm.UserId" filterable remote :loading="state.loading" :remote-method="handleUserIds" @change="handleUserIdChange">
|
||||
<el-option v-for="(item, index) in state.userids" :key="index" :label="item.MachineName" :value="item.UserId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.wlistName')" prop="Name">
|
||||
<el-input v-model="state.ruleForm.Name" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t(`server.wlistNodes${state.ruleForm.Type}`)" prop="Nodes">
|
||||
<el-form-item v-if="state.ruleForm.Type == 'Relay'" :label="$t(`server.wlistNodes${state.ruleForm.Type}`)" prop="Nodes">
|
||||
<el-input type="textarea" :value="state.nodes" @click="handleShowNodes" readonly resize="none" rows="4"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="state.ruleForm.Type == 'SForward'" :label="$t(`server.wlistNodes${state.ruleForm.Type}`)" prop="Nodes">
|
||||
<el-input type="textarea" v-model="state.ports" resize="none" rows="4" @change="handlePortChange"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.wlistRemark')" prop="Remark">
|
||||
<el-input v-model="state.ruleForm.Remark" />
|
||||
</el-form-item>
|
||||
@@ -47,9 +53,10 @@
|
||||
|
||||
<script>
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { computed, inject, reactive, ref, watch } from 'vue'
|
||||
import { computed, inject, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { wlistAdd } from '@/apis/wlist';
|
||||
import { getSignInUserIds } from '@/apis/signin';
|
||||
export default {
|
||||
props: ['modelValue'],
|
||||
emits: ['update:modelValue','success'],
|
||||
@@ -78,7 +85,11 @@ export default {
|
||||
Nodes: [{ required: true, message: "required", trigger: "blur" }],
|
||||
},
|
||||
showNodes:false,
|
||||
nodeIds: []
|
||||
nodeIds: [],
|
||||
|
||||
ports: editState.value.Type == 'SForward' ? editState.value.Nodes.join(',') : '',
|
||||
|
||||
userids:[]
|
||||
});
|
||||
watch(() => state.show, (val) => {
|
||||
if (!val) {
|
||||
@@ -99,6 +110,21 @@ export default {
|
||||
state.ruleForm.Nodes = state.nodeIds;
|
||||
state.showNodes = false;
|
||||
}
|
||||
const handlePortChange = ()=>{
|
||||
state.ruleForm.Nodes = state.ports.split(',').map(c=>c.replace(/\s/g,'')).filter(c=>!!c);
|
||||
}
|
||||
const handleUserIdChange = ()=>{
|
||||
try{
|
||||
state.ruleForm.Name = state.userids.filter(c=>c.UserId == state.ruleForm.UserId)[0].MachineName
|
||||
}catch(e){
|
||||
}
|
||||
}
|
||||
|
||||
const handleUserIds = (query)=>{
|
||||
getSignInUserIds(query).then(data=>{
|
||||
state.userids = data;
|
||||
});
|
||||
}
|
||||
|
||||
const ruleFormRef = ref(null);
|
||||
const handleSave = ()=>{
|
||||
@@ -115,7 +141,12 @@ export default {
|
||||
});
|
||||
});
|
||||
}
|
||||
return {state,nodes,handleShowNodes,srcFilterMethod,handleNodes,ruleFormRef,handleSave}
|
||||
|
||||
onMounted(()=>{
|
||||
handleUserIds(state.ruleForm.UserId);
|
||||
})
|
||||
|
||||
return {state,nodes,handleShowNodes,srcFilterMethod,handleNodes,ruleFormRef,handleSave,handlePortChange,handleUserIdChange,handleUserIds}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@@ -23,7 +23,8 @@
|
||||
<el-table-column prop="Name" :label="$t('server.wlistName')"></el-table-column>
|
||||
<el-table-column prop="Nodes" :label="$t(`server.wlistNodes${state.page.Type}`)">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.Nodes.map(c=>state.nodes[c]).join(',') }}</span>
|
||||
<span v-if="scope.row.Type == 'Relay'">{{ scope.row.Nodes.map(c=>state.nodes[c]).join(',') }}</span>
|
||||
<span v-else-if="scope.row.Type == 'SForward'">{{ scope.row.Nodes.join(',') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="Remark" :label="$t('server.wlistRemark')"></el-table-column>
|
||||
|
@@ -111,14 +111,11 @@ export default {
|
||||
webport: globalData.value.config.Client.CApi.WebPort,
|
||||
|
||||
relay:true,
|
||||
sforward:true,
|
||||
updater:true,
|
||||
server:true,
|
||||
super:true,
|
||||
super:false,
|
||||
group:true,
|
||||
tunnel:true,
|
||||
cdkey:true,
|
||||
whitelist:true,
|
||||
|
||||
copyContent:'',
|
||||
showCopy:false,
|
||||
@@ -144,14 +141,11 @@ export default {
|
||||
apipassword:state.apipassword,
|
||||
webport:+state.webport,
|
||||
relay:state.relay,
|
||||
sforward:state.sforward,
|
||||
updater:state.updater,
|
||||
server:state.server,
|
||||
super:state.super,
|
||||
group:state.group,
|
||||
tunnel:state.tunnel,
|
||||
cdkey:state.cdkey,
|
||||
whitelist:state.whitelist,
|
||||
tunnel:state.tunnel
|
||||
}
|
||||
|
||||
if(json.single){
|
||||
|
@@ -1,5 +1,5 @@
|
||||
v1.8.6
|
||||
2025-07-07 17:50:09
|
||||
2025-07-08 14:41:36
|
||||
1. 一些累计更新
|
||||
2. 白名单
|
||||
3. 优化防火墙
|
||||
|
Reference in New Issue
Block a user