mirror of
https://github.com/VaalaCat/frp-panel.git
synced 2025-10-30 10:16:33 +08:00
feat: proxy list [新增代理列表实体]
refactor: change client manager structure [重构:更改客户端管理器结构适配影子客户端] feat: add proxy config table and dao [添加代理配置独立数据表和DAO层] feat: new proxy config entity [新建的代理配置实体] feat: update and delete proxy config [更新和删除代理配置接口] feat: get config api and beautify proxy item [更新获取配置API并美化代理项] feat: change proxy form style [美化修改代理的表单样式] fix: client edit [修复:编辑客户端的问题] fix: shadow copy status error [修复:影子客户端复制状态错误] fix: http proxy bug [修复:HTTP代理类型的错误] fix: cannot update client [修复:无法更新客户端] feat: record trigger refetch [自动重新获取表格内的数据] fix: filter string length [修复:过滤字符串长度] fix: add client error [修复:添加客户端错误] fix: do not notify client when stopped [修复:停止时不通知客户端] fix: delete when proxy duplicate [修复:代理重复时删除] feat: add http proxy location [添加HTTP代理路由路径] chore: edit style [编辑样式美化] fix: remove expired client [修复:自动移除过期客户端] feat: proxy status [新增代理状态提示] fix: build [修复:构建] fix: refetch trigger [修复:重新获取数据的问题] fix: remove all expired client [修复:移除所有过期客户端] feat: i18n for proxy [代理页面的国际化翻译]
This commit is contained in:
42
biz/client/get_proxy_info.go
Normal file
42
biz/client/get_proxy_info.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/VaalaCat/frp-panel/logger"
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
"github.com/VaalaCat/frp-panel/tunnel"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
func GetProxyConfig(c context.Context, req *pb.GetProxyConfigRequest) (*pb.GetProxyConfigResponse, error) {
|
||||
var (
|
||||
clientID = req.GetClientId()
|
||||
serverID = req.GetServerId()
|
||||
proxyName = req.GetName()
|
||||
)
|
||||
|
||||
ctrl := tunnel.GetClientController()
|
||||
cli := ctrl.Get(clientID, serverID)
|
||||
if cli == nil {
|
||||
logger.Logger(c).Errorf("cannot get client, clientID: [%s], serverID: [%s]", clientID, serverID)
|
||||
return nil, fmt.Errorf("cannot get client")
|
||||
}
|
||||
workingStatus, ok := cli.GetProxyStatus(proxyName)
|
||||
if !ok {
|
||||
logger.Logger(c).Errorf("cannot get proxy status, client: [%s], server: [%s], proxy name: [%s]", clientID, serverID, proxyName)
|
||||
return nil, fmt.Errorf("cannot get proxy status")
|
||||
}
|
||||
|
||||
return &pb.GetProxyConfigResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "success"},
|
||||
WorkingStatus: &pb.ProxyWorkingStatus{
|
||||
Name: lo.ToPtr(workingStatus.Name),
|
||||
Type: lo.ToPtr(workingStatus.Type),
|
||||
Status: lo.ToPtr(workingStatus.Phase),
|
||||
Err: lo.ToPtr(workingStatus.Err),
|
||||
RemoteAddr: lo.ToPtr(workingStatus.RemoteAddr),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -2,23 +2,20 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/VaalaCat/frp-panel/logger"
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
"github.com/VaalaCat/frp-panel/tunnel"
|
||||
)
|
||||
|
||||
func RemoveFrpcHandler(ctx context.Context, req *pb.RemoveFRPCRequest) (*pb.RemoveFRPCResponse, error) {
|
||||
logger.Logger(ctx).Infof("remove frpc, req: [%+v]", req)
|
||||
cli := tunnel.GetClientController().Get(req.GetClientId())
|
||||
if cli == nil {
|
||||
logger.Logger(ctx).Infof("client not found, no need to remove")
|
||||
return &pb.RemoveFRPCResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "client not found"},
|
||||
}, nil
|
||||
}
|
||||
cli.Stop()
|
||||
tunnel.GetClientController().Delete(req.GetClientId())
|
||||
logger.Logger(ctx).Infof("remove frpc, req: [%+v], will exit in 10s", req)
|
||||
|
||||
go func() {
|
||||
time.Sleep(10 * time.Second)
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
return &pb.RemoveFRPCResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"},
|
||||
|
||||
@@ -36,6 +36,8 @@ func HandleServerMessage(req *pb.ServerMessage) *pb.ClientMessage {
|
||||
return common.WrapperServerMsg(req, StopSteamLogHandler)
|
||||
case pb.Event_EVENT_START_PTY_CONNECT:
|
||||
return common.WrapperServerMsg(req, StartPTYConnect)
|
||||
case pb.Event_EVENT_GET_PROXY_INFO:
|
||||
return common.WrapperServerMsg(req, GetProxyConfig)
|
||||
case pb.Event_EVENT_PING:
|
||||
rawData, _ := proto.Marshal(conf.GetVersion().ToProto())
|
||||
return &pb.ClientMessage{
|
||||
|
||||
@@ -10,10 +10,12 @@ import (
|
||||
"github.com/VaalaCat/frp-panel/services/client"
|
||||
"github.com/VaalaCat/frp-panel/tunnel"
|
||||
"github.com/VaalaCat/frp-panel/utils"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
func PullConfig(clientID, clientSecret string) error {
|
||||
ctx := context.Background()
|
||||
ctrl := tunnel.GetClientController()
|
||||
|
||||
logger.Logger(ctx).Infof("start to pull client config, clientID: [%s]", clientID)
|
||||
cli, err := rpc.MasterCli(ctx)
|
||||
@@ -32,6 +34,38 @@ func PullConfig(clientID, clientSecret string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp.GetClient().GetStopped() {
|
||||
logger.Logger(ctx).Infof("client [%s] is stopped, stop client", clientID)
|
||||
ctrl.StopByClient(clientID)
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(resp.GetClient().GetOriginClientId()) == 0 {
|
||||
currentClientIDs := ctrl.List()
|
||||
if idsToRemove, _ := lo.Difference(resp.GetClient().GetClientIds(), currentClientIDs); len(idsToRemove) > 0 {
|
||||
logger.Logger(ctx).Infof("client [%s] has %d expired child clients, remove clientIDs: [%+v]", clientID, len(idsToRemove), idsToRemove)
|
||||
for _, id := range idsToRemove {
|
||||
ctrl.StopByClient(id)
|
||||
ctrl.DeleteByClient(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this client is shadow client, has no config
|
||||
// pull child client config
|
||||
if len(resp.GetClient().GetClientIds()) > 0 {
|
||||
for _, id := range resp.GetClient().GetClientIds() {
|
||||
if id == clientID {
|
||||
logger.Logger(ctx).Infof("client [%s] is shadow client, skip", clientID)
|
||||
continue
|
||||
}
|
||||
if err := PullConfig(id, clientSecret); err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Errorf("cannot pull child client config, id: [%s]", id)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(resp.GetClient().GetConfig()) == 0 {
|
||||
logger.Logger(ctx).Infof("client [%s] config is empty, wait for server init", clientID)
|
||||
return nil
|
||||
@@ -43,37 +77,38 @@ func PullConfig(clientID, clientSecret string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
ctrl := tunnel.GetClientController()
|
||||
serverID := resp.GetClient().GetServerId()
|
||||
|
||||
if t := ctrl.Get(clientID); t == nil {
|
||||
ctrl.Add(clientID, client.NewClientHandler(c, p, v))
|
||||
ctrl.Run(clientID)
|
||||
if t := ctrl.Get(clientID, serverID); t == nil {
|
||||
logger.Logger(ctx).Infof("client [%s] for server [%s] not exists, create it", clientID, serverID)
|
||||
ctrl.Add(clientID, serverID, client.NewClientHandler(c, p, v))
|
||||
ctrl.Run(clientID, serverID)
|
||||
} else {
|
||||
if !reflect.DeepEqual(t.GetCommonCfg(), c) {
|
||||
logger.Logger(ctx).Infof("client %s config changed, will recreate it", clientID)
|
||||
tcli := ctrl.Get(clientID)
|
||||
logger.Logger(ctx).Infof("client [%s] for server [%s] config changed, will recreate it", clientID, serverID)
|
||||
tcli := ctrl.Get(clientID, serverID)
|
||||
if tcli != nil {
|
||||
tcli.Stop()
|
||||
ctrl.Delete(clientID)
|
||||
ctrl.Delete(clientID, serverID)
|
||||
}
|
||||
ctrl.Add(clientID, client.NewClientHandler(c, p, v))
|
||||
ctrl.Run(clientID)
|
||||
ctrl.Add(clientID, serverID, client.NewClientHandler(c, p, v))
|
||||
ctrl.Run(clientID, serverID)
|
||||
} else {
|
||||
logger.Logger(ctx).Infof("client %s already exists, update if need", clientID)
|
||||
tcli := ctrl.Get(clientID)
|
||||
logger.Logger(ctx).Infof("client [%s] for server [%s] already exists, update if need", clientID, serverID)
|
||||
tcli := ctrl.Get(clientID, serverID)
|
||||
if tcli == nil || !tcli.Running() {
|
||||
if tcli != nil {
|
||||
tcli.Stop()
|
||||
ctrl.Delete(clientID)
|
||||
ctrl.Delete(clientID, serverID)
|
||||
}
|
||||
ctrl.Add(clientID, client.NewClientHandler(c, p, v))
|
||||
ctrl.Run(clientID)
|
||||
ctrl.Add(clientID, serverID, client.NewClientHandler(c, p, v))
|
||||
ctrl.Run(clientID, serverID)
|
||||
} else {
|
||||
tcli.Update(p, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.Logger(ctx).Infof("pull client config success, clientID: [%s]", clientID)
|
||||
logger.Logger(ctx).Infof("pull client config success, clientID: [%s], serverID: [%s]", clientID, serverID)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,15 +3,18 @@ package client
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/VaalaCat/frp-panel/conf"
|
||||
"github.com/VaalaCat/frp-panel/logger"
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
"github.com/VaalaCat/frp-panel/tunnel"
|
||||
)
|
||||
|
||||
func StartFRPCHandler(ctx context.Context, req *pb.StartFRPCRequest) (*pb.StartFRPCResponse, error) {
|
||||
logger.Logger(ctx).Infof("client get a start client request, origin is: [%+v]", req)
|
||||
|
||||
tunnel.GetClientController().Run(req.GetClientId())
|
||||
if err := PullConfig(req.GetClientId(), conf.Get().Client.Secret); err != nil {
|
||||
logger.Logger(ctx).WithError(err).Error("cannot pull client config")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.StartFRPCResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"},
|
||||
|
||||
@@ -11,7 +11,8 @@ import (
|
||||
func StopFRPCHandler(ctx context.Context, req *pb.StopFRPCRequest) (*pb.StopFRPCResponse, error) {
|
||||
logger.Logger(ctx).Infof("client get a stop client request, origin is: [%+v]", req)
|
||||
|
||||
tunnel.GetClientController().Stop(req.GetClientId())
|
||||
tunnel.GetClientController().StopAll()
|
||||
tunnel.GetClientController().DeleteAll()
|
||||
|
||||
return &pb.StopFRPCResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"},
|
||||
|
||||
@@ -16,27 +16,27 @@ func UpdateFrpcHander(ctx context.Context, req *pb.UpdateFRPCRequest) (*pb.Updat
|
||||
content := req.GetConfig()
|
||||
c, p, v, err := utils.LoadClientConfig(content, false)
|
||||
if err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Errorf("cannot load config")
|
||||
logger.Logger(ctx).WithError(err).Errorf("cannot load config")
|
||||
return &pb.UpdateFRPCResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: err.Error()},
|
||||
}, err
|
||||
}
|
||||
|
||||
cli := tunnel.GetClientController().Get(req.GetClientId())
|
||||
cli := tunnel.GetClientController().Get(req.GetClientId(), req.GetServerId())
|
||||
if cli != nil {
|
||||
if reflect.DeepEqual(c, cli.GetCommonCfg()) {
|
||||
logger.Logger(ctx).Warnf("client common config not changed")
|
||||
cli.Update(p, v)
|
||||
} else {
|
||||
cli.Stop()
|
||||
tunnel.GetClientController().Delete(req.GetClientId())
|
||||
tunnel.GetClientController().Add(req.GetClientId(), client.NewClientHandler(c, p, v))
|
||||
tunnel.GetClientController().Run(req.GetClientId())
|
||||
tunnel.GetClientController().Delete(req.GetClientId(), req.GetServerId())
|
||||
tunnel.GetClientController().Add(req.GetClientId(), req.GetServerId(), client.NewClientHandler(c, p, v))
|
||||
tunnel.GetClientController().Run(req.GetClientId(), req.GetServerId())
|
||||
}
|
||||
logger.Logger(ctx).Infof("update client, id: [%s] success, running", req.GetClientId())
|
||||
} else {
|
||||
tunnel.GetClientController().Add(req.GetClientId(), client.NewClientHandler(c, p, v))
|
||||
tunnel.GetClientController().Run(req.GetClientId())
|
||||
tunnel.GetClientController().Add(req.GetClientId(), req.GetServerId(), client.NewClientHandler(c, p, v))
|
||||
tunnel.GetClientController().Run(req.GetClientId(), req.GetServerId())
|
||||
logger.Logger(ctx).Infof("add new client, id: [%s], running", req.GetClientId())
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/VaalaCat/frp-panel/dao"
|
||||
"github.com/VaalaCat/frp-panel/models"
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
"github.com/VaalaCat/frp-panel/utils"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
@@ -20,7 +21,7 @@ func InitClientHandler(c context.Context, req *pb.InitClientRequest) (*pb.InitCl
|
||||
}, nil
|
||||
}
|
||||
|
||||
if len(userClientID) == 0 {
|
||||
if len(userClientID) == 0 || !utils.IsClientIDPermited(userClientID) {
|
||||
return &pb.InitClientResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid client id"},
|
||||
}, nil
|
||||
@@ -34,6 +35,7 @@ func InitClientHandler(c context.Context, req *pb.InitClientRequest) (*pb.InitCl
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
UserID: userInfo.GetUserID(),
|
||||
ConnectSecret: uuid.New().String(),
|
||||
IsShadow: true,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -32,6 +32,10 @@ func DeleteClientHandler(ctx context.Context, req *pb.DeleteClientRequest) (*pb.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := dao.DeleteProxyConfigsByClientIDOrOriginClientID(userInfo, clientID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go func() {
|
||||
resp, err := rpc.CallClient(context.Background(), req.GetClientId(), pb.Event_EVENT_REMOVE_FRPC, req)
|
||||
if err != nil {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"github.com/VaalaCat/frp-panel/common"
|
||||
"github.com/VaalaCat/frp-panel/dao"
|
||||
"github.com/VaalaCat/frp-panel/logger"
|
||||
"github.com/VaalaCat/frp-panel/models"
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
@@ -16,6 +17,7 @@ func GetClientHandler(ctx context.Context, req *pb.GetClientRequest) (*pb.GetCli
|
||||
var (
|
||||
userInfo = common.GetUserInfo(ctx)
|
||||
clientID = req.GetClientId()
|
||||
serverID = req.GetServerId()
|
||||
)
|
||||
|
||||
if !userInfo.Valid() {
|
||||
@@ -30,20 +32,54 @@ func GetClientHandler(ctx context.Context, req *pb.GetClientRequest) (*pb.GetCli
|
||||
}, nil
|
||||
}
|
||||
|
||||
client, err := dao.GetClientByClientID(userInfo, clientID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
respCli := &pb.Client{}
|
||||
if len(serverID) == 0 {
|
||||
client, err := dao.GetClientByClientID(userInfo, clientID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clientIDs, err := dao.GetClientIDsInShadowByClientID(userInfo, clientID)
|
||||
if err != nil {
|
||||
logger.Logger(ctx).WithError(err).Errorf("cannot get client ids in shadow, id: [%s]", clientID)
|
||||
}
|
||||
|
||||
respCli = &pb.Client{
|
||||
Id: lo.ToPtr(client.ClientID),
|
||||
Secret: lo.ToPtr(client.ConnectSecret),
|
||||
Config: lo.ToPtr(string(client.ConfigContent)),
|
||||
ServerId: lo.ToPtr(client.ServerID),
|
||||
Stopped: lo.ToPtr(client.Stopped),
|
||||
Comment: lo.ToPtr(client.Comment),
|
||||
ClientIds: clientIDs,
|
||||
}
|
||||
} else {
|
||||
client, err := dao.GetClientByFilter(userInfo, &models.ClientEntity{
|
||||
OriginClientID: clientID,
|
||||
ServerID: serverID,
|
||||
}, lo.ToPtr(false))
|
||||
if err != nil {
|
||||
client, err = dao.GetClientByFilter(userInfo, &models.ClientEntity{
|
||||
ClientID: clientID,
|
||||
ServerID: serverID,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
respCli = &pb.Client{
|
||||
Id: lo.ToPtr(client.ClientID),
|
||||
Secret: lo.ToPtr(client.ConnectSecret),
|
||||
Config: lo.ToPtr(string(client.ConfigContent)),
|
||||
ServerId: lo.ToPtr(client.ServerID),
|
||||
Stopped: lo.ToPtr(client.Stopped),
|
||||
Comment: lo.ToPtr(client.Comment),
|
||||
ClientIds: nil,
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.GetClientResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"},
|
||||
Client: &pb.Client{
|
||||
Id: lo.ToPtr(client.ClientID),
|
||||
Secret: lo.ToPtr(client.ConnectSecret),
|
||||
Config: lo.ToPtr(string(client.ConfigContent)),
|
||||
ServerId: lo.ToPtr(client.ServerID),
|
||||
Stopped: lo.ToPtr(client.Stopped),
|
||||
Comment: lo.ToPtr(client.Comment),
|
||||
},
|
||||
Client: respCli,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/VaalaCat/frp-panel/common"
|
||||
"github.com/VaalaCat/frp-panel/dao"
|
||||
"github.com/VaalaCat/frp-panel/logger"
|
||||
"github.com/VaalaCat/frp-panel/models"
|
||||
"github.com/samber/lo"
|
||||
"github.com/tiendc/go-deepcopy"
|
||||
)
|
||||
|
||||
type ValidateableClientRequest interface {
|
||||
@@ -32,3 +37,79 @@ func ValidateClientRequest(req ValidateableClientRequest) (*models.ClientEntity,
|
||||
|
||||
return cli, nil
|
||||
}
|
||||
|
||||
func MakeClientShadowed(c context.Context, serverID string, clientEntity *models.ClientEntity) (*models.ClientEntity, error) {
|
||||
userInfo := common.GetUserInfo(c)
|
||||
|
||||
var clientID = clientEntity.ClientID
|
||||
var childClient *models.ClientEntity
|
||||
var err error
|
||||
if len(clientEntity.ConfigContent) != 0 {
|
||||
childClient, err = ChildClientForServer(c, serverID, clientEntity)
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot create child client, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := dao.RebuildProxyConfigFromClient(userInfo, &models.Client{ClientEntity: childClient}); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot rebuild proxy config from client, id: [%s]", childClient.ClientID)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
clientEntity.IsShadow = true
|
||||
clientEntity.ConfigContent = nil
|
||||
clientEntity.ServerID = ""
|
||||
if err := dao.UpdateClient(userInfo, clientEntity); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot update client, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := dao.DeleteProxyConfigsByClientID(userInfo, clientID); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot delete proxy configs, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return childClient, nil
|
||||
}
|
||||
|
||||
// ChildClientForServer 支持传入serverID和任意类型client,返回serverID对应的client in shadow,如果不存在则新建
|
||||
func ChildClientForServer(c context.Context, serverID string, clientEntity *models.ClientEntity) (*models.ClientEntity, error) {
|
||||
userInfo := common.GetUserInfo(c)
|
||||
|
||||
originClientID := clientEntity.ClientID
|
||||
if len(clientEntity.OriginClientID) != 0 {
|
||||
originClientID = clientEntity.OriginClientID
|
||||
}
|
||||
|
||||
existClient, err := dao.GetClientByFilter(userInfo, &models.ClientEntity{
|
||||
ServerID: serverID,
|
||||
OriginClientID: originClientID,
|
||||
}, lo.ToPtr(false))
|
||||
if err == nil {
|
||||
return existClient, nil
|
||||
}
|
||||
|
||||
shadowCount, err := dao.CountClientsInShadow(userInfo, originClientID)
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot count shadow clients, id: [%s]", originClientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
copiedClient := &models.ClientEntity{}
|
||||
if err := deepcopy.Copy(copiedClient, clientEntity); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot copy client, id: [%s]", originClientID)
|
||||
return nil, err
|
||||
}
|
||||
copiedClient.ServerID = serverID
|
||||
copiedClient.ClientID = common.ShadowedClientID(originClientID, shadowCount+1)
|
||||
copiedClient.OriginClientID = originClientID
|
||||
copiedClient.IsShadow = false
|
||||
copiedClient.Stopped = false
|
||||
if err := dao.CreateClient(userInfo, copiedClient); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot create child client, id: [%s]", copiedClient.ClientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return copiedClient, nil
|
||||
}
|
||||
|
||||
@@ -55,13 +55,19 @@ func ListClientsHandler(ctx context.Context, req *pb.ListClientsRequest) (*pb.Li
|
||||
}
|
||||
|
||||
respClients := lo.Map(clients, func(c *models.ClientEntity, _ int) *pb.Client {
|
||||
clientIDs, err := dao.GetClientIDsInShadowByClientID(userInfo, c.ClientID)
|
||||
if err != nil {
|
||||
logger.Logger(ctx).Errorf("get client ids in shadow by client id error: %v", err)
|
||||
}
|
||||
|
||||
return &pb.Client{
|
||||
Id: lo.ToPtr(c.ClientID),
|
||||
Secret: lo.ToPtr(c.ConnectSecret),
|
||||
Config: lo.ToPtr(string(c.ConfigContent)),
|
||||
ServerId: lo.ToPtr(c.ServerID),
|
||||
Stopped: lo.ToPtr(c.Stopped),
|
||||
Comment: lo.ToPtr(c.Comment),
|
||||
Id: lo.ToPtr(c.ClientID),
|
||||
Secret: lo.ToPtr(c.ConnectSecret),
|
||||
Config: lo.ToPtr(string(c.ConfigContent)),
|
||||
ServerId: lo.ToPtr(c.ServerID),
|
||||
Stopped: lo.ToPtr(c.Stopped),
|
||||
Comment: lo.ToPtr(c.Comment),
|
||||
ClientIds: clientIDs,
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/VaalaCat/frp-panel/dao"
|
||||
"github.com/VaalaCat/frp-panel/logger"
|
||||
"github.com/VaalaCat/frp-panel/models"
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
"github.com/samber/lo"
|
||||
@@ -11,22 +13,37 @@ import (
|
||||
|
||||
func RPCPullConfig(ctx context.Context, req *pb.PullClientConfigReq) (*pb.PullClientConfigResp, error) {
|
||||
var (
|
||||
err error
|
||||
cli *models.ClientEntity
|
||||
err error
|
||||
cli *models.ClientEntity
|
||||
clientIDs []string
|
||||
)
|
||||
|
||||
if cli, err = ValidateClientRequest(req.GetBase()); err != nil {
|
||||
logger.Logger(ctx).WithError(err).Errorf("cannot validate client request")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cli.Stopped {
|
||||
if cli.IsShadow {
|
||||
proxies, err := dao.AdminListProxyConfigsWithFilters(&models.ProxyConfigEntity{
|
||||
OriginClientID: cli.ClientID,
|
||||
})
|
||||
if err != nil {
|
||||
logger.Logger(ctx).Infof("cannot get client ids in shadow, maybe not a shadow client, id: [%s]", cli.ClientID)
|
||||
}
|
||||
clientIDs = lo.Map(proxies, func(p *models.ProxyConfig, _ int) string { return p.ClientID })
|
||||
}
|
||||
|
||||
if cli.Stopped && cli.IsShadow {
|
||||
return nil, fmt.Errorf("client is stopped")
|
||||
}
|
||||
|
||||
return &pb.PullClientConfigResp{
|
||||
Client: &pb.Client{
|
||||
Id: lo.ToPtr(cli.ClientID),
|
||||
Config: lo.ToPtr(string(cli.ConfigContent)),
|
||||
Id: lo.ToPtr(cli.ClientID),
|
||||
ServerId: lo.ToPtr(cli.ServerID),
|
||||
Config: lo.ToPtr(string(cli.ConfigContent)),
|
||||
OriginClientId: lo.ToPtr(cli.OriginClientID),
|
||||
ClientIds: clientIDs,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/VaalaCat/frp-panel/common"
|
||||
"github.com/VaalaCat/frp-panel/dao"
|
||||
"github.com/VaalaCat/frp-panel/logger"
|
||||
"github.com/VaalaCat/frp-panel/models"
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
"github.com/VaalaCat/frp-panel/rpc"
|
||||
"github.com/VaalaCat/frp-panel/utils"
|
||||
@@ -18,31 +19,57 @@ import (
|
||||
func UpdateFrpcHander(c context.Context, req *pb.UpdateFRPCRequest) (*pb.UpdateFRPCResponse, error) {
|
||||
logger.Logger(c).Infof("update frpc, req: [%+v]", req)
|
||||
var (
|
||||
content = req.GetConfig()
|
||||
serverID = req.GetServerId()
|
||||
clientID = req.GetClientId()
|
||||
userInfo = common.GetUserInfo(c)
|
||||
content = req.GetConfig()
|
||||
serverID = req.GetServerId()
|
||||
reqClientID = req.GetClientId() // may be shadow or child
|
||||
userInfo = common.GetUserInfo(c)
|
||||
)
|
||||
|
||||
cliCfg, err := utils.LoadClientConfigNormal(content, true)
|
||||
if err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Errorf("cannot load config")
|
||||
logger.Logger(c).WithError(err).Errorf("cannot load config")
|
||||
return &pb.UpdateFRPCResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: err.Error()},
|
||||
}, err
|
||||
}
|
||||
|
||||
cli, err := dao.GetClientByClientID(userInfo, req.GetClientId())
|
||||
cli, err := dao.GetClientByClientID(userInfo, reqClientID)
|
||||
if err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Errorf("cannot get client, id: [%s]", req.GetClientId())
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get client, id: [%s]", reqClientID)
|
||||
return &pb.UpdateFRPCResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "cannot get client"},
|
||||
}, fmt.Errorf("cannot get client")
|
||||
}
|
||||
|
||||
if cli.IsShadow {
|
||||
cli, err = ChildClientForServer(c, serverID, cli)
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get child client, id: [%s]", reqClientID)
|
||||
return &pb.UpdateFRPCResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "cannot get child client"},
|
||||
}, fmt.Errorf("cannot get child client")
|
||||
}
|
||||
}
|
||||
|
||||
if cli.IsShadow && len(cli.ConfigContent) == 0 {
|
||||
logger.Logger(c).Warnf("client is shadowed, cannot update, id: [%s]", reqClientID)
|
||||
return nil, fmt.Errorf("client is shadowed, cannot update")
|
||||
}
|
||||
|
||||
if !cli.IsShadow && len(cli.OriginClientID) == 0 {
|
||||
logger.Logger(c).Warnf("client is not shadowed, make it shadow, id: [%s]", reqClientID)
|
||||
cli, err = MakeClientShadowed(c, serverID, cli)
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot make client shadowed, id: [%s]", reqClientID)
|
||||
return &pb.UpdateFRPCResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "cannot make client shadowed"},
|
||||
}, fmt.Errorf("cannot make client shadowed")
|
||||
}
|
||||
}
|
||||
|
||||
srv, err := dao.GetServerByServerID(userInfo, req.GetServerId())
|
||||
if err != nil || srv == nil || len(srv.ServerIP) == 0 || len(srv.ConfigContent) == 0 {
|
||||
logger.Logger(context.Background()).WithError(err).Errorf("cannot get server, server is not prepared, id: [%s]", req.GetServerId())
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get server, server is not prepared, id: [%s]", req.GetServerId())
|
||||
return &pb.UpdateFRPCResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "cannot get server"},
|
||||
}, fmt.Errorf("cannot get server")
|
||||
@@ -50,7 +77,7 @@ func UpdateFrpcHander(c context.Context, req *pb.UpdateFRPCRequest) (*pb.UpdateF
|
||||
|
||||
srvConf, err := srv.GetConfigContent()
|
||||
if srvConf == nil || err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Errorf("cannot get server, id: [%s]", serverID)
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get server, id: [%s]", serverID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -60,26 +87,22 @@ func UpdateFrpcHander(c context.Context, req *pb.UpdateFRPCRequest) (*pb.UpdateF
|
||||
cliCfg.Auth = v1.AuthClientConfig{}
|
||||
cliCfg.Metadatas = map[string]string{
|
||||
common.FRPAuthTokenKey: userInfo.GetToken(),
|
||||
common.FRPClientIDKey: clientID,
|
||||
common.FRPClientIDKey: reqClientID,
|
||||
}
|
||||
|
||||
newCfg := struct {
|
||||
v1.ClientCommonConfig
|
||||
Proxies []v1.ProxyConfigurer `json:"proxies,omitempty"`
|
||||
Visitors []v1.VisitorBaseConfig `json:"visitors,omitempty"`
|
||||
Visitors []v1.VisitorConfigurer `json:"visitors,omitempty"`
|
||||
}{
|
||||
ClientCommonConfig: cliCfg.ClientCommonConfig,
|
||||
Proxies: lo.Map(cliCfg.Proxies, func(item v1.TypedProxyConfig, _ int) v1.ProxyConfigurer {
|
||||
return item.ProxyConfigurer
|
||||
}),
|
||||
Visitors: lo.Map(cliCfg.Visitors, func(item v1.TypedVisitorConfig, _ int) v1.VisitorBaseConfig {
|
||||
return *item.GetBaseConfig()
|
||||
}),
|
||||
Proxies: lo.Map(cliCfg.Proxies, func(item v1.TypedProxyConfig, _ int) v1.ProxyConfigurer { return item.ProxyConfigurer }),
|
||||
Visitors: lo.Map(cliCfg.Visitors, func(item v1.TypedVisitorConfig, _ int) v1.VisitorConfigurer { return item.VisitorConfigurer }),
|
||||
}
|
||||
|
||||
rawCliConf, err := json.Marshal(newCfg)
|
||||
if err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Error("cannot marshal config")
|
||||
logger.Logger(c).WithError(err).Error("cannot marshal config")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -90,28 +113,45 @@ func UpdateFrpcHander(c context.Context, req *pb.UpdateFRPCRequest) (*pb.UpdateF
|
||||
}
|
||||
|
||||
if err := dao.UpdateClient(userInfo, cli); err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Errorf("cannot update client, id: [%s]", clientID)
|
||||
logger.Logger(c).WithError(err).Errorf("cannot update client, id: [%s]", cli.ClientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := dao.RebuildProxyConfigFromClient(userInfo, &models.Client{ClientEntity: cli}); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot rebuild proxy config from client, id: [%s]", cli.ClientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cliReq := &pb.UpdateFRPCRequest{
|
||||
ClientId: lo.ToPtr(clientID),
|
||||
ClientId: lo.ToPtr(cli.ClientID),
|
||||
ServerId: lo.ToPtr(serverID),
|
||||
Config: rawCliConf,
|
||||
}
|
||||
|
||||
go func() {
|
||||
resp, err := rpc.CallClient(context.Background(), req.GetClientId(), pb.Event_EVENT_UPDATE_FRPC, cliReq)
|
||||
childCtx := context.Background()
|
||||
cliToUpdate, err := dao.GetClientByFilter(userInfo, &models.ClientEntity{ClientID: cli.OriginClientID}, nil)
|
||||
if err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Errorf("update event send to client error, server: [%s], client: [%s]", serverID, req.GetClientId())
|
||||
logger.Logger(childCtx).WithError(err).Errorf("cannot get origin client, id: [%s]", cliToUpdate.OriginClientID)
|
||||
return
|
||||
}
|
||||
|
||||
if cliToUpdate.Stopped {
|
||||
logger.Logger(childCtx).Infof("client [%s] is stopped, do not send update event", cliToUpdate.OriginClientID)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := rpc.CallClient(childCtx, cliToUpdate.ClientID, pb.Event_EVENT_UPDATE_FRPC, cliReq)
|
||||
if err != nil {
|
||||
logger.Logger(childCtx).WithError(err).Errorf("update event send to client error, server: [%s], client: [%+v], updated client: [%+v]", serverID, cliToUpdate, cli)
|
||||
}
|
||||
|
||||
if resp == nil {
|
||||
logger.Logger(c).Errorf("cannot get response, server: [%s], client: [%s]", serverID, req.GetClientId())
|
||||
logger.Logger(childCtx).Errorf("cannot get response, server: [%s], client: [%s]", serverID, cliToUpdate.OriginClientID)
|
||||
}
|
||||
}()
|
||||
|
||||
logger.Logger(c).Infof("update frpc success, client id: [%s]", req.GetClientId())
|
||||
logger.Logger(c).Infof("update frpc success, client id: [%s]", reqClientID)
|
||||
return &pb.UpdateFRPCResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"},
|
||||
}, nil
|
||||
|
||||
@@ -74,8 +74,13 @@ func ConfigureRouter(router *gin.Engine) {
|
||||
}
|
||||
proxyRouter := v1.Group("/proxy", middleware.JWTAuth, middleware.AuthCtx)
|
||||
{
|
||||
proxyRouter.POST("/get_by_cid", common.Wrapper(proxy.GetProxyByCID))
|
||||
proxyRouter.POST("/get_by_sid", common.Wrapper(proxy.GetProxyBySID))
|
||||
proxyRouter.POST("/get_by_cid", common.Wrapper(proxy.GetProxyStatsByClientID))
|
||||
proxyRouter.POST("/get_by_sid", common.Wrapper(proxy.GetProxyStatsByServerID))
|
||||
proxyRouter.POST("/list_configs", common.Wrapper(proxy.ListProxyConfigs))
|
||||
proxyRouter.POST("/create_config", common.Wrapper(proxy.CreateProxyConfig))
|
||||
proxyRouter.POST("/update_config", common.Wrapper(proxy.UpdateProxyConfig))
|
||||
proxyRouter.POST("/delete_config", common.Wrapper(proxy.DeleteProxyConfig))
|
||||
proxyRouter.POST("/get_config", common.Wrapper(proxy.GetProxyConfig))
|
||||
}
|
||||
v1.GET("/pty/:clientID", middleware.JWTAuth, middleware.AuthCtx, shell.PTYHandler)
|
||||
v1.GET("/log", middleware.JWTAuth, middleware.AuthCtx, streamlog.GetLogHander)
|
||||
|
||||
@@ -66,7 +66,7 @@ func GetClientsStatus(c context.Context, req *pb.GetClientsStatusRequest) (*pb.G
|
||||
Ping: int32(pingTime),
|
||||
Version: clientVersion,
|
||||
Addr: lo.ToPtr(mgr.ClientAddr(clientID)),
|
||||
ConnectTime: lo.ToPtr(int32(connectTime.UnixMilli())),
|
||||
ConnectTime: lo.ToPtr(connectTime.UnixMilli()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
151
biz/master/proxy/create_proxy_config.go
Normal file
151
biz/master/proxy/create_proxy_config.go
Normal file
@@ -0,0 +1,151 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/VaalaCat/frp-panel/biz/master/client"
|
||||
"github.com/VaalaCat/frp-panel/common"
|
||||
"github.com/VaalaCat/frp-panel/dao"
|
||||
"github.com/VaalaCat/frp-panel/logger"
|
||||
"github.com/VaalaCat/frp-panel/models"
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
"github.com/VaalaCat/frp-panel/utils"
|
||||
v1 "github.com/fatedier/frp/pkg/config/v1"
|
||||
"github.com/samber/lo"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func CreateProxyConfig(c context.Context, req *pb.CreateProxyConfigRequest) (*pb.CreateProxyConfigResponse, error) {
|
||||
|
||||
if len(req.GetClientId()) == 0 || len(req.GetServerId()) == 0 || len(req.GetConfig()) == 0 {
|
||||
return nil, fmt.Errorf("request invalid")
|
||||
}
|
||||
|
||||
var (
|
||||
userInfo = common.GetUserInfo(c)
|
||||
clientID = req.GetClientId()
|
||||
serverID = req.GetServerId()
|
||||
)
|
||||
|
||||
// 1. 检查是否有已连接该服务端的客户端
|
||||
// 2. 检查是否有Shadow客户端
|
||||
// 3. 如果没有,则新建Shadow客户端和子客户端
|
||||
clientEntity, err := dao.GetClientByFilter(userInfo, &models.ClientEntity{OriginClientID: clientID, ServerID: serverID}, lo.ToPtr(false))
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
clientEntity, err = dao.GetClientByFilter(userInfo, &models.ClientEntity{ClientID: clientID}, nil)
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get client, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
if (!clientEntity.IsShadow || len(clientEntity.ConfigContent) != 0) && len(clientEntity.OriginClientID) == 0 {
|
||||
// 没shadow过,需要shadow
|
||||
_, err = client.MakeClientShadowed(c, serverID, clientEntity)
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot make client shadow, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// shadow过,但没找到子客户端,需要新建
|
||||
clientEntity, err = client.ChildClientForServer(c, serverID, clientEntity)
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot create child client, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// 有任何失败,返回
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get client, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = dao.GetServerByServerID(userInfo, serverID)
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get server, id: [%s]", serverID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
proxyCfg := &models.ProxyConfigEntity{}
|
||||
|
||||
if err := proxyCfg.FillClientConfig(clientEntity); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot fill client config, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
typedProxyCfgs, err := utils.LoadProxiesFromContent(req.GetConfig())
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot load proxies from content")
|
||||
return nil, err
|
||||
}
|
||||
if len(typedProxyCfgs) == 0 || len(typedProxyCfgs) > 1 {
|
||||
logger.Logger(c).Errorf("invalid config, cfg len: [%d]", len(typedProxyCfgs))
|
||||
return nil, fmt.Errorf("invalid config")
|
||||
}
|
||||
|
||||
if err := proxyCfg.FillTypedProxyConfig(typedProxyCfgs[0]); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot fill typed proxy config")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var existedProxyCfg *models.ProxyConfig
|
||||
existedProxyCfg, err = dao.GetProxyConfigByOriginClientIDAndName(userInfo, clientID, proxyCfg.Name)
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get proxy config, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !req.GetOverwrite() && err == nil {
|
||||
logger.Logger(c).Errorf("proxy config already exist, cfg: [%+v]", proxyCfg)
|
||||
return nil, fmt.Errorf("proxy config already exist")
|
||||
}
|
||||
|
||||
// update client config
|
||||
if oldCfg, err := clientEntity.GetConfigContent(); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get client config, id: [%s]", clientID)
|
||||
return nil, err
|
||||
} else {
|
||||
oldCfg.Proxies = lo.Filter(oldCfg.Proxies, func(proxy v1.TypedProxyConfig, _ int) bool {
|
||||
return proxy.GetBaseConfig().Name != typedProxyCfgs[0].GetBaseConfig().Name
|
||||
})
|
||||
oldCfg.Proxies = append(oldCfg.Proxies, typedProxyCfgs...)
|
||||
|
||||
if err := clientEntity.SetConfigContent(*oldCfg); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot set client config, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
rawCfg, err := clientEntity.MarshalJSONConfig()
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot marshal client config, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = client.UpdateFrpcHander(c, &pb.UpdateFRPCRequest{
|
||||
ClientId: &clientEntity.ClientID,
|
||||
ServerId: &serverID,
|
||||
Config: rawCfg,
|
||||
Comment: &clientEntity.Comment,
|
||||
})
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Warnf("cannot update frpc failed, id: [%s]", clientID)
|
||||
}
|
||||
|
||||
if existedProxyCfg != nil && existedProxyCfg.ServerID != serverID {
|
||||
logger.Logger(c).Warnf("client and server not match, delete old proxy, client: [%s], server: [%s], proxy: [%s]", clientID, serverID, proxyCfg.Name)
|
||||
if _, err := DeleteProxyConfig(c, &pb.DeleteProxyConfigRequest{
|
||||
ClientId: lo.ToPtr(existedProxyCfg.ClientID),
|
||||
ServerId: lo.ToPtr(existedProxyCfg.ServerID),
|
||||
Name: &proxyCfg.Name,
|
||||
}); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot delete old proxy, client: [%s], server: [%s], proxy: [%s]", clientID, clientEntity.ServerID, proxyCfg.Name)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.CreateProxyConfigResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"},
|
||||
}, nil
|
||||
}
|
||||
82
biz/master/proxy/delete_proxy_config.go
Normal file
82
biz/master/proxy/delete_proxy_config.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/VaalaCat/frp-panel/biz/master/client"
|
||||
"github.com/VaalaCat/frp-panel/common"
|
||||
"github.com/VaalaCat/frp-panel/dao"
|
||||
"github.com/VaalaCat/frp-panel/logger"
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
v1 "github.com/fatedier/frp/pkg/config/v1"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
func DeleteProxyConfig(c context.Context, req *pb.DeleteProxyConfigRequest) (*pb.DeleteProxyConfigResponse, error) {
|
||||
var (
|
||||
userInfo = common.GetUserInfo(c)
|
||||
clientID = req.GetClientId()
|
||||
serverID = req.GetServerId()
|
||||
proxyName = req.GetName()
|
||||
)
|
||||
|
||||
if len(clientID) == 0 || len(serverID) == 0 || len(proxyName) == 0 {
|
||||
return nil, fmt.Errorf("request invalid")
|
||||
}
|
||||
|
||||
cli, err := dao.GetClientByClientID(userInfo, clientID)
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get client, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
if cli.ServerID != serverID {
|
||||
return nil, fmt.Errorf("client and server not match")
|
||||
}
|
||||
|
||||
oldCfg, err := cli.GetConfigContent()
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get client config content, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oldCfg.Proxies = lo.Filter(oldCfg.Proxies, func(p v1.TypedProxyConfig, _ int) bool {
|
||||
return p.GetBaseConfig().Name != proxyName
|
||||
})
|
||||
|
||||
if err := cli.SetConfigContent(*oldCfg); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot set client config, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := dao.UpdateClient(userInfo, cli); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot update client, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rawCfg, err := cli.MarshalJSONConfig()
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot marshal client config, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = client.UpdateFrpcHander(c, &pb.UpdateFRPCRequest{
|
||||
ClientId: &cli.ClientID,
|
||||
ServerId: &serverID,
|
||||
Config: rawCfg,
|
||||
Comment: &cli.Comment,
|
||||
})
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot update frpc, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := dao.DeleteProxyConfig(userInfo, clientID, proxyName); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot delete proxy config, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logger.Logger(c).Infof("delete proxy config, id: [%s], name: [%s]", clientID, proxyName)
|
||||
|
||||
return &pb.DeleteProxyConfigResponse{}, nil
|
||||
}
|
||||
65
biz/master/proxy/get_proxy_config.go
Normal file
65
biz/master/proxy/get_proxy_config.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/VaalaCat/frp-panel/common"
|
||||
"github.com/VaalaCat/frp-panel/dao"
|
||||
"github.com/VaalaCat/frp-panel/logger"
|
||||
"github.com/VaalaCat/frp-panel/models"
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
"github.com/VaalaCat/frp-panel/rpc"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
func GetProxyConfig(c context.Context, req *pb.GetProxyConfigRequest) (*pb.GetProxyConfigResponse, error) {
|
||||
var (
|
||||
userInfo = common.GetUserInfo(c)
|
||||
clientID = req.GetClientId()
|
||||
serverID = req.GetServerId()
|
||||
proxyName = req.GetName()
|
||||
)
|
||||
|
||||
proxyConfig, err := dao.GetProxyConfigByFilter(userInfo, &models.ProxyConfigEntity{
|
||||
ClientID: clientID,
|
||||
ServerID: serverID,
|
||||
Name: proxyName,
|
||||
})
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get proxy config, client: [%s], server: [%s], proxy name: [%s]", clientID, serverID, proxyName)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := &pb.GetProxyConfigResponse{}
|
||||
if err := rpc.CallClientWrapper(c, proxyConfig.OriginClientID, pb.Event_EVENT_GET_PROXY_INFO, &pb.GetProxyConfigRequest{
|
||||
ClientId: lo.ToPtr(proxyConfig.ClientID),
|
||||
ServerId: lo.ToPtr(proxyConfig.ServerID),
|
||||
Name: lo.ToPtr(fmt.Sprintf("%s.%s", userInfo.GetUserName(), proxyName)),
|
||||
}, resp); err != nil {
|
||||
resp.WorkingStatus = &pb.ProxyWorkingStatus{
|
||||
Status: lo.ToPtr("error"),
|
||||
}
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get proxy config, client: [%s], server: [%s], proxy name: [%s]", proxyConfig.OriginClientID, proxyConfig.ServerID, proxyConfig.Name)
|
||||
}
|
||||
|
||||
if len(resp.GetWorkingStatus().GetStatus()) == 0 {
|
||||
resp.WorkingStatus = &pb.ProxyWorkingStatus{
|
||||
Status: lo.ToPtr("unknown"),
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.GetProxyConfigResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "success"},
|
||||
ProxyConfig: &pb.ProxyConfig{
|
||||
Id: lo.ToPtr(uint32(proxyConfig.ID)),
|
||||
Name: lo.ToPtr(proxyConfig.Name),
|
||||
Type: lo.ToPtr(proxyConfig.Type),
|
||||
ClientId: lo.ToPtr(proxyConfig.ClientID),
|
||||
ServerId: lo.ToPtr(proxyConfig.ServerID),
|
||||
Config: lo.ToPtr(string(proxyConfig.Content)),
|
||||
OriginClientId: lo.ToPtr(proxyConfig.OriginClientID),
|
||||
},
|
||||
WorkingStatus: resp.GetWorkingStatus(),
|
||||
}, nil
|
||||
}
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
)
|
||||
|
||||
// GetProxyByCID get proxy info by client id
|
||||
func GetProxyByCID(c context.Context, req *pb.GetProxyByCIDRequest) (*pb.GetProxyByCIDResponse, error) {
|
||||
// GetProxyStatsByClientID get proxy info by client id
|
||||
func GetProxyStatsByClientID(c context.Context, req *pb.GetProxyStatsByClientIDRequest) (*pb.GetProxyStatsByClientIDResponse, error) {
|
||||
logger.Logger(c).Infof("get proxy by client id, req: [%+v]", req)
|
||||
var (
|
||||
clientID = req.GetClientId()
|
||||
@@ -22,13 +22,13 @@ func GetProxyByCID(c context.Context, req *pb.GetProxyByCIDRequest) (*pb.GetProx
|
||||
return nil, fmt.Errorf("request invalid")
|
||||
}
|
||||
|
||||
proxyList, err := dao.GetProxyByClientID(userInfo, clientID)
|
||||
if proxyList == nil || err != nil {
|
||||
proxyStatsList, err := dao.GetProxyStatsByClientID(userInfo, clientID)
|
||||
if proxyStatsList == nil || err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Errorf("cannot get proxy, client id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
return &pb.GetProxyByCIDResponse{
|
||||
return &pb.GetProxyStatsByClientIDResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"},
|
||||
ProxyInfos: convertProxyList(proxyList),
|
||||
ProxyInfos: convertProxyStatsList(proxyStatsList),
|
||||
}, nil
|
||||
}
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
)
|
||||
|
||||
// GetProxyBySID get proxy info by server id
|
||||
func GetProxyBySID(c context.Context, req *pb.GetProxyBySIDRequest) (*pb.GetProxyBySIDResponse, error) {
|
||||
// GetProxyStatsByServerID get proxy info by server id
|
||||
func GetProxyStatsByServerID(c context.Context, req *pb.GetProxyStatsByServerIDRequest) (*pb.GetProxyStatsByServerIDResponse, error) {
|
||||
logger.Logger(c).Infof("get proxy by server id, req: [%+v]", req)
|
||||
var (
|
||||
serverID = req.GetServerId()
|
||||
@@ -22,13 +22,13 @@ func GetProxyBySID(c context.Context, req *pb.GetProxyBySIDRequest) (*pb.GetProx
|
||||
return nil, fmt.Errorf("request invalid")
|
||||
}
|
||||
|
||||
proxyList, err := dao.GetProxyByServerID(userInfo, serverID)
|
||||
proxyList, err := dao.GetProxyStatsByServerID(userInfo, serverID)
|
||||
if proxyList == nil || err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Errorf("cannot get proxy, server id: [%s]", serverID)
|
||||
return nil, err
|
||||
}
|
||||
return &pb.GetProxyBySIDResponse{
|
||||
return &pb.GetProxyStatsByServerIDResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"},
|
||||
ProxyInfos: convertProxyList(proxyList),
|
||||
ProxyInfos: convertProxyStatsList(proxyList),
|
||||
}, nil
|
||||
}
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
func convertProxyList(proxyList []*models.ProxyEntity) []*pb.ProxyInfo {
|
||||
return lo.Map(proxyList, func(item *models.ProxyEntity, index int) *pb.ProxyInfo {
|
||||
func convertProxyStatsList(proxyList []*models.ProxyStatsEntity) []*pb.ProxyInfo {
|
||||
return lo.Map(proxyList, func(item *models.ProxyStatsEntity, index int) *pb.ProxyInfo {
|
||||
return &pb.ProxyInfo{
|
||||
Name: lo.ToPtr(item.Name),
|
||||
Type: lo.ToPtr(item.Type),
|
||||
|
||||
86
biz/master/proxy/list_config.go
Normal file
86
biz/master/proxy/list_config.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/VaalaCat/frp-panel/common"
|
||||
"github.com/VaalaCat/frp-panel/dao"
|
||||
"github.com/VaalaCat/frp-panel/logger"
|
||||
"github.com/VaalaCat/frp-panel/models"
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
func ListProxyConfigs(ctx context.Context, req *pb.ListProxyConfigsRequest) (*pb.ListProxyConfigsResponse, error) {
|
||||
logger.Logger(ctx).Infof("list proxy configs, req: [%+v]", req)
|
||||
|
||||
var (
|
||||
userInfo = common.GetUserInfo(ctx)
|
||||
)
|
||||
|
||||
if !userInfo.Valid() {
|
||||
return &pb.ListProxyConfigsResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid user"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
var (
|
||||
page = int(req.GetPage())
|
||||
pageSize = int(req.GetPageSize())
|
||||
keyword = req.GetKeyword()
|
||||
clientID = req.GetClientId()
|
||||
serverID = req.GetServerId()
|
||||
hasKeyword = len(keyword) > 0
|
||||
hasClientID = len(clientID) > 0
|
||||
hasServerID = len(serverID) > 0
|
||||
proxyConfigs []*models.ProxyConfig
|
||||
err error
|
||||
proxyCounts int64
|
||||
filter = &models.ProxyConfigEntity{}
|
||||
)
|
||||
|
||||
if hasClientID {
|
||||
filter.OriginClientID = clientID
|
||||
}
|
||||
if hasServerID {
|
||||
filter.ServerID = serverID
|
||||
}
|
||||
|
||||
if hasKeyword {
|
||||
proxyConfigs, err = dao.ListProxyConfigsWithFiltersAndKeyword(userInfo, page, pageSize, filter, keyword)
|
||||
} else {
|
||||
proxyConfigs, err = dao.ListProxyConfigsWithFilters(userInfo, page, pageSize, filter)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if hasKeyword {
|
||||
proxyCounts, err = dao.CountProxyConfigsWithFiltersAndKeyword(userInfo, filter, keyword)
|
||||
} else {
|
||||
proxyCounts, err = dao.CountProxyConfigsWithFilters(userInfo, filter)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
respProxyConfigs := lo.Map(proxyConfigs, func(item *models.ProxyConfig, _ int) *pb.ProxyConfig {
|
||||
return &pb.ProxyConfig{
|
||||
Id: lo.ToPtr(uint32(item.ID)),
|
||||
Name: lo.ToPtr(item.Name),
|
||||
Type: lo.ToPtr(item.Type),
|
||||
ClientId: lo.ToPtr(item.ClientID),
|
||||
ServerId: lo.ToPtr(item.ServerID),
|
||||
Config: lo.ToPtr(string(item.Content)),
|
||||
OriginClientId: lo.ToPtr(item.OriginClientID),
|
||||
}
|
||||
})
|
||||
|
||||
return &pb.ListProxyConfigsResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "success"},
|
||||
ProxyConfigs: respProxyConfigs,
|
||||
Total: lo.ToPtr(int32(proxyCounts)),
|
||||
}, nil
|
||||
}
|
||||
@@ -19,23 +19,24 @@ func CollectDailyStats() error {
|
||||
}
|
||||
}()
|
||||
|
||||
proxies, err := dao.AdminGetAllProxies(tx)
|
||||
proxies, err := dao.AdminGetAllProxyStats(tx)
|
||||
if err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Error("CollectDailyStats cannot get proxies")
|
||||
return err
|
||||
}
|
||||
|
||||
proxyDailyStats := lo.Map(proxies, func(item *models.ProxyEntity, _ int) *models.HistoryProxyStats {
|
||||
proxyDailyStats := lo.Map(proxies, func(item *models.ProxyStatsEntity, _ int) *models.HistoryProxyStats {
|
||||
return &models.HistoryProxyStats{
|
||||
ProxyID: item.ProxyID,
|
||||
ServerID: item.ServerID,
|
||||
ClientID: item.ClientID,
|
||||
Name: item.Name,
|
||||
Type: item.Type,
|
||||
UserID: item.UserID,
|
||||
TenantID: item.TenantID,
|
||||
TrafficIn: item.HistoryTrafficIn,
|
||||
TrafficOut: item.HistoryTrafficOut,
|
||||
ProxyID: item.ProxyID,
|
||||
ServerID: item.ServerID,
|
||||
ClientID: item.ClientID,
|
||||
OriginClientID: item.OriginClientID,
|
||||
Name: item.Name,
|
||||
Type: item.Type,
|
||||
UserID: item.UserID,
|
||||
TenantID: item.TenantID,
|
||||
TrafficIn: item.HistoryTrafficIn,
|
||||
TrafficOut: item.HistoryTrafficOut,
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
127
biz/master/proxy/update_proxy_config.go
Normal file
127
biz/master/proxy/update_proxy_config.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/VaalaCat/frp-panel/biz/master/client"
|
||||
"github.com/VaalaCat/frp-panel/common"
|
||||
"github.com/VaalaCat/frp-panel/dao"
|
||||
"github.com/VaalaCat/frp-panel/logger"
|
||||
"github.com/VaalaCat/frp-panel/models"
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
"github.com/VaalaCat/frp-panel/utils"
|
||||
v1 "github.com/fatedier/frp/pkg/config/v1"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
func UpdateProxyConfig(c context.Context, req *pb.UpdateProxyConfigRequest) (*pb.UpdateProxyConfigResponse, error) {
|
||||
if len(req.GetClientId()) == 0 || len(req.GetServerId()) == 0 || len(req.GetConfig()) == 0 {
|
||||
return nil, fmt.Errorf("request invalid")
|
||||
}
|
||||
|
||||
var (
|
||||
userInfo = common.GetUserInfo(c)
|
||||
clientID = req.GetClientId()
|
||||
serverID = req.GetServerId()
|
||||
)
|
||||
|
||||
clientEntity, err := dao.GetClientByClientID(userInfo, clientID)
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get client, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if clientEntity.ServerID != serverID {
|
||||
logger.Logger(c).Errorf("client and server not match, find or create client, client: [%s], server: [%s]", clientID, serverID)
|
||||
originClient, err := dao.GetClientByClientID(userInfo, clientEntity.OriginClientID)
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get origin client, id: [%s]", clientEntity.OriginClientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clientEntity, err = client.ChildClientForServer(c, serverID, originClient)
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot create child client, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = dao.GetServerByServerID(userInfo, serverID)
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get server, id: [%s]", serverID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
proxyCfg := &models.ProxyConfigEntity{}
|
||||
if err := proxyCfg.FillClientConfig(clientEntity); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot fill client config, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
typedProxyCfgs, err := utils.LoadProxiesFromContent(req.GetConfig())
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot load proxies from content")
|
||||
return nil, err
|
||||
}
|
||||
if len(typedProxyCfgs) == 0 || len(typedProxyCfgs) > 1 {
|
||||
logger.Logger(c).Errorf("invalid config, cfg len: [%d]", len(typedProxyCfgs))
|
||||
return nil, fmt.Errorf("invalid config")
|
||||
}
|
||||
|
||||
if err := proxyCfg.FillTypedProxyConfig(typedProxyCfgs[0]); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot fill typed proxy config")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oldProxyCfg, err := dao.GetProxyConfigByOriginClientIDAndName(userInfo, clientID, proxyCfg.Name)
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get proxy config, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if dao.UpdateProxyConfig(userInfo, &models.ProxyConfig{
|
||||
Model: oldProxyCfg.Model,
|
||||
ProxyConfigEntity: proxyCfg,
|
||||
}) != nil {
|
||||
logger.Logger(c).Errorf("update proxy config failed, cfg: [%+v]", proxyCfg)
|
||||
return nil, fmt.Errorf("update proxy config failed")
|
||||
}
|
||||
|
||||
// update client config
|
||||
if oldCfg, err := clientEntity.GetConfigContent(); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot get client config, id: [%s]", clientID)
|
||||
return nil, err
|
||||
} else {
|
||||
oldCfg.Proxies = lo.Filter(oldCfg.Proxies, func(proxy v1.TypedProxyConfig, _ int) bool {
|
||||
return proxy.GetBaseConfig().Name != typedProxyCfgs[0].GetBaseConfig().Name
|
||||
})
|
||||
oldCfg.Proxies = append(oldCfg.Proxies, typedProxyCfgs...)
|
||||
|
||||
if err := clientEntity.SetConfigContent(*oldCfg); err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot set client config, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
rawCfg, err := clientEntity.MarshalJSONConfig()
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot marshal client config, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = client.UpdateFrpcHander(c, &pb.UpdateFRPCRequest{
|
||||
ClientId: &clientEntity.ClientID,
|
||||
ServerId: &serverID,
|
||||
Config: rawCfg,
|
||||
Comment: &clientEntity.Comment,
|
||||
})
|
||||
if err != nil {
|
||||
logger.Logger(c).WithError(err).Errorf("cannot update frpc, id: [%s]", clientID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.UpdateProxyConfigResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"},
|
||||
}, nil
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/VaalaCat/frp-panel/dao"
|
||||
"github.com/VaalaCat/frp-panel/models"
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
"github.com/VaalaCat/frp-panel/utils"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
@@ -23,7 +24,7 @@ func InitServerHandler(c context.Context, req *pb.InitServerRequest) (*pb.InitSe
|
||||
}, nil
|
||||
}
|
||||
|
||||
if len(userServerID) == 0 || len(serverIP) == 0 {
|
||||
if len(userServerID) == 0 || len(serverIP) == 0 || !utils.IsClientIDPermited(userServerID) {
|
||||
return &pb.InitServerResponse{
|
||||
Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "request invalid"},
|
||||
}, nil
|
||||
|
||||
@@ -16,7 +16,7 @@ func PushProxyInfo(ctx context.Context, req *pb.PushProxyInfoReq) (*pb.PushProxy
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = dao.AdminUpdateProxy(srv, req.GetProxyInfos()); err != nil {
|
||||
if err = dao.AdminUpdateProxyStats(srv, req.GetProxyInfos()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.PushProxyInfoResp{
|
||||
|
||||
@@ -28,7 +28,7 @@ func UpdateFrpsHander(ctx context.Context, req *pb.UpdateFRPSRequest) (*pb.Updat
|
||||
if cli := tunnel.GetServerController().Get(serverID); cli != nil {
|
||||
if !reflect.DeepEqual(cli.GetCommonCfg(), s) {
|
||||
cli.Stop()
|
||||
tunnel.GetClientController().Delete(serverID)
|
||||
tunnel.GetServerController().Delete(serverID)
|
||||
logger.Logger(ctx).Infof("server %s config changed, will recreate it", serverID)
|
||||
} else {
|
||||
logger.Logger(ctx).Infof("server %s config not changed", serverID)
|
||||
|
||||
@@ -74,6 +74,10 @@ func initDatabase(c context.Context) {
|
||||
logger.Logger(c).Infof("start to init database, type: %s", conf.Get().DB.Type)
|
||||
models.MustInitDBManager(nil, conf.Get().DB.Type)
|
||||
|
||||
if conf.Get().IsDebug {
|
||||
models.GetDBManager().SetDebug(true)
|
||||
}
|
||||
|
||||
switch conf.Get().DB.Type {
|
||||
case "sqlite3":
|
||||
if sqlitedb, err := gorm.Open(sqlite.Open(conf.Get().DB.DSN), &gorm.Config{}); err != nil {
|
||||
|
||||
@@ -14,6 +14,10 @@ func GlobalClientID(username, clientType, clientID string) string {
|
||||
return fmt.Sprintf("%s.%s.%s", username, clientType, clientID)
|
||||
}
|
||||
|
||||
func ShadowedClientID(clientID string, shadowCount int64) string {
|
||||
return fmt.Sprintf("%s@%d", clientID, shadowCount)
|
||||
}
|
||||
|
||||
func Wrapper[T ReqType, U RespType](handler func(context.Context, *T) (*U, error)) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
req, err := GetProtoRequest[T](c)
|
||||
|
||||
@@ -22,7 +22,9 @@ type ReqType interface {
|
||||
pb.GetPlatformInfoRequest | pb.GetClientsStatusRequest |
|
||||
pb.GetClientCertRequest |
|
||||
pb.StartFRPCRequest | pb.StopFRPCRequest | pb.StartFRPSRequest | pb.StopFRPSRequest |
|
||||
pb.GetProxyByCIDRequest | pb.GetProxyBySIDRequest
|
||||
pb.GetProxyStatsByClientIDRequest | pb.GetProxyStatsByServerIDRequest |
|
||||
pb.CreateProxyConfigRequest | pb.ListProxyConfigsRequest | pb.UpdateProxyConfigRequest |
|
||||
pb.DeleteProxyConfigRequest | pb.GetProxyConfigRequest
|
||||
}
|
||||
|
||||
func GetProtoRequest[T ReqType](c *gin.Context) (r *T, err error) {
|
||||
@@ -47,60 +49,14 @@ func GetProtoRequest[T ReqType](c *gin.Context) (r *T, err error) {
|
||||
}
|
||||
|
||||
func GetServerMessageRequest[T ReqType](b []byte, r *T, trans func(b []byte, m protoreflect.ProtoMessage) error) (err error) {
|
||||
switch ptr := any(r).(type) {
|
||||
case *pb.CommonRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.UpdateFRPCRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.RemoveFRPCRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.UpdateFRPSRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.RemoveFRPSRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.RegisterRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.LoginRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.InitClientRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.ListClientsRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.GetClientRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.DeleteClientRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.InitServerRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.ListServersRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.GetServerRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.DeleteServerRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.GetUserInfoRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.UpdateUserInfoRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.GetPlatformInfoRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.GetClientsStatusRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.GetClientCertRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.StartFRPCRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.StopFRPCRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.StartFRPSRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.StopFRPSRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.GetProxyByCIDRequest:
|
||||
return trans(b, ptr)
|
||||
case *pb.GetProxyBySIDRequest:
|
||||
return trans(b, ptr)
|
||||
default:
|
||||
msg, ok := any(r).(protoreflect.ProtoMessage)
|
||||
if !ok {
|
||||
return fmt.Errorf("type does not implement protoreflect.ProtoMessage")
|
||||
}
|
||||
return fmt.Errorf("cannot unmarshal unknown type: %T", r)
|
||||
|
||||
err = trans(b, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
"github.com/gin-gonic/gin"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
)
|
||||
|
||||
type RespType interface {
|
||||
@@ -21,7 +22,9 @@ type RespType interface {
|
||||
pb.GetPlatformInfoResponse | pb.GetClientsStatusResponse |
|
||||
pb.GetClientCertResponse |
|
||||
pb.StartFRPCResponse | pb.StopFRPCResponse | pb.StartFRPSResponse | pb.StopFRPSResponse |
|
||||
pb.GetProxyByCIDResponse | pb.GetProxyBySIDResponse
|
||||
pb.GetProxyStatsByClientIDResponse | pb.GetProxyStatsByServerIDResponse |
|
||||
pb.CreateProxyConfigResponse | pb.ListProxyConfigsResponse | pb.UpdateProxyConfigResponse |
|
||||
pb.DeleteProxyConfigResponse | pb.GetProxyConfigResponse
|
||||
}
|
||||
|
||||
func OKResp[T RespType](c *gin.Context, origin *T) {
|
||||
@@ -53,89 +56,45 @@ func ErrUnAuthorized(c *gin.Context, err string) {
|
||||
}
|
||||
|
||||
func ProtoResp[T RespType](origin *T) (*pb.ClientMessage, error) {
|
||||
event, msg, err := getEvent(origin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rawData, err := proto.Marshal(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.ClientMessage{
|
||||
Event: event,
|
||||
Data: rawData,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getEvent(origin interface{}) (pb.Event, protoreflect.ProtoMessage, error) {
|
||||
switch ptr := any(origin).(type) {
|
||||
case *pb.CommonResponse:
|
||||
rawData, err := proto.Marshal(ptr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.ClientMessage{
|
||||
Event: pb.Event_EVENT_DATA,
|
||||
Data: rawData,
|
||||
}, nil
|
||||
return pb.Event_EVENT_DATA, ptr, nil
|
||||
case *pb.UpdateFRPCResponse:
|
||||
rawData, err := proto.Marshal(ptr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.ClientMessage{
|
||||
Event: pb.Event_EVENT_UPDATE_FRPC,
|
||||
Data: rawData,
|
||||
}, nil
|
||||
return pb.Event_EVENT_UPDATE_FRPC, ptr, nil
|
||||
case *pb.RemoveFRPCResponse:
|
||||
rawData, err := proto.Marshal(ptr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.ClientMessage{
|
||||
Event: pb.Event_EVENT_REMOVE_FRPC,
|
||||
Data: rawData,
|
||||
}, nil
|
||||
return pb.Event_EVENT_REMOVE_FRPC, ptr, nil
|
||||
case *pb.UpdateFRPSResponse:
|
||||
rawData, err := proto.Marshal(ptr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.ClientMessage{
|
||||
Event: pb.Event_EVENT_UPDATE_FRPC,
|
||||
Data: rawData,
|
||||
}, nil
|
||||
return pb.Event_EVENT_UPDATE_FRPC, ptr, nil
|
||||
case *pb.RemoveFRPSResponse:
|
||||
rawData, err := proto.Marshal(ptr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.ClientMessage{
|
||||
Event: pb.Event_EVENT_REMOVE_FRPC,
|
||||
Data: rawData,
|
||||
}, nil
|
||||
return pb.Event_EVENT_REMOVE_FRPC, ptr, nil
|
||||
case *pb.StartFRPCResponse:
|
||||
rawData, err := proto.Marshal(ptr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.ClientMessage{
|
||||
Event: pb.Event_EVENT_START_FRPC,
|
||||
Data: rawData,
|
||||
}, nil
|
||||
return pb.Event_EVENT_START_FRPC, ptr, nil
|
||||
case *pb.StopFRPCResponse:
|
||||
rawData, err := proto.Marshal(ptr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.ClientMessage{
|
||||
Event: pb.Event_EVENT_STOP_FRPC,
|
||||
Data: rawData,
|
||||
}, nil
|
||||
return pb.Event_EVENT_STOP_FRPC, ptr, nil
|
||||
case *pb.StartFRPSResponse:
|
||||
rawData, err := proto.Marshal(ptr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.ClientMessage{
|
||||
Event: pb.Event_EVENT_START_FRPS,
|
||||
Data: rawData,
|
||||
}, nil
|
||||
return pb.Event_EVENT_START_FRPS, ptr, nil
|
||||
case *pb.StopFRPSResponse:
|
||||
rawData, err := proto.Marshal(ptr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.ClientMessage{
|
||||
Event: pb.Event_EVENT_STOP_FRPS,
|
||||
Data: rawData,
|
||||
}, nil
|
||||
return pb.Event_EVENT_STOP_FRPS, ptr, nil
|
||||
case *pb.GetProxyConfigResponse:
|
||||
return pb.Event_EVENT_GET_PROXY_INFO, ptr, nil
|
||||
default:
|
||||
return 0, nil, fmt.Errorf("cannot unmarshal unknown type: %T", origin)
|
||||
}
|
||||
return nil, fmt.Errorf("cannot unmarshal unknown type: %T", origin)
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ type Config struct {
|
||||
ID string `env:"ID" env-description:"client id"`
|
||||
Secret string `env:"SECRET" env-description:"client secret"`
|
||||
} `env-prefix:"CLIENT_"`
|
||||
IsDebug bool `env:"IS_DEBUG" env-default:"false" env-description:"is debug mode"`
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
143
dao/client.go
143
dao/client.go
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/VaalaCat/frp-panel/models"
|
||||
"github.com/samber/lo"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func ValidateClientSecret(clientID, clientSecret string) (*models.ClientEntity, error) {
|
||||
@@ -63,6 +64,56 @@ func GetClientByClientID(userInfo models.UserInfo, clientID string) (*models.Cli
|
||||
return c.ClientEntity, nil
|
||||
}
|
||||
|
||||
func GetClientByFilter(userInfo models.UserInfo, client *models.ClientEntity, shadow *bool) (*models.ClientEntity, error) {
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
filter := &models.ClientEntity{}
|
||||
if len(client.ClientID) != 0 {
|
||||
filter.ClientID = client.ClientID
|
||||
}
|
||||
if len(client.OriginClientID) != 0 {
|
||||
filter.OriginClientID = client.OriginClientID
|
||||
}
|
||||
if len(client.ConnectSecret) != 0 {
|
||||
filter.ConnectSecret = client.ConnectSecret
|
||||
}
|
||||
if len(client.ServerID) != 0 {
|
||||
filter.ServerID = client.ServerID
|
||||
}
|
||||
if shadow != nil {
|
||||
filter.IsShadow = *shadow
|
||||
}
|
||||
c := &models.Client{}
|
||||
|
||||
err := db.
|
||||
Where(&models.Client{ClientEntity: &models.ClientEntity{
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
}}).
|
||||
Where(filter).
|
||||
First(c).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.ClientEntity, nil
|
||||
}
|
||||
|
||||
func GetClientByOriginClientID(originClientID string) (*models.ClientEntity, error) {
|
||||
if originClientID == "" {
|
||||
return nil, fmt.Errorf("invalid origin client id")
|
||||
}
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
c := &models.Client{}
|
||||
err := db.
|
||||
Where(&models.Client{ClientEntity: &models.ClientEntity{
|
||||
OriginClientID: originClientID,
|
||||
}}).
|
||||
First(c).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.ClientEntity, nil
|
||||
}
|
||||
|
||||
func CreateClient(userInfo models.UserInfo, client *models.ClientEntity) error {
|
||||
client.UserID = userInfo.GetUserID()
|
||||
client.TenantID = userInfo.GetTenantID()
|
||||
@@ -84,11 +135,13 @@ func DeleteClient(userInfo models.UserInfo, clientID string) error {
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
},
|
||||
}).Delete(&models.Client{
|
||||
}).Or(&models.Client{
|
||||
ClientEntity: &models.ClientEntity{
|
||||
ClientID: clientID,
|
||||
OriginClientID: clientID,
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
},
|
||||
}).Error
|
||||
}).Delete(&models.Client{}).Error
|
||||
}
|
||||
|
||||
func UpdateClient(userInfo models.UserInfo, client *models.ClientEntity) error {
|
||||
@@ -118,7 +171,14 @@ func ListClients(userInfo models.UserInfo, page, pageSize int) ([]*models.Client
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
},
|
||||
}).Offset(offset).Limit(pageSize).Find(&clients).Error
|
||||
}).
|
||||
Where(
|
||||
db.Where(
|
||||
normalClientFilter(db),
|
||||
).Or(
|
||||
"is_shadow = ?", true,
|
||||
),
|
||||
).Offset(offset).Limit(pageSize).Find(&clients).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -129,6 +189,8 @@ func ListClients(userInfo models.UserInfo, page, pageSize int) ([]*models.Client
|
||||
}
|
||||
|
||||
func ListClientsWithKeyword(userInfo models.UserInfo, page, pageSize int, keyword string) ([]*models.ClientEntity, error) {
|
||||
// 只获取没shadow且config有东西
|
||||
// 或isShadow的client
|
||||
if page < 1 || pageSize < 1 || len(keyword) == 0 {
|
||||
return nil, fmt.Errorf("invalid page or page size or keyword")
|
||||
}
|
||||
@@ -137,12 +199,13 @@ func ListClientsWithKeyword(userInfo models.UserInfo, page, pageSize int, keywor
|
||||
offset := (page - 1) * pageSize
|
||||
|
||||
var clients []*models.Client
|
||||
err := db.Where(&models.Client{
|
||||
ClientEntity: &models.ClientEntity{
|
||||
err := db.Where("client_id like ?", "%"+keyword+"%").
|
||||
Where(&models.Client{ClientEntity: &models.ClientEntity{
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
},
|
||||
}).Where("client_id like ?", "%"+keyword+"%").Offset(offset).Limit(pageSize).Find(&clients).Error
|
||||
}}).
|
||||
Where(normalClientFilter(db)).
|
||||
Offset(offset).Limit(pageSize).Find(&clients).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -178,7 +241,8 @@ func CountClients(userInfo models.UserInfo) (int64, error) {
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
},
|
||||
}).Count(&count).Error
|
||||
}).
|
||||
Where(normalClientFilter(db)).Count(&count).Error
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -193,7 +257,8 @@ func CountClientsWithKeyword(userInfo models.UserInfo, keyword string) (int64, e
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
},
|
||||
}).Where("client_id like ?", "%"+keyword+"%").Count(&count).Error
|
||||
}).
|
||||
Where(normalClientFilter(db)).Where("client_id like ?", "%"+keyword+"%").Count(&count).Error
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -209,9 +274,23 @@ func CountConfiguredClients(userInfo models.UserInfo) (int64, error) {
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
}}).
|
||||
Not(&models.Client{
|
||||
Where(normalClientFilter(db)).
|
||||
Count(&count).Error
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func CountClientsInShadow(userInfo models.UserInfo, clientID string) (int64, error) {
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
var count int64
|
||||
err := db.Model(&models.Client{}).
|
||||
Where(&models.Client{
|
||||
ClientEntity: &models.ClientEntity{
|
||||
ConfigContent: []byte{},
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
OriginClientID: clientID,
|
||||
}}).
|
||||
Count(&count).Error
|
||||
if err != nil {
|
||||
@@ -219,3 +298,43 @@ func CountConfiguredClients(userInfo models.UserInfo) (int64, error) {
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func GetClientIDsInShadowByClientID(userInfo models.UserInfo, clientID string) ([]string, error) {
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
var clients []*models.Client
|
||||
err := db.Where(&models.Client{
|
||||
ClientEntity: &models.ClientEntity{
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
OriginClientID: clientID,
|
||||
}}).Find(&clients).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return lo.Map(clients, func(c *models.Client, _ int) string {
|
||||
return c.ClientID
|
||||
}), nil
|
||||
}
|
||||
|
||||
func AdminGetClientIDsInShadowByClientID(clientID string) ([]string, error) {
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
var clients []*models.Client
|
||||
err := db.Where(&models.Client{
|
||||
ClientEntity: &models.ClientEntity{
|
||||
OriginClientID: clientID,
|
||||
}}).Find(&clients).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return lo.Map(clients, func(c *models.Client, _ int) string {
|
||||
return c.ClientID
|
||||
}), nil
|
||||
}
|
||||
|
||||
func normalClientFilter(db *gorm.DB) *gorm.DB {
|
||||
// 1. 没shadow过的老client
|
||||
// 2. shadow过的shadow client
|
||||
return db.Where("origin_client_id is NULL").
|
||||
Or("is_shadow = ?", true).
|
||||
Or("LENGTH(origin_client_id) = ?", 0)
|
||||
}
|
||||
|
||||
392
dao/proxy.go
392
dao/proxy.go
@@ -1,10 +1,12 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/VaalaCat/frp-panel/logger"
|
||||
"github.com/VaalaCat/frp-panel/models"
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
"github.com/VaalaCat/frp-panel/utils"
|
||||
@@ -14,44 +16,54 @@ import (
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
func GetProxyByClientID(userInfo models.UserInfo, clientID string) ([]*models.ProxyEntity, error) {
|
||||
func GetProxyStatsByClientID(userInfo models.UserInfo, clientID string) ([]*models.ProxyStatsEntity, error) {
|
||||
if clientID == "" {
|
||||
return nil, fmt.Errorf("invalid client id")
|
||||
}
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
list := []*models.Proxy{}
|
||||
list := []*models.ProxyStats{}
|
||||
err := db.
|
||||
Where(&models.Proxy{ProxyEntity: &models.ProxyEntity{
|
||||
Where(&models.ProxyStats{ProxyStatsEntity: &models.ProxyStatsEntity{
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
ClientID: clientID,
|
||||
}}).
|
||||
Or(&models.Proxy{ProxyEntity: &models.ProxyEntity{
|
||||
Or(&models.ProxyStats{ProxyStatsEntity: &models.ProxyStatsEntity{
|
||||
UserID: 0,
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
ClientID: clientID,
|
||||
}}).
|
||||
Or(&models.ProxyStats{ProxyStatsEntity: &models.ProxyStatsEntity{
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
OriginClientID: clientID,
|
||||
}}).
|
||||
Or(&models.ProxyStats{ProxyStatsEntity: &models.ProxyStatsEntity{
|
||||
UserID: 0,
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
OriginClientID: clientID,
|
||||
}}).
|
||||
Find(&list).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return lo.Map(list, func(item *models.Proxy, _ int) *models.ProxyEntity {
|
||||
return item.ProxyEntity
|
||||
return lo.Map(list, func(item *models.ProxyStats, _ int) *models.ProxyStatsEntity {
|
||||
return item.ProxyStatsEntity
|
||||
}), nil
|
||||
}
|
||||
|
||||
func GetProxyByServerID(userInfo models.UserInfo, serverID string) ([]*models.ProxyEntity, error) {
|
||||
func GetProxyStatsByServerID(userInfo models.UserInfo, serverID string) ([]*models.ProxyStatsEntity, error) {
|
||||
if serverID == "" {
|
||||
return nil, fmt.Errorf("invalid server id")
|
||||
}
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
list := []*models.Proxy{}
|
||||
list := []*models.ProxyStats{}
|
||||
err := db.
|
||||
Where(&models.Proxy{ProxyEntity: &models.ProxyEntity{
|
||||
Where(&models.ProxyStats{ProxyStatsEntity: &models.ProxyStatsEntity{
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
ServerID: serverID,
|
||||
}}).Or(&models.Proxy{ProxyEntity: &models.ProxyEntity{
|
||||
}}).Or(&models.ProxyStats{ProxyStatsEntity: &models.ProxyStatsEntity{
|
||||
UserID: 0,
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
ServerID: serverID,
|
||||
@@ -60,12 +72,12 @@ func GetProxyByServerID(userInfo models.UserInfo, serverID string) ([]*models.Pr
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return lo.Map(list, func(item *models.Proxy, _ int) *models.ProxyEntity {
|
||||
return item.ProxyEntity
|
||||
return lo.Map(list, func(item *models.ProxyStats, _ int) *models.ProxyStatsEntity {
|
||||
return item.ProxyStatsEntity
|
||||
}), nil
|
||||
}
|
||||
|
||||
func AdminUpdateProxy(srv *models.ServerEntity, inputs []*pb.ProxyInfo) error {
|
||||
func AdminUpdateProxyStats(srv *models.ServerEntity, inputs []*pb.ProxyInfo) error {
|
||||
if srv.ServerID == "" {
|
||||
return fmt.Errorf("invalid server id")
|
||||
}
|
||||
@@ -105,15 +117,15 @@ func AdminUpdateProxy(srv *models.ServerEntity, inputs []*pb.ProxyInfo) error {
|
||||
)
|
||||
p.Go(
|
||||
func() error {
|
||||
oldProxy := []*models.Proxy{}
|
||||
oldProxy := []*models.ProxyStats{}
|
||||
if err := tx.
|
||||
Where(&models.Proxy{ProxyEntity: &models.ProxyEntity{
|
||||
Where(&models.ProxyStats{ProxyStatsEntity: &models.ProxyStatsEntity{
|
||||
UserID: srv.UserID,
|
||||
ServerID: srv.ServerID,
|
||||
}}).Find(&oldProxy).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
oldProxyMap := lo.SliceToMap(oldProxy, func(p *models.Proxy) (string, *models.Proxy) {
|
||||
oldProxyMap := lo.SliceToMap(oldProxy, func(p *models.ProxyStats) (string, *models.ProxyStats) {
|
||||
return p.Name, p
|
||||
})
|
||||
queryResults[2] = oldProxyMap
|
||||
@@ -126,16 +138,16 @@ func AdminUpdateProxy(srv *models.ServerEntity, inputs []*pb.ProxyInfo) error {
|
||||
|
||||
user := queryResults[0].(models.User)
|
||||
clients := queryResults[1].([]*models.Client)
|
||||
oldProxyMap := queryResults[2].(map[string]*models.Proxy)
|
||||
oldProxyMap := queryResults[2].(map[string]*models.ProxyStats)
|
||||
|
||||
inputMap := map[string]*pb.ProxyInfo{}
|
||||
proxyMap := map[string]*models.ProxyEntity{}
|
||||
proxyMap := map[string]*models.ProxyStatsEntity{}
|
||||
for _, proxyInfo := range inputs {
|
||||
if proxyInfo == nil {
|
||||
continue
|
||||
}
|
||||
proxyName := strings.TrimPrefix(proxyInfo.GetName(), user.UserName+".")
|
||||
proxyMap[proxyName] = &models.ProxyEntity{
|
||||
proxyMap[proxyName] = &models.ProxyStatsEntity{
|
||||
ServerID: srv.ServerID,
|
||||
Name: proxyName,
|
||||
Type: proxyInfo.GetType(),
|
||||
@@ -147,7 +159,7 @@ func AdminUpdateProxy(srv *models.ServerEntity, inputs []*pb.ProxyInfo) error {
|
||||
inputMap[proxyName] = proxyInfo
|
||||
}
|
||||
|
||||
proxyEntityMap := map[string]*models.ProxyEntity{}
|
||||
proxyEntityMap := map[string]*models.ProxyStatsEntity{}
|
||||
for _, client := range clients {
|
||||
cliCfg, err := client.GetConfigContent()
|
||||
if err != nil || cliCfg == nil {
|
||||
@@ -156,15 +168,16 @@ func AdminUpdateProxy(srv *models.ServerEntity, inputs []*pb.ProxyInfo) error {
|
||||
for _, cfg := range cliCfg.Proxies {
|
||||
if proxy, ok := proxyMap[cfg.GetBaseConfig().Name]; ok {
|
||||
proxy.ClientID = client.ClientID
|
||||
proxy.OriginClientID = client.OriginClientID
|
||||
proxyEntityMap[proxy.Name] = proxy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nowTime := time.Now()
|
||||
results := lo.Values(lo.MapValues(proxyEntityMap, func(p *models.ProxyEntity, name string) *models.Proxy {
|
||||
item := &models.Proxy{
|
||||
ProxyEntity: p,
|
||||
results := lo.Values(lo.MapValues(proxyEntityMap, func(p *models.ProxyStatsEntity, name string) *models.ProxyStats {
|
||||
item := &models.ProxyStats{
|
||||
ProxyStatsEntity: p,
|
||||
}
|
||||
if oldProxy, ok := oldProxyMap[name]; ok {
|
||||
item.ProxyID = oldProxy.ProxyID
|
||||
@@ -188,31 +201,346 @@ func AdminUpdateProxy(srv *models.ServerEntity, inputs []*pb.ProxyInfo) error {
|
||||
})
|
||||
}
|
||||
|
||||
func AdminGetTenantProxies(tenantID int) ([]*models.ProxyEntity, error) {
|
||||
func AdminGetTenantProxyStats(tenantID int) ([]*models.ProxyStatsEntity, error) {
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
list := []*models.Proxy{}
|
||||
list := []*models.ProxyStats{}
|
||||
err := db.
|
||||
Where(&models.Proxy{ProxyEntity: &models.ProxyEntity{
|
||||
Where(&models.ProxyStats{ProxyStatsEntity: &models.ProxyStatsEntity{
|
||||
TenantID: tenantID,
|
||||
}}).
|
||||
Find(&list).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return lo.Map(list, func(item *models.Proxy, _ int) *models.ProxyEntity {
|
||||
return item.ProxyEntity
|
||||
return lo.Map(list, func(item *models.ProxyStats, _ int) *models.ProxyStatsEntity {
|
||||
return item.ProxyStatsEntity
|
||||
}), nil
|
||||
}
|
||||
|
||||
func AdminGetAllProxies(tx *gorm.DB) ([]*models.ProxyEntity, error) {
|
||||
func AdminGetAllProxyStats(tx *gorm.DB) ([]*models.ProxyStatsEntity, error) {
|
||||
db := tx
|
||||
list := []*models.Proxy{}
|
||||
list := []*models.ProxyStats{}
|
||||
err := db.Clauses(clause.Locking{Strength: "UPDATE"}).
|
||||
Find(&list).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return lo.Map(list, func(item *models.Proxy, _ int) *models.ProxyEntity {
|
||||
return item.ProxyEntity
|
||||
return lo.Map(list, func(item *models.ProxyStats, _ int) *models.ProxyStatsEntity {
|
||||
return item.ProxyStatsEntity
|
||||
}), nil
|
||||
}
|
||||
|
||||
func AdminCreateProxyConfig(proxyCfg *models.ProxyConfig) error {
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
return db.Create(proxyCfg).Error
|
||||
}
|
||||
|
||||
// RebuildProxyConfigFromClient rebuild proxy from client
|
||||
func RebuildProxyConfigFromClient(userInfo models.UserInfo, client *models.Client) error {
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
|
||||
pxyCfgs, err := utils.LoadProxiesFromContent(client.ConfigContent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
proxyConfigEntities := []*models.ProxyConfig{}
|
||||
|
||||
for _, pxyCfg := range pxyCfgs {
|
||||
proxyCfg := &models.ProxyConfig{
|
||||
ProxyConfigEntity: &models.ProxyConfigEntity{},
|
||||
}
|
||||
if oldProxyCfg, err := GetProxyConfigByOriginClientIDAndName(userInfo, client.ClientID, pxyCfg.GetBaseConfig().Name); err == nil {
|
||||
logger.Logger(context.Background()).WithError(err).Warnf("proxy config already exist, will be override, clientID: [%s], name: [%s]",
|
||||
client.ClientID, pxyCfg.GetBaseConfig().Name)
|
||||
proxyCfg.Model = oldProxyCfg.Model
|
||||
}
|
||||
|
||||
if err := proxyCfg.FillClientConfig(client.ClientEntity); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := proxyCfg.FillTypedProxyConfig(pxyCfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
proxyConfigEntities = append(proxyConfigEntities, proxyCfg)
|
||||
}
|
||||
|
||||
if err := DeleteProxyConfigsByClientIDOrOriginClientID(userInfo, client.ClientID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(proxyConfigEntities) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return db.Save(proxyConfigEntities).Error
|
||||
}
|
||||
|
||||
func AdminGetProxyConfigByClientIDAndName(clientID string, name string) (*models.ProxyConfig, error) {
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
proxyCfg := &models.ProxyConfig{}
|
||||
err := db.
|
||||
Where(&models.ProxyConfig{ProxyConfigEntity: &models.ProxyConfigEntity{
|
||||
ClientID: clientID,
|
||||
Name: name,
|
||||
}}).
|
||||
First(proxyCfg).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return proxyCfg, nil
|
||||
}
|
||||
|
||||
func GetProxyConfigsByClientID(userInfo models.UserInfo, clientID string) ([]*models.ProxyConfigEntity, error) {
|
||||
if clientID == "" {
|
||||
return nil, fmt.Errorf("invalid client id")
|
||||
}
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
list := []*models.ProxyConfig{}
|
||||
err := db.
|
||||
Where(&models.ProxyConfig{ProxyConfigEntity: &models.ProxyConfigEntity{
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
ClientID: clientID,
|
||||
}}).
|
||||
Find(&list).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return lo.Map(list, func(item *models.ProxyConfig, _ int) *models.ProxyConfigEntity {
|
||||
return item.ProxyConfigEntity
|
||||
}), nil
|
||||
}
|
||||
|
||||
func GetProxyConfigByFilter(userInfo models.UserInfo, proxyConfig *models.ProxyConfigEntity) (*models.ProxyConfig, error) {
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
filter := &models.ProxyConfigEntity{}
|
||||
|
||||
if len(proxyConfig.ClientID) != 0 {
|
||||
filter.ClientID = proxyConfig.ClientID
|
||||
}
|
||||
if len(proxyConfig.OriginClientID) != 0 {
|
||||
filter.OriginClientID = proxyConfig.OriginClientID
|
||||
}
|
||||
if len(proxyConfig.Name) != 0 {
|
||||
filter.Name = proxyConfig.Name
|
||||
}
|
||||
if len(proxyConfig.Type) != 0 {
|
||||
filter.Type = proxyConfig.Type
|
||||
}
|
||||
if len(proxyConfig.ServerID) != 0 {
|
||||
filter.ServerID = proxyConfig.ServerID
|
||||
}
|
||||
|
||||
filter.UserID = userInfo.GetUserID()
|
||||
filter.TenantID = userInfo.GetTenantID()
|
||||
|
||||
respProxyCfg := &models.ProxyConfig{}
|
||||
err := db.
|
||||
Where(&models.ProxyConfig{ProxyConfigEntity: filter}).
|
||||
First(respProxyCfg).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return respProxyCfg, nil
|
||||
}
|
||||
|
||||
func ListProxyConfigsWithFilters(userInfo models.UserInfo, page, pageSize int, filters *models.ProxyConfigEntity) ([]*models.ProxyConfig, error) {
|
||||
if page < 1 || pageSize < 1 {
|
||||
return nil, fmt.Errorf("invalid page or page size")
|
||||
}
|
||||
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
offset := (page - 1) * pageSize
|
||||
|
||||
filters.UserID = userInfo.GetUserID()
|
||||
filters.TenantID = userInfo.GetTenantID()
|
||||
|
||||
var proxyConfigs []*models.ProxyConfig
|
||||
err := db.Where(&models.ProxyConfig{
|
||||
ProxyConfigEntity: filters,
|
||||
}).Where(filters).Offset(offset).Limit(pageSize).Find(&proxyConfigs).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return proxyConfigs, nil
|
||||
}
|
||||
|
||||
func AdminListProxyConfigsWithFilters(filters *models.ProxyConfigEntity) ([]*models.ProxyConfig, error) {
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
|
||||
var proxyConfigs []*models.ProxyConfig
|
||||
err := db.Where(&models.ProxyConfig{
|
||||
ProxyConfigEntity: filters,
|
||||
}).Where(filters).Find(&proxyConfigs).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return proxyConfigs, nil
|
||||
}
|
||||
|
||||
func ListProxyConfigsWithFiltersAndKeyword(userInfo models.UserInfo, page, pageSize int, filters *models.ProxyConfigEntity, keyword string) ([]*models.ProxyConfig, error) {
|
||||
if page < 1 || pageSize < 1 || len(keyword) == 0 {
|
||||
return nil, fmt.Errorf("invalid page or page size or keyword")
|
||||
}
|
||||
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
offset := (page - 1) * pageSize
|
||||
|
||||
filters.UserID = userInfo.GetUserID()
|
||||
filters.TenantID = userInfo.GetTenantID()
|
||||
|
||||
var proxyConfigs []*models.ProxyConfig
|
||||
err := db.Where(&models.ProxyConfig{
|
||||
ProxyConfigEntity: filters,
|
||||
}).Where(filters).Where("name like ?", "%"+keyword+"%").Offset(offset).Limit(pageSize).Find(&proxyConfigs).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return proxyConfigs, nil
|
||||
}
|
||||
|
||||
func ListProxyConfigsWithKeyword(userInfo models.UserInfo, page, pageSize int, keyword string) ([]*models.ProxyConfig, error) {
|
||||
return ListProxyConfigsWithFiltersAndKeyword(userInfo, page, pageSize, &models.ProxyConfigEntity{}, keyword)
|
||||
}
|
||||
|
||||
func ListProxyConfigs(userInfo models.UserInfo, page, pageSize int) ([]*models.ProxyConfig, error) {
|
||||
return ListProxyConfigsWithFilters(userInfo, page, pageSize, &models.ProxyConfigEntity{})
|
||||
}
|
||||
|
||||
func CreateProxyConfig(userInfo models.UserInfo, proxyCfg *models.ProxyConfigEntity) error {
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
proxyCfg.UserID = userInfo.GetUserID()
|
||||
proxyCfg.TenantID = userInfo.GetTenantID()
|
||||
return db.Create(&models.ProxyConfig{ProxyConfigEntity: proxyCfg}).Error
|
||||
}
|
||||
|
||||
func UpdateProxyConfig(userInfo models.UserInfo, proxyCfg *models.ProxyConfig) error {
|
||||
if proxyCfg.ID == 0 {
|
||||
return fmt.Errorf("invalid proxy config id")
|
||||
}
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
proxyCfg.UserID = userInfo.GetUserID()
|
||||
proxyCfg.TenantID = userInfo.GetTenantID()
|
||||
return db.Where(&models.ProxyConfig{
|
||||
ProxyConfigEntity: &models.ProxyConfigEntity{
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
ClientID: proxyCfg.ClientID,
|
||||
},
|
||||
Model: &gorm.Model{
|
||||
ID: proxyCfg.ID,
|
||||
},
|
||||
}).Save(proxyCfg).Error
|
||||
}
|
||||
|
||||
func DeleteProxyConfig(userInfo models.UserInfo, clientID, name string) error {
|
||||
if clientID == "" || name == "" {
|
||||
return fmt.Errorf("invalid client id or name")
|
||||
}
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
return db.Unscoped().
|
||||
Where(&models.ProxyConfig{ProxyConfigEntity: &models.ProxyConfigEntity{
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
ClientID: clientID,
|
||||
Name: name,
|
||||
}}).
|
||||
Delete(&models.ProxyConfig{}).Error
|
||||
}
|
||||
|
||||
func DeleteProxyConfigsByClientIDOrOriginClientID(userInfo models.UserInfo, clientID string) error {
|
||||
if clientID == "" {
|
||||
return fmt.Errorf("invalid client id")
|
||||
}
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
return db.Unscoped().
|
||||
Where(&models.ProxyConfig{ProxyConfigEntity: &models.ProxyConfigEntity{
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
ClientID: clientID,
|
||||
}}).
|
||||
Or(&models.ProxyConfig{ProxyConfigEntity: &models.ProxyConfigEntity{
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
OriginClientID: clientID,
|
||||
}}).
|
||||
Delete(&models.ProxyConfig{}).Error
|
||||
}
|
||||
|
||||
func DeleteProxyConfigsByClientID(userInfo models.UserInfo, clientID string) error {
|
||||
if clientID == "" {
|
||||
return fmt.Errorf("invalid client id")
|
||||
}
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
return db.Unscoped().
|
||||
Where(&models.ProxyConfig{ProxyConfigEntity: &models.ProxyConfigEntity{
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
ClientID: clientID,
|
||||
}}).
|
||||
Delete(&models.ProxyConfig{}).Error
|
||||
}
|
||||
|
||||
func GetProxyConfigByOriginClientIDAndName(userInfo models.UserInfo, clientID string, name string) (*models.ProxyConfig, error) {
|
||||
if clientID == "" || name == "" {
|
||||
return nil, fmt.Errorf("invalid client id or name")
|
||||
}
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
item := &models.ProxyConfig{}
|
||||
err := db.
|
||||
Where(&models.ProxyConfig{ProxyConfigEntity: &models.ProxyConfigEntity{
|
||||
UserID: userInfo.GetUserID(),
|
||||
TenantID: userInfo.GetTenantID(),
|
||||
OriginClientID: clientID,
|
||||
Name: name,
|
||||
}}).
|
||||
First(&item).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func CountProxyConfigs(userInfo models.UserInfo) (int64, error) {
|
||||
return CountProxyConfigsWithFilters(userInfo, &models.ProxyConfigEntity{})
|
||||
}
|
||||
|
||||
func CountProxyConfigsWithFilters(userInfo models.UserInfo, filters *models.ProxyConfigEntity) (int64, error) {
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
filters.UserID = userInfo.GetUserID()
|
||||
filters.TenantID = userInfo.GetTenantID()
|
||||
|
||||
var count int64
|
||||
err := db.Model(&models.ProxyConfig{}).Where(&models.ProxyConfig{
|
||||
ProxyConfigEntity: filters,
|
||||
}).Count(&count).Error
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func CountProxyConfigsWithFiltersAndKeyword(userInfo models.UserInfo, filters *models.ProxyConfigEntity, keyword string) (int64, error) {
|
||||
if len(keyword) == 0 {
|
||||
return CountProxyConfigsWithFilters(userInfo, filters)
|
||||
}
|
||||
|
||||
db := models.GetDBManager().GetDefaultDB()
|
||||
filters.UserID = userInfo.GetUserID()
|
||||
filters.TenantID = userInfo.GetTenantID()
|
||||
|
||||
var count int64
|
||||
err := db.Model(&models.ProxyConfig{}).Where(&models.ProxyConfig{
|
||||
ProxyConfigEntity: filters,
|
||||
}).Where("name like ?", "%"+keyword+"%").Count(&count).Error
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
1
go.mod
1
go.mod
@@ -25,6 +25,7 @@ require (
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/sourcegraph/conc v0.3.0
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/tiendc/go-deepcopy v1.2.0
|
||||
golang.org/x/crypto v0.25.0
|
||||
google.golang.org/grpc v1.65.0
|
||||
google.golang.org/protobuf v1.35.2
|
||||
|
||||
2
go.sum
2
go.sum
@@ -258,6 +258,8 @@ github.com/templexxx/cpu v0.1.1 h1:isxHaxBXpYFWnk2DReuKkigaZyrjs2+9ypIdGP4h+HI=
|
||||
github.com/templexxx/cpu v0.1.1/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
|
||||
github.com/templexxx/xorsimd v0.4.3 h1:9AQTFHd7Bhk3dIT7Al2XeBX5DWOvsUPZCuhyAtNbHjU=
|
||||
github.com/templexxx/xorsimd v0.4.3/go.mod h1:oZQcD6RFDisW2Am58dSAGwwL6rHjbzrlu25VDqfWkQg=
|
||||
github.com/tiendc/go-deepcopy v1.2.0 h1:6vCCs+qdLQHzFqY1fcPirsAWOmrLbuccilfp8UzD1Qo=
|
||||
github.com/tiendc/go-deepcopy v1.2.0/go.mod h1:toXoeQoUqXOOS/X4sKuiAoSk6elIdqc0pN7MTgOOo2I=
|
||||
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
||||
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
|
||||
@@ -28,6 +28,7 @@ message ListClientsResponse {
|
||||
|
||||
message GetClientRequest {
|
||||
optional string client_id = 1;
|
||||
optional string server_id = 2;
|
||||
}
|
||||
|
||||
message GetClientResponse {
|
||||
@@ -78,11 +79,69 @@ message StartFRPCResponse {
|
||||
optional common.Status status = 1;
|
||||
}
|
||||
|
||||
message GetProxyByCIDRequest {
|
||||
message GetProxyStatsByClientIDRequest {
|
||||
optional string client_id = 1;
|
||||
}
|
||||
|
||||
message GetProxyByCIDResponse {
|
||||
message GetProxyStatsByClientIDResponse {
|
||||
optional common.Status status = 1;
|
||||
repeated common.ProxyInfo proxy_infos = 2;
|
||||
}
|
||||
|
||||
message ListProxyConfigsRequest {
|
||||
optional int32 page = 1;
|
||||
optional int32 page_size = 2;
|
||||
optional string keyword = 3;
|
||||
optional string client_id = 4;
|
||||
optional string server_id = 5;
|
||||
}
|
||||
|
||||
message ListProxyConfigsResponse {
|
||||
optional common.Status status = 1;
|
||||
optional int32 total = 2;
|
||||
repeated common.ProxyConfig proxy_configs = 3;
|
||||
}
|
||||
|
||||
message CreateProxyConfigRequest {
|
||||
optional string client_id = 1;
|
||||
optional string server_id = 2;
|
||||
optional bytes config = 3;
|
||||
optional bool overwrite = 4;
|
||||
}
|
||||
|
||||
message CreateProxyConfigResponse {
|
||||
optional common.Status status = 1;
|
||||
}
|
||||
|
||||
message DeleteProxyConfigRequest {
|
||||
optional string client_id = 1;
|
||||
optional string server_id = 2;
|
||||
optional string name = 3;
|
||||
}
|
||||
|
||||
message DeleteProxyConfigResponse {
|
||||
optional common.Status status = 1;
|
||||
}
|
||||
|
||||
message UpdateProxyConfigRequest {
|
||||
optional string client_id = 1;
|
||||
optional string server_id = 2;
|
||||
optional string name = 3;
|
||||
optional bytes config = 4;
|
||||
}
|
||||
|
||||
message UpdateProxyConfigResponse {
|
||||
optional common.Status status = 1;
|
||||
}
|
||||
|
||||
message GetProxyConfigRequest {
|
||||
optional string client_id = 1;
|
||||
optional string server_id = 2;
|
||||
optional string name = 3;
|
||||
}
|
||||
|
||||
message GetProxyConfigResponse {
|
||||
optional common.Status status = 1;
|
||||
optional common.ProxyConfig proxy_config = 2;
|
||||
optional common.ProxyWorkingStatus working_status = 3;
|
||||
}
|
||||
@@ -17,7 +17,7 @@ message ClientStatus {
|
||||
int32 ping = 4; // 单位为毫秒
|
||||
optional ClientVersion version = 5;
|
||||
optional string addr = 6;
|
||||
optional int32 connect_time = 7; // 连接建立的时间
|
||||
optional int64 connect_time = 7; // 连接建立的时间
|
||||
}
|
||||
|
||||
message ClientVersion {
|
||||
|
||||
@@ -79,11 +79,11 @@ message StartFRPSResponse {
|
||||
optional common.Status status = 1;
|
||||
}
|
||||
|
||||
message GetProxyBySIDRequest {
|
||||
message GetProxyStatsByServerIDRequest {
|
||||
optional string server_id = 1;
|
||||
}
|
||||
|
||||
message GetProxyBySIDResponse {
|
||||
message GetProxyStatsByServerIDResponse {
|
||||
optional common.Status status = 1;
|
||||
repeated common.ProxyInfo proxy_infos = 2;
|
||||
}
|
||||
@@ -40,6 +40,8 @@ message Client {
|
||||
optional string comment = 5; // 用户自定义的备注
|
||||
optional string server_id = 6;
|
||||
optional bool stopped = 7;
|
||||
repeated string client_ids = 8; // some client can connected to more than one server, make a shadow client to handle this
|
||||
optional string origin_client_id = 9;
|
||||
}
|
||||
|
||||
message Server {
|
||||
@@ -72,3 +74,21 @@ message ProxyInfo {
|
||||
optional int64 history_traffic_out = 8;
|
||||
optional bool first_sync = 9;
|
||||
}
|
||||
|
||||
message ProxyConfig {
|
||||
optional uint32 id = 1;
|
||||
optional string name = 2;
|
||||
optional string type = 3;
|
||||
optional string client_id = 4;
|
||||
optional string server_id = 5;
|
||||
optional string config = 6;
|
||||
optional string origin_client_id = 7;
|
||||
}
|
||||
|
||||
message ProxyWorkingStatus {
|
||||
optional string name = 1;
|
||||
optional string type = 2;
|
||||
optional string status = 3;
|
||||
optional string err = 4;
|
||||
optional string remote_addr = 5;
|
||||
}
|
||||
@@ -23,6 +23,7 @@ enum Event {
|
||||
EVENT_START_STREAM_LOG = 15;
|
||||
EVENT_STOP_STREAM_LOG = 16;
|
||||
EVENT_START_PTY_CONNECT = 17;
|
||||
EVENT_GET_PROXY_INFO = 18;
|
||||
}
|
||||
|
||||
message ServerBase {
|
||||
|
||||
@@ -15,17 +15,19 @@ type Client struct {
|
||||
}
|
||||
|
||||
type ClientEntity struct {
|
||||
ClientID string `json:"client_id" gorm:"uniqueIndex;not null;primaryKey"`
|
||||
ServerID string `json:"server_id"`
|
||||
TenantID int `json:"tenant_id" gorm:"not null"`
|
||||
UserID int `json:"user_id" gorm:"not null"`
|
||||
ConfigContent []byte `json:"config_content"`
|
||||
ConnectSecret string `json:"connect_secret" gorm:"not null"`
|
||||
Stopped bool `json:"stopped"`
|
||||
Comment string `json:"comment"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||
ClientID string `json:"client_id" gorm:"uniqueIndex;not null;primaryKey"`
|
||||
ServerID string `json:"server_id"`
|
||||
TenantID int `json:"tenant_id" gorm:"not null"`
|
||||
UserID int `json:"user_id" gorm:"not null"`
|
||||
ConfigContent []byte `json:"config_content"`
|
||||
ConnectSecret string `json:"connect_secret" gorm:"not null"`
|
||||
Stopped bool `json:"stopped"`
|
||||
Comment string `json:"comment"`
|
||||
IsShadow bool `json:"is_shadow" gorm:"index"`
|
||||
OriginClientID string `json:"origin_client_id" gorm:"index"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||
}
|
||||
|
||||
func (*Client) TableName() string {
|
||||
@@ -61,3 +63,11 @@ func (c *ClientEntity) GetConfigContent() (*v1.ClientConfig, error) {
|
||||
}
|
||||
return cliCfg, err
|
||||
}
|
||||
|
||||
func (c *ClientEntity) MarshalJSONConfig() ([]byte, error) {
|
||||
cliCfg, err := c.GetConfigContent()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(cliCfg)
|
||||
}
|
||||
|
||||
19
models/db.go
19
models/db.go
@@ -12,12 +12,14 @@ type DBManager interface {
|
||||
GetDefaultDB() *gorm.DB
|
||||
SetDB(dbType string, db *gorm.DB)
|
||||
RemoveDB(dbType string)
|
||||
SetDebug(bool)
|
||||
Init()
|
||||
}
|
||||
|
||||
type dbManagerImpl struct {
|
||||
DBs map[string]*gorm.DB // key: db type
|
||||
defaultDBType string
|
||||
debug bool
|
||||
}
|
||||
|
||||
func (dbm *dbManagerImpl) Init() {
|
||||
@@ -34,12 +36,15 @@ func (dbm *dbManagerImpl) Init() {
|
||||
if err := db.AutoMigrate(&Cert{}); err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Fatalf("cannot init db table [%s]", (&Cert{}).TableName())
|
||||
}
|
||||
if err := db.AutoMigrate(&Proxy{}); err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Fatalf("cannot init db table [%s]", (&Proxy{}).TableName())
|
||||
if err := db.AutoMigrate(&ProxyStats{}); err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Fatalf("cannot init db table [%s]", (&ProxyStats{}).TableName())
|
||||
}
|
||||
if err := db.AutoMigrate(&HistoryProxyStats{}); err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Fatalf("cannot init db table [%s]", (&HistoryProxyStats{}).TableName())
|
||||
}
|
||||
if err := db.AutoMigrate(&ProxyConfig{}); err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Fatalf("cannot init db table [%s]", (&ProxyConfig{}).TableName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,5 +88,13 @@ func (dbm *dbManagerImpl) RemoveDB(dbType string) {
|
||||
}
|
||||
|
||||
func (dbm *dbManagerImpl) GetDefaultDB() *gorm.DB {
|
||||
return dbm.DBs[dbm.defaultDBType]
|
||||
db := dbm.DBs[dbm.defaultDBType]
|
||||
if dbm.debug {
|
||||
return db.Debug()
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func (dbm *dbManagerImpl) SetDebug(debug bool) {
|
||||
dbm.debug = debug
|
||||
}
|
||||
|
||||
74
models/helper.go
Normal file
74
models/helper.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/VaalaCat/frp-panel/logger"
|
||||
"github.com/VaalaCat/frp-panel/utils"
|
||||
v1 "github.com/fatedier/frp/pkg/config/v1"
|
||||
"github.com/tiendc/go-deepcopy"
|
||||
)
|
||||
|
||||
func ParseProxyConfigFromClient(client *Client) ([]*ProxyConfigEntity, error) {
|
||||
proxyCfg, err := utils.LoadProxiesFromContent(client.ConfigContent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := []*ProxyConfigEntity{}
|
||||
|
||||
for _, cfg := range proxyCfg {
|
||||
tmpProxyEntity := &ProxyConfigEntity{}
|
||||
|
||||
if err := tmpProxyEntity.FillClientConfig(client.ClientEntity); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := tmpProxyEntity.FillTypedProxyConfig(cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp = append(resp, tmpProxyEntity)
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func BuildClientConfigFromProxyConfig(client *Client, proxyCfgs []*ProxyConfig) (*Client, error) {
|
||||
if client == nil || len(proxyCfgs) == 0 {
|
||||
return nil, errors.New("client or proxy config is nil")
|
||||
}
|
||||
|
||||
resp := &Client{}
|
||||
if err := deepcopy.Copy(resp, client); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cliCfg, err := utils.LoadClientConfigNormal(client.ConfigContent, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pxyCfgs := []v1.TypedProxyConfig{}
|
||||
for _, proxyCfg := range proxyCfgs {
|
||||
pxy, err := utils.LoadProxiesFromContent(proxyCfg.Content)
|
||||
if err != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Errorf("cannot load proxy config, name: [%s]", proxyCfg.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
pxyCfgs = append(pxyCfgs, pxy...)
|
||||
}
|
||||
|
||||
cliCfg.Proxies = pxyCfgs
|
||||
cliCfgBytes, err := json.Marshal(cliCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client.ConfigContent = cliCfgBytes
|
||||
|
||||
return client, nil
|
||||
}
|
||||
48
models/proxy_config.go
Normal file
48
models/proxy_config.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
v1 "github.com/fatedier/frp/pkg/config/v1"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type ProxyConfig struct {
|
||||
*gorm.Model
|
||||
*ProxyConfigEntity
|
||||
}
|
||||
|
||||
type ProxyConfigEntity struct {
|
||||
ServerID string `json:"server_id" gorm:"index"`
|
||||
ClientID string `json:"client_id" gorm:"index"`
|
||||
Name string `json:"name" gorm:"index"`
|
||||
Type string `json:"type" gorm:"index"`
|
||||
UserID int `json:"user_id" gorm:"index"`
|
||||
TenantID int `json:"tenant_id" gorm:"index"`
|
||||
OriginClientID string `json:"origin_client_id" gorm:"index"`
|
||||
Content []byte `json:"content"`
|
||||
}
|
||||
|
||||
func (*ProxyConfig) TableName() string {
|
||||
return "proxy_config"
|
||||
}
|
||||
|
||||
func (p *ProxyConfigEntity) FillTypedProxyConfig(cfg v1.TypedProxyConfig) error {
|
||||
var err error
|
||||
p.Name = cfg.GetBaseConfig().Name
|
||||
p.Type = cfg.GetBaseConfig().Type
|
||||
p.Content, err = cfg.MarshalJSON()
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *ProxyConfigEntity) FillClientConfig(cli *ClientEntity) error {
|
||||
if cli == nil {
|
||||
return fmt.Errorf("invalid client, client is nil")
|
||||
}
|
||||
p.ServerID = cli.ServerID
|
||||
p.ClientID = cli.ClientID
|
||||
p.UserID = cli.UserID
|
||||
p.TenantID = cli.TenantID
|
||||
p.OriginClientID = cli.OriginClientID
|
||||
return nil
|
||||
}
|
||||
@@ -6,14 +6,15 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Proxy struct {
|
||||
*ProxyEntity
|
||||
type ProxyStats struct {
|
||||
*ProxyStatsEntity
|
||||
}
|
||||
|
||||
type ProxyEntity struct {
|
||||
type ProxyStatsEntity struct {
|
||||
ProxyID int `json:"proxy_id" gorm:"primary_key;auto_increment"`
|
||||
ServerID string `json:"server_id" gorm:"index"`
|
||||
ClientID string `json:"client_id" gorm:"index"`
|
||||
OriginClientID string `json:"origin_client_id" gorm:"index"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
UserID int `json:"user_id" gorm:"index"`
|
||||
@@ -27,23 +28,24 @@ type ProxyEntity struct {
|
||||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||
}
|
||||
|
||||
func (*Proxy) TableName() string {
|
||||
return "proxies"
|
||||
func (*ProxyStats) TableName() string {
|
||||
return "proxy_stats"
|
||||
}
|
||||
|
||||
// HistoryProxyStats 历史流量统计,不保证精准,只是为了展示。精准请使用 proxies 表中的 history_traffic_in/history_traffic_out
|
||||
// 后续看看是否要改成时序类数据 https://github.com/nakabonne/tstorage
|
||||
type HistoryProxyStats struct {
|
||||
gorm.Model
|
||||
ProxyID int `json:"proxy_id" gorm:"index"`
|
||||
ServerID string `json:"server_id" gorm:"index"`
|
||||
ClientID string `json:"client_id" gorm:"index"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
UserID int `json:"user_id" gorm:"index"`
|
||||
TenantID int `json:"tenant_id" gorm:"index"`
|
||||
TrafficIn int64 `json:"traffic_in"`
|
||||
TrafficOut int64 `json:"traffic_out"`
|
||||
ProxyID int `json:"proxy_id" gorm:"index"`
|
||||
ServerID string `json:"server_id" gorm:"index"`
|
||||
ClientID string `json:"client_id" gorm:"index"`
|
||||
OriginClientID string `json:"origin_client_id" gorm:"index"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
UserID int `json:"user_id" gorm:"index"`
|
||||
TenantID int `json:"tenant_id" gorm:"index"`
|
||||
TrafficIn int64 `json:"traffic_in"`
|
||||
TrafficOut int64 `json:"traffic_out"`
|
||||
}
|
||||
|
||||
func (*HistoryProxyStats) TableName() string {
|
||||
File diff suppressed because it is too large
Load Diff
@@ -83,7 +83,7 @@ type ClientStatus struct {
|
||||
Ping int32 `protobuf:"varint,4,opt,name=ping,proto3" json:"ping,omitempty"` // 单位为毫秒
|
||||
Version *ClientVersion `protobuf:"bytes,5,opt,name=version,proto3,oneof" json:"version,omitempty"`
|
||||
Addr *string `protobuf:"bytes,6,opt,name=addr,proto3,oneof" json:"addr,omitempty"`
|
||||
ConnectTime *int32 `protobuf:"varint,7,opt,name=connect_time,json=connectTime,proto3,oneof" json:"connect_time,omitempty"` // 连接建立的时间
|
||||
ConnectTime *int64 `protobuf:"varint,7,opt,name=connect_time,json=connectTime,proto3,oneof" json:"connect_time,omitempty"` // 连接建立的时间
|
||||
}
|
||||
|
||||
func (x *ClientStatus) Reset() {
|
||||
@@ -158,7 +158,7 @@ func (x *ClientStatus) GetAddr() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ClientStatus) GetConnectTime() int32 {
|
||||
func (x *ClientStatus) GetConnectTime() int64 {
|
||||
if x != nil && x.ConnectTime != nil {
|
||||
return *x.ConnectTime
|
||||
}
|
||||
@@ -493,7 +493,7 @@ var file_api_master_proto_rawDesc = []byte{
|
||||
0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x06,
|
||||
0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x88, 0x01, 0x01, 0x12,
|
||||
0x26, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18,
|
||||
0x07, 0x20, 0x01, 0x28, 0x05, 0x48, 0x02, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
|
||||
0x07, 0x20, 0x01, 0x28, 0x03, 0x48, 0x02, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
|
||||
0x54, 0x69, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x22, 0x59, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75,
|
||||
0x73, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50,
|
||||
0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x54, 0x41,
|
||||
|
||||
@@ -828,7 +828,7 @@ func (x *StartFRPSResponse) GetStatus() *Status {
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetProxyBySIDRequest struct {
|
||||
type GetProxyStatsByServerIDRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
@@ -836,20 +836,20 @@ type GetProxyBySIDRequest struct {
|
||||
ServerId *string `protobuf:"bytes,1,opt,name=server_id,json=serverId,proto3,oneof" json:"server_id,omitempty"`
|
||||
}
|
||||
|
||||
func (x *GetProxyBySIDRequest) Reset() {
|
||||
*x = GetProxyBySIDRequest{}
|
||||
func (x *GetProxyStatsByServerIDRequest) Reset() {
|
||||
*x = GetProxyStatsByServerIDRequest{}
|
||||
mi := &file_api_server_proto_msgTypes[16]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetProxyBySIDRequest) String() string {
|
||||
func (x *GetProxyStatsByServerIDRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetProxyBySIDRequest) ProtoMessage() {}
|
||||
func (*GetProxyStatsByServerIDRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetProxyBySIDRequest) ProtoReflect() protoreflect.Message {
|
||||
func (x *GetProxyStatsByServerIDRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_server_proto_msgTypes[16]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
@@ -861,19 +861,19 @@ func (x *GetProxyBySIDRequest) ProtoReflect() protoreflect.Message {
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetProxyBySIDRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetProxyBySIDRequest) Descriptor() ([]byte, []int) {
|
||||
// Deprecated: Use GetProxyStatsByServerIDRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetProxyStatsByServerIDRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_server_proto_rawDescGZIP(), []int{16}
|
||||
}
|
||||
|
||||
func (x *GetProxyBySIDRequest) GetServerId() string {
|
||||
func (x *GetProxyStatsByServerIDRequest) GetServerId() string {
|
||||
if x != nil && x.ServerId != nil {
|
||||
return *x.ServerId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type GetProxyBySIDResponse struct {
|
||||
type GetProxyStatsByServerIDResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
@@ -882,20 +882,20 @@ type GetProxyBySIDResponse struct {
|
||||
ProxyInfos []*ProxyInfo `protobuf:"bytes,2,rep,name=proxy_infos,json=proxyInfos,proto3" json:"proxy_infos,omitempty"`
|
||||
}
|
||||
|
||||
func (x *GetProxyBySIDResponse) Reset() {
|
||||
*x = GetProxyBySIDResponse{}
|
||||
func (x *GetProxyStatsByServerIDResponse) Reset() {
|
||||
*x = GetProxyStatsByServerIDResponse{}
|
||||
mi := &file_api_server_proto_msgTypes[17]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetProxyBySIDResponse) String() string {
|
||||
func (x *GetProxyStatsByServerIDResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetProxyBySIDResponse) ProtoMessage() {}
|
||||
func (*GetProxyStatsByServerIDResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetProxyBySIDResponse) ProtoReflect() protoreflect.Message {
|
||||
func (x *GetProxyStatsByServerIDResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_server_proto_msgTypes[17]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
@@ -907,19 +907,19 @@ func (x *GetProxyBySIDResponse) ProtoReflect() protoreflect.Message {
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetProxyBySIDResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetProxyBySIDResponse) Descriptor() ([]byte, []int) {
|
||||
// Deprecated: Use GetProxyStatsByServerIDResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetProxyStatsByServerIDResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_server_proto_rawDescGZIP(), []int{17}
|
||||
}
|
||||
|
||||
func (x *GetProxyBySIDResponse) GetStatus() *Status {
|
||||
func (x *GetProxyStatsByServerIDResponse) GetStatus() *Status {
|
||||
if x != nil {
|
||||
return x.Status
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *GetProxyBySIDResponse) GetProxyInfos() []*ProxyInfo {
|
||||
func (x *GetProxyStatsByServerIDResponse) GetProxyInfos() []*ProxyInfo {
|
||||
if x != nil {
|
||||
return x.ProxyInfos
|
||||
}
|
||||
@@ -1035,21 +1035,22 @@ var file_api_server_proto_rawDesc = []byte{
|
||||
0x65, 0x12, 0x2b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75,
|
||||
0x73, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x88, 0x01, 0x01, 0x42, 0x09,
|
||||
0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x46, 0x0a, 0x14, 0x47, 0x65, 0x74,
|
||||
0x50, 0x72, 0x6f, 0x78, 0x79, 0x42, 0x79, 0x53, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x12, 0x20, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64,
|
||||
0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69,
|
||||
0x64, 0x22, 0x83, 0x01, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x42, 0x79,
|
||||
0x53, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x06, 0x73,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x6f,
|
||||
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48, 0x00, 0x52, 0x06, 0x73,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x88, 0x01, 0x01, 0x12, 0x32, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x78,
|
||||
0x79, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x49, 0x6e, 0x66, 0x6f,
|
||||
0x52, 0x0a, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x73, 0x42, 0x09, 0x0a, 0x07,
|
||||
0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x07, 0x5a, 0x05, 0x2e, 0x2e, 0x2f, 0x70, 0x62,
|
||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x50, 0x0a, 0x1e, 0x47, 0x65, 0x74,
|
||||
0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76,
|
||||
0x65, 0x72, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x09, 0x73,
|
||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00,
|
||||
0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a,
|
||||
0x0a, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x22, 0x8d, 0x01, 0x0a, 0x1f,
|
||||
0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x42, 0x79, 0x53,
|
||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x2b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x0e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48,
|
||||
0x00, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x88, 0x01, 0x01, 0x12, 0x32, 0x0a, 0x0b,
|
||||
0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
|
||||
0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79,
|
||||
0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x73,
|
||||
0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x07, 0x5a, 0x05, 0x2e,
|
||||
0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -1066,27 +1067,27 @@ func file_api_server_proto_rawDescGZIP() []byte {
|
||||
|
||||
var file_api_server_proto_msgTypes = make([]protoimpl.MessageInfo, 18)
|
||||
var file_api_server_proto_goTypes = []any{
|
||||
(*InitServerRequest)(nil), // 0: api_server.InitServerRequest
|
||||
(*InitServerResponse)(nil), // 1: api_server.InitServerResponse
|
||||
(*ListServersRequest)(nil), // 2: api_server.ListServersRequest
|
||||
(*ListServersResponse)(nil), // 3: api_server.ListServersResponse
|
||||
(*GetServerRequest)(nil), // 4: api_server.GetServerRequest
|
||||
(*GetServerResponse)(nil), // 5: api_server.GetServerResponse
|
||||
(*DeleteServerRequest)(nil), // 6: api_server.DeleteServerRequest
|
||||
(*DeleteServerResponse)(nil), // 7: api_server.DeleteServerResponse
|
||||
(*UpdateFRPSRequest)(nil), // 8: api_server.UpdateFRPSRequest
|
||||
(*UpdateFRPSResponse)(nil), // 9: api_server.UpdateFRPSResponse
|
||||
(*RemoveFRPSRequest)(nil), // 10: api_server.RemoveFRPSRequest
|
||||
(*RemoveFRPSResponse)(nil), // 11: api_server.RemoveFRPSResponse
|
||||
(*StopFRPSRequest)(nil), // 12: api_server.StopFRPSRequest
|
||||
(*StopFRPSResponse)(nil), // 13: api_server.StopFRPSResponse
|
||||
(*StartFRPSRequest)(nil), // 14: api_server.StartFRPSRequest
|
||||
(*StartFRPSResponse)(nil), // 15: api_server.StartFRPSResponse
|
||||
(*GetProxyBySIDRequest)(nil), // 16: api_server.GetProxyBySIDRequest
|
||||
(*GetProxyBySIDResponse)(nil), // 17: api_server.GetProxyBySIDResponse
|
||||
(*Status)(nil), // 18: common.Status
|
||||
(*Server)(nil), // 19: common.Server
|
||||
(*ProxyInfo)(nil), // 20: common.ProxyInfo
|
||||
(*InitServerRequest)(nil), // 0: api_server.InitServerRequest
|
||||
(*InitServerResponse)(nil), // 1: api_server.InitServerResponse
|
||||
(*ListServersRequest)(nil), // 2: api_server.ListServersRequest
|
||||
(*ListServersResponse)(nil), // 3: api_server.ListServersResponse
|
||||
(*GetServerRequest)(nil), // 4: api_server.GetServerRequest
|
||||
(*GetServerResponse)(nil), // 5: api_server.GetServerResponse
|
||||
(*DeleteServerRequest)(nil), // 6: api_server.DeleteServerRequest
|
||||
(*DeleteServerResponse)(nil), // 7: api_server.DeleteServerResponse
|
||||
(*UpdateFRPSRequest)(nil), // 8: api_server.UpdateFRPSRequest
|
||||
(*UpdateFRPSResponse)(nil), // 9: api_server.UpdateFRPSResponse
|
||||
(*RemoveFRPSRequest)(nil), // 10: api_server.RemoveFRPSRequest
|
||||
(*RemoveFRPSResponse)(nil), // 11: api_server.RemoveFRPSResponse
|
||||
(*StopFRPSRequest)(nil), // 12: api_server.StopFRPSRequest
|
||||
(*StopFRPSResponse)(nil), // 13: api_server.StopFRPSResponse
|
||||
(*StartFRPSRequest)(nil), // 14: api_server.StartFRPSRequest
|
||||
(*StartFRPSResponse)(nil), // 15: api_server.StartFRPSResponse
|
||||
(*GetProxyStatsByServerIDRequest)(nil), // 16: api_server.GetProxyStatsByServerIDRequest
|
||||
(*GetProxyStatsByServerIDResponse)(nil), // 17: api_server.GetProxyStatsByServerIDResponse
|
||||
(*Status)(nil), // 18: common.Status
|
||||
(*Server)(nil), // 19: common.Server
|
||||
(*ProxyInfo)(nil), // 20: common.ProxyInfo
|
||||
}
|
||||
var file_api_server_proto_depIdxs = []int32{
|
||||
18, // 0: api_server.InitServerResponse.status:type_name -> common.Status
|
||||
@@ -1099,8 +1100,8 @@ var file_api_server_proto_depIdxs = []int32{
|
||||
18, // 7: api_server.RemoveFRPSResponse.status:type_name -> common.Status
|
||||
18, // 8: api_server.StopFRPSResponse.status:type_name -> common.Status
|
||||
18, // 9: api_server.StartFRPSResponse.status:type_name -> common.Status
|
||||
18, // 10: api_server.GetProxyBySIDResponse.status:type_name -> common.Status
|
||||
20, // 11: api_server.GetProxyBySIDResponse.proxy_infos:type_name -> common.ProxyInfo
|
||||
18, // 10: api_server.GetProxyStatsByServerIDResponse.status:type_name -> common.Status
|
||||
20, // 11: api_server.GetProxyStatsByServerIDResponse.proxy_infos:type_name -> common.ProxyInfo
|
||||
12, // [12:12] is the sub-list for method output_type
|
||||
12, // [12:12] is the sub-list for method input_type
|
||||
12, // [12:12] is the sub-list for extension type_name
|
||||
|
||||
442
pb/common.pb.go
442
pb/common.pb.go
@@ -286,12 +286,14 @@ type Client struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Id *string `protobuf:"bytes,1,opt,name=id,proto3,oneof" json:"id,omitempty"`
|
||||
Secret *string `protobuf:"bytes,2,opt,name=secret,proto3,oneof" json:"secret,omitempty"`
|
||||
Config *string `protobuf:"bytes,3,opt,name=config,proto3,oneof" json:"config,omitempty"`
|
||||
Comment *string `protobuf:"bytes,5,opt,name=comment,proto3,oneof" json:"comment,omitempty"` // 用户自定义的备注
|
||||
ServerId *string `protobuf:"bytes,6,opt,name=server_id,json=serverId,proto3,oneof" json:"server_id,omitempty"`
|
||||
Stopped *bool `protobuf:"varint,7,opt,name=stopped,proto3,oneof" json:"stopped,omitempty"`
|
||||
Id *string `protobuf:"bytes,1,opt,name=id,proto3,oneof" json:"id,omitempty"`
|
||||
Secret *string `protobuf:"bytes,2,opt,name=secret,proto3,oneof" json:"secret,omitempty"`
|
||||
Config *string `protobuf:"bytes,3,opt,name=config,proto3,oneof" json:"config,omitempty"`
|
||||
Comment *string `protobuf:"bytes,5,opt,name=comment,proto3,oneof" json:"comment,omitempty"` // 用户自定义的备注
|
||||
ServerId *string `protobuf:"bytes,6,opt,name=server_id,json=serverId,proto3,oneof" json:"server_id,omitempty"`
|
||||
Stopped *bool `protobuf:"varint,7,opt,name=stopped,proto3,oneof" json:"stopped,omitempty"`
|
||||
ClientIds []string `protobuf:"bytes,8,rep,name=client_ids,json=clientIds,proto3" json:"client_ids,omitempty"` // some client can connected to more than one server, make a shadow client to handle this
|
||||
OriginClientId *string `protobuf:"bytes,9,opt,name=origin_client_id,json=originClientId,proto3,oneof" json:"origin_client_id,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Client) Reset() {
|
||||
@@ -366,6 +368,20 @@ func (x *Client) GetStopped() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *Client) GetClientIds() []string {
|
||||
if x != nil {
|
||||
return x.ClientIds
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Client) GetOriginClientId() string {
|
||||
if x != nil && x.OriginClientId != nil {
|
||||
return *x.OriginClientId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -653,6 +669,176 @@ func (x *ProxyInfo) GetFirstSync() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type ProxyConfig struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Id *uint32 `protobuf:"varint,1,opt,name=id,proto3,oneof" json:"id,omitempty"`
|
||||
Name *string `protobuf:"bytes,2,opt,name=name,proto3,oneof" json:"name,omitempty"`
|
||||
Type *string `protobuf:"bytes,3,opt,name=type,proto3,oneof" json:"type,omitempty"`
|
||||
ClientId *string `protobuf:"bytes,4,opt,name=client_id,json=clientId,proto3,oneof" json:"client_id,omitempty"`
|
||||
ServerId *string `protobuf:"bytes,5,opt,name=server_id,json=serverId,proto3,oneof" json:"server_id,omitempty"`
|
||||
Config *string `protobuf:"bytes,6,opt,name=config,proto3,oneof" json:"config,omitempty"`
|
||||
OriginClientId *string `protobuf:"bytes,7,opt,name=origin_client_id,json=originClientId,proto3,oneof" json:"origin_client_id,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ProxyConfig) Reset() {
|
||||
*x = ProxyConfig{}
|
||||
mi := &file_common_proto_msgTypes[7]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ProxyConfig) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ProxyConfig) ProtoMessage() {}
|
||||
|
||||
func (x *ProxyConfig) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_common_proto_msgTypes[7]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ProxyConfig.ProtoReflect.Descriptor instead.
|
||||
func (*ProxyConfig) Descriptor() ([]byte, []int) {
|
||||
return file_common_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
func (x *ProxyConfig) GetId() uint32 {
|
||||
if x != nil && x.Id != nil {
|
||||
return *x.Id
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ProxyConfig) GetName() string {
|
||||
if x != nil && x.Name != nil {
|
||||
return *x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ProxyConfig) GetType() string {
|
||||
if x != nil && x.Type != nil {
|
||||
return *x.Type
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ProxyConfig) GetClientId() string {
|
||||
if x != nil && x.ClientId != nil {
|
||||
return *x.ClientId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ProxyConfig) GetServerId() string {
|
||||
if x != nil && x.ServerId != nil {
|
||||
return *x.ServerId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ProxyConfig) GetConfig() string {
|
||||
if x != nil && x.Config != nil {
|
||||
return *x.Config
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ProxyConfig) GetOriginClientId() string {
|
||||
if x != nil && x.OriginClientId != nil {
|
||||
return *x.OriginClientId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ProxyWorkingStatus struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Name *string `protobuf:"bytes,1,opt,name=name,proto3,oneof" json:"name,omitempty"`
|
||||
Type *string `protobuf:"bytes,2,opt,name=type,proto3,oneof" json:"type,omitempty"`
|
||||
Status *string `protobuf:"bytes,3,opt,name=status,proto3,oneof" json:"status,omitempty"`
|
||||
Err *string `protobuf:"bytes,4,opt,name=err,proto3,oneof" json:"err,omitempty"`
|
||||
RemoteAddr *string `protobuf:"bytes,5,opt,name=remote_addr,json=remoteAddr,proto3,oneof" json:"remote_addr,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ProxyWorkingStatus) Reset() {
|
||||
*x = ProxyWorkingStatus{}
|
||||
mi := &file_common_proto_msgTypes[8]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ProxyWorkingStatus) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ProxyWorkingStatus) ProtoMessage() {}
|
||||
|
||||
func (x *ProxyWorkingStatus) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_common_proto_msgTypes[8]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ProxyWorkingStatus.ProtoReflect.Descriptor instead.
|
||||
func (*ProxyWorkingStatus) Descriptor() ([]byte, []int) {
|
||||
return file_common_proto_rawDescGZIP(), []int{8}
|
||||
}
|
||||
|
||||
func (x *ProxyWorkingStatus) GetName() string {
|
||||
if x != nil && x.Name != nil {
|
||||
return *x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ProxyWorkingStatus) GetType() string {
|
||||
if x != nil && x.Type != nil {
|
||||
return *x.Type
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ProxyWorkingStatus) GetStatus() string {
|
||||
if x != nil && x.Status != nil {
|
||||
return *x.Status
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ProxyWorkingStatus) GetErr() string {
|
||||
if x != nil && x.Err != nil {
|
||||
return *x.Err
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ProxyWorkingStatus) GetRemoteAddr() string {
|
||||
if x != nil && x.RemoteAddr != nil {
|
||||
return *x.RemoteAddr
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_common_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_common_proto_rawDesc = []byte{
|
||||
@@ -672,7 +858,7 @@ var file_common_proto_rawDesc = []byte{
|
||||
0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||
0x48, 0x01, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f,
|
||||
0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x22,
|
||||
0xfa, 0x01, 0x0a, 0x06, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x13, 0x0a, 0x02, 0x69, 0x64,
|
||||
0xdd, 0x02, 0x0a, 0x06, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x13, 0x0a, 0x02, 0x69, 0x64,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x88, 0x01, 0x01, 0x12,
|
||||
0x1b, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48,
|
||||
0x01, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06,
|
||||
@@ -683,95 +869,135 @@ var file_common_proto_rawDesc = []byte{
|
||||
0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x08, 0x73,
|
||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x73, 0x74,
|
||||
0x6f, 0x70, 0x70, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x48, 0x05, 0x52, 0x07, 0x73,
|
||||
0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x88, 0x01, 0x01, 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x69, 0x64,
|
||||
0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x5f,
|
||||
0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64,
|
||||
0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x22, 0xbb, 0x01, 0x0a,
|
||||
0x06, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x13, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06,
|
||||
0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x06,
|
||||
0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x88, 0x01, 0x01, 0x12, 0x13, 0x0a, 0x02, 0x69, 0x70, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x02, 0x69, 0x70, 0x88, 0x01, 0x01, 0x12, 0x1b,
|
||||
0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03,
|
||||
0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x63,
|
||||
0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x07,
|
||||
0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x69,
|
||||
0x64, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x42, 0x05, 0x0a, 0x03,
|
||||
0x5f, 0x69, 0x70, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x0a,
|
||||
0x0a, 0x08, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0xd5, 0x02, 0x0a, 0x04, 0x55,
|
||||
0x73, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x88, 0x01, 0x01,
|
||||
0x12, 0x1f, 0x0a, 0x08, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x03, 0x48, 0x01, 0x52, 0x08, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x44, 0x88, 0x01,
|
||||
0x01, 0x12, 0x1f, 0x0a, 0x08, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x08, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x88,
|
||||
0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x09, 0x48, 0x03, 0x52, 0x05, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a,
|
||||
0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52,
|
||||
0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x52, 0x6f,
|
||||
0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x04, 0x52, 0x6f, 0x6c, 0x65,
|
||||
0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x07, 0x20, 0x01,
|
||||
0x28, 0x09, 0x48, 0x06, 0x52, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x25,
|
||||
0x0a, 0x0b, 0x52, 0x61, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x08, 0x20,
|
||||
0x01, 0x28, 0x09, 0x48, 0x07, 0x52, 0x0b, 0x52, 0x61, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||
0x72, 0x64, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44,
|
||||
0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x44, 0x42, 0x0b, 0x0a,
|
||||
0x09, 0x5f, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x45,
|
||||
0x6d, 0x61, 0x69, 0x6c, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42,
|
||||
0x07, 0x0a, 0x05, 0x5f, 0x52, 0x6f, 0x6c, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x54, 0x6f, 0x6b,
|
||||
0x65, 0x6e, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x52, 0x61, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||
0x72, 0x64, 0x22, 0x84, 0x04, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x49, 0x6e, 0x66, 0x6f,
|
||||
0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00,
|
||||
0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x74, 0x79, 0x70,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x88,
|
||||
0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49,
|
||||
0x64, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69,
|
||||
0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65,
|
||||
0x72, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x10, 0x74, 0x6f, 0x64, 0x61, 0x79, 0x5f,
|
||||
0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03,
|
||||
0x48, 0x04, 0x52, 0x0e, 0x74, 0x6f, 0x64, 0x61, 0x79, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63,
|
||||
0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x11, 0x74, 0x6f, 0x64, 0x61, 0x79, 0x5f, 0x74,
|
||||
0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03,
|
||||
0x48, 0x05, 0x52, 0x0f, 0x74, 0x6f, 0x64, 0x61, 0x79, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63,
|
||||
0x4f, 0x75, 0x74, 0x88, 0x01, 0x01, 0x12, 0x31, 0x0a, 0x12, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72,
|
||||
0x79, 0x5f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x01,
|
||||
0x28, 0x03, 0x48, 0x06, 0x52, 0x10, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x54, 0x72, 0x61,
|
||||
0x66, 0x66, 0x69, 0x63, 0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x33, 0x0a, 0x13, 0x68, 0x69, 0x73,
|
||||
0x74, 0x6f, 0x72, 0x79, 0x5f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x6f, 0x75, 0x74,
|
||||
0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x48, 0x07, 0x52, 0x11, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72,
|
||||
0x79, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x4f, 0x75, 0x74, 0x88, 0x01, 0x01, 0x12, 0x22,
|
||||
0x0a, 0x0a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x18, 0x09, 0x20, 0x01,
|
||||
0x28, 0x08, 0x48, 0x08, 0x52, 0x09, 0x66, 0x69, 0x72, 0x73, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x88,
|
||||
0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x5f,
|
||||
0x74, 0x79, 0x70, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f,
|
||||
0x69, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64,
|
||||
0x42, 0x13, 0x0a, 0x11, 0x5f, 0x74, 0x6f, 0x64, 0x61, 0x79, 0x5f, 0x74, 0x72, 0x61, 0x66, 0x66,
|
||||
0x69, 0x63, 0x5f, 0x69, 0x6e, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x74, 0x6f, 0x64, 0x61, 0x79, 0x5f,
|
||||
0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x6f, 0x75, 0x74, 0x42, 0x15, 0x0a, 0x13, 0x5f,
|
||||
0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x69,
|
||||
0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x63,
|
||||
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x73, 0x12, 0x2d, 0x0a, 0x10, 0x6f, 0x72, 0x69, 0x67,
|
||||
0x69, 0x6e, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01,
|
||||
0x28, 0x09, 0x48, 0x06, 0x52, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x43, 0x6c, 0x69, 0x65,
|
||||
0x6e, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x69, 0x64, 0x42, 0x09,
|
||||
0x0a, 0x07, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x63, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x42, 0x0a,
|
||||
0x0a, 0x08, 0x5f, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x6f,
|
||||
0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x22,
|
||||
0xbb, 0x01, 0x0a, 0x06, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x13, 0x0a, 0x02, 0x69, 0x64,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x88, 0x01, 0x01, 0x12,
|
||||
0x1b, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48,
|
||||
0x01, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x88, 0x01, 0x01, 0x12, 0x13, 0x0a, 0x02,
|
||||
0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x02, 0x69, 0x70, 0x88, 0x01,
|
||||
0x01, 0x12, 0x1b, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x09, 0x48, 0x03, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x88, 0x01, 0x01, 0x12, 0x1d,
|
||||
0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48,
|
||||
0x04, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x42, 0x05, 0x0a,
|
||||
0x03, 0x5f, 0x69, 0x64, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x42,
|
||||
0x05, 0x0a, 0x03, 0x5f, 0x69, 0x70, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x67, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0xd5, 0x02,
|
||||
0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44,
|
||||
0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x44, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x03, 0x48, 0x01, 0x52, 0x08, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49,
|
||||
0x44, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x08, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x61,
|
||||
0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x04,
|
||||
0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x05, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x88, 0x01, 0x01,
|
||||
0x12, 0x1b, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
|
||||
0x48, 0x04, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a,
|
||||
0x04, 0x52, 0x6f, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x04, 0x52,
|
||||
0x6f, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18,
|
||||
0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x06, 0x52, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x88, 0x01,
|
||||
0x01, 0x12, 0x25, 0x0a, 0x0b, 0x52, 0x61, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
|
||||
0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x07, 0x52, 0x0b, 0x52, 0x61, 0x77, 0x50, 0x61, 0x73,
|
||||
0x73, 0x77, 0x6f, 0x72, 0x64, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x55, 0x73, 0x65,
|
||||
0x72, 0x49, 0x44, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x44,
|
||||
0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x42, 0x08, 0x0a,
|
||||
0x06, 0x5f, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x53, 0x74, 0x61, 0x74,
|
||||
0x75, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x52, 0x6f, 0x6c, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x5f,
|
||||
0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x52, 0x61, 0x77, 0x50, 0x61, 0x73,
|
||||
0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x84, 0x04, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x49,
|
||||
0x6e, 0x66, 0x6f, 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04,
|
||||
0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x04, 0x74, 0x79,
|
||||
0x70, 0x65, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65,
|
||||
0x6e, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65,
|
||||
0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x08, 0x73, 0x65,
|
||||
0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x10, 0x74, 0x6f, 0x64,
|
||||
0x61, 0x79, 0x5f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x69, 0x6e, 0x18, 0x05, 0x20,
|
||||
0x01, 0x28, 0x03, 0x48, 0x04, 0x52, 0x0e, 0x74, 0x6f, 0x64, 0x61, 0x79, 0x54, 0x72, 0x61, 0x66,
|
||||
0x66, 0x69, 0x63, 0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x11, 0x74, 0x6f, 0x64, 0x61,
|
||||
0x79, 0x5f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x06, 0x20,
|
||||
0x01, 0x28, 0x03, 0x48, 0x05, 0x52, 0x0f, 0x74, 0x6f, 0x64, 0x61, 0x79, 0x54, 0x72, 0x61, 0x66,
|
||||
0x66, 0x69, 0x63, 0x4f, 0x75, 0x74, 0x88, 0x01, 0x01, 0x12, 0x31, 0x0a, 0x12, 0x68, 0x69, 0x73,
|
||||
0x74, 0x6f, 0x72, 0x79, 0x5f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x69, 0x6e, 0x18,
|
||||
0x07, 0x20, 0x01, 0x28, 0x03, 0x48, 0x06, 0x52, 0x10, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79,
|
||||
0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x33, 0x0a, 0x13,
|
||||
0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f,
|
||||
0x69, 0x6e, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x74,
|
||||
0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x6f, 0x75, 0x74, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x66,
|
||||
0x69, 0x72, 0x73, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x2a, 0xbc, 0x01, 0x0a, 0x08, 0x52, 0x65,
|
||||
0x73, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x45, 0x53, 0x50, 0x5f, 0x43,
|
||||
0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
|
||||
0x00, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x53, 0x50, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x53,
|
||||
0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x53, 0x50,
|
||||
0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10,
|
||||
0x02, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x53, 0x50, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x41,
|
||||
0x4c, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x10, 0x03, 0x12,
|
||||
0x15, 0x0a, 0x11, 0x52, 0x45, 0x53, 0x50, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x49, 0x4e, 0x56,
|
||||
0x41, 0x4c, 0x49, 0x44, 0x10, 0x04, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x45, 0x53, 0x50, 0x5f, 0x43,
|
||||
0x4f, 0x44, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x49, 0x53, 0x48, 0x10, 0x05, 0x12, 0x1a, 0x0a, 0x16,
|
||||
0x52, 0x45, 0x53, 0x50, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48,
|
||||
0x4f, 0x52, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x06, 0x2a, 0x55, 0x0a, 0x0a, 0x43, 0x6c, 0x69, 0x65,
|
||||
0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54,
|
||||
0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
|
||||
0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59,
|
||||
0x50, 0x45, 0x5f, 0x46, 0x52, 0x50, 0x43, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4c, 0x49,
|
||||
0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x52, 0x50, 0x53, 0x10, 0x02, 0x42,
|
||||
0x07, 0x5a, 0x05, 0x2e, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x6f, 0x75, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x48, 0x07, 0x52, 0x11, 0x68, 0x69, 0x73,
|
||||
0x74, 0x6f, 0x72, 0x79, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x4f, 0x75, 0x74, 0x88, 0x01,
|
||||
0x01, 0x12, 0x22, 0x0a, 0x0a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x18,
|
||||
0x09, 0x20, 0x01, 0x28, 0x08, 0x48, 0x08, 0x52, 0x09, 0x66, 0x69, 0x72, 0x73, 0x74, 0x53, 0x79,
|
||||
0x6e, 0x63, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x07,
|
||||
0x0a, 0x05, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x6c, 0x69, 0x65,
|
||||
0x6e, 0x74, 0x5f, 0x69, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||
0x5f, 0x69, 0x64, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x74, 0x6f, 0x64, 0x61, 0x79, 0x5f, 0x74, 0x72,
|
||||
0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x69, 0x6e, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x74, 0x6f, 0x64,
|
||||
0x61, 0x79, 0x5f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x6f, 0x75, 0x74, 0x42, 0x15,
|
||||
0x0a, 0x13, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x74, 0x72, 0x61, 0x66, 0x66,
|
||||
0x69, 0x63, 0x5f, 0x69, 0x6e, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72,
|
||||
0x79, 0x5f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x6f, 0x75, 0x74, 0x42, 0x0d, 0x0a,
|
||||
0x0b, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x22, 0xb9, 0x02, 0x0a,
|
||||
0x0b, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x13, 0x0a, 0x02,
|
||||
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x88, 0x01,
|
||||
0x01, 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48,
|
||||
0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x74, 0x79,
|
||||
0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
|
||||
0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
|
||||
0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76,
|
||||
0x65, 0x72, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x67, 0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x10, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x63,
|
||||
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x06,
|
||||
0x52, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64,
|
||||
0x88, 0x01, 0x01, 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x69, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x42, 0x0c, 0x0a, 0x0a,
|
||||
0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x73,
|
||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x63, 0x6f, 0x6e,
|
||||
0x66, 0x69, 0x67, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x63,
|
||||
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x22, 0xd5, 0x01, 0x0a, 0x12, 0x50, 0x72, 0x6f,
|
||||
0x78, 0x79, 0x57, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
|
||||
0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52,
|
||||
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x88, 0x01,
|
||||
0x01, 0x12, 0x1b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||
0x09, 0x48, 0x02, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x88, 0x01, 0x01, 0x12, 0x15,
|
||||
0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x03, 0x65,
|
||||
0x72, 0x72, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f,
|
||||
0x61, 0x64, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x0a, 0x72, 0x65,
|
||||
0x6d, 0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x42, 0x09, 0x0a,
|
||||
0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x65, 0x72, 0x72,
|
||||
0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72,
|
||||
0x2a, 0xbc, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x19, 0x0a,
|
||||
0x15, 0x52, 0x45, 0x53, 0x50, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
|
||||
0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x53, 0x50,
|
||||
0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12,
|
||||
0x17, 0x0a, 0x13, 0x52, 0x45, 0x53, 0x50, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x4f, 0x54,
|
||||
0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x53, 0x50,
|
||||
0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x41, 0x4c, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x45, 0x58,
|
||||
0x49, 0x53, 0x54, 0x53, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x53, 0x50, 0x5f, 0x43,
|
||||
0x4f, 0x44, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x04, 0x12, 0x14, 0x0a,
|
||||
0x10, 0x52, 0x45, 0x53, 0x50, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x49, 0x53,
|
||||
0x48, 0x10, 0x05, 0x12, 0x1a, 0x0a, 0x16, 0x52, 0x45, 0x53, 0x50, 0x5f, 0x43, 0x4f, 0x44, 0x45,
|
||||
0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x06, 0x2a,
|
||||
0x55, 0x0a, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a,
|
||||
0x17, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53,
|
||||
0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4c,
|
||||
0x49, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x52, 0x50, 0x43, 0x10, 0x01,
|
||||
0x12, 0x14, 0x0a, 0x10, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f,
|
||||
0x46, 0x52, 0x50, 0x53, 0x10, 0x02, 0x42, 0x07, 0x5a, 0x05, 0x2e, 0x2e, 0x2f, 0x70, 0x62, 0x62,
|
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -787,17 +1013,19 @@ func file_common_proto_rawDescGZIP() []byte {
|
||||
}
|
||||
|
||||
var file_common_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||
var file_common_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
||||
var file_common_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
|
||||
var file_common_proto_goTypes = []any{
|
||||
(RespCode)(0), // 0: common.RespCode
|
||||
(ClientType)(0), // 1: common.ClientType
|
||||
(*Status)(nil), // 2: common.Status
|
||||
(*CommonRequest)(nil), // 3: common.CommonRequest
|
||||
(*CommonResponse)(nil), // 4: common.CommonResponse
|
||||
(*Client)(nil), // 5: common.Client
|
||||
(*Server)(nil), // 6: common.Server
|
||||
(*User)(nil), // 7: common.User
|
||||
(*ProxyInfo)(nil), // 8: common.ProxyInfo
|
||||
(RespCode)(0), // 0: common.RespCode
|
||||
(ClientType)(0), // 1: common.ClientType
|
||||
(*Status)(nil), // 2: common.Status
|
||||
(*CommonRequest)(nil), // 3: common.CommonRequest
|
||||
(*CommonResponse)(nil), // 4: common.CommonResponse
|
||||
(*Client)(nil), // 5: common.Client
|
||||
(*Server)(nil), // 6: common.Server
|
||||
(*User)(nil), // 7: common.User
|
||||
(*ProxyInfo)(nil), // 8: common.ProxyInfo
|
||||
(*ProxyConfig)(nil), // 9: common.ProxyConfig
|
||||
(*ProxyWorkingStatus)(nil), // 10: common.ProxyWorkingStatus
|
||||
}
|
||||
var file_common_proto_depIdxs = []int32{
|
||||
0, // 0: common.Status.code:type_name -> common.RespCode
|
||||
@@ -820,13 +1048,15 @@ func file_common_proto_init() {
|
||||
file_common_proto_msgTypes[4].OneofWrappers = []any{}
|
||||
file_common_proto_msgTypes[5].OneofWrappers = []any{}
|
||||
file_common_proto_msgTypes[6].OneofWrappers = []any{}
|
||||
file_common_proto_msgTypes[7].OneofWrappers = []any{}
|
||||
file_common_proto_msgTypes[8].OneofWrappers = []any{}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_common_proto_rawDesc,
|
||||
NumEnums: 2,
|
||||
NumMessages: 7,
|
||||
NumMessages: 9,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
|
||||
@@ -41,6 +41,7 @@ const (
|
||||
Event_EVENT_START_STREAM_LOG Event = 15
|
||||
Event_EVENT_STOP_STREAM_LOG Event = 16
|
||||
Event_EVENT_START_PTY_CONNECT Event = 17
|
||||
Event_EVENT_GET_PROXY_INFO Event = 18
|
||||
)
|
||||
|
||||
// Enum value maps for Event.
|
||||
@@ -64,6 +65,7 @@ var (
|
||||
15: "EVENT_START_STREAM_LOG",
|
||||
16: "EVENT_STOP_STREAM_LOG",
|
||||
17: "EVENT_START_PTY_CONNECT",
|
||||
18: "EVENT_GET_PROXY_INFO",
|
||||
}
|
||||
Event_value = map[string]int32{
|
||||
"EVENT_UNSPECIFIED": 0,
|
||||
@@ -84,6 +86,7 @@ var (
|
||||
"EVENT_START_STREAM_LOG": 15,
|
||||
"EVENT_STOP_STREAM_LOG": 16,
|
||||
"EVENT_START_PTY_CONNECT": 17,
|
||||
"EVENT_GET_PROXY_INFO": 18,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1220,7 +1223,7 @@ var file_rpc_master_proto_rawDesc = []byte{
|
||||
0x02, 0x52, 0x05, 0x77, 0x69, 0x64, 0x74, 0x68, 0x88, 0x01, 0x01, 0x12, 0x12, 0x0a, 0x04, 0x64,
|
||||
0x6f, 0x6e, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x64, 0x6f, 0x6e, 0x65, 0x42,
|
||||
0x07, 0x0a, 0x05, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x68, 0x65, 0x69,
|
||||
0x67, 0x68, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2a, 0x9b, 0x03,
|
||||
0x67, 0x68, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2a, 0xb5, 0x03,
|
||||
0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x56, 0x45, 0x4e, 0x54,
|
||||
0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19,
|
||||
0x0a, 0x15, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52,
|
||||
@@ -1246,46 +1249,47 @@ var file_rpc_master_proto_rawDesc = []byte{
|
||||
0x47, 0x10, 0x0f, 0x12, 0x19, 0x0a, 0x15, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x4f,
|
||||
0x50, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, 0x10, 0x10, 0x12, 0x1b,
|
||||
0x0a, 0x17, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x5f, 0x50, 0x54,
|
||||
0x59, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x10, 0x11, 0x32, 0xd7, 0x04, 0x0a, 0x06,
|
||||
0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x0a, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||
0x53, 0x65, 0x6e, 0x64, 0x12, 0x15, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6c,
|
||||
0x69, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x15, 0x2e, 0x6d, 0x61,
|
||||
0x73, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61,
|
||||
0x67, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x10, 0x50, 0x75, 0x6c, 0x6c, 0x43, 0x6c,
|
||||
0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1b, 0x2e, 0x6d, 0x61, 0x73,
|
||||
0x74, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x6c, 0x6c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72,
|
||||
0x2e, 0x50, 0x75, 0x6c, 0x6c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x67, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4d, 0x0a, 0x10, 0x50, 0x75, 0x6c, 0x6c, 0x53, 0x65, 0x72,
|
||||
0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1b, 0x2e, 0x6d, 0x61, 0x73, 0x74,
|
||||
0x65, 0x72, 0x2e, 0x50, 0x75, 0x6c, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e,
|
||||
0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e,
|
||||
0x50, 0x75, 0x6c, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||
0x52, 0x65, 0x73, 0x70, 0x12, 0x3b, 0x0a, 0x08, 0x46, 0x52, 0x50, 0x43, 0x41, 0x75, 0x74, 0x68,
|
||||
0x12, 0x16, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x46, 0x52, 0x50, 0x41, 0x75, 0x74,
|
||||
0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65,
|
||||
0x72, 0x2e, 0x46, 0x52, 0x50, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x12, 0x44, 0x0a, 0x0d, 0x50, 0x75, 0x73, 0x68, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x49, 0x6e,
|
||||
0x66, 0x6f, 0x12, 0x18, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x73, 0x68,
|
||||
0x50, 0x72, 0x6f, 0x78, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x6d,
|
||||
0x59, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x10, 0x11, 0x12, 0x18, 0x0a, 0x14, 0x45,
|
||||
0x56, 0x45, 0x4e, 0x54, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x49,
|
||||
0x4e, 0x46, 0x4f, 0x10, 0x12, 0x32, 0xd7, 0x04, 0x0a, 0x06, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72,
|
||||
0x12, 0x3e, 0x0a, 0x0a, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x15,
|
||||
0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x65,
|
||||
0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x15, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x53,
|
||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x28, 0x01, 0x30, 0x01,
|
||||
0x12, 0x4d, 0x0a, 0x10, 0x50, 0x75, 0x6c, 0x6c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x12, 0x1b, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x50, 0x75,
|
||||
0x6c, 0x6c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65,
|
||||
0x71, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x6c, 0x6c, 0x43,
|
||||
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x12,
|
||||
0x4d, 0x0a, 0x10, 0x50, 0x75, 0x6c, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e,
|
||||
0x66, 0x69, 0x67, 0x12, 0x1b, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x6c,
|
||||
0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71,
|
||||
0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x6c, 0x6c, 0x53, 0x65,
|
||||
0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3b,
|
||||
0x0a, 0x08, 0x46, 0x52, 0x50, 0x43, 0x41, 0x75, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x6d, 0x61, 0x73,
|
||||
0x74, 0x65, 0x72, 0x2e, 0x46, 0x52, 0x50, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x46, 0x52, 0x50, 0x41,
|
||||
0x75, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0d, 0x50,
|
||||
0x75, 0x73, 0x68, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x2e, 0x6d,
|
||||
0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x49,
|
||||
0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12, 0x52, 0x0a, 0x13, 0x50, 0x75, 0x73, 0x68, 0x43,
|
||||
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x6f, 0x67, 0x12, 0x1e,
|
||||
0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x43, 0x6c, 0x69, 0x65,
|
||||
0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x1a, 0x19,
|
||||
0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x53, 0x74, 0x72, 0x65,
|
||||
0x61, 0x6d, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x28, 0x01, 0x12, 0x52, 0x0a, 0x13, 0x50,
|
||||
0x75, 0x73, 0x68, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c,
|
||||
0x6f, 0x67, 0x12, 0x1e, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x73, 0x68,
|
||||
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x6f, 0x67, 0x52,
|
||||
0x65, 0x71, 0x1a, 0x19, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x73, 0x68,
|
||||
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x28, 0x01, 0x12,
|
||||
0x44, 0x0a, 0x0a, 0x50, 0x54, 0x59, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x18, 0x2e,
|
||||
0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x50, 0x54, 0x59, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74,
|
||||
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x18, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72,
|
||||
0x2e, 0x50, 0x54, 0x59, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x07, 0x5a, 0x05, 0x2e, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e,
|
||||
0x50, 0x75, 0x73, 0x68, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73,
|
||||
0x70, 0x12, 0x52, 0x0a, 0x13, 0x50, 0x75, 0x73, 0x68, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53,
|
||||
0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x6f, 0x67, 0x12, 0x1e, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65,
|
||||
0x72, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65,
|
||||
0x61, 0x6d, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65,
|
||||
0x72, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x6f, 0x67, 0x52,
|
||||
0x65, 0x73, 0x70, 0x28, 0x01, 0x12, 0x52, 0x0a, 0x13, 0x50, 0x75, 0x73, 0x68, 0x53, 0x65, 0x72,
|
||||
0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x6f, 0x67, 0x12, 0x1e, 0x2e, 0x6d,
|
||||
0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x6d,
|
||||
0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d,
|
||||
0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x28, 0x01, 0x12, 0x44, 0x0a, 0x0a, 0x50, 0x54, 0x59,
|
||||
0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x18, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72,
|
||||
0x2e, 0x50, 0x54, 0x59, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x1a, 0x18, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x50, 0x54, 0x59, 0x53, 0x65,
|
||||
0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42,
|
||||
0x07, 0x5a, 0x05, 0x2e, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -6,13 +6,29 @@ import (
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/VaalaCat/frp-panel/common"
|
||||
"github.com/VaalaCat/frp-panel/logger"
|
||||
"github.com/VaalaCat/frp-panel/pb"
|
||||
"github.com/google/uuid"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
)
|
||||
|
||||
func CallClientWrapper[R common.RespType](c context.Context, clientID string, event pb.Event, req proto.Message, resp *R) error {
|
||||
cresp, err := CallClient(c, clientID, event, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
protoMsgRef, ok := any(resp).(protoreflect.ProtoMessage)
|
||||
if !ok {
|
||||
return fmt.Errorf("type does not implement protoreflect.ProtoMessage")
|
||||
}
|
||||
|
||||
return proto.Unmarshal(cresp.GetData(), protoMsgRef)
|
||||
}
|
||||
|
||||
func CallClient(c context.Context, clientID string, event pb.Event, msg proto.Message) (*pb.ClientMessage, error) {
|
||||
sender := GetClientsManager().Get(clientID)
|
||||
if sender == nil {
|
||||
|
||||
@@ -69,13 +69,14 @@ func GetGlobalClientSerivce() ClientHandler {
|
||||
func NewClientHandler(commonCfg *v1.ClientCommonConfig,
|
||||
proxyCfgs []v1.ProxyConfigurer,
|
||||
visitorCfgs []v1.VisitorConfigurer) *Client {
|
||||
ctx := context.Background()
|
||||
|
||||
warning, err := validation.ValidateAllClientConfig(commonCfg, proxyCfgs, visitorCfgs)
|
||||
if warning != nil {
|
||||
logger.Logger(context.Background()).WithError(err).Warnf("validate client config warning: %+v", warning)
|
||||
logger.Logger(ctx).WithError(err).Warnf("validate client config warning: %+v", warning)
|
||||
}
|
||||
if err != nil {
|
||||
logrus.Panic(err)
|
||||
logger.Logger(ctx).Panic(err)
|
||||
}
|
||||
|
||||
log.InitLogger(commonCfg.Log.To, commonCfg.Log.Level, int(commonCfg.Log.MaxDays), commonCfg.Log.DisablePrintColor)
|
||||
@@ -85,7 +86,7 @@ func NewClientHandler(commonCfg *v1.ClientCommonConfig,
|
||||
VisitorCfgs: visitorCfgs,
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Panic(err)
|
||||
logger.Logger(ctx).Panic(err)
|
||||
}
|
||||
|
||||
return &Client{
|
||||
@@ -98,12 +99,14 @@ func NewClientHandler(commonCfg *v1.ClientCommonConfig,
|
||||
|
||||
func (c *Client) Run() {
|
||||
if c.running {
|
||||
logger.Logger(context.Background()).Warn("client is running, skip run")
|
||||
return
|
||||
}
|
||||
|
||||
shouldGracefulClose := c.Common.Transport.Protocol == "kcp" || c.Common.Transport.Protocol == "quic"
|
||||
if shouldGracefulClose {
|
||||
go handleTermSignal(c.cli)
|
||||
var wg conc.WaitGroup
|
||||
wg.Go(func() { handleTermSignal(c.cli) })
|
||||
}
|
||||
c.running = true
|
||||
c.done = make(chan bool)
|
||||
@@ -113,15 +116,14 @@ func (c *Client) Run() {
|
||||
close(c.done)
|
||||
}()
|
||||
|
||||
wg := conc.NewWaitGroup()
|
||||
wg.Go(
|
||||
func() {
|
||||
ctx := context.Background()
|
||||
if err := c.cli.Run(ctx); err != nil {
|
||||
logger.Logger(ctx).Errorf("run client error: %v", err)
|
||||
}
|
||||
},
|
||||
)
|
||||
var wg conc.WaitGroup
|
||||
wg.Go(func() {
|
||||
ctx := context.Background()
|
||||
logger.Logger(ctx).Infof("start to run client")
|
||||
if err := c.cli.Run(ctx); err != nil {
|
||||
logger.Logger(ctx).Errorf("run client error: %v", err)
|
||||
}
|
||||
})
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
|
||||
144
tunnel/client.go
144
tunnel/client.go
@@ -1,23 +1,32 @@
|
||||
package tunnel
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"context"
|
||||
|
||||
"github.com/VaalaCat/frp-panel/logger"
|
||||
"github.com/VaalaCat/frp-panel/services/client"
|
||||
"github.com/VaalaCat/frp-panel/utils"
|
||||
)
|
||||
|
||||
type ClientController interface {
|
||||
Add(clientID string, clientHandler client.ClientHandler)
|
||||
Get(clientID string) client.ClientHandler
|
||||
Delete(clientID string)
|
||||
Set(clientID string, clientHandler client.ClientHandler)
|
||||
Run(clientID string) // 不阻塞
|
||||
Stop(clientID string)
|
||||
Add(clientID string, serverID string, clientHandler client.ClientHandler)
|
||||
Get(clientID string, serverID string) client.ClientHandler
|
||||
Delete(clientID string, serverID string)
|
||||
Set(clientID string, serverID string, clientHandler client.ClientHandler)
|
||||
Run(clientID string, serverID string) // 不阻塞
|
||||
Stop(clientID string, serverID string)
|
||||
GetByClient(clientID string) *utils.SyncMap[string, client.ClientHandler]
|
||||
DeleteByClient(clientID string)
|
||||
RunByClient(clientID string) // 不阻塞
|
||||
StopByClient(clientID string)
|
||||
StopAll()
|
||||
DeleteAll()
|
||||
RunAll()
|
||||
List() []string
|
||||
}
|
||||
|
||||
type clientController struct {
|
||||
clients *sync.Map
|
||||
clients *utils.SyncMap[string, *utils.SyncMap[string, client.ClientHandler]]
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -26,7 +35,7 @@ var (
|
||||
|
||||
func NewClientController() ClientController {
|
||||
return &clientController{
|
||||
clients: &sync.Map{},
|
||||
clients: &utils.SyncMap[string, *utils.SyncMap[string, client.ClientHandler]]{},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,48 +46,129 @@ func GetClientController() ClientController {
|
||||
return clientControllerInstance
|
||||
}
|
||||
|
||||
func (c *clientController) Add(clientID string, clientHandler client.ClientHandler) {
|
||||
c.clients.Store(clientID, clientHandler)
|
||||
func (c *clientController) Add(clientID string, serverID string, clientHandler client.ClientHandler) {
|
||||
m, _ := c.clients.LoadOrStore(clientID, &utils.SyncMap[string, client.ClientHandler]{})
|
||||
oldClientHandler, loaded := m.LoadAndDelete(serverID)
|
||||
if loaded {
|
||||
oldClientHandler.Stop()
|
||||
}
|
||||
m.Store(serverID, clientHandler)
|
||||
}
|
||||
|
||||
func (c *clientController) Get(clientID string) client.ClientHandler {
|
||||
func (c *clientController) Get(clientID string, serverID string) client.ClientHandler {
|
||||
v, ok := c.clients.Load(clientID)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return v.(client.ClientHandler)
|
||||
vv, ok := v.Load(serverID)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return vv
|
||||
}
|
||||
|
||||
func (c *clientController) Delete(clientID string) {
|
||||
c.Stop(clientID)
|
||||
func (c *clientController) GetByClient(clientID string) *utils.SyncMap[string, client.ClientHandler] {
|
||||
v, ok := c.clients.Load(clientID)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
func (c *clientController) Delete(clientID string, serverID string) {
|
||||
c.Stop(clientID, serverID)
|
||||
v, ok := c.clients.Load(clientID)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
v.Delete(serverID)
|
||||
}
|
||||
|
||||
func (c *clientController) DeleteByClient(clientID string) {
|
||||
c.clients.Delete(clientID)
|
||||
}
|
||||
|
||||
func (c *clientController) Set(clientID string, clientHandler client.ClientHandler) {
|
||||
c.clients.Store(clientID, clientHandler)
|
||||
func (c *clientController) Set(clientID string, serverID string, clientHandler client.ClientHandler) {
|
||||
v, _ := c.clients.LoadOrStore(clientID, &utils.SyncMap[string, client.ClientHandler]{})
|
||||
v.Store(serverID, clientHandler)
|
||||
}
|
||||
|
||||
func (c *clientController) Run(clientID string) {
|
||||
func (c *clientController) Run(clientID string, serverID string) {
|
||||
ctx := context.Background()
|
||||
v, ok := c.clients.Load(clientID)
|
||||
if !ok {
|
||||
logger.Logger(ctx).Errorf("cannot get client by clientID, clientID: [%s] serverID: [%s]", clientID, serverID)
|
||||
return
|
||||
}
|
||||
vv, ok := v.Load(serverID)
|
||||
if !ok {
|
||||
logger.Logger(ctx).Errorf("cannot load client connected server, clientID: [%s] serverID: [%s]", clientID, serverID)
|
||||
return
|
||||
}
|
||||
|
||||
go vv.Run()
|
||||
}
|
||||
|
||||
func (c *clientController) RunByClient(clientID string) {
|
||||
v, ok := c.clients.Load(clientID)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
go v.(client.ClientHandler).Run()
|
||||
v.Range(func(k string, v client.ClientHandler) bool {
|
||||
v.Run()
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (c *clientController) Stop(clientID string) {
|
||||
func (c *clientController) Stop(clientID string, serverID string) {
|
||||
v, ok := c.clients.Load(clientID)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
v.(client.ClientHandler).Stop()
|
||||
vv, ok := v.Load(serverID)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
vv.Stop()
|
||||
}
|
||||
|
||||
func (c *clientController) StopByClient(clientID string) {
|
||||
v, ok := c.clients.Load(clientID)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
v.Range(func(k string, v client.ClientHandler) bool {
|
||||
v.Stop()
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (c *clientController) StopAll() {
|
||||
c.clients.Range(func(k string, v *utils.SyncMap[string, client.ClientHandler]) bool {
|
||||
v.Range(func(k string, v client.ClientHandler) bool {
|
||||
v.Stop()
|
||||
return true
|
||||
})
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (c *clientController) DeleteAll() {
|
||||
c.clients.Range(func(k string, v *utils.SyncMap[string, client.ClientHandler]) bool {
|
||||
c.DeleteByClient(k)
|
||||
return true
|
||||
})
|
||||
c.clients = &utils.SyncMap[string, *utils.SyncMap[string, client.ClientHandler]]{}
|
||||
}
|
||||
|
||||
func (c *clientController) RunAll() {
|
||||
c.clients.Range(func(k string, v *utils.SyncMap[string, client.ClientHandler]) bool {
|
||||
c.RunByClient(k)
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (c *clientController) List() []string {
|
||||
keys := make([]string, 0)
|
||||
c.clients.Range(func(key, value interface{}) bool {
|
||||
keys = append(keys, key.(string))
|
||||
return true
|
||||
})
|
||||
return keys
|
||||
return c.clients.Keys()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
v1 "github.com/fatedier/frp/pkg/config/v1"
|
||||
)
|
||||
|
||||
@@ -62,3 +64,7 @@ func TransformVisitorConfigurerToMap(origin v1.VisitorConfigurer) (key string, r
|
||||
r = origin
|
||||
return
|
||||
}
|
||||
|
||||
func NewProxyKey(clientID, serverID, proxyName string) string {
|
||||
return fmt.Sprintf("%s/%s/%s", clientID, serverID, proxyName)
|
||||
}
|
||||
|
||||
@@ -19,6 +19,26 @@ func LoadConfigureFromContent(content []byte, c any, strict bool) error {
|
||||
return config.LoadConfigure(ans, c, strict)
|
||||
}
|
||||
|
||||
func LoadProxiesFromContent(content []byte) ([]v1.TypedProxyConfig, error) {
|
||||
allCfg := &v1.ClientConfig{}
|
||||
|
||||
if err := LoadConfigureFromContent(content, allCfg, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return allCfg.Proxies, nil
|
||||
}
|
||||
|
||||
func LoadVisitorsFromContent(content []byte) ([]v1.TypedVisitorConfig, error) {
|
||||
allCfg := &v1.ClientConfig{}
|
||||
|
||||
if err := LoadConfigureFromContent(content, allCfg, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return allCfg.Visitors, nil
|
||||
}
|
||||
|
||||
func LoadClientConfigNormal(content []byte, strict bool) (*v1.ClientConfig, error) {
|
||||
var (
|
||||
cliCfg *v1.ClientCommonConfig
|
||||
|
||||
23
utils/load_test.go
Normal file
23
utils/load_test.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
v1 "github.com/fatedier/frp/pkg/config/v1"
|
||||
)
|
||||
|
||||
func TestLoadConfigureFromContent(t *testing.T) {
|
||||
content := []byte(`[[proxies]]
|
||||
name = "ssh"
|
||||
type = "tcp"
|
||||
localIP = "127.0.0.1"
|
||||
localPort = 22
|
||||
remotePort = 6000`)
|
||||
|
||||
allCfg := &v1.ClientConfig{}
|
||||
|
||||
if err := LoadConfigureFromContent(content, allCfg, true); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
t.Errorf("%+v", allCfg)
|
||||
}
|
||||
21
utils/validate.go
Normal file
21
utils/validate.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package utils
|
||||
|
||||
func IsClientIDPermited(clientID string) bool {
|
||||
whiteListChar := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
|
||||
if len(clientID) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
chrMap := make(map[rune]bool)
|
||||
for _, chr := range whiteListChar {
|
||||
chrMap[chr] = true
|
||||
}
|
||||
|
||||
for _, chr := range clientID {
|
||||
if !chrMap[chr] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
40
www/api/proxy.ts
Normal file
40
www/api/proxy.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import http from '@/api/http'
|
||||
import { API_PATH } from '@/lib/consts'
|
||||
import {
|
||||
CreateProxyConfigRequest,
|
||||
CreateProxyConfigResponse,
|
||||
DeleteProxyConfigRequest,
|
||||
DeleteProxyConfigResponse,
|
||||
GetProxyConfigRequest,
|
||||
GetProxyConfigResponse,
|
||||
ListProxyConfigsRequest,
|
||||
ListProxyConfigsResponse,
|
||||
UpdateProxyConfigRequest,
|
||||
UpdateProxyConfigResponse
|
||||
} from '@/lib/pb/api_client'
|
||||
import { BaseResponse } from '@/types/api'
|
||||
|
||||
export const createProxyConfig = async (req: CreateProxyConfigRequest) => {
|
||||
const res = await http.post(API_PATH + '/proxy/create_config', CreateProxyConfigRequest.toJson(req))
|
||||
return CreateProxyConfigResponse.fromJson((res.data as BaseResponse).body)
|
||||
}
|
||||
|
||||
export const listProxyConfig = async (req: ListProxyConfigsRequest) => {
|
||||
const res = await http.post(API_PATH + '/proxy/list_configs', ListProxyConfigsRequest.toJson(req))
|
||||
return ListProxyConfigsResponse.fromJson((res.data as BaseResponse).body)
|
||||
}
|
||||
|
||||
export const updateProxyConfig = async (req: UpdateProxyConfigRequest) => {
|
||||
const res = await http.post(API_PATH + '/proxy/update_config', UpdateProxyConfigRequest.toJson(req))
|
||||
return UpdateProxyConfigResponse.fromJson((res.data as BaseResponse).body)
|
||||
}
|
||||
|
||||
export const deleteProxyConfig = async (req: DeleteProxyConfigRequest) => {
|
||||
const res = await http.post(API_PATH + '/proxy/delete_config', DeleteProxyConfigRequest.toJson(req))
|
||||
return DeleteProxyConfigResponse.fromJson((res.data as BaseResponse).body)
|
||||
}
|
||||
|
||||
export const getProxyConfig = async (req: GetProxyConfigRequest) => {
|
||||
const res = await http.post(API_PATH + '/proxy/get_config', GetProxyConfigRequest.toJson(req))
|
||||
return GetProxyConfigResponse.fromJson((res.data as BaseResponse).body)
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import http from '@/api/http'
|
||||
import { API_PATH } from '@/lib/consts'
|
||||
import { GetProxyByCIDRequest, GetProxyByCIDResponse } from '@/lib/pb/api_client'
|
||||
import { GetProxyBySIDRequest, GetProxyBySIDResponse } from '@/lib/pb/api_server'
|
||||
import { GetProxyStatsByClientIDRequest, GetProxyStatsByClientIDResponse } from '@/lib/pb/api_client'
|
||||
import { GetProxyStatsByServerIDRequest, GetProxyStatsByServerIDResponse } from '@/lib/pb/api_server'
|
||||
import { BaseResponse } from '@/types/api'
|
||||
|
||||
export const getProxyStatsByClientID = async (req: GetProxyByCIDRequest) => {
|
||||
export const getProxyStatsByClientID = async (req: GetProxyStatsByClientIDRequest) => {
|
||||
// return {
|
||||
// proxyInfos: [
|
||||
// {
|
||||
@@ -16,11 +16,11 @@ export const getProxyStatsByClientID = async (req: GetProxyByCIDRequest) => {
|
||||
// },
|
||||
// ],
|
||||
// } as GetProxyByCIDResponse
|
||||
const res = await http.post(API_PATH + '/proxy/get_by_cid', GetProxyByCIDRequest.toJson(req))
|
||||
return GetProxyByCIDResponse.fromJson((res.data as BaseResponse).body)
|
||||
const res = await http.post(API_PATH + '/proxy/get_by_cid', GetProxyStatsByClientIDRequest.toJson(req))
|
||||
return GetProxyStatsByClientIDResponse.fromJson((res.data as BaseResponse).body)
|
||||
}
|
||||
|
||||
export const getProxyStatsByServerID = async (req: GetProxyBySIDRequest) => {
|
||||
const res = await http.post(API_PATH + '/proxy/get_by_sid', GetProxyBySIDRequest.toJson(req))
|
||||
return GetProxyBySIDResponse.fromJson((res.data as BaseResponse).body)
|
||||
export const getProxyStatsByServerID = async (req: GetProxyStatsByServerIDRequest) => {
|
||||
const res = await http.post(API_PATH + '/proxy/get_by_sid', GetProxyStatsByServerIDRequest.toJson(req))
|
||||
return GetProxyStatsByServerIDResponse.fromJson((res.data as BaseResponse).body)
|
||||
}
|
||||
@@ -1,17 +1,6 @@
|
||||
import * as React from "react"
|
||||
import {
|
||||
SquareTerminal,
|
||||
ServerCogIcon,
|
||||
ServerIcon,
|
||||
MonitorSmartphoneIcon,
|
||||
MonitorCogIcon,
|
||||
ChartNetworkIcon,
|
||||
Scroll,
|
||||
} from "lucide-react"
|
||||
|
||||
import { NavMain } from "@/components/nav-main"
|
||||
import { NavUser } from "@/components/nav-user"
|
||||
import { TeamSwitcher } from "@/components/team-switcher"
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
@@ -27,7 +16,7 @@ import { RegisterAndLogin } from "./header"
|
||||
import { useRouter } from "next/navigation"
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
import { getPlatformInfo } from "@/api/platform"
|
||||
import { teams, getNavItems } from '@/config/nav'
|
||||
import { getNavItems } from '@/config/nav'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export interface AppSidebarProps extends React.ComponentProps<typeof Sidebar> {
|
||||
|
||||
@@ -14,7 +14,7 @@ export const ClientDetail = ({ clientStatus }: { clientStatus: ClientStatus }) =
|
||||
|
||||
const locale = i18n.language === 'zh' ? zhCN : enUS
|
||||
const connectTime = clientStatus.connectTime ?
|
||||
formatDistanceToNow(new Date(clientStatus.connectTime), {
|
||||
formatDistanceToNow(new Date(parseInt(clientStatus.connectTime.toString())), {
|
||||
addSuffix: true,
|
||||
locale
|
||||
}) : '-'
|
||||
|
||||
@@ -67,7 +67,9 @@ export function Combobox({
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
className={cn("w-full justify-between font-normal", className)}
|
||||
className={cn("w-full justify-between font-normal", className,
|
||||
!value && "text-muted-foreground"
|
||||
)}
|
||||
>
|
||||
{value
|
||||
? (dataList.find((item) => item.value === value)?.label || value)
|
||||
|
||||
46
www/components/base/drop-down-menu.tsx
Normal file
46
www/components/base/drop-down-menu.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import { Button } from "@/components/ui/button"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
import { LucideIcon } from "lucide-react"
|
||||
|
||||
export interface DropdownMenuProps {
|
||||
menuGroup: {
|
||||
name: string,
|
||||
onClick: () => void
|
||||
icon?: LucideIcon
|
||||
className?: string
|
||||
}[][]
|
||||
title: string
|
||||
trigger: React.ReactNode
|
||||
}
|
||||
|
||||
export function BaseDropdownMenu({ menuGroup, title, trigger }: DropdownMenuProps) {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
{trigger || <Button variant="outline">Open</Button>}
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-fit">
|
||||
<DropdownMenuLabel>{title}</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
{menuGroup.map((items, id1) => (
|
||||
<DropdownMenuGroup key={id1}>
|
||||
{items.map((item, id2) => (
|
||||
<DropdownMenuItem onClick={item.onClick} key={id2} className={item.className}>
|
||||
{/* {<>{item.icon}</>} */}
|
||||
{item.name}
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuGroup>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
}
|
||||
@@ -16,16 +16,15 @@ export const IdInput: React.FC<IdInputProps> = ({ setKeyword, keyword, refetchTr
|
||||
const [input, setInput] = useState(keyword)
|
||||
|
||||
return (
|
||||
<div className="flex flex-1 flex-row gap-2">
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
<Input
|
||||
className="max-w-40 h-auto"
|
||||
className="text-sm"
|
||||
defaultValue={keyword}
|
||||
placeholder={t('input.id.placeholder')}
|
||||
placeholder={t('input.keyword.placeholder')}
|
||||
onChange={(e) => setInput(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setKeyword(input)
|
||||
refetchTrigger && refetchTrigger(JSON.stringify(Math.random()))
|
||||
|
||||
70
www/components/base/list-input.tsx
Normal file
70
www/components/base/list-input.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Badge } from '../ui/badge';
|
||||
import { Input } from '../ui/input';
|
||||
import { Button } from '../ui/button';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface StringListInputProps {
|
||||
value: string[];
|
||||
onChange: React.Dispatch<React.SetStateAction<string[]>>;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
const StringListInput: React.FC<StringListInputProps> = ({ value, onChange, placeholder }) => {
|
||||
const { t } = useTranslation();
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
|
||||
const handleAdd = () => {
|
||||
if (inputValue.trim()) {
|
||||
if (value && value.includes(inputValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
onChange([...value, inputValue]);
|
||||
} else {
|
||||
onChange([inputValue]);
|
||||
}
|
||||
setInputValue('');
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemove = (itemToRemove: string) => {
|
||||
onChange(value.filter(item => item !== itemToRemove));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mx-auto">
|
||||
<div className="flex items-center mb-4">
|
||||
<Input
|
||||
type="text"
|
||||
value={inputValue}
|
||||
onChange={(e) => setInputValue(e.target.value)}
|
||||
className="flex-1 px-4 py-2 border rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
|
||||
placeholder={placeholder || t('input.list.placeholder')}
|
||||
/>
|
||||
<Button
|
||||
disabled={!inputValue || value && value.includes(inputValue)}
|
||||
onClick={handleAdd}
|
||||
className="ml-2 px-4 py-2"
|
||||
>
|
||||
{t('input.list.add')}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{value && value.map((item, index) => (
|
||||
<Badge key={index} className='flex flex-row items-center justify-start'>{item}
|
||||
<div
|
||||
onClick={() => handleRemove(item)}
|
||||
className="ml-1 h-4 w-4 text-center rounded-full hover:text-red-500 cursor-pointer"
|
||||
>
|
||||
×
|
||||
</div>
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StringListInput;
|
||||
@@ -1,24 +1,26 @@
|
||||
"use client"
|
||||
|
||||
import React from 'react'
|
||||
import React, { useEffect } from 'react'
|
||||
import { keepPreviousData, useQuery } from '@tanstack/react-query'
|
||||
import { listServer } from '@/api/server'
|
||||
import { Combobox } from './combobox'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Server } from '@/lib/pb/common'
|
||||
|
||||
export interface ServerSelectorProps {
|
||||
serverID?: string
|
||||
setServerID: (serverID: string) => void
|
||||
onOpenChange?: () => void
|
||||
setServer?: (server: Server) => void
|
||||
}
|
||||
|
||||
export const ServerSelector: React.FC<ServerSelectorProps> = ({
|
||||
serverID,
|
||||
setServerID,
|
||||
onOpenChange
|
||||
onOpenChange,
|
||||
setServer,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const handleServerChange = (value: string) => { setServerID(value) }
|
||||
const [keyword, setKeyword] = React.useState('')
|
||||
|
||||
const { data: serverList, refetch: refetchServers } = useQuery({
|
||||
@@ -29,6 +31,16 @@ export const ServerSelector: React.FC<ServerSelectorProps> = ({
|
||||
placeholderData: keepPreviousData,
|
||||
})
|
||||
|
||||
const handleServerChange = (value: string) => {
|
||||
setServerID(value)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (serverID) {
|
||||
setServer && setServer(serverList?.servers.find((server) => server.id == serverID) || {})
|
||||
}
|
||||
}, [serverID])
|
||||
|
||||
return (
|
||||
<Combobox
|
||||
placeholder={t('selector.server.placeholder')}
|
||||
|
||||
57
www/components/base/visit-preview.tsx
Normal file
57
www/components/base/visit-preview.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import { Server } from "@/lib/pb/common";
|
||||
import { HTTPProxyConfig, TypedProxyConfig } from "@/types/proxy";
|
||||
import { ServerConfig } from "@/types/server";
|
||||
import { ArrowRight, Globe, Monitor } from 'lucide-react';
|
||||
|
||||
export function VisitPreview({ server, typedProxyConfig }: { server: Server; typedProxyConfig: TypedProxyConfig }) {
|
||||
const serverCfg = JSON.parse(server?.config || '{}') as ServerConfig;
|
||||
const serverAddress = server.ip || serverCfg.bindAddr || 'Unknown';
|
||||
const serverPort = getServerPort(typedProxyConfig, serverCfg);
|
||||
const localAddress = typedProxyConfig.localIP || '127.0.0.1';
|
||||
const localPort = typedProxyConfig.localPort;
|
||||
|
||||
function getServerPath(httpProxyConfig: HTTPProxyConfig) {
|
||||
if (!httpProxyConfig.locations) {
|
||||
return "";
|
||||
}
|
||||
if (httpProxyConfig.locations.length == 0) {
|
||||
return "";
|
||||
}
|
||||
if (httpProxyConfig.locations.length == 1) {
|
||||
return httpProxyConfig.locations[0];
|
||||
}
|
||||
return `[${httpProxyConfig.locations.join(",")}]`;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-start p-2 text-sm font-mono text-nowrap">
|
||||
<div className="flex items-center mb-2 sm:mb-0">
|
||||
<Globe className="w-4 h-4 text-blue-500 mr-2 flex-shrink-0" />
|
||||
<span className="text-nowrap">{typedProxyConfig.type == "http" ? "http://" : ""}{
|
||||
typedProxyConfig.type == "http" ? `${(typedProxyConfig as HTTPProxyConfig).subdomain}.${serverCfg.subDomainHost}` : serverAddress}:{
|
||||
serverPort}{typedProxyConfig.type == "http" ? getServerPath(typedProxyConfig as HTTPProxyConfig) : ""}</span>
|
||||
</div>
|
||||
<ArrowRight className="hidden sm:block w-4 h-4 text-gray-400 mx-2 flex-shrink-0" />
|
||||
<div className="flex items-center mb-2 sm:mb-0">
|
||||
<Monitor className="w-4 h-4 text-green-500 mr-2 flex-shrink-0" />
|
||||
<span className="text-nowrap">{localAddress}:{localPort}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getServerPort(proxyConfig: TypedProxyConfig, serverConfig: ServerConfig): number | undefined {
|
||||
switch (proxyConfig.type) {
|
||||
case 'tcp':
|
||||
return (proxyConfig as any).remotePort;
|
||||
case 'udp':
|
||||
return (proxyConfig as any).remotePort;
|
||||
case 'http':
|
||||
return serverConfig.vhostHTTPPort;
|
||||
case 'https':
|
||||
return serverConfig.vhostHTTPSPort;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ export const CreateClientDialog = ({refetchTrigger}: {refetchTrigger?: (randStr:
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" size={'sm'}>
|
||||
<Button variant="outline">
|
||||
{t('client.create.button')}
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
|
||||
@@ -29,15 +29,16 @@ import { useStore } from '@nanostores/react'
|
||||
import { $platformInfo } from '@/store/user'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
|
||||
import { getClientsStatus } from '@/api/platform'
|
||||
import { ClientType } from '@/lib/pb/common'
|
||||
import { Client, ClientType } from '@/lib/pb/common'
|
||||
import { ClientStatus, ClientStatus_Status } from '@/lib/pb/api_master'
|
||||
import { startFrpc, stopFrpc } from '@/api/frp'
|
||||
import { Badge } from '../ui/badge'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { ClientDetail } from '../base/client_detail'
|
||||
import { Input } from '../ui/input'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { toast } from 'sonner'
|
||||
import { $clientTableRefetchTrigger } from '@/store/refetch-trigger'
|
||||
import { NeedUpgrade } from '@/config/notify'
|
||||
|
||||
export type ClientTableSchema = {
|
||||
id: string
|
||||
@@ -46,6 +47,7 @@ export type ClientTableSchema = {
|
||||
stopped: boolean
|
||||
info?: string
|
||||
config?: string
|
||||
originClient: Client
|
||||
}
|
||||
|
||||
export interface TableMetaType extends TableMeta<ClientTableSchema> {
|
||||
@@ -213,12 +215,17 @@ export const ClientInfo = ({ client }: { client: ClientTableSchema }) => {
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2 flex-row">
|
||||
<Badge variant={"secondary"} className={`p-2 border rounded font-mono w-fit ${infoColor} text-nowrap rounded-full h-6`}>
|
||||
<Badge variant={"secondary"} className={`p-2 border font-mono w-fit ${infoColor} text-nowrap rounded-full h-6`}>
|
||||
{`${clientsStatus?.clients[client.id].ping}ms,${t(trans(clientsStatus?.clients[client.id]))}`}
|
||||
</Badge>
|
||||
{clientsStatus?.clients[client.id].version &&
|
||||
<ClientDetail clientStatus={clientsStatus?.clients[client.id]} />
|
||||
}
|
||||
{NeedUpgrade(clientsStatus?.clients[client.id].version) &&
|
||||
<Badge variant={"destructive"} className={`p-2 border font-mono w-fit text-nowrap rounded-full h-6`}>
|
||||
{`需要升级!`}
|
||||
</Badge>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -252,7 +259,7 @@ export const ClientSecret = ({ client }: { client: ClientTableSchema }) => {
|
||||
<div className="space-y-2">
|
||||
<h4 className="font-medium leading-none">{t('client.start.title')}</h4>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{t('client.install.description')} (<a className='text-blue-500' href='https://github.com/VaalaCat/frp-panel/releases' target="_blank" rel="noopener noreferrer">{t('common.download')}</a>)
|
||||
{t('client.start.description')} (<a className='text-blue-500' href='https://github.com/VaalaCat/frp-panel/releases' target="_blank" rel="noopener noreferrer">{t('common.download')}</a>)
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
@@ -285,19 +292,17 @@ export const ClientActions: React.FC<ClientItemProps> = ({ client, table }) => {
|
||||
const router = useRouter()
|
||||
const platformInfo = useStore($platformInfo)
|
||||
|
||||
// placeholder for refetch
|
||||
const refetchList = () => {}
|
||||
|
||||
const removeClient = useMutation({
|
||||
mutationFn: deleteClient,
|
||||
onSuccess: () => {
|
||||
toast(t('client.delete.success'))
|
||||
refetchList()
|
||||
$clientTableRefetchTrigger.set(Math.random())
|
||||
},
|
||||
onError: (e) => {
|
||||
toast(t('client.delete.failed'), {
|
||||
description: e.message,
|
||||
})
|
||||
$clientTableRefetchTrigger.set(Math.random())
|
||||
},
|
||||
})
|
||||
|
||||
@@ -305,12 +310,13 @@ export const ClientActions: React.FC<ClientItemProps> = ({ client, table }) => {
|
||||
mutationFn: stopFrpc,
|
||||
onSuccess: () => {
|
||||
toast(t('client.operation.stop_success'))
|
||||
refetchList()
|
||||
$clientTableRefetchTrigger.set(Math.random())
|
||||
},
|
||||
onError: (e) => {
|
||||
toast(t('client.operation.stop_failed'), {
|
||||
description: e.message,
|
||||
})
|
||||
$clientTableRefetchTrigger.set(Math.random())
|
||||
},
|
||||
})
|
||||
|
||||
@@ -318,12 +324,13 @@ export const ClientActions: React.FC<ClientItemProps> = ({ client, table }) => {
|
||||
mutationFn: startFrpc,
|
||||
onSuccess: () => {
|
||||
toast(t('client.operation.start_success'))
|
||||
refetchList()
|
||||
$clientTableRefetchTrigger.set(Math.random())
|
||||
},
|
||||
onError: (e) => {
|
||||
toast(t('client.operation.start_failed'), {
|
||||
description: e.message,
|
||||
})
|
||||
$clientTableRefetchTrigger.set(Math.random())
|
||||
},
|
||||
})
|
||||
|
||||
@@ -357,7 +364,7 @@ export const ClientActions: React.FC<ClientItemProps> = ({ client, table }) => {
|
||||
toast(t('client.actions_menu.copy_failed'))
|
||||
}
|
||||
} catch (error) {
|
||||
toast(t('client.actions_menu.copy_failed'),{
|
||||
toast(t('client.actions_menu.copy_failed'), {
|
||||
description: JSON.stringify(error)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -14,8 +14,11 @@ import {
|
||||
} from '@tanstack/react-table'
|
||||
|
||||
import React from 'react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { keepPreviousData, useQuery } from '@tanstack/react-query'
|
||||
import { listClient } from '@/api/client'
|
||||
import { ClientConfigured } from '@/lib/consts'
|
||||
import { useStore } from '@nanostores/react'
|
||||
import { $clientTableRefetchTrigger } from '@/store/refetch-trigger'
|
||||
|
||||
export interface ClientListProps {
|
||||
Clients: Client[]
|
||||
@@ -26,13 +29,16 @@ export interface ClientListProps {
|
||||
export const ClientList: React.FC<ClientListProps> = ({ Clients, Keyword, TriggerRefetch }) => {
|
||||
const [sorting, setSorting] = React.useState<SortingState>([])
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([])
|
||||
const globalRefetchTrigger = useStore($clientTableRefetchTrigger)
|
||||
|
||||
const data = Clients.map(
|
||||
(client) =>
|
||||
({
|
||||
id: client.id == undefined ? '' : client.id,
|
||||
status: client.config == undefined || client.config == '' ? 'invalid' : 'valid',
|
||||
status: ClientConfigured(client) ? 'valid' : 'invalid',
|
||||
secret: client.secret == undefined ? '' : client.secret,
|
||||
config: client.config,
|
||||
originClient: client,
|
||||
}) as ClientTableSchema,
|
||||
)
|
||||
|
||||
@@ -46,6 +52,7 @@ export const ClientList: React.FC<ClientListProps> = ({ Clients, Keyword, Trigge
|
||||
pageSize,
|
||||
Keyword,
|
||||
TriggerRefetch,
|
||||
globalRefetchTrigger,
|
||||
}
|
||||
const pagination = React.useMemo(
|
||||
() => ({
|
||||
@@ -60,6 +67,7 @@ export const ClientList: React.FC<ClientListProps> = ({ Clients, Keyword, Trigge
|
||||
queryFn: async () => {
|
||||
return await listClient({ page: fetchDataOptions.pageIndex + 1, pageSize: fetchDataOptions.pageSize, keyword: fetchDataOptions.Keyword })
|
||||
},
|
||||
placeholderData: keepPreviousData,
|
||||
})
|
||||
|
||||
const table = useReactTable({
|
||||
@@ -67,10 +75,11 @@ export const ClientList: React.FC<ClientListProps> = ({ Clients, Keyword, Trigge
|
||||
dataQuery.data?.clients.map((client) => {
|
||||
return {
|
||||
id: client.id == undefined ? '' : client.id,
|
||||
status: client.config == undefined || client.config == '' ? 'invalid' : 'valid',
|
||||
status: ClientConfigured(client) ? 'valid' : 'invalid',
|
||||
secret: client.secret == undefined ? '' : client.secret,
|
||||
config: client.config,
|
||||
stopped: client.stopped,
|
||||
originClient: client,
|
||||
} as ClientTableSchema
|
||||
}) ?? data,
|
||||
pageCount: Math.ceil(
|
||||
|
||||
@@ -15,6 +15,7 @@ import { TypedProxyConfig } from '@/types/proxy'
|
||||
import { ClientSelector } from '../base/client-selector'
|
||||
import { ServerSelector } from '../base/server-selector'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
export interface FRPCFormCardProps {
|
||||
clientID?: string
|
||||
@@ -42,13 +43,20 @@ export const FRPCFormCard: React.FC<FRPCFormCardProps> = ({
|
||||
}
|
||||
}, [defaultClientID, defaultServerID])
|
||||
|
||||
const { data: client, refetch: refetchClient } = useQuery({
|
||||
queryKey: ['getClient', clientID],
|
||||
const { data: client, refetch: refetchClient, error } = useQuery({
|
||||
queryKey: ['getClient', clientID, serverID],
|
||||
queryFn: () => {
|
||||
return getClient({ clientId: clientID })
|
||||
return getClient({ clientId: clientID, serverId: serverID })
|
||||
},
|
||||
retry: false,
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
setClientProxyConfigs([])
|
||||
}
|
||||
}, [error])
|
||||
|
||||
useEffect(() => {
|
||||
if (!client || !client?.client) return
|
||||
if (client?.client?.config == undefined) return
|
||||
@@ -56,7 +64,6 @@ export const FRPCFormCard: React.FC<FRPCFormCardProps> = ({
|
||||
const clientConf = JSON.parse(client?.client?.config || '{}') as ClientConfig
|
||||
|
||||
const proxyConfs = clientConf.proxies
|
||||
console.log('proxyConfs', proxyConfs)
|
||||
if (proxyConfs) {
|
||||
setClientProxyConfigs(proxyConfs)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import React, { useEffect } from 'react'
|
||||
import { useState } from 'react'
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
|
||||
import { Label } from '@radix-ui/react-label'
|
||||
import { HTTPProxyForm, STCPProxyForm, TCPProxyForm, UDPProxyForm } from './proxy_form'
|
||||
import { HTTPProxyForm, STCPProxyForm, TCPProxyForm, TypedProxyForm, UDPProxyForm } from './proxy_form'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Client, RespCode } from '@/lib/pb/common'
|
||||
import { ClientConfig } from '@/types/client'
|
||||
@@ -123,73 +123,35 @@ export const FRPCForm: React.FC<FRPCFormProps> = ({ clientID, serverID, client,
|
||||
<p>{t('proxy.form.expand', { count: clientProxyConfigs.length })}</p>
|
||||
</AccordionHeader>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-4">
|
||||
{clientProxyConfigs.map((item) => {
|
||||
<AccordionContent className="grid gap-2 grid-cols-1">
|
||||
{clientProxyConfigs.map((item, index) => {
|
||||
return (
|
||||
<Card key={item.name}>
|
||||
<CardContent>
|
||||
<div className="flex flex-col w-full pt-2">
|
||||
<Accordion type="single" collapsible>
|
||||
<AccordionItem value={item.name}>
|
||||
<AccordionHeader className="flex flex-row justify-between">
|
||||
<div>{t('proxy.form.tunnel_name')}: {item.name}</div>
|
||||
<Button
|
||||
variant={'outline'}
|
||||
onClick={() => {
|
||||
handleDeleteProxy(item.name)
|
||||
}}
|
||||
>
|
||||
{t('proxy.form.delete')}
|
||||
</Button>
|
||||
</AccordionHeader>
|
||||
<AccordionTrigger>{t('proxy.form.type_label', { type: item.type })}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
{item.type === 'tcp' && serverID && clientID && (
|
||||
<TCPProxyForm
|
||||
defaultProxyConfig={item}
|
||||
proxyName={item.name}
|
||||
serverID={serverID}
|
||||
clientID={clientID}
|
||||
clientProxyConfigs={clientProxyConfigs}
|
||||
setClientProxyConfigs={setClientProxyConfigs}
|
||||
/>
|
||||
)}
|
||||
{item.type === 'udp' && serverID && clientID && (
|
||||
<UDPProxyForm
|
||||
defaultProxyConfig={item}
|
||||
proxyName={item.name}
|
||||
serverID={serverID}
|
||||
clientID={clientID}
|
||||
clientProxyConfigs={clientProxyConfigs}
|
||||
setClientProxyConfigs={setClientProxyConfigs}
|
||||
/>
|
||||
)}
|
||||
{item.type === 'http' && serverID && clientID && (
|
||||
<HTTPProxyForm
|
||||
defaultProxyConfig={item}
|
||||
proxyName={item.name}
|
||||
serverID={serverID}
|
||||
clientID={clientID}
|
||||
clientProxyConfigs={clientProxyConfigs}
|
||||
setClientProxyConfigs={setClientProxyConfigs}
|
||||
/>
|
||||
)}
|
||||
{item.type === 'stcp' && serverID && clientID && (
|
||||
<STCPProxyForm
|
||||
defaultProxyConfig={item}
|
||||
proxyName={item.name}
|
||||
serverID={serverID}
|
||||
clientID={clientID}
|
||||
clientProxyConfigs={clientProxyConfigs}
|
||||
setClientProxyConfigs={setClientProxyConfigs}
|
||||
/>
|
||||
)}
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Accordion type="single" collapsible key={index}>
|
||||
<AccordionItem value={item.name}>
|
||||
<AccordionTrigger>
|
||||
<div className='flex flex-row justify-start items-center w-full gap-4'>
|
||||
<Button variant={'outline'} onClick={() => { handleDeleteProxy(item.name) }}>
|
||||
{t('proxy.form.delete')}
|
||||
</Button>
|
||||
<div>{t('proxy.form.tunnel_name')}: {item.name}</div>
|
||||
<div>{t('proxy.form.type_label', { type: item.type })}</div>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className='border rounded-xl p-4'>
|
||||
{serverID && clientID && (
|
||||
<TypedProxyForm
|
||||
enablePreview
|
||||
defaultProxyConfig={item}
|
||||
proxyName={item.name}
|
||||
serverID={serverID}
|
||||
clientID={clientID}
|
||||
clientProxyConfigs={clientProxyConfigs}
|
||||
setClientProxyConfigs={setClientProxyConfigs}
|
||||
/>
|
||||
)}
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
)
|
||||
})}
|
||||
</AccordionContent>
|
||||
|
||||
@@ -4,7 +4,7 @@ import React from 'react'
|
||||
import { ZodPortSchema, ZodStringSchema } from '@/lib/consts'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import { Control, FieldValues, useForm } from 'react-hook-form'
|
||||
import { Control, useForm } from 'react-hook-form'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'
|
||||
import { Input } from '@/components/ui/input'
|
||||
@@ -13,8 +13,8 @@ import { YesIcon } from '@/components/ui/icon'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { getServer } from '@/api/server'
|
||||
import { ServerConfig } from '@/types/server'
|
||||
import { ArrowRightIcon } from 'lucide-react'
|
||||
import { VisitPreview } from '../base/visit-preview'
|
||||
import StringListInput from '../base/list-input'
|
||||
|
||||
export const TCPConfigSchema = z.object({
|
||||
remotePort: ZodPortSchema,
|
||||
@@ -31,7 +31,8 @@ export const UDPConfigSchema = z.object({
|
||||
export const HTTPConfigSchema = z.object({
|
||||
localPort: ZodPortSchema,
|
||||
localIP: ZodStringSchema.default('127.0.0.1'),
|
||||
subDomain: ZodStringSchema,
|
||||
subdomain: ZodStringSchema,
|
||||
locations: z.array(ZodStringSchema).optional(),
|
||||
})
|
||||
|
||||
export const STCPConfigSchema = z.object({
|
||||
@@ -44,6 +45,7 @@ export interface ProxyFormProps {
|
||||
clientID: string
|
||||
serverID: string
|
||||
proxyName: string
|
||||
enablePreview?: boolean
|
||||
defaultProxyConfig?: TypedProxyConfig
|
||||
clientProxyConfigs: TypedProxyConfig[]
|
||||
setClientProxyConfigs: React.Dispatch<React.SetStateAction<TypedProxyConfig[]>>
|
||||
@@ -71,7 +73,7 @@ const HostField = ({
|
||||
<FormItem>
|
||||
<FormLabel>{t(label)}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={placeholder || '127.0.0.1'} {...field} />
|
||||
<Input className='text-sm' placeholder={placeholder || '127.0.0.1'} {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -102,7 +104,7 @@ const PortField = ({
|
||||
<FormItem>
|
||||
<FormLabel>{t(label)}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={placeholder || '1234'} {...field} />
|
||||
<Input className='text-sm' placeholder={placeholder || '1234'} {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -133,7 +135,7 @@ const SecretStringField = ({
|
||||
<FormItem>
|
||||
<FormLabel>{t(label)}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={placeholder || "secret"} {...field} />
|
||||
<Input className='text-sm' placeholder={placeholder || "secret"} {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -165,7 +167,7 @@ const StringField = ({
|
||||
<FormItem>
|
||||
<FormLabel>{t(label)}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={placeholder || '127.0.0.1'} {...field} />
|
||||
<Input className='text-sm' placeholder={placeholder || '127.0.0.1'} {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -175,9 +177,93 @@ const StringField = ({
|
||||
)
|
||||
}
|
||||
|
||||
export const TCPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, defaultProxyConfig, proxyName, clientProxyConfigs, setClientProxyConfigs }) => {
|
||||
const StringArrayField = ({
|
||||
control,
|
||||
name,
|
||||
label,
|
||||
placeholder,
|
||||
defaultValue,
|
||||
}: {
|
||||
control: Control<any>
|
||||
name: string
|
||||
label: string
|
||||
placeholder?: string
|
||||
defaultValue?: string[]
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<FormField
|
||||
name={name}
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t(label)}</FormLabel>
|
||||
<FormControl>
|
||||
<StringListInput placeholder={placeholder || '/path'} {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
defaultValue={defaultValue}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export const TypedProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, defaultProxyConfig, proxyName, clientProxyConfigs, setClientProxyConfigs, enablePreview }) => {
|
||||
if (!defaultProxyConfig) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return (<> {defaultProxyConfig.type === 'tcp' && serverID && clientID && (
|
||||
<TCPProxyForm
|
||||
defaultProxyConfig={defaultProxyConfig}
|
||||
proxyName={proxyName}
|
||||
serverID={serverID}
|
||||
clientID={clientID}
|
||||
clientProxyConfigs={clientProxyConfigs}
|
||||
setClientProxyConfigs={setClientProxyConfigs}
|
||||
enablePreview={enablePreview}
|
||||
/>
|
||||
)}
|
||||
{defaultProxyConfig.type === 'udp' && serverID && clientID && (
|
||||
<UDPProxyForm
|
||||
defaultProxyConfig={defaultProxyConfig}
|
||||
proxyName={proxyName}
|
||||
serverID={serverID}
|
||||
clientID={clientID}
|
||||
clientProxyConfigs={clientProxyConfigs}
|
||||
setClientProxyConfigs={setClientProxyConfigs}
|
||||
enablePreview={enablePreview}
|
||||
/>
|
||||
)}
|
||||
{defaultProxyConfig.type === 'http' && serverID && clientID && (
|
||||
<HTTPProxyForm
|
||||
defaultProxyConfig={defaultProxyConfig}
|
||||
proxyName={proxyName}
|
||||
serverID={serverID}
|
||||
clientID={clientID}
|
||||
clientProxyConfigs={clientProxyConfigs}
|
||||
setClientProxyConfigs={setClientProxyConfigs}
|
||||
enablePreview={enablePreview}
|
||||
/>
|
||||
)}
|
||||
{defaultProxyConfig.type === 'stcp' && serverID && clientID && (
|
||||
<STCPProxyForm
|
||||
defaultProxyConfig={defaultProxyConfig}
|
||||
proxyName={proxyName}
|
||||
serverID={serverID}
|
||||
clientID={clientID}
|
||||
clientProxyConfigs={clientProxyConfigs}
|
||||
setClientProxyConfigs={setClientProxyConfigs}
|
||||
enablePreview={enablePreview}
|
||||
/>
|
||||
)}</>)
|
||||
}
|
||||
|
||||
export const TCPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, defaultProxyConfig, proxyName, clientProxyConfigs, setClientProxyConfigs, enablePreview }) => {
|
||||
const defaultConfig = defaultProxyConfig as TCPProxyConfig
|
||||
const [_, setTCPConfig] = useState<TCPProxyConfig | undefined>()
|
||||
const [timeoutID, setTimeoutID] = useState<NodeJS.Timeout | undefined>()
|
||||
const form = useForm<z.infer<typeof TCPConfigSchema>>({
|
||||
resolver: zodResolver(TCPConfigSchema),
|
||||
defaultValues: {
|
||||
@@ -201,6 +287,7 @@ export const TCPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, def
|
||||
}
|
||||
return proxyCfg
|
||||
})
|
||||
console.log('newProxiyConfigs', newProxiyConfigs)
|
||||
setClientProxyConfigs(newProxiyConfigs)
|
||||
}
|
||||
|
||||
@@ -208,9 +295,12 @@ export const TCPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, def
|
||||
|
||||
const handleSave = () => {
|
||||
setSaveDisabled(true)
|
||||
setTimeout(() => {
|
||||
if (timeoutID) {
|
||||
clearTimeout(timeoutID)
|
||||
}
|
||||
setTimeoutID(setTimeout(() => {
|
||||
setSaveDisabled(false)
|
||||
}, 3000)
|
||||
}, 3000))
|
||||
}
|
||||
|
||||
const { t } = useTranslation()
|
||||
@@ -225,26 +315,18 @@ export const TCPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, def
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4 px-0.5">
|
||||
<Label className="text-sm font-medium">{t('proxy.form.access_method')}</Label>
|
||||
{server?.server?.ip && defaultConfig.remotePort && defaultConfig.localIP && defaultConfig.localPort && (
|
||||
<div className="flex items-center space-x-2">
|
||||
<Input
|
||||
value={`${server?.server?.ip}:${defaultConfig?.remotePort}`}
|
||||
className="text-sm font-mono"
|
||||
disabled
|
||||
/>{' '}
|
||||
<ArrowRightIcon className="h-4 w-4" />{' '}
|
||||
<Input
|
||||
value={`${defaultConfig?.localIP}:${defaultConfig?.localPort}`}
|
||||
className="text-sm font-mono"
|
||||
disabled
|
||||
/>
|
||||
{server?.server?.ip && defaultConfig.remotePort && defaultConfig.localIP && defaultConfig.localPort && enablePreview && (
|
||||
<div className="flex items-center space-x-2 flex-col justify-start w-full">
|
||||
<Label className="text-sm font-medium text-start w-full">{t('proxy.form.access_method')}</Label>
|
||||
<div className='w-full justify-start overflow-x-scroll'>
|
||||
<VisitPreview server={server?.server} typedProxyConfig={defaultConfig} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<PortField name="localPort" control={form.control} label={t('proxy.form.local_port')} />
|
||||
<HostField name="localIP" control={form.control} label={t('proxy.form.local_ip')} />
|
||||
<PortField name="remotePort" control={form.control} label={t('proxy.form.remote_port')} placeholder='4321'/>
|
||||
<Button type="submit" disabled={isSaveDisabled} variant={'outline'}>
|
||||
<PortField name="remotePort" control={form.control} label={t('proxy.form.remote_port')} placeholder='4321' />
|
||||
<Button type="submit" disabled={isSaveDisabled} variant={'outline'} className='w-full'>
|
||||
<YesIcon className={`mr-2 h-4 w-4 ${isSaveDisabled ? '' : 'hidden'}`}></YesIcon>
|
||||
{t('proxy.form.save_changes')}
|
||||
</Button>
|
||||
@@ -253,9 +335,10 @@ export const TCPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, def
|
||||
)
|
||||
}
|
||||
|
||||
export const STCPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, defaultProxyConfig, proxyName, clientProxyConfigs, setClientProxyConfigs }) => {
|
||||
export const STCPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, defaultProxyConfig, proxyName, clientProxyConfigs, setClientProxyConfigs, enablePreview }) => {
|
||||
const defaultConfig = defaultProxyConfig as STCPProxyConfig
|
||||
const [_, setSTCPConfig] = useState<STCPProxyConfig | undefined>()
|
||||
const [timeoutID, setTimeoutID] = useState<NodeJS.Timeout | undefined>()
|
||||
const form = useForm<z.infer<typeof STCPConfigSchema>>({
|
||||
resolver: zodResolver(STCPConfigSchema),
|
||||
defaultValues: {
|
||||
@@ -286,9 +369,12 @@ export const STCPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, de
|
||||
|
||||
const handleSave = () => {
|
||||
setSaveDisabled(true)
|
||||
setTimeout(() => {
|
||||
if (timeoutID) {
|
||||
clearTimeout(timeoutID)
|
||||
}
|
||||
setTimeoutID(setTimeout(() => {
|
||||
setSaveDisabled(false)
|
||||
}, 3000)
|
||||
}, 3000))
|
||||
}
|
||||
|
||||
const { t } = useTranslation()
|
||||
@@ -299,7 +385,7 @@ export const STCPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, de
|
||||
<PortField name="localPort" control={form.control} label={t('proxy.form.local_port')} />
|
||||
<HostField name="localIP" control={form.control} label={t('proxy.form.local_ip')} />
|
||||
<SecretStringField name="secretKey" control={form.control} label={t('proxy.form.secret_key')} />
|
||||
<Button type="submit" disabled={isSaveDisabled} variant={'outline'}>
|
||||
<Button type="submit" disabled={isSaveDisabled} variant={'outline'} className='w-full'>
|
||||
<YesIcon className={`mr-2 h-4 w-4 ${isSaveDisabled ? '' : 'hidden'}`}></YesIcon>
|
||||
{t('proxy.form.save_changes')}
|
||||
</Button>
|
||||
@@ -308,9 +394,10 @@ export const STCPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, de
|
||||
)
|
||||
}
|
||||
|
||||
export const UDPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, defaultProxyConfig, proxyName, clientProxyConfigs, setClientProxyConfigs }) => {
|
||||
export const UDPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, defaultProxyConfig, proxyName, clientProxyConfigs, setClientProxyConfigs, enablePreview }) => {
|
||||
const defaultConfig = defaultProxyConfig as UDPProxyConfig
|
||||
const [_, setUDPConfig] = useState<UDPProxyConfig | undefined>()
|
||||
const [timeoutID, setTimeoutID] = useState<NodeJS.Timeout | undefined>()
|
||||
const form = useForm<z.infer<typeof UDPConfigSchema>>({
|
||||
resolver: zodResolver(UDPConfigSchema),
|
||||
defaultValues: {
|
||||
@@ -341,9 +428,12 @@ export const UDPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, def
|
||||
|
||||
const handleSave = () => {
|
||||
setSaveDisabled(true)
|
||||
setTimeout(() => {
|
||||
if (timeoutID) {
|
||||
clearTimeout(timeoutID)
|
||||
}
|
||||
setTimeoutID(setTimeout(() => {
|
||||
setSaveDisabled(false)
|
||||
}, 3000)
|
||||
}, 3000))
|
||||
}
|
||||
|
||||
const { t } = useTranslation()
|
||||
@@ -358,25 +448,18 @@ export const UDPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, def
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4 px-0.5">
|
||||
{server?.server?.ip && defaultConfig.remotePort && defaultConfig.localIP && defaultConfig.localPort && (
|
||||
<div className="flex items-center space-x-2">
|
||||
<Input
|
||||
value={`${server?.server?.ip}:${defaultConfig?.remotePort}`}
|
||||
className="text-sm font-mono"
|
||||
disabled
|
||||
/>{' '}
|
||||
<ArrowRightIcon className="h-4 w-4" />{' '}
|
||||
<Input
|
||||
value={`${defaultConfig?.localIP}:${defaultConfig?.localPort}`}
|
||||
className="text-sm font-mono"
|
||||
disabled
|
||||
/>
|
||||
{server?.server?.ip && defaultConfig.remotePort && defaultConfig.localIP && defaultConfig.localPort && enablePreview && (
|
||||
<div className="flex items-center space-x-2 flex-col justify-start w-full">
|
||||
<Label className="text-sm font-medium text-start w-full">{t('proxy.form.access_method')}</Label>
|
||||
<div className='w-full justify-start overflow-x-scroll'>
|
||||
<VisitPreview server={server?.server} typedProxyConfig={defaultConfig} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<PortField name="localPort" control={form.control} label={t('proxy.form.local_port')} />
|
||||
<HostField name="localIP" control={form.control} label={t('proxy.form.local_ip')} />
|
||||
<PortField name="remotePort" control={form.control} label={t('proxy.form.remote_port')} />
|
||||
<Button type="submit" disabled={isSaveDisabled} variant={'outline'}>
|
||||
<Button type="submit" disabled={isSaveDisabled} variant={'outline'} className='w-full'>
|
||||
<YesIcon className={`mr-2 h-4 w-4 ${isSaveDisabled ? '' : 'hidden'}`}></YesIcon>
|
||||
{t('proxy.form.save_changes')}
|
||||
</Button>
|
||||
@@ -385,11 +468,18 @@ export const UDPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, def
|
||||
)
|
||||
}
|
||||
|
||||
export const HTTPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, defaultProxyConfig, proxyName, clientProxyConfigs, setClientProxyConfigs }) => {
|
||||
export const HTTPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, defaultProxyConfig, proxyName, clientProxyConfigs, setClientProxyConfigs, enablePreview }) => {
|
||||
const defaultConfig = defaultProxyConfig as HTTPProxyConfig
|
||||
const [_, setHTTPConfig] = useState<HTTPProxyConfig | undefined>()
|
||||
const [serverConfig, setServerConfig] = useState<ServerConfig | undefined>()
|
||||
const [timeoutID, setTimeoutID] = useState<NodeJS.Timeout | undefined>()
|
||||
const form = useForm<z.infer<typeof HTTPConfigSchema>>({
|
||||
resolver: zodResolver(HTTPConfigSchema),
|
||||
defaultValues: {
|
||||
localIP: defaultConfig?.localIP,
|
||||
localPort: defaultConfig?.localPort,
|
||||
subdomain: defaultConfig?.subdomain,
|
||||
locations: defaultConfig?.locations,
|
||||
}
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
@@ -413,9 +503,12 @@ export const HTTPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, de
|
||||
|
||||
const handleSave = () => {
|
||||
setSaveDisabled(true)
|
||||
setTimeout(() => {
|
||||
if (timeoutID) {
|
||||
clearTimeout(timeoutID)
|
||||
}
|
||||
setTimeoutID(setTimeout(() => {
|
||||
setSaveDisabled(false)
|
||||
}, 3000)
|
||||
}, 3000))
|
||||
}
|
||||
|
||||
const { t } = useTranslation()
|
||||
@@ -427,24 +520,23 @@ export const HTTPProxyForm: React.FC<ProxyFormProps> = ({ serverID, clientID, de
|
||||
},
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (server && server.server?.config) {
|
||||
setServerConfig(JSON.parse(server.server?.config) as ServerConfig)
|
||||
}
|
||||
}, [server])
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4 px-0.5">
|
||||
<Label className="text-sm font-medium">{t('proxy.form.access_method')}</Label>
|
||||
<p className="text-sm border rounded p-2 my-2 font-mono overflow-auto">
|
||||
{`http://${(defaultProxyConfig as HTTPProxyConfig).subdomain}.${serverConfig?.subDomainHost}:${serverConfig?.vhostHTTPPort
|
||||
} -> ${defaultProxyConfig?.localIP}:${defaultProxyConfig?.localPort}`}
|
||||
</p>
|
||||
{server && server.server && server.server.ip && defaultConfig &&
|
||||
defaultConfig.localIP && defaultConfig.localPort &&
|
||||
defaultConfig.subdomain
|
||||
&& enablePreview && <div className="flex items-center space-x-2 flex-col justify-start w-full">
|
||||
<Label className="text-sm font-medium text-start w-full">{t('proxy.form.access_method')}</Label>
|
||||
<div className='w-full justify-start overflow-x-scroll'>
|
||||
<VisitPreview server={server?.server} typedProxyConfig={defaultConfig} />
|
||||
</div>
|
||||
</div>}
|
||||
<PortField name="localPort" control={form.control} label={t('proxy.form.local_port')} />
|
||||
<HostField name="localIP" control={form.control} label={t('proxy.form.local_ip')} />
|
||||
<StringField name="subDomain" control={form.control} label={t('proxy.form.subdomain')} placeholder={"your_sub_domain"} />
|
||||
<Button type="submit" disabled={isSaveDisabled} variant={'outline'}>
|
||||
<StringField name="subdomain" control={form.control} label={t('proxy.form.subdomain')} placeholder={"your_sub_domain"} />
|
||||
<StringArrayField name="locations" control={form.control} label={t('proxy.form.route')} placeholder={"/path"} />
|
||||
<Button type="submit" disabled={isSaveDisabled} variant={'outline'} className='w-full'>
|
||||
<YesIcon className={`mr-2 h-4 w-4 ${isSaveDisabled ? '' : 'hidden'}`}></YesIcon>
|
||||
{t('proxy.form.save_changes')}
|
||||
</Button>
|
||||
|
||||
@@ -49,7 +49,7 @@ export const CreateServerDialog = ({refetchTrigger}: {refetchTrigger?: (randStr:
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" size={'sm'}>
|
||||
<Button variant="outline">
|
||||
{t('server.create.button')}
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
|
||||
@@ -36,6 +36,7 @@ import { ClientDetail } from '../base/client_detail'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { toast } from 'sonner'
|
||||
import { $serverTableRefetchTrigger } from '@/store/refetch-trigger'
|
||||
|
||||
export type ServerTableSchema = {
|
||||
id: string
|
||||
@@ -257,7 +258,7 @@ export const ServerSecret = ({ server }: { server: ServerTableSchema }) => {
|
||||
<div className="space-y-2">
|
||||
<h4 className="font-medium leading-none">{t('server.start.title')}</h4>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{t('server.install.description')} (<a className='text-blue-500' href='https://github.com/VaalaCat/frp-panel/releases' target="_blank" rel="noopener noreferrer">{t('common.download')}</a>)
|
||||
{t('server.start.description')} (<a className='text-blue-500' href='https://github.com/VaalaCat/frp-panel/releases' target="_blank" rel="noopener noreferrer">{t('common.download')}</a>)
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
@@ -290,18 +291,17 @@ export const ServerActions: React.FC<ServerItemProps> = ({ server, table }) => {
|
||||
const router = useRouter()
|
||||
const platformInfo = useStore($platformInfo)
|
||||
|
||||
const refetchList = () => { }
|
||||
|
||||
const removeServer = useMutation({
|
||||
mutationFn: deleteServer,
|
||||
onSuccess: () => {
|
||||
toast(t('server.delete.success'))
|
||||
refetchList()
|
||||
$serverTableRefetchTrigger.set(Math.random())
|
||||
},
|
||||
onError: (e) => {
|
||||
toast(t('server.delete.failed'), {
|
||||
description: e.message,
|
||||
})
|
||||
$serverTableRefetchTrigger.set(Math.random())
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -14,8 +14,10 @@ import {
|
||||
} from '@tanstack/react-table'
|
||||
|
||||
import React from 'react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { keepPreviousData, useQuery } from '@tanstack/react-query'
|
||||
import { listServer } from '@/api/server'
|
||||
import { $serverTableRefetchTrigger } from '@/store/refetch-trigger'
|
||||
import { useStore } from '@nanostores/react'
|
||||
|
||||
export interface ServerListProps {
|
||||
Servers: Server[]
|
||||
@@ -26,6 +28,8 @@ export interface ServerListProps {
|
||||
export const ServerList: React.FC<ServerListProps> = ({ Servers, Keyword, TriggerRefetch }) => {
|
||||
const [sorting, setSorting] = React.useState<SortingState>([])
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([])
|
||||
const globalRefetchTrigger = useStore($serverTableRefetchTrigger)
|
||||
|
||||
const data = Servers.map(
|
||||
(server) =>
|
||||
({
|
||||
@@ -46,6 +50,7 @@ export const ServerList: React.FC<ServerListProps> = ({ Servers, Keyword, Trigge
|
||||
pageSize,
|
||||
Keyword,
|
||||
TriggerRefetch,
|
||||
globalRefetchTrigger,
|
||||
}
|
||||
const pagination = React.useMemo(
|
||||
() => ({
|
||||
@@ -60,6 +65,7 @@ export const ServerList: React.FC<ServerListProps> = ({ Servers, Keyword, Trigge
|
||||
queryFn: async () => {
|
||||
return await listServer({ page: fetchDataOptions.pageIndex + 1, pageSize: fetchDataOptions.pageSize, keyword: fetchDataOptions.Keyword })
|
||||
},
|
||||
placeholderData: keepPreviousData,
|
||||
})
|
||||
|
||||
const table = useReactTable({
|
||||
|
||||
146
www/components/proxy/mutate_proxy_config.tsx
Normal file
146
www/components/proxy/mutate_proxy_config.tsx
Normal file
@@ -0,0 +1,146 @@
|
||||
"use client"
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useMutation } from '@tanstack/react-query'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from '@/components/ui/dialog'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { ServerSelector } from '../base/server-selector'
|
||||
import { ClientSelector } from '../base/client-selector'
|
||||
import { TypedProxyForm } from '../frpc/proxy_form'
|
||||
import { ProxyType, TypedProxyConfig } from '@/types/proxy'
|
||||
import { BaseSelector } from '../base/selector'
|
||||
import { createProxyConfig } from '@/api/proxy'
|
||||
import { ClientConfig } from '@/types/client'
|
||||
import { ObjToUint8Array } from '@/lib/utils'
|
||||
import { VisitPreview } from '../base/visit-preview'
|
||||
import { ProxyConfig, Server } from '@/lib/pb/common'
|
||||
import { TypedProxyConfigValid } from '@/lib/consts'
|
||||
import { toast } from 'sonner'
|
||||
import { $proxyTableRefetchTrigger } from '@/store/refetch-trigger'
|
||||
|
||||
export type ProxyConfigMutateDialogProps = {
|
||||
overwrite?: boolean
|
||||
defaultProxyConfig?: TypedProxyConfig
|
||||
defaultOriginalProxyConfig?: ProxyConfig
|
||||
disableChangeProxyName?: boolean
|
||||
}
|
||||
|
||||
export const ProxyConfigMutateDialog = ({ ...props }: ProxyConfigMutateDialogProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" className='w-fit'>
|
||||
{t('proxy.config.create')}
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className='max-h-screen overflow-auto'>
|
||||
<ProxyConfigMutateForm {...props} />
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
export const ProxyConfigMutateForm = ({ overwrite, defaultProxyConfig, defaultOriginalProxyConfig, disableChangeProxyName }: ProxyConfigMutateDialogProps) => {
|
||||
const { t } = useTranslation()
|
||||
const [newClientID, setNewClientID] = useState<string | undefined>()
|
||||
const [newServerID, setNewServerID] = useState<string | undefined>()
|
||||
const [proxyConfigs, setProxyConfigs] = useState<TypedProxyConfig[]>([])
|
||||
const [proxyName, setProxyName] = useState<string | undefined>('')
|
||||
const [proxyType, setProxyType] = useState<ProxyType>('http')
|
||||
const [selectedServer, setSelectedServer] = useState<Server | undefined>()
|
||||
const supportedProxyTypes: ProxyType[] = ["http", "tcp", "udp"]
|
||||
|
||||
const createProxyConfigMutation = useMutation({
|
||||
mutationKey: ['createProxyConfig', newClientID, newServerID],
|
||||
mutationFn: () => createProxyConfig({
|
||||
clientId: newClientID!,
|
||||
serverId: newServerID!,
|
||||
config: ObjToUint8Array({
|
||||
proxies: proxyConfigs
|
||||
} as ClientConfig),
|
||||
overwrite,
|
||||
}),
|
||||
onSuccess: () => {
|
||||
toast(t('proxy.config.create_success'))
|
||||
$proxyTableRefetchTrigger.set(Math.random())
|
||||
},
|
||||
onError: (e) => {
|
||||
toast(t('proxy.config.create_failed'), {
|
||||
description: JSON.stringify(e),
|
||||
})
|
||||
$proxyTableRefetchTrigger.set(Math.random())
|
||||
}
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (proxyName && proxyType) {
|
||||
setProxyConfigs([{ name: proxyName, type: proxyType }])
|
||||
}
|
||||
}, [proxyName, proxyType])
|
||||
|
||||
useEffect(() => {
|
||||
if (defaultProxyConfig && defaultOriginalProxyConfig) {
|
||||
setProxyConfigs([defaultProxyConfig])
|
||||
setProxyType(defaultProxyConfig.type)
|
||||
setProxyName(defaultProxyConfig.name)
|
||||
setNewClientID(defaultOriginalProxyConfig.originClientId)
|
||||
setNewServerID(defaultOriginalProxyConfig.serverId)
|
||||
}
|
||||
}, [defaultProxyConfig, defaultOriginalProxyConfig])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Label>{t('proxy.config.select_server')} </Label>
|
||||
<ServerSelector setServerID={setNewServerID} serverID={newServerID} setServer={setSelectedServer} />
|
||||
<Label>{t('proxy.config.select_client')} </Label>
|
||||
<ClientSelector setClientID={setNewClientID} clientID={newClientID} />
|
||||
<Label>{t('proxy.config.select_proxy_type')} </Label>
|
||||
<BaseSelector
|
||||
dataList={supportedProxyTypes.map((type) => ({ value: type, label: type }))}
|
||||
value={proxyType}
|
||||
setValue={(value) => { setProxyType(value as ProxyType) }}
|
||||
/>
|
||||
<div className='flex flex-row w-full overflow-auto'>
|
||||
{proxyConfigs && selectedServer && proxyConfigs.length > 0 &&
|
||||
proxyConfigs[0] && TypedProxyConfigValid(proxyConfigs[0]) &&
|
||||
<div className='flex flex-col'>
|
||||
<VisitPreview server={selectedServer} typedProxyConfig={proxyConfigs[0]} />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<Label>{t('proxy.config.proxy_name')} </Label>
|
||||
<Input className='text-sm' defaultValue={proxyName} onChange={(e) => setProxyName(e.target.value)} disabled={disableChangeProxyName} />
|
||||
{proxyName && newClientID && newServerID && <TypedProxyForm
|
||||
serverID={newServerID}
|
||||
clientID={newClientID}
|
||||
proxyName={proxyName}
|
||||
defaultProxyConfig={proxyConfigs && proxyConfigs.length > 0 ? proxyConfigs[0] : undefined}
|
||||
clientProxyConfigs={proxyConfigs}
|
||||
setClientProxyConfigs={setProxyConfigs}
|
||||
enablePreview={false}
|
||||
/>}
|
||||
<Button
|
||||
disabled={!TypedProxyConfigValid(proxyConfigs[0])}
|
||||
onClick={() => {
|
||||
if (!TypedProxyConfigValid(proxyConfigs[0])) {
|
||||
toast(t('proxy.config.invalid_config'))
|
||||
return
|
||||
}
|
||||
createProxyConfigMutation.mutate()
|
||||
}} >{t('proxy.config.submit')}</Button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
102
www/components/proxy/proxy_config_actions.tsx
Normal file
102
www/components/proxy/proxy_config_actions.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
import { ProxyType, TypedProxyConfig } from "@/types/proxy"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Button } from "../ui/button"
|
||||
import { BaseDropdownMenu } from "../base/drop-down-menu"
|
||||
import { deleteProxyConfig } from "@/api/proxy"
|
||||
import { useMutation } from "@tanstack/react-query"
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog'
|
||||
import { ProxyConfigMutateForm } from "./mutate_proxy_config"
|
||||
import { useEffect, useState } from "react"
|
||||
import { Row } from "@tanstack/react-table"
|
||||
import { ProxyConfigTableSchema } from "./proxy_config_item"
|
||||
import { MoreHorizontal } from "lucide-react"
|
||||
import { toast } from "sonner"
|
||||
import { $proxyTableRefetchTrigger } from "@/store/refetch-trigger"
|
||||
|
||||
export interface ProxyConfigActionsProps {
|
||||
serverID: string
|
||||
clientID: string
|
||||
name: string
|
||||
row: Row<ProxyConfigTableSchema>
|
||||
}
|
||||
|
||||
export function ProxyConfigActions({ serverID, clientID, name, row }: ProxyConfigActionsProps) {
|
||||
const { t } = useTranslation()
|
||||
const [proxyMutateFormOpen, setProxyMutateFormOpen] = useState(false)
|
||||
const [deleteWarnDialogOpen, setDeleteWarnDialogOpen] = useState(false)
|
||||
|
||||
const deleteProxyConfigMutation = useMutation({
|
||||
mutationKey: ['deleteProxyConfig', serverID, clientID, name],
|
||||
mutationFn: () => deleteProxyConfig({
|
||||
serverId: serverID,
|
||||
clientId: clientID,
|
||||
name,
|
||||
}),
|
||||
onSuccess: () => {
|
||||
toast(t('proxy.action.delete_success'))
|
||||
$proxyTableRefetchTrigger.set(Math.random())
|
||||
},
|
||||
onError: (e) => {
|
||||
toast(t('proxy.action.delete_failed'), {
|
||||
description: JSON.stringify(e),
|
||||
})
|
||||
$proxyTableRefetchTrigger.set(Math.random())
|
||||
},
|
||||
})
|
||||
|
||||
const menuActions = [[
|
||||
{
|
||||
name: t('proxy.action.edit'),
|
||||
onClick: () => { setProxyMutateFormOpen(true) },
|
||||
},
|
||||
{
|
||||
name: t('proxy.action.delete'),
|
||||
onClick: () => { setDeleteWarnDialogOpen(true) },
|
||||
className: 'text-destructive',
|
||||
},
|
||||
]]
|
||||
return (<>
|
||||
<Dialog open={proxyMutateFormOpen} onOpenChange={setProxyMutateFormOpen}>
|
||||
<DialogContent className="max-h-screen overflow-auto">
|
||||
<ProxyConfigMutateForm
|
||||
disableChangeProxyName
|
||||
defaultProxyConfig={JSON.parse(row.original.config || '{}') as TypedProxyConfig}
|
||||
overwrite={true}
|
||||
defaultOriginalProxyConfig={row.original.originalProxyConfig}
|
||||
/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<Dialog open={deleteWarnDialogOpen} onOpenChange={setDeleteWarnDialogOpen}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{t('proxy.action.delete_tunnel')}</DialogTitle>
|
||||
<DialogDescription>
|
||||
<p className="text-destructive">{t('proxy.action.delete_attention_title')}</p>
|
||||
<p className="text-gray-500 border-l-4 border-gray-500 pl-4 py-2">
|
||||
{t('proxy.action.delete_attention_description')}
|
||||
</p>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter><DialogClose asChild><Button type="submit" onClick={() => {
|
||||
deleteProxyConfigMutation.mutate()
|
||||
}}>
|
||||
{t('proxy.action.delete_attention_confirm')}
|
||||
</Button></DialogClose></DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<BaseDropdownMenu
|
||||
menuGroup={menuActions}
|
||||
title={t('proxy.action.title')}
|
||||
trigger={<Button variant="ghost" className="h-8 w-8 p-0">
|
||||
<MoreHorizontal className="h-4 w-4" />
|
||||
</Button>} />
|
||||
</>)
|
||||
}
|
||||
152
www/components/proxy/proxy_config_item.tsx
Normal file
152
www/components/proxy/proxy_config_item.tsx
Normal file
@@ -0,0 +1,152 @@
|
||||
import { ColumnDef, Row, Table } from '@tanstack/react-table'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { VisitPreview } from '../base/visit-preview'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { getServer } from '@/api/server'
|
||||
import { ProxyType, TypedProxyConfig } from '@/types/proxy'
|
||||
import { ProxyConfigActions } from './proxy_config_actions'
|
||||
import { ProxyConfig } from '@/lib/pb/common'
|
||||
import { getProxyConfig } from '@/api/proxy'
|
||||
import { Badge } from '../ui/badge'
|
||||
import { useStore } from '@nanostores/react'
|
||||
import { $proxyTableRefetchTrigger } from '@/store/refetch-trigger'
|
||||
|
||||
export type ProxyConfigTableSchema = {
|
||||
serverID: string
|
||||
clientID: string
|
||||
name: string
|
||||
type: ProxyType
|
||||
localIP?: string
|
||||
localPort?: number
|
||||
visitPreview: string
|
||||
config?: string
|
||||
originalProxyConfig: ProxyConfig
|
||||
}
|
||||
|
||||
export const columns: ColumnDef<ProxyConfigTableSchema>[] = [
|
||||
{
|
||||
accessorKey: 'clientID',
|
||||
header: function Header() {
|
||||
const { t } = useTranslation()
|
||||
return t('proxy.item.client_id')
|
||||
},
|
||||
cell: ({ row }) => {
|
||||
return <div className='font-mono text-nowrap'>{row.original.originalProxyConfig.originClientId}</div>
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'name',
|
||||
header: function Header() {
|
||||
const { t } = useTranslation()
|
||||
return t('proxy.item.proxy_name')
|
||||
},
|
||||
cell: ({ row }) => {
|
||||
return <div className='font-mono text-nowrap'>{row.original.name}</div>
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'type',
|
||||
header: function Header() {
|
||||
const { t } = useTranslation()
|
||||
return t('proxy.item.proxy_type')
|
||||
},
|
||||
cell: ({ row }) => {
|
||||
return <div className='font-mono text-nowrap'>{row.original.type}</div>
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'serverID',
|
||||
header: function Header() {
|
||||
const { t } = useTranslation()
|
||||
return t('proxy.item.server_id')
|
||||
},
|
||||
cell: ({ row }) => {
|
||||
return <div className='font-mono text-nowrap'>{row.original.serverID}</div>
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'status',
|
||||
header: function Header() {
|
||||
const { t } = useTranslation()
|
||||
return t('proxy.item.status')
|
||||
},
|
||||
cell: ProxyStatus,
|
||||
},
|
||||
{
|
||||
accessorKey: 'visitPreview',
|
||||
header: function Header() {
|
||||
const { t } = useTranslation()
|
||||
return t('proxy.item.visit_preview')
|
||||
},
|
||||
cell: ({ row }) => {
|
||||
return <VisitPreviewField row={row} />
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'action',
|
||||
cell: ({ row }) => {
|
||||
return <ProxyConfigActions
|
||||
row={row}
|
||||
serverID={row.original.serverID}
|
||||
clientID={row.original.clientID}
|
||||
name={row.original.name}
|
||||
/>
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
function VisitPreviewField({ row }: { row: Row<ProxyConfigTableSchema> }) {
|
||||
const { data: server } = useQuery({
|
||||
queryKey: ['getServer', row.original.serverID],
|
||||
queryFn: () => {
|
||||
return getServer({ serverId: row.original.serverID })
|
||||
},
|
||||
})
|
||||
|
||||
const typedProxyConfig = JSON.parse(row.original.config || '{}') as TypedProxyConfig
|
||||
|
||||
return <VisitPreview
|
||||
server={server?.server || {}}
|
||||
typedProxyConfig={typedProxyConfig} />
|
||||
}
|
||||
|
||||
function ProxyStatus({ row }: { row: Row<ProxyConfigTableSchema> }) {
|
||||
const refetchTrigger = useStore($proxyTableRefetchTrigger)
|
||||
const { data } = useQuery({
|
||||
queryKey: ['getProxyConfig', row.original.clientID, row.original.serverID, row.original.name, refetchTrigger],
|
||||
queryFn: () => {
|
||||
return getProxyConfig({
|
||||
clientId: row.original.clientID,
|
||||
serverId: row.original.serverID,
|
||||
name: row.original.name
|
||||
})
|
||||
},
|
||||
refetchInterval: 10000
|
||||
})
|
||||
|
||||
function getStatusColor(status: string): string {
|
||||
switch (status) {
|
||||
case 'new':
|
||||
return 'text-blue-500'
|
||||
case 'wait start':
|
||||
return 'text-yellow-400';
|
||||
case 'start error':
|
||||
return 'text-red-500';
|
||||
case 'running':
|
||||
return 'text-green-500';
|
||||
case 'check failed':
|
||||
return 'text-orange-500';
|
||||
case 'error':
|
||||
return 'text-red-600';
|
||||
default:
|
||||
return 'text-gray-500';
|
||||
}
|
||||
}
|
||||
|
||||
return <div className="flex items-center gap-2 flex-row text-nowrap">
|
||||
<Badge variant={"secondary"} className={`p-2 border rounded font-mono w-fit ${getStatusColor(data?.workingStatus?.status || 'unknown')} text-nowrap rounded-full h-6`}>
|
||||
{data?.workingStatus?.status || "loading"}
|
||||
</Badge>
|
||||
</div>
|
||||
}
|
||||
125
www/components/proxy/proxy_config_list.tsx
Normal file
125
www/components/proxy/proxy_config_list.tsx
Normal file
@@ -0,0 +1,125 @@
|
||||
import { ProxyConfig } from '@/lib/pb/common'
|
||||
import { ProxyConfigTableSchema, columns as proxyConfigColumnsDef } from './proxy_config_item'
|
||||
import { DataTable } from '../base/data_table'
|
||||
|
||||
import {
|
||||
getSortedRowModel,
|
||||
getCoreRowModel,
|
||||
ColumnFiltersState,
|
||||
useReactTable,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
SortingState,
|
||||
PaginationState,
|
||||
} from '@tanstack/react-table'
|
||||
|
||||
import React from 'react'
|
||||
import { keepPreviousData, useQuery } from '@tanstack/react-query'
|
||||
import { listProxyConfig } from '@/api/proxy'
|
||||
import { TypedProxyConfig } from '@/types/proxy'
|
||||
import { $proxyTableRefetchTrigger } from '@/store/refetch-trigger'
|
||||
import { useStore } from '@nanostores/react'
|
||||
|
||||
export interface ProxyConfigListProps {
|
||||
ProxyConfigs: ProxyConfig[]
|
||||
Keyword?: string
|
||||
ClientID?: string
|
||||
ServerID?: string
|
||||
TriggerRefetch?: string
|
||||
}
|
||||
|
||||
export const ProxyConfigList: React.FC<ProxyConfigListProps> = ({ ProxyConfigs, Keyword, TriggerRefetch, ClientID, ServerID }) => {
|
||||
const [sorting, setSorting] = React.useState<SortingState>([])
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([])
|
||||
const globalRefetchTrigger = useStore($proxyTableRefetchTrigger)
|
||||
|
||||
const data = ProxyConfigs.map(
|
||||
(proxy_config) =>
|
||||
({
|
||||
id: proxy_config.id || '',
|
||||
clientID: proxy_config.clientId || '',
|
||||
serverID: proxy_config.serverId || '',
|
||||
name: proxy_config.name || '',
|
||||
type: proxy_config.type || '',
|
||||
visitPreview: "for test",
|
||||
originalProxyConfig: proxy_config,
|
||||
}) as ProxyConfigTableSchema,
|
||||
)
|
||||
|
||||
const [{ pageIndex, pageSize }, setPagination] = React.useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
})
|
||||
|
||||
const fetchDataOptions = {
|
||||
pageIndex,
|
||||
pageSize,
|
||||
Keyword,
|
||||
TriggerRefetch,
|
||||
ClientID,
|
||||
ServerID,
|
||||
globalRefetchTrigger,
|
||||
}
|
||||
const pagination = React.useMemo(
|
||||
() => ({
|
||||
pageIndex,
|
||||
pageSize,
|
||||
}),
|
||||
[pageIndex, pageSize],
|
||||
)
|
||||
|
||||
const dataQuery = useQuery({
|
||||
queryKey: ['listProxyConfigs', fetchDataOptions],
|
||||
queryFn: async () => {
|
||||
return await listProxyConfig({
|
||||
page: fetchDataOptions.pageIndex + 1,
|
||||
pageSize: fetchDataOptions.pageSize,
|
||||
keyword: fetchDataOptions.Keyword,
|
||||
clientId: fetchDataOptions.ClientID,
|
||||
serverId: fetchDataOptions.ServerID,
|
||||
})
|
||||
},
|
||||
placeholderData: keepPreviousData,
|
||||
})
|
||||
|
||||
const table = useReactTable({
|
||||
data:
|
||||
dataQuery.data?.proxyConfigs.map((proxy_config) => {
|
||||
return {
|
||||
id: proxy_config.id || '',
|
||||
name: proxy_config.name || '',
|
||||
clientID: proxy_config.clientId || '',
|
||||
serverID: proxy_config.serverId || '',
|
||||
type: proxy_config.type || '',
|
||||
config: proxy_config.config || '',
|
||||
localIP: proxy_config.config && ParseProxyConfig(proxy_config.config).localIP,
|
||||
localPort: proxy_config.config && ParseProxyConfig(proxy_config.config).localPort,
|
||||
visitPreview: "",
|
||||
originalProxyConfig: proxy_config,
|
||||
} as ProxyConfigTableSchema
|
||||
}) ?? data,
|
||||
pageCount: Math.ceil(
|
||||
//@ts-ignore
|
||||
(dataQuery.data?.total == undefined ? 0 : dataQuery.data?.total) / fetchDataOptions.pageSize ?? 0,
|
||||
),
|
||||
columns: proxyConfigColumnsDef,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
onSortingChange: setSorting,
|
||||
onPaginationChange: setPagination,
|
||||
onColumnFiltersChange: setColumnFilters,
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
manualPagination: true,
|
||||
state: {
|
||||
sorting,
|
||||
pagination,
|
||||
columnFilters,
|
||||
},
|
||||
})
|
||||
return <DataTable table={table} columns={proxyConfigColumnsDef} />
|
||||
}
|
||||
|
||||
function ParseProxyConfig(cfg: string): TypedProxyConfig {
|
||||
return JSON.parse(cfg)
|
||||
}
|
||||
@@ -35,7 +35,7 @@ export function RegisterComponent() {
|
||||
}
|
||||
|
||||
const onSubmit = async (values: z.infer<typeof RegisterSchema>) => {
|
||||
toast('auth.registering')
|
||||
toast(t('auth.registering'))
|
||||
try {
|
||||
const res = await register({ ...values })
|
||||
if (res.status?.code === RespCode.SUCCESS) {
|
||||
|
||||
@@ -28,8 +28,8 @@ export const ClientStatsCard: React.FC<ClientStatsCardProps> = ({ clientID: defa
|
||||
|
||||
const { data: clientStatsList, refetch: refetchClientStats } = useQuery({
|
||||
queryKey: ['clientStats', clientID],
|
||||
queryFn: async () => {
|
||||
return await getProxyStatsByClientID({ clientId: clientID! })
|
||||
queryFn: () => {
|
||||
return getProxyStatsByClientID({ clientId: clientID! })
|
||||
},
|
||||
})
|
||||
|
||||
@@ -98,8 +98,8 @@ export const ClientStatsCard: React.FC<ClientStatsCardProps> = ({ clientID: defa
|
||||
setProxyname={setProxyName} />
|
||||
<div className="w-full grid gap-4 grid-cols-1">
|
||||
{clientStatsList && clientStatsList.proxyInfos.length > 0 &&
|
||||
<ProxyStatusCard
|
||||
proxyInfo={mergeProxyInfos(clientStatsList.proxyInfos).find((proxyInfo) => proxyInfo.name === proxyName)} />}
|
||||
<ProxyStatusCard
|
||||
proxyInfo={mergeProxyInfos(clientStatsList.proxyInfos).find((proxyInfo) => proxyInfo.name === proxyName)} />}
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
MonitorCogIcon,
|
||||
ChartNetworkIcon,
|
||||
Scroll,
|
||||
Cable,
|
||||
} from "lucide-react"
|
||||
import { TbBuildingTunnel } from "react-icons/tb"
|
||||
|
||||
@@ -30,6 +31,11 @@ export const getNavItems = (t: any) => [
|
||||
url: "/servers",
|
||||
icon: ServerIcon,
|
||||
},
|
||||
{
|
||||
title: t('nav.editTunnel'),
|
||||
url: "/proxies",
|
||||
icon: Cable,
|
||||
},
|
||||
{
|
||||
title: t('nav.editClient'),
|
||||
url: "/clientedit",
|
||||
|
||||
9
www/config/notify.ts
Normal file
9
www/config/notify.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { ClientVersion } from "@/lib/pb/api_master"
|
||||
|
||||
export function NeedUpgrade(version: ClientVersion | undefined) {
|
||||
if (!(version)) return false
|
||||
if (!version.gitVersion) return false
|
||||
const versionString = version?.gitVersion
|
||||
const [a, b, c] = versionString.split('.')
|
||||
return Number(b) < 1
|
||||
}
|
||||
@@ -11,11 +11,12 @@
|
||||
"nav": {
|
||||
"clients": "Clients",
|
||||
"servers": "Servers",
|
||||
"editClient": "Edit Tunnel",
|
||||
"editClient": "Edit Client",
|
||||
"editServer": "Edit Server",
|
||||
"trafficStats": "Traffic Stats",
|
||||
"realTimeLog": "Real-time Log",
|
||||
"console": "Console",
|
||||
"editTunnel": "Edit Tunnel",
|
||||
"user": {
|
||||
"profile": "Profile",
|
||||
"settings": "Settings"
|
||||
@@ -65,7 +66,6 @@
|
||||
"info": "Information",
|
||||
"download": "Click here to download",
|
||||
"copy": "Copy",
|
||||
"download": "Download",
|
||||
"submit": "Submit",
|
||||
"cancel": "Cancel",
|
||||
"save": "Save",
|
||||
@@ -114,7 +114,10 @@
|
||||
"totalServers": "Total Servers",
|
||||
"totalClients": "Total Clients",
|
||||
"unit": "",
|
||||
"menuHint": "Please modify in the left menu"
|
||||
"menuHint": "Please modify in the left menu",
|
||||
"refresh": {
|
||||
"data": "Refresh Data"
|
||||
}
|
||||
},
|
||||
"server": {
|
||||
"configuration": "Server Configuration",
|
||||
@@ -151,7 +154,7 @@
|
||||
},
|
||||
"start": {
|
||||
"title": "Start Command",
|
||||
"description": "Copy and run the following command to start frps",
|
||||
"description": "Copy and run the following command to start frp-panel server",
|
||||
"copy": "Copy Command"
|
||||
},
|
||||
"actions_menu": {
|
||||
@@ -245,7 +248,7 @@
|
||||
},
|
||||
"start": {
|
||||
"title": "Start Command",
|
||||
"description": "Copy and run the following command to start frpc",
|
||||
"description": "Copy and run the following command to start frp-panel client",
|
||||
"copy": "Copy Command"
|
||||
},
|
||||
"actions_menu": {
|
||||
@@ -340,7 +343,43 @@
|
||||
"save_success": "Save successful",
|
||||
"save_error": "Save failed",
|
||||
"save_changes": "Save Changes",
|
||||
"submit": "Submit Changes"
|
||||
"submit": "Submit Changes",
|
||||
"default_port": "Default Port",
|
||||
"port_placeholder": "Port (1-65535)",
|
||||
"ip_placeholder": "IP Address (eg. 127.0.0.1)",
|
||||
"subdomain_placeholder": "Input Subdomain",
|
||||
"secret_placeholder": "Input Secret Key",
|
||||
"route": "Route"
|
||||
},
|
||||
"config": {
|
||||
"create": "Create",
|
||||
"create_success": "Create successful",
|
||||
"create_failed": "Create failed",
|
||||
"select_server": "Select Server",
|
||||
"select_client": "Select Client",
|
||||
"select_proxy_type": "Select Tunnel Type",
|
||||
"proxy_name": "Tunnel Name",
|
||||
"invalid_config": "Invalid configuration",
|
||||
"submit": "Submit"
|
||||
},
|
||||
"action": {
|
||||
"delete_success": "Delete Successful",
|
||||
"delete_failed": "Delete Failed",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"delete_tunnel": "Delete Tunnel",
|
||||
"delete_attention_title": "Tunnel will be permanently deleted, please confirm",
|
||||
"delete_attention_description": "After deletion, Tunnel will not be recovered, please be careful",
|
||||
"delete_attention_confirm": "Confirm",
|
||||
"title": "Tunnel Operation"
|
||||
},
|
||||
"item": {
|
||||
"client_id": "Client ID",
|
||||
"proxy_name": "Tunnel Name",
|
||||
"proxy_type": "Tunnel Type",
|
||||
"server_id": "Server ID",
|
||||
"status": "Status",
|
||||
"visit_preview": "Visit Preview"
|
||||
},
|
||||
"type": {
|
||||
"http": "HTTP",
|
||||
@@ -379,10 +418,10 @@
|
||||
},
|
||||
"frpc": {
|
||||
"form": {
|
||||
"title": "Edit Tunnel",
|
||||
"title": "Edit Client",
|
||||
"description": {
|
||||
"warning": "Warning⚠️: The selected 'Server' must be configured in advance!",
|
||||
"instruction": "Select client and server to edit tunnel"
|
||||
"instruction": "Select client and server to edit configuration"
|
||||
},
|
||||
"advanced": {
|
||||
"title": "Advanced Mode",
|
||||
@@ -428,9 +467,13 @@
|
||||
}
|
||||
},
|
||||
"input": {
|
||||
"list": {
|
||||
"placeholder": "Please enter ...",
|
||||
"add": "Add"
|
||||
},
|
||||
"search": "Search",
|
||||
"id": {
|
||||
"placeholder": "Enter ID"
|
||||
"keyword": {
|
||||
"placeholder": "Enter keyword"
|
||||
}
|
||||
},
|
||||
"table": {
|
||||
|
||||
@@ -11,11 +11,12 @@
|
||||
"nav": {
|
||||
"clients": "客户端",
|
||||
"servers": "服务端",
|
||||
"editClient": "编辑隧道",
|
||||
"editClient": "编辑客户端",
|
||||
"editServer": "编辑服务端",
|
||||
"trafficStats": "流量统计",
|
||||
"realTimeLog": "实时日志",
|
||||
"console": "控制台",
|
||||
"editTunnel": "编辑隧道",
|
||||
"user": {
|
||||
"profile": "个人资料",
|
||||
"settings": "设置"
|
||||
@@ -153,7 +154,7 @@
|
||||
},
|
||||
"start": {
|
||||
"title": "启动命令",
|
||||
"description": "复制并运行以下命令来启动 frps",
|
||||
"description": "复制并运行以下命令来启动 frp-panel 服务端",
|
||||
"copy": "复制命令"
|
||||
},
|
||||
"actions_menu": {
|
||||
@@ -247,7 +248,7 @@
|
||||
},
|
||||
"start": {
|
||||
"title": "启动命令",
|
||||
"description": "复制并运行以下命令来启动 frpc",
|
||||
"description": "复制并运行以下命令来启动 frp-panel 客户端",
|
||||
"copy": "复制命令"
|
||||
},
|
||||
"actions_menu": {
|
||||
@@ -347,7 +348,38 @@
|
||||
"port_placeholder": "请输入端口号 (1-65535)",
|
||||
"ip_placeholder": "请输入IP地址 (例如: 127.0.0.1)",
|
||||
"subdomain_placeholder": "请输入子域名",
|
||||
"secret_placeholder": "请输入密钥"
|
||||
"secret_placeholder": "请输入密钥",
|
||||
"route": "路由"
|
||||
},
|
||||
"config": {
|
||||
"create": "创建",
|
||||
"create_success": "创建成功",
|
||||
"create_failed": "创建失败",
|
||||
"select_server": "选择服务器",
|
||||
"select_client": "选择客户端",
|
||||
"select_proxy_type": "选择隧道类型",
|
||||
"proxy_name": "隧道名称",
|
||||
"invalid_config": "配置不正确",
|
||||
"submit": "提交"
|
||||
},
|
||||
"action": {
|
||||
"delete_success": "删除成功",
|
||||
"delete_failed": "删除失败",
|
||||
"edit": "编辑",
|
||||
"delete": "删除",
|
||||
"delete_tunnel": "删除隧道",
|
||||
"delete_attention_title": "隧道将被永久删除,请确认",
|
||||
"delete_attention_description": "删除后将无法恢复,请谨慎操作",
|
||||
"delete_attention_confirm": "确认删除",
|
||||
"title": "隧道操作"
|
||||
},
|
||||
"item": {
|
||||
"client_id": "客户端ID",
|
||||
"proxy_name": "隧道名称",
|
||||
"proxy_type": "隧道类型",
|
||||
"server_id": "服务端ID",
|
||||
"status": "状态",
|
||||
"visit_preview": "访问预览"
|
||||
},
|
||||
"type": {
|
||||
"http": "HTTP",
|
||||
@@ -386,10 +418,10 @@
|
||||
},
|
||||
"frpc": {
|
||||
"form": {
|
||||
"title": "编辑隧道",
|
||||
"title": "编辑客户端",
|
||||
"description": {
|
||||
"warning": "注意⚠️:选择的「服务端」必须提前配置!",
|
||||
"instruction": "选择客户端和服务端以编辑隧道"
|
||||
"instruction": "选择客户端和服务端以配置"
|
||||
},
|
||||
"advanced": {
|
||||
"title": "高级模式",
|
||||
@@ -434,9 +466,13 @@
|
||||
}
|
||||
},
|
||||
"input": {
|
||||
"list": {
|
||||
"placeholder": "请输入...",
|
||||
"add": "添加"
|
||||
},
|
||||
"search": "搜索",
|
||||
"id": {
|
||||
"placeholder": "请输入ID"
|
||||
"keyword": {
|
||||
"placeholder": "请输入关键词"
|
||||
}
|
||||
},
|
||||
"table": {
|
||||
|
||||
@@ -1,24 +1,37 @@
|
||||
import * as z from 'zod'
|
||||
import { Client, Server } from './pb/common'
|
||||
import { GetPlatformInfoResponse } from './pb/api_user'
|
||||
import { TypedProxyConfig } from '@/types/proxy'
|
||||
|
||||
export const API_PATH = '/api/v1'
|
||||
export const SET_TOKEN_HEADER = 'x-set-authorization'
|
||||
export const X_CLIENT_REQUEST_ID = 'x-client-request-id'
|
||||
export const LOCAL_STORAGE_TOKEN_KEY = 'token'
|
||||
export const ZodPortSchema = z.coerce
|
||||
.number({required_error: 'validation.required'})
|
||||
.number({ required_error: 'validation.required' })
|
||||
.min(1, { message: 'validation.portRange.min' })
|
||||
.max(65535, { message: 'validation.portRange.max' })
|
||||
|
||||
export const ZodIPSchema = z.string({required_error: 'validation.required'})
|
||||
export const ZodIPSchema = z.string({ required_error: 'validation.required' })
|
||||
.regex(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/, { message: 'validation.ipAddress' })
|
||||
export const ZodStringSchema = z.string({required_error: 'validation.required'})
|
||||
export const ZodStringSchema = z.string({ required_error: 'validation.required' })
|
||||
.min(1, { message: 'validation.required' })
|
||||
export const ZodEmailSchema = z.string({required_error: 'validation.required'})
|
||||
export const ZodEmailSchema = z.string({ required_error: 'validation.required' })
|
||||
.min(1, { message: 'validation.required' })
|
||||
.email({ message: 'auth.email.invalid' })
|
||||
|
||||
export const TypedProxyConfigValid = (typedProxyCfg: TypedProxyConfig | undefined): boolean => {
|
||||
return (typedProxyCfg?.localPort && typedProxyCfg.localIP && typedProxyCfg.name && typedProxyCfg.type) ? true : false
|
||||
}
|
||||
|
||||
export const ClientConfigured = (client: Client | undefined): boolean => {
|
||||
if (client == undefined) {
|
||||
return false
|
||||
}
|
||||
return !((client.config == undefined || client.config == '') &&
|
||||
(client.clientIds == undefined || client.clientIds.length == 0))
|
||||
}
|
||||
|
||||
// .refine((e) => e === "abcd@fg.com", "This email is not in our database")
|
||||
|
||||
export const ExecCommandStr = <T extends Client | Server>(
|
||||
|
||||
@@ -10,6 +10,8 @@ import { UnknownFieldHandler } from "@protobuf-ts/runtime";
|
||||
import type { PartialMessage } from "@protobuf-ts/runtime";
|
||||
import { reflectionMergePartial } from "@protobuf-ts/runtime";
|
||||
import { MessageType } from "@protobuf-ts/runtime";
|
||||
import { ProxyWorkingStatus } from "./common";
|
||||
import { ProxyConfig } from "./common";
|
||||
import { ProxyInfo } from "./common";
|
||||
import { Client } from "./common";
|
||||
import { Status } from "./common";
|
||||
@@ -77,6 +79,10 @@ export interface GetClientRequest {
|
||||
* @generated from protobuf field: optional string client_id = 1;
|
||||
*/
|
||||
clientId?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string server_id = 2;
|
||||
*/
|
||||
serverId?: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message api_client.GetClientResponse
|
||||
@@ -194,18 +200,18 @@ export interface StartFRPCResponse {
|
||||
status?: Status;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message api_client.GetProxyByCIDRequest
|
||||
* @generated from protobuf message api_client.GetProxyStatsByClientIDRequest
|
||||
*/
|
||||
export interface GetProxyByCIDRequest {
|
||||
export interface GetProxyStatsByClientIDRequest {
|
||||
/**
|
||||
* @generated from protobuf field: optional string client_id = 1;
|
||||
*/
|
||||
clientId?: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message api_client.GetProxyByCIDResponse
|
||||
* @generated from protobuf message api_client.GetProxyStatsByClientIDResponse
|
||||
*/
|
||||
export interface GetProxyByCIDResponse {
|
||||
export interface GetProxyStatsByClientIDResponse {
|
||||
/**
|
||||
* @generated from protobuf field: optional common.Status status = 1;
|
||||
*/
|
||||
@@ -215,6 +221,168 @@ export interface GetProxyByCIDResponse {
|
||||
*/
|
||||
proxyInfos: ProxyInfo[];
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message api_client.ListProxyConfigsRequest
|
||||
*/
|
||||
export interface ListProxyConfigsRequest {
|
||||
/**
|
||||
* @generated from protobuf field: optional int32 page = 1;
|
||||
*/
|
||||
page?: number;
|
||||
/**
|
||||
* @generated from protobuf field: optional int32 page_size = 2;
|
||||
*/
|
||||
pageSize?: number;
|
||||
/**
|
||||
* @generated from protobuf field: optional string keyword = 3;
|
||||
*/
|
||||
keyword?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string client_id = 4;
|
||||
*/
|
||||
clientId?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string server_id = 5;
|
||||
*/
|
||||
serverId?: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message api_client.ListProxyConfigsResponse
|
||||
*/
|
||||
export interface ListProxyConfigsResponse {
|
||||
/**
|
||||
* @generated from protobuf field: optional common.Status status = 1;
|
||||
*/
|
||||
status?: Status;
|
||||
/**
|
||||
* @generated from protobuf field: optional int32 total = 2;
|
||||
*/
|
||||
total?: number;
|
||||
/**
|
||||
* @generated from protobuf field: repeated common.ProxyConfig proxy_configs = 3;
|
||||
*/
|
||||
proxyConfigs: ProxyConfig[];
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message api_client.CreateProxyConfigRequest
|
||||
*/
|
||||
export interface CreateProxyConfigRequest {
|
||||
/**
|
||||
* @generated from protobuf field: optional string client_id = 1;
|
||||
*/
|
||||
clientId?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string server_id = 2;
|
||||
*/
|
||||
serverId?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional bytes config = 3;
|
||||
*/
|
||||
config?: Uint8Array;
|
||||
/**
|
||||
* @generated from protobuf field: optional bool overwrite = 4;
|
||||
*/
|
||||
overwrite?: boolean;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message api_client.CreateProxyConfigResponse
|
||||
*/
|
||||
export interface CreateProxyConfigResponse {
|
||||
/**
|
||||
* @generated from protobuf field: optional common.Status status = 1;
|
||||
*/
|
||||
status?: Status;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message api_client.DeleteProxyConfigRequest
|
||||
*/
|
||||
export interface DeleteProxyConfigRequest {
|
||||
/**
|
||||
* @generated from protobuf field: optional string client_id = 1;
|
||||
*/
|
||||
clientId?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string server_id = 2;
|
||||
*/
|
||||
serverId?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string name = 3;
|
||||
*/
|
||||
name?: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message api_client.DeleteProxyConfigResponse
|
||||
*/
|
||||
export interface DeleteProxyConfigResponse {
|
||||
/**
|
||||
* @generated from protobuf field: optional common.Status status = 1;
|
||||
*/
|
||||
status?: Status;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message api_client.UpdateProxyConfigRequest
|
||||
*/
|
||||
export interface UpdateProxyConfigRequest {
|
||||
/**
|
||||
* @generated from protobuf field: optional string client_id = 1;
|
||||
*/
|
||||
clientId?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string server_id = 2;
|
||||
*/
|
||||
serverId?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string name = 3;
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional bytes config = 4;
|
||||
*/
|
||||
config?: Uint8Array;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message api_client.UpdateProxyConfigResponse
|
||||
*/
|
||||
export interface UpdateProxyConfigResponse {
|
||||
/**
|
||||
* @generated from protobuf field: optional common.Status status = 1;
|
||||
*/
|
||||
status?: Status;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message api_client.GetProxyConfigRequest
|
||||
*/
|
||||
export interface GetProxyConfigRequest {
|
||||
/**
|
||||
* @generated from protobuf field: optional string client_id = 1;
|
||||
*/
|
||||
clientId?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string server_id = 2;
|
||||
*/
|
||||
serverId?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string name = 3;
|
||||
*/
|
||||
name?: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message api_client.GetProxyConfigResponse
|
||||
*/
|
||||
export interface GetProxyConfigResponse {
|
||||
/**
|
||||
* @generated from protobuf field: optional common.Status status = 1;
|
||||
*/
|
||||
status?: Status;
|
||||
/**
|
||||
* @generated from protobuf field: optional common.ProxyConfig proxy_config = 2;
|
||||
*/
|
||||
proxyConfig?: ProxyConfig;
|
||||
/**
|
||||
* @generated from protobuf field: optional common.ProxyWorkingStatus working_status = 3;
|
||||
*/
|
||||
workingStatus?: ProxyWorkingStatus;
|
||||
}
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class InitClientRequest$Type extends MessageType<InitClientRequest> {
|
||||
constructor() {
|
||||
@@ -439,7 +607,8 @@ export const ListClientsResponse = new ListClientsResponse$Type();
|
||||
class GetClientRequest$Type extends MessageType<GetClientRequest> {
|
||||
constructor() {
|
||||
super("api_client.GetClientRequest", [
|
||||
{ no: 1, name: "client_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ }
|
||||
{ no: 1, name: "client_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 2, name: "server_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<GetClientRequest>): GetClientRequest {
|
||||
@@ -456,6 +625,9 @@ class GetClientRequest$Type extends MessageType<GetClientRequest> {
|
||||
case /* optional string client_id */ 1:
|
||||
message.clientId = reader.string();
|
||||
break;
|
||||
case /* optional string server_id */ 2:
|
||||
message.serverId = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
@@ -471,6 +643,9 @@ class GetClientRequest$Type extends MessageType<GetClientRequest> {
|
||||
/* optional string client_id = 1; */
|
||||
if (message.clientId !== undefined)
|
||||
writer.tag(1, WireType.LengthDelimited).string(message.clientId);
|
||||
/* optional string server_id = 2; */
|
||||
if (message.serverId !== undefined)
|
||||
writer.tag(2, WireType.LengthDelimited).string(message.serverId);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
@@ -1016,19 +1191,19 @@ class StartFRPCResponse$Type extends MessageType<StartFRPCResponse> {
|
||||
*/
|
||||
export const StartFRPCResponse = new StartFRPCResponse$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class GetProxyByCIDRequest$Type extends MessageType<GetProxyByCIDRequest> {
|
||||
class GetProxyStatsByClientIDRequest$Type extends MessageType<GetProxyStatsByClientIDRequest> {
|
||||
constructor() {
|
||||
super("api_client.GetProxyByCIDRequest", [
|
||||
super("api_client.GetProxyStatsByClientIDRequest", [
|
||||
{ no: 1, name: "client_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<GetProxyByCIDRequest>): GetProxyByCIDRequest {
|
||||
create(value?: PartialMessage<GetProxyStatsByClientIDRequest>): GetProxyStatsByClientIDRequest {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<GetProxyByCIDRequest>(this, message, value);
|
||||
reflectionMergePartial<GetProxyStatsByClientIDRequest>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GetProxyByCIDRequest): GetProxyByCIDRequest {
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GetProxyStatsByClientIDRequest): GetProxyStatsByClientIDRequest {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
@@ -1047,7 +1222,7 @@ class GetProxyByCIDRequest$Type extends MessageType<GetProxyByCIDRequest> {
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: GetProxyByCIDRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
internalBinaryWrite(message: GetProxyStatsByClientIDRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* optional string client_id = 1; */
|
||||
if (message.clientId !== undefined)
|
||||
writer.tag(1, WireType.LengthDelimited).string(message.clientId);
|
||||
@@ -1058,25 +1233,25 @@ class GetProxyByCIDRequest$Type extends MessageType<GetProxyByCIDRequest> {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message api_client.GetProxyByCIDRequest
|
||||
* @generated MessageType for protobuf message api_client.GetProxyStatsByClientIDRequest
|
||||
*/
|
||||
export const GetProxyByCIDRequest = new GetProxyByCIDRequest$Type();
|
||||
export const GetProxyStatsByClientIDRequest = new GetProxyStatsByClientIDRequest$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class GetProxyByCIDResponse$Type extends MessageType<GetProxyByCIDResponse> {
|
||||
class GetProxyStatsByClientIDResponse$Type extends MessageType<GetProxyStatsByClientIDResponse> {
|
||||
constructor() {
|
||||
super("api_client.GetProxyByCIDResponse", [
|
||||
super("api_client.GetProxyStatsByClientIDResponse", [
|
||||
{ no: 1, name: "status", kind: "message", T: () => Status },
|
||||
{ no: 2, name: "proxy_infos", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => ProxyInfo }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<GetProxyByCIDResponse>): GetProxyByCIDResponse {
|
||||
create(value?: PartialMessage<GetProxyStatsByClientIDResponse>): GetProxyStatsByClientIDResponse {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.proxyInfos = [];
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<GetProxyByCIDResponse>(this, message, value);
|
||||
reflectionMergePartial<GetProxyStatsByClientIDResponse>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GetProxyByCIDResponse): GetProxyByCIDResponse {
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GetProxyStatsByClientIDResponse): GetProxyStatsByClientIDResponse {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
@@ -1098,7 +1273,7 @@ class GetProxyByCIDResponse$Type extends MessageType<GetProxyByCIDResponse> {
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: GetProxyByCIDResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
internalBinaryWrite(message: GetProxyStatsByClientIDResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* optional common.Status status = 1; */
|
||||
if (message.status)
|
||||
Status.internalBinaryWrite(message.status, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
||||
@@ -1112,6 +1287,593 @@ class GetProxyByCIDResponse$Type extends MessageType<GetProxyByCIDResponse> {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message api_client.GetProxyByCIDResponse
|
||||
* @generated MessageType for protobuf message api_client.GetProxyStatsByClientIDResponse
|
||||
*/
|
||||
export const GetProxyByCIDResponse = new GetProxyByCIDResponse$Type();
|
||||
export const GetProxyStatsByClientIDResponse = new GetProxyStatsByClientIDResponse$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class ListProxyConfigsRequest$Type extends MessageType<ListProxyConfigsRequest> {
|
||||
constructor() {
|
||||
super("api_client.ListProxyConfigsRequest", [
|
||||
{ no: 1, name: "page", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ },
|
||||
{ no: 2, name: "page_size", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ },
|
||||
{ no: 3, name: "keyword", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 4, name: "client_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 5, name: "server_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<ListProxyConfigsRequest>): ListProxyConfigsRequest {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<ListProxyConfigsRequest>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ListProxyConfigsRequest): ListProxyConfigsRequest {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* optional int32 page */ 1:
|
||||
message.page = reader.int32();
|
||||
break;
|
||||
case /* optional int32 page_size */ 2:
|
||||
message.pageSize = reader.int32();
|
||||
break;
|
||||
case /* optional string keyword */ 3:
|
||||
message.keyword = reader.string();
|
||||
break;
|
||||
case /* optional string client_id */ 4:
|
||||
message.clientId = reader.string();
|
||||
break;
|
||||
case /* optional string server_id */ 5:
|
||||
message.serverId = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: ListProxyConfigsRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* optional int32 page = 1; */
|
||||
if (message.page !== undefined)
|
||||
writer.tag(1, WireType.Varint).int32(message.page);
|
||||
/* optional int32 page_size = 2; */
|
||||
if (message.pageSize !== undefined)
|
||||
writer.tag(2, WireType.Varint).int32(message.pageSize);
|
||||
/* optional string keyword = 3; */
|
||||
if (message.keyword !== undefined)
|
||||
writer.tag(3, WireType.LengthDelimited).string(message.keyword);
|
||||
/* optional string client_id = 4; */
|
||||
if (message.clientId !== undefined)
|
||||
writer.tag(4, WireType.LengthDelimited).string(message.clientId);
|
||||
/* optional string server_id = 5; */
|
||||
if (message.serverId !== undefined)
|
||||
writer.tag(5, WireType.LengthDelimited).string(message.serverId);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message api_client.ListProxyConfigsRequest
|
||||
*/
|
||||
export const ListProxyConfigsRequest = new ListProxyConfigsRequest$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class ListProxyConfigsResponse$Type extends MessageType<ListProxyConfigsResponse> {
|
||||
constructor() {
|
||||
super("api_client.ListProxyConfigsResponse", [
|
||||
{ no: 1, name: "status", kind: "message", T: () => Status },
|
||||
{ no: 2, name: "total", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ },
|
||||
{ no: 3, name: "proxy_configs", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => ProxyConfig }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<ListProxyConfigsResponse>): ListProxyConfigsResponse {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.proxyConfigs = [];
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<ListProxyConfigsResponse>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ListProxyConfigsResponse): ListProxyConfigsResponse {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* optional common.Status status */ 1:
|
||||
message.status = Status.internalBinaryRead(reader, reader.uint32(), options, message.status);
|
||||
break;
|
||||
case /* optional int32 total */ 2:
|
||||
message.total = reader.int32();
|
||||
break;
|
||||
case /* repeated common.ProxyConfig proxy_configs */ 3:
|
||||
message.proxyConfigs.push(ProxyConfig.internalBinaryRead(reader, reader.uint32(), options));
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: ListProxyConfigsResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* optional common.Status status = 1; */
|
||||
if (message.status)
|
||||
Status.internalBinaryWrite(message.status, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
||||
/* optional int32 total = 2; */
|
||||
if (message.total !== undefined)
|
||||
writer.tag(2, WireType.Varint).int32(message.total);
|
||||
/* repeated common.ProxyConfig proxy_configs = 3; */
|
||||
for (let i = 0; i < message.proxyConfigs.length; i++)
|
||||
ProxyConfig.internalBinaryWrite(message.proxyConfigs[i], writer.tag(3, WireType.LengthDelimited).fork(), options).join();
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message api_client.ListProxyConfigsResponse
|
||||
*/
|
||||
export const ListProxyConfigsResponse = new ListProxyConfigsResponse$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class CreateProxyConfigRequest$Type extends MessageType<CreateProxyConfigRequest> {
|
||||
constructor() {
|
||||
super("api_client.CreateProxyConfigRequest", [
|
||||
{ no: 1, name: "client_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 2, name: "server_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 3, name: "config", kind: "scalar", opt: true, T: 12 /*ScalarType.BYTES*/ },
|
||||
{ no: 4, name: "overwrite", kind: "scalar", opt: true, T: 8 /*ScalarType.BOOL*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<CreateProxyConfigRequest>): CreateProxyConfigRequest {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<CreateProxyConfigRequest>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: CreateProxyConfigRequest): CreateProxyConfigRequest {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* optional string client_id */ 1:
|
||||
message.clientId = reader.string();
|
||||
break;
|
||||
case /* optional string server_id */ 2:
|
||||
message.serverId = reader.string();
|
||||
break;
|
||||
case /* optional bytes config */ 3:
|
||||
message.config = reader.bytes();
|
||||
break;
|
||||
case /* optional bool overwrite */ 4:
|
||||
message.overwrite = reader.bool();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: CreateProxyConfigRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* optional string client_id = 1; */
|
||||
if (message.clientId !== undefined)
|
||||
writer.tag(1, WireType.LengthDelimited).string(message.clientId);
|
||||
/* optional string server_id = 2; */
|
||||
if (message.serverId !== undefined)
|
||||
writer.tag(2, WireType.LengthDelimited).string(message.serverId);
|
||||
/* optional bytes config = 3; */
|
||||
if (message.config !== undefined)
|
||||
writer.tag(3, WireType.LengthDelimited).bytes(message.config);
|
||||
/* optional bool overwrite = 4; */
|
||||
if (message.overwrite !== undefined)
|
||||
writer.tag(4, WireType.Varint).bool(message.overwrite);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message api_client.CreateProxyConfigRequest
|
||||
*/
|
||||
export const CreateProxyConfigRequest = new CreateProxyConfigRequest$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class CreateProxyConfigResponse$Type extends MessageType<CreateProxyConfigResponse> {
|
||||
constructor() {
|
||||
super("api_client.CreateProxyConfigResponse", [
|
||||
{ no: 1, name: "status", kind: "message", T: () => Status }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<CreateProxyConfigResponse>): CreateProxyConfigResponse {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<CreateProxyConfigResponse>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: CreateProxyConfigResponse): CreateProxyConfigResponse {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* optional common.Status status */ 1:
|
||||
message.status = Status.internalBinaryRead(reader, reader.uint32(), options, message.status);
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: CreateProxyConfigResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* optional common.Status status = 1; */
|
||||
if (message.status)
|
||||
Status.internalBinaryWrite(message.status, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message api_client.CreateProxyConfigResponse
|
||||
*/
|
||||
export const CreateProxyConfigResponse = new CreateProxyConfigResponse$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class DeleteProxyConfigRequest$Type extends MessageType<DeleteProxyConfigRequest> {
|
||||
constructor() {
|
||||
super("api_client.DeleteProxyConfigRequest", [
|
||||
{ no: 1, name: "client_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 2, name: "server_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 3, name: "name", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<DeleteProxyConfigRequest>): DeleteProxyConfigRequest {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<DeleteProxyConfigRequest>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DeleteProxyConfigRequest): DeleteProxyConfigRequest {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* optional string client_id */ 1:
|
||||
message.clientId = reader.string();
|
||||
break;
|
||||
case /* optional string server_id */ 2:
|
||||
message.serverId = reader.string();
|
||||
break;
|
||||
case /* optional string name */ 3:
|
||||
message.name = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: DeleteProxyConfigRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* optional string client_id = 1; */
|
||||
if (message.clientId !== undefined)
|
||||
writer.tag(1, WireType.LengthDelimited).string(message.clientId);
|
||||
/* optional string server_id = 2; */
|
||||
if (message.serverId !== undefined)
|
||||
writer.tag(2, WireType.LengthDelimited).string(message.serverId);
|
||||
/* optional string name = 3; */
|
||||
if (message.name !== undefined)
|
||||
writer.tag(3, WireType.LengthDelimited).string(message.name);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message api_client.DeleteProxyConfigRequest
|
||||
*/
|
||||
export const DeleteProxyConfigRequest = new DeleteProxyConfigRequest$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class DeleteProxyConfigResponse$Type extends MessageType<DeleteProxyConfigResponse> {
|
||||
constructor() {
|
||||
super("api_client.DeleteProxyConfigResponse", [
|
||||
{ no: 1, name: "status", kind: "message", T: () => Status }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<DeleteProxyConfigResponse>): DeleteProxyConfigResponse {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<DeleteProxyConfigResponse>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DeleteProxyConfigResponse): DeleteProxyConfigResponse {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* optional common.Status status */ 1:
|
||||
message.status = Status.internalBinaryRead(reader, reader.uint32(), options, message.status);
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: DeleteProxyConfigResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* optional common.Status status = 1; */
|
||||
if (message.status)
|
||||
Status.internalBinaryWrite(message.status, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message api_client.DeleteProxyConfigResponse
|
||||
*/
|
||||
export const DeleteProxyConfigResponse = new DeleteProxyConfigResponse$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class UpdateProxyConfigRequest$Type extends MessageType<UpdateProxyConfigRequest> {
|
||||
constructor() {
|
||||
super("api_client.UpdateProxyConfigRequest", [
|
||||
{ no: 1, name: "client_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 2, name: "server_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 3, name: "name", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 4, name: "config", kind: "scalar", opt: true, T: 12 /*ScalarType.BYTES*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<UpdateProxyConfigRequest>): UpdateProxyConfigRequest {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<UpdateProxyConfigRequest>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: UpdateProxyConfigRequest): UpdateProxyConfigRequest {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* optional string client_id */ 1:
|
||||
message.clientId = reader.string();
|
||||
break;
|
||||
case /* optional string server_id */ 2:
|
||||
message.serverId = reader.string();
|
||||
break;
|
||||
case /* optional string name */ 3:
|
||||
message.name = reader.string();
|
||||
break;
|
||||
case /* optional bytes config */ 4:
|
||||
message.config = reader.bytes();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: UpdateProxyConfigRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* optional string client_id = 1; */
|
||||
if (message.clientId !== undefined)
|
||||
writer.tag(1, WireType.LengthDelimited).string(message.clientId);
|
||||
/* optional string server_id = 2; */
|
||||
if (message.serverId !== undefined)
|
||||
writer.tag(2, WireType.LengthDelimited).string(message.serverId);
|
||||
/* optional string name = 3; */
|
||||
if (message.name !== undefined)
|
||||
writer.tag(3, WireType.LengthDelimited).string(message.name);
|
||||
/* optional bytes config = 4; */
|
||||
if (message.config !== undefined)
|
||||
writer.tag(4, WireType.LengthDelimited).bytes(message.config);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message api_client.UpdateProxyConfigRequest
|
||||
*/
|
||||
export const UpdateProxyConfigRequest = new UpdateProxyConfigRequest$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class UpdateProxyConfigResponse$Type extends MessageType<UpdateProxyConfigResponse> {
|
||||
constructor() {
|
||||
super("api_client.UpdateProxyConfigResponse", [
|
||||
{ no: 1, name: "status", kind: "message", T: () => Status }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<UpdateProxyConfigResponse>): UpdateProxyConfigResponse {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<UpdateProxyConfigResponse>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: UpdateProxyConfigResponse): UpdateProxyConfigResponse {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* optional common.Status status */ 1:
|
||||
message.status = Status.internalBinaryRead(reader, reader.uint32(), options, message.status);
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: UpdateProxyConfigResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* optional common.Status status = 1; */
|
||||
if (message.status)
|
||||
Status.internalBinaryWrite(message.status, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message api_client.UpdateProxyConfigResponse
|
||||
*/
|
||||
export const UpdateProxyConfigResponse = new UpdateProxyConfigResponse$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class GetProxyConfigRequest$Type extends MessageType<GetProxyConfigRequest> {
|
||||
constructor() {
|
||||
super("api_client.GetProxyConfigRequest", [
|
||||
{ no: 1, name: "client_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 2, name: "server_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 3, name: "name", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<GetProxyConfigRequest>): GetProxyConfigRequest {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<GetProxyConfigRequest>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GetProxyConfigRequest): GetProxyConfigRequest {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* optional string client_id */ 1:
|
||||
message.clientId = reader.string();
|
||||
break;
|
||||
case /* optional string server_id */ 2:
|
||||
message.serverId = reader.string();
|
||||
break;
|
||||
case /* optional string name */ 3:
|
||||
message.name = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: GetProxyConfigRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* optional string client_id = 1; */
|
||||
if (message.clientId !== undefined)
|
||||
writer.tag(1, WireType.LengthDelimited).string(message.clientId);
|
||||
/* optional string server_id = 2; */
|
||||
if (message.serverId !== undefined)
|
||||
writer.tag(2, WireType.LengthDelimited).string(message.serverId);
|
||||
/* optional string name = 3; */
|
||||
if (message.name !== undefined)
|
||||
writer.tag(3, WireType.LengthDelimited).string(message.name);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message api_client.GetProxyConfigRequest
|
||||
*/
|
||||
export const GetProxyConfigRequest = new GetProxyConfigRequest$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class GetProxyConfigResponse$Type extends MessageType<GetProxyConfigResponse> {
|
||||
constructor() {
|
||||
super("api_client.GetProxyConfigResponse", [
|
||||
{ no: 1, name: "status", kind: "message", T: () => Status },
|
||||
{ no: 2, name: "proxy_config", kind: "message", T: () => ProxyConfig },
|
||||
{ no: 3, name: "working_status", kind: "message", T: () => ProxyWorkingStatus }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<GetProxyConfigResponse>): GetProxyConfigResponse {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<GetProxyConfigResponse>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GetProxyConfigResponse): GetProxyConfigResponse {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* optional common.Status status */ 1:
|
||||
message.status = Status.internalBinaryRead(reader, reader.uint32(), options, message.status);
|
||||
break;
|
||||
case /* optional common.ProxyConfig proxy_config */ 2:
|
||||
message.proxyConfig = ProxyConfig.internalBinaryRead(reader, reader.uint32(), options, message.proxyConfig);
|
||||
break;
|
||||
case /* optional common.ProxyWorkingStatus working_status */ 3:
|
||||
message.workingStatus = ProxyWorkingStatus.internalBinaryRead(reader, reader.uint32(), options, message.workingStatus);
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: GetProxyConfigResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* optional common.Status status = 1; */
|
||||
if (message.status)
|
||||
Status.internalBinaryWrite(message.status, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
||||
/* optional common.ProxyConfig proxy_config = 2; */
|
||||
if (message.proxyConfig)
|
||||
ProxyConfig.internalBinaryWrite(message.proxyConfig, writer.tag(2, WireType.LengthDelimited).fork(), options).join();
|
||||
/* optional common.ProxyWorkingStatus working_status = 3; */
|
||||
if (message.workingStatus)
|
||||
ProxyWorkingStatus.internalBinaryWrite(message.workingStatus, writer.tag(3, WireType.LengthDelimited).fork(), options).join();
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message api_client.GetProxyConfigResponse
|
||||
*/
|
||||
export const GetProxyConfigResponse = new GetProxyConfigResponse$Type();
|
||||
|
||||
@@ -41,9 +41,9 @@ export interface ClientStatus {
|
||||
*/
|
||||
addr?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional int32 connect_time = 7;
|
||||
* @generated from protobuf field: optional int64 connect_time = 7;
|
||||
*/
|
||||
connectTime?: number; // 连接建立的时间
|
||||
connectTime?: bigint; // 连接建立的时间
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf enum api_master.ClientStatus.Status
|
||||
@@ -163,7 +163,7 @@ class ClientStatus$Type extends MessageType<ClientStatus> {
|
||||
{ no: 4, name: "ping", kind: "scalar", T: 5 /*ScalarType.INT32*/ },
|
||||
{ no: 5, name: "version", kind: "message", T: () => ClientVersion },
|
||||
{ no: 6, name: "addr", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 7, name: "connect_time", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ }
|
||||
{ no: 7, name: "connect_time", kind: "scalar", opt: true, T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<ClientStatus>): ClientStatus {
|
||||
@@ -199,8 +199,8 @@ class ClientStatus$Type extends MessageType<ClientStatus> {
|
||||
case /* optional string addr */ 6:
|
||||
message.addr = reader.string();
|
||||
break;
|
||||
case /* optional int32 connect_time */ 7:
|
||||
message.connectTime = reader.int32();
|
||||
case /* optional int64 connect_time */ 7:
|
||||
message.connectTime = reader.int64().toBigInt();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
@@ -232,9 +232,9 @@ class ClientStatus$Type extends MessageType<ClientStatus> {
|
||||
/* optional string addr = 6; */
|
||||
if (message.addr !== undefined)
|
||||
writer.tag(6, WireType.LengthDelimited).string(message.addr);
|
||||
/* optional int32 connect_time = 7; */
|
||||
/* optional int64 connect_time = 7; */
|
||||
if (message.connectTime !== undefined)
|
||||
writer.tag(7, WireType.Varint).int32(message.connectTime);
|
||||
writer.tag(7, WireType.Varint).int64(message.connectTime);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
|
||||
@@ -202,18 +202,18 @@ export interface StartFRPSResponse {
|
||||
status?: Status;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message api_server.GetProxyBySIDRequest
|
||||
* @generated from protobuf message api_server.GetProxyStatsByServerIDRequest
|
||||
*/
|
||||
export interface GetProxyBySIDRequest {
|
||||
export interface GetProxyStatsByServerIDRequest {
|
||||
/**
|
||||
* @generated from protobuf field: optional string server_id = 1;
|
||||
*/
|
||||
serverId?: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message api_server.GetProxyBySIDResponse
|
||||
* @generated from protobuf message api_server.GetProxyStatsByServerIDResponse
|
||||
*/
|
||||
export interface GetProxyBySIDResponse {
|
||||
export interface GetProxyStatsByServerIDResponse {
|
||||
/**
|
||||
* @generated from protobuf field: optional common.Status status = 1;
|
||||
*/
|
||||
@@ -1038,19 +1038,19 @@ class StartFRPSResponse$Type extends MessageType<StartFRPSResponse> {
|
||||
*/
|
||||
export const StartFRPSResponse = new StartFRPSResponse$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class GetProxyBySIDRequest$Type extends MessageType<GetProxyBySIDRequest> {
|
||||
class GetProxyStatsByServerIDRequest$Type extends MessageType<GetProxyStatsByServerIDRequest> {
|
||||
constructor() {
|
||||
super("api_server.GetProxyBySIDRequest", [
|
||||
super("api_server.GetProxyStatsByServerIDRequest", [
|
||||
{ no: 1, name: "server_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<GetProxyBySIDRequest>): GetProxyBySIDRequest {
|
||||
create(value?: PartialMessage<GetProxyStatsByServerIDRequest>): GetProxyStatsByServerIDRequest {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<GetProxyBySIDRequest>(this, message, value);
|
||||
reflectionMergePartial<GetProxyStatsByServerIDRequest>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GetProxyBySIDRequest): GetProxyBySIDRequest {
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GetProxyStatsByServerIDRequest): GetProxyStatsByServerIDRequest {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
@@ -1069,7 +1069,7 @@ class GetProxyBySIDRequest$Type extends MessageType<GetProxyBySIDRequest> {
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: GetProxyBySIDRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
internalBinaryWrite(message: GetProxyStatsByServerIDRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* optional string server_id = 1; */
|
||||
if (message.serverId !== undefined)
|
||||
writer.tag(1, WireType.LengthDelimited).string(message.serverId);
|
||||
@@ -1080,25 +1080,25 @@ class GetProxyBySIDRequest$Type extends MessageType<GetProxyBySIDRequest> {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message api_server.GetProxyBySIDRequest
|
||||
* @generated MessageType for protobuf message api_server.GetProxyStatsByServerIDRequest
|
||||
*/
|
||||
export const GetProxyBySIDRequest = new GetProxyBySIDRequest$Type();
|
||||
export const GetProxyStatsByServerIDRequest = new GetProxyStatsByServerIDRequest$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class GetProxyBySIDResponse$Type extends MessageType<GetProxyBySIDResponse> {
|
||||
class GetProxyStatsByServerIDResponse$Type extends MessageType<GetProxyStatsByServerIDResponse> {
|
||||
constructor() {
|
||||
super("api_server.GetProxyBySIDResponse", [
|
||||
super("api_server.GetProxyStatsByServerIDResponse", [
|
||||
{ no: 1, name: "status", kind: "message", T: () => Status },
|
||||
{ no: 2, name: "proxy_infos", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => ProxyInfo }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<GetProxyBySIDResponse>): GetProxyBySIDResponse {
|
||||
create(value?: PartialMessage<GetProxyStatsByServerIDResponse>): GetProxyStatsByServerIDResponse {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.proxyInfos = [];
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<GetProxyBySIDResponse>(this, message, value);
|
||||
reflectionMergePartial<GetProxyStatsByServerIDResponse>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GetProxyBySIDResponse): GetProxyBySIDResponse {
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GetProxyStatsByServerIDResponse): GetProxyStatsByServerIDResponse {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
@@ -1120,7 +1120,7 @@ class GetProxyBySIDResponse$Type extends MessageType<GetProxyBySIDResponse> {
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: GetProxyBySIDResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
internalBinaryWrite(message: GetProxyStatsByServerIDResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* optional common.Status status = 1; */
|
||||
if (message.status)
|
||||
Status.internalBinaryWrite(message.status, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
||||
@@ -1134,6 +1134,6 @@ class GetProxyBySIDResponse$Type extends MessageType<GetProxyBySIDResponse> {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message api_server.GetProxyBySIDResponse
|
||||
* @generated MessageType for protobuf message api_server.GetProxyStatsByServerIDResponse
|
||||
*/
|
||||
export const GetProxyBySIDResponse = new GetProxyBySIDResponse$Type();
|
||||
export const GetProxyStatsByServerIDResponse = new GetProxyStatsByServerIDResponse$Type();
|
||||
|
||||
@@ -73,6 +73,14 @@ export interface Client {
|
||||
* @generated from protobuf field: optional bool stopped = 7;
|
||||
*/
|
||||
stopped?: boolean;
|
||||
/**
|
||||
* @generated from protobuf field: repeated string client_ids = 8;
|
||||
*/
|
||||
clientIds: string[]; // some client can connected to more than one server, make a shadow client to handle this
|
||||
/**
|
||||
* @generated from protobuf field: optional string origin_client_id = 9;
|
||||
*/
|
||||
originClientId?: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message common.Server
|
||||
@@ -177,6 +185,64 @@ export interface ProxyInfo {
|
||||
*/
|
||||
firstSync?: boolean;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message common.ProxyConfig
|
||||
*/
|
||||
export interface ProxyConfig {
|
||||
/**
|
||||
* @generated from protobuf field: optional uint32 id = 1;
|
||||
*/
|
||||
id?: number;
|
||||
/**
|
||||
* @generated from protobuf field: optional string name = 2;
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string type = 3;
|
||||
*/
|
||||
type?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string client_id = 4;
|
||||
*/
|
||||
clientId?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string server_id = 5;
|
||||
*/
|
||||
serverId?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string config = 6;
|
||||
*/
|
||||
config?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string origin_client_id = 7;
|
||||
*/
|
||||
originClientId?: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message common.ProxyWorkingStatus
|
||||
*/
|
||||
export interface ProxyWorkingStatus {
|
||||
/**
|
||||
* @generated from protobuf field: optional string name = 1;
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string type = 2;
|
||||
*/
|
||||
type?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string status = 3;
|
||||
*/
|
||||
status?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string err = 4;
|
||||
*/
|
||||
err?: string;
|
||||
/**
|
||||
* @generated from protobuf field: optional string remote_addr = 5;
|
||||
*/
|
||||
remoteAddr?: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf enum common.RespCode
|
||||
*/
|
||||
@@ -390,11 +456,14 @@ class Client$Type extends MessageType<Client> {
|
||||
{ no: 3, name: "config", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 5, name: "comment", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 6, name: "server_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 7, name: "stopped", kind: "scalar", opt: true, T: 8 /*ScalarType.BOOL*/ }
|
||||
{ no: 7, name: "stopped", kind: "scalar", opt: true, T: 8 /*ScalarType.BOOL*/ },
|
||||
{ no: 8, name: "client_ids", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 9, name: "origin_client_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<Client>): Client {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.clientIds = [];
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<Client>(this, message, value);
|
||||
return message;
|
||||
@@ -422,6 +491,12 @@ class Client$Type extends MessageType<Client> {
|
||||
case /* optional bool stopped */ 7:
|
||||
message.stopped = reader.bool();
|
||||
break;
|
||||
case /* repeated string client_ids */ 8:
|
||||
message.clientIds.push(reader.string());
|
||||
break;
|
||||
case /* optional string origin_client_id */ 9:
|
||||
message.originClientId = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
@@ -452,6 +527,12 @@ class Client$Type extends MessageType<Client> {
|
||||
/* optional bool stopped = 7; */
|
||||
if (message.stopped !== undefined)
|
||||
writer.tag(7, WireType.Varint).bool(message.stopped);
|
||||
/* repeated string client_ids = 8; */
|
||||
for (let i = 0; i < message.clientIds.length; i++)
|
||||
writer.tag(8, WireType.LengthDelimited).string(message.clientIds[i]);
|
||||
/* optional string origin_client_id = 9; */
|
||||
if (message.originClientId !== undefined)
|
||||
writer.tag(9, WireType.LengthDelimited).string(message.originClientId);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
@@ -733,3 +814,165 @@ class ProxyInfo$Type extends MessageType<ProxyInfo> {
|
||||
* @generated MessageType for protobuf message common.ProxyInfo
|
||||
*/
|
||||
export const ProxyInfo = new ProxyInfo$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class ProxyConfig$Type extends MessageType<ProxyConfig> {
|
||||
constructor() {
|
||||
super("common.ProxyConfig", [
|
||||
{ no: 1, name: "id", kind: "scalar", opt: true, T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 2, name: "name", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 3, name: "type", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 4, name: "client_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 5, name: "server_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 6, name: "config", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 7, name: "origin_client_id", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<ProxyConfig>): ProxyConfig {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<ProxyConfig>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProxyConfig): ProxyConfig {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* optional uint32 id */ 1:
|
||||
message.id = reader.uint32();
|
||||
break;
|
||||
case /* optional string name */ 2:
|
||||
message.name = reader.string();
|
||||
break;
|
||||
case /* optional string type */ 3:
|
||||
message.type = reader.string();
|
||||
break;
|
||||
case /* optional string client_id */ 4:
|
||||
message.clientId = reader.string();
|
||||
break;
|
||||
case /* optional string server_id */ 5:
|
||||
message.serverId = reader.string();
|
||||
break;
|
||||
case /* optional string config */ 6:
|
||||
message.config = reader.string();
|
||||
break;
|
||||
case /* optional string origin_client_id */ 7:
|
||||
message.originClientId = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: ProxyConfig, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* optional uint32 id = 1; */
|
||||
if (message.id !== undefined)
|
||||
writer.tag(1, WireType.Varint).uint32(message.id);
|
||||
/* optional string name = 2; */
|
||||
if (message.name !== undefined)
|
||||
writer.tag(2, WireType.LengthDelimited).string(message.name);
|
||||
/* optional string type = 3; */
|
||||
if (message.type !== undefined)
|
||||
writer.tag(3, WireType.LengthDelimited).string(message.type);
|
||||
/* optional string client_id = 4; */
|
||||
if (message.clientId !== undefined)
|
||||
writer.tag(4, WireType.LengthDelimited).string(message.clientId);
|
||||
/* optional string server_id = 5; */
|
||||
if (message.serverId !== undefined)
|
||||
writer.tag(5, WireType.LengthDelimited).string(message.serverId);
|
||||
/* optional string config = 6; */
|
||||
if (message.config !== undefined)
|
||||
writer.tag(6, WireType.LengthDelimited).string(message.config);
|
||||
/* optional string origin_client_id = 7; */
|
||||
if (message.originClientId !== undefined)
|
||||
writer.tag(7, WireType.LengthDelimited).string(message.originClientId);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message common.ProxyConfig
|
||||
*/
|
||||
export const ProxyConfig = new ProxyConfig$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class ProxyWorkingStatus$Type extends MessageType<ProxyWorkingStatus> {
|
||||
constructor() {
|
||||
super("common.ProxyWorkingStatus", [
|
||||
{ no: 1, name: "name", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 2, name: "type", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 3, name: "status", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 4, name: "err", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 5, name: "remote_addr", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<ProxyWorkingStatus>): ProxyWorkingStatus {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<ProxyWorkingStatus>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProxyWorkingStatus): ProxyWorkingStatus {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* optional string name */ 1:
|
||||
message.name = reader.string();
|
||||
break;
|
||||
case /* optional string type */ 2:
|
||||
message.type = reader.string();
|
||||
break;
|
||||
case /* optional string status */ 3:
|
||||
message.status = reader.string();
|
||||
break;
|
||||
case /* optional string err */ 4:
|
||||
message.err = reader.string();
|
||||
break;
|
||||
case /* optional string remote_addr */ 5:
|
||||
message.remoteAddr = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: ProxyWorkingStatus, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* optional string name = 1; */
|
||||
if (message.name !== undefined)
|
||||
writer.tag(1, WireType.LengthDelimited).string(message.name);
|
||||
/* optional string type = 2; */
|
||||
if (message.type !== undefined)
|
||||
writer.tag(2, WireType.LengthDelimited).string(message.type);
|
||||
/* optional string status = 3; */
|
||||
if (message.status !== undefined)
|
||||
writer.tag(3, WireType.LengthDelimited).string(message.status);
|
||||
/* optional string err = 4; */
|
||||
if (message.err !== undefined)
|
||||
writer.tag(4, WireType.LengthDelimited).string(message.err);
|
||||
/* optional string remote_addr = 5; */
|
||||
if (message.remoteAddr !== undefined)
|
||||
writer.tag(5, WireType.LengthDelimited).string(message.remoteAddr);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message common.ProxyWorkingStatus
|
||||
*/
|
||||
export const ProxyWorkingStatus = new ProxyWorkingStatus$Type();
|
||||
|
||||
@@ -12,3 +12,8 @@ export function formatBytes(bytes: number): string {
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
|
||||
}
|
||||
|
||||
export function ObjToUint8Array(obj: any): Uint8Array {
|
||||
const buffer = Buffer.from(JSON.stringify(obj))
|
||||
return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength)
|
||||
}
|
||||
@@ -7,8 +7,8 @@ export default function ClientEditPage() {
|
||||
return (
|
||||
<Providers>
|
||||
<RootLayout mainHeader={<Header />}>
|
||||
<div className="w-full">
|
||||
<div className="flex-1 flex-col">
|
||||
<div className="w-full flex items-center justify-center">
|
||||
<div className="flex-1 flex-col max-w-2xl">
|
||||
<FRPCFormCard />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
40
www/pages/proxies.tsx
Normal file
40
www/pages/proxies.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import { Providers } from '@/components/providers'
|
||||
import { RootLayout } from '@/components/layout'
|
||||
import { Header } from '@/components/header'
|
||||
import { ProxyConfigList } from '@/components/proxy/proxy_config_list'
|
||||
import { useState } from 'react'
|
||||
import { ProxyConfigMutateDialog } from '@/components/proxy/mutate_proxy_config'
|
||||
import { IdInput } from '@/components/base/id_input'
|
||||
import { ClientSelector } from '@/components/base/client-selector'
|
||||
import { ServerSelector } from '@/components/base/server-selector'
|
||||
import { $proxyTableRefetchTrigger } from '@/store/refetch-trigger'
|
||||
|
||||
export default function Proxies() {
|
||||
const [keyword, setKeyword] = useState('')
|
||||
const [clientID, setClientID] = useState<string | undefined>(undefined)
|
||||
const [serverID, setServerID] = useState<string | undefined>(undefined)
|
||||
|
||||
const triggerRefetch = (n:string) => {
|
||||
$proxyTableRefetchTrigger.set(Math.random())
|
||||
}
|
||||
|
||||
return (
|
||||
<Providers>
|
||||
<RootLayout mainHeader={<Header />}>
|
||||
<div className="w-full">
|
||||
<div className="flex flex-1 flex-col">
|
||||
<div className="flex flex-1 flex-row mb-2 gap-2">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-2">
|
||||
<ClientSelector clientID={clientID} setClientID={setClientID} />
|
||||
<ServerSelector serverID={serverID} setServerID={setServerID} />
|
||||
<IdInput setKeyword={setKeyword} keyword={keyword} refetchTrigger={triggerRefetch} />
|
||||
<ProxyConfigMutateDialog />
|
||||
</div>
|
||||
</div>
|
||||
<ProxyConfigList Keyword={keyword} ProxyConfigs={[]} ClientID={clientID} ServerID={serverID} />
|
||||
</div>
|
||||
</div>
|
||||
</RootLayout>
|
||||
</Providers>
|
||||
)
|
||||
}
|
||||
@@ -7,8 +7,8 @@ export default function ServerListPage() {
|
||||
return (
|
||||
<Providers>
|
||||
<RootLayout mainHeader={<Header />}>
|
||||
<div className="w-full">
|
||||
<div className="flex-1 flex-col">
|
||||
<div className="w-full flex items-center justify-center">
|
||||
<div className="flex-1 flex-col max-w-2xl">
|
||||
<FRPSFormCard />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,19 +5,58 @@ import { Separator } from '@/components/ui/separator'
|
||||
import { FRPSFormCard } from '@/components/frps/frps_card'
|
||||
import { RootLayout } from '@/components/layout'
|
||||
import { Header } from '@/components/header'
|
||||
import { createProxyConfig, listProxyConfig } from '@/api/proxy'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { TypedProxyConfig } from '@/types/proxy'
|
||||
import { ClientConfig } from '@/types/client'
|
||||
import { ProxyConfigList } from '@/components/proxy/proxy_config_list'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { useState } from 'react'
|
||||
|
||||
export default function Test() {
|
||||
const [name, setName] = useState<string>('')
|
||||
const [triggerRefetch, setTriggerRefetch] = useState<number>(0)
|
||||
|
||||
function create() {
|
||||
const buffer = Buffer.from(
|
||||
JSON.stringify({
|
||||
proxies: [{
|
||||
name: name,
|
||||
type: 'tcp',
|
||||
localIP: '127.0.0.1',
|
||||
localPort: 1234,
|
||||
remotePort: 4321,
|
||||
} as TypedProxyConfig]
|
||||
} as ClientConfig),
|
||||
)
|
||||
const uint8Array: Uint8Array = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
||||
createProxyConfig({
|
||||
clientId: 'admin.c.test',
|
||||
config: uint8Array,
|
||||
serverId: 'default',
|
||||
})
|
||||
.then(() => {
|
||||
setTriggerRefetch(triggerRefetch + 1)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
return (
|
||||
<></>
|
||||
// <RootLayout header={<Header />} sidebar={<SideBar />}>
|
||||
// <Providers>
|
||||
// <div className='grid grid-cols-1 md:grid-cols-2 gap-8'>
|
||||
// <FRPCFormCard></FRPCFormCard>
|
||||
// <FRPSFormCard></FRPSFormCard>
|
||||
// </div>
|
||||
// <Separator className='my-2' />
|
||||
// <APITest />
|
||||
// </Providers>
|
||||
// </RootLayout>
|
||||
// <>
|
||||
// </>
|
||||
<Providers>
|
||||
<RootLayout mainHeader={<Header />}>
|
||||
<div className="w-full">
|
||||
<div className="flex flex-1 flex-col">
|
||||
<div className="flex flex-1 flex-row mb-2 gap-2">
|
||||
<Button onClick={create}>新建</Button>
|
||||
<Input value={name} onChange={(e) => setName(e.target.value)} ></Input>
|
||||
</div>
|
||||
<ProxyConfigList Keyword="" ProxyConfigs={[]} TriggerRefetch={triggerRefetch.toString()} />
|
||||
</div>
|
||||
</div>
|
||||
</RootLayout>
|
||||
</Providers>
|
||||
)
|
||||
}
|
||||
|
||||
5
www/store/refetch-trigger.ts
Normal file
5
www/store/refetch-trigger.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { atom } from 'nanostores'
|
||||
|
||||
export const $clientTableRefetchTrigger = atom<number>(0)
|
||||
export const $serverTableRefetchTrigger = atom<number>(0)
|
||||
export const $proxyTableRefetchTrigger = atom<number>(0)
|
||||
Reference in New Issue
Block a user