From 88197a5e11417d74a508d43113d0e7ea44f72b9a Mon Sep 17 00:00:00 2001 From: vaalacat Date: Sat, 6 Jan 2024 09:36:56 +0000 Subject: [PATCH] init repo --- .env.sample | 2 + .gitignore | 6 + README.md | 61 + biz/client/remove_tunnel.go | 26 + biz/client/rpc_handler.go | 23 + biz/client/rpc_pull_config.go | 78 + biz/client/update_tunnel.go | 50 + biz/master/auth/handler.go | 84 + biz/master/auth/init.go | 24 + biz/master/auth/login.go | 37 + biz/master/auth/register.go | 51 + biz/master/client/create_client.go | 45 + biz/master/client/delete_client.go | 37 + biz/master/client/delete_tunnel.go | 54 + biz/master/client/get_client.go | 46 + biz/master/client/helper.go | 34 + biz/master/client/list_client.go | 46 + biz/master/client/rpc_pull_config.go | 27 + biz/master/client/sync_tunnel.go | 41 + biz/master/client/update_tunnel.go | 113 + biz/master/handler.go | 60 + biz/master/server/create_server.go | 49 + biz/master/server/delete_server.go | 36 + biz/master/server/delete_tunnel.go | 46 + biz/master/server/get_server.go | 43 + biz/master/server/helper.go | 34 + biz/master/server/list_server.go | 40 + biz/master/server/rpc_frp_auth.go | 31 + biz/master/server/rpc_pull_config.go | 25 + biz/master/server/update_tunnel.go | 63 + biz/master/user/get_user_info.go | 26 + biz/master/user/update_user_info.go | 70 + biz/server/auth_handler.go | 91 + biz/server/remove_tunnel.go | 35 + biz/server/rpc_handler.go | 23 + biz/server/rpc_pull_config.go | 65 + biz/server/update_tunnel.go | 37 + cache/freecache.go | 21 + cmd/client.go | 47 + cmd/cmd.go | 61 + cmd/main.go | 18 + cmd/master.go | 64 + cmd/server.go | 54 + cmd/test.go | 20 + codegen.sh | 4 + common/const.go | 47 + common/context.go | 21 + common/helper.go | 64 + common/request.go | 84 + common/response.go | 101 + common/result.go | 55 + conf/helper.go | 77 + conf/settings.go | 74 + dao/client.go | 147 ++ dao/server.go | 134 + dao/user.go | 114 + doc/callvis.gv | 309 +++ doc/callvis.svg | 924 +++++++ go.mod | 112 + go.sum | 380 +++ idl/api_auth.proto | 25 + idl/api_client.proto | 61 + idl/api_server.proto | 60 + idl/api_user.proto | 20 + idl/common.proto | 47 + idl/rpc_master.proto | 79 + middleware/auth.go | 65 + middleware/jwt.go | 157 ++ models/client.go | 60 + models/db.go | 76 + models/enums.go | 12 + models/init.go | 2 + models/server.go | 49 + models/user.go | 107 + pb/api_auth.pb.go | 388 +++ pb/api_client.pb.go | 954 +++++++ pb/api_server.pb.go | 954 +++++++ pb/api_user.pb.go | 350 +++ pb/common.pb.go | 612 +++++ pb/rpc_master.pb.go | 976 +++++++ pb/rpc_master_grpc.pb.go | 253 ++ rpc/client.go | 106 + rpc/client_manager.go | 63 + rpc/init.go | 5 + rpc/master.go | 23 + services/api/service.go | 42 + services/client/frpc_service.go | 179 ++ services/master/grpc_server.go | 132 + services/master/grpc_service.go | 49 + services/rpcclient/rpc_handler.go | 113 + services/rpcclient/rpc_service.go | 68 + services/server/frps_service.go | 82 + tunnel/client.go | 83 + tunnel/master.go | 1 + tunnel/server.go | 83 + utils/conv.go | 38 + utils/ctx.go | 60 + utils/frp_config.go | 64 + utils/hash.go | 32 + utils/jwt.go | 65 + utils/load.go | 94 + watcher/client.go | 44 + www/.eslintrc.json | 3 + www/.gitignore | 36 + www/README.md | 40 + www/api/auth.ts | 17 + www/api/client.ts | 30 + www/api/frp.ts | 35 + www/api/http.ts | 29 + www/api/server.ts | 31 + www/api/user.ts | 19 + www/components.json | 17 + www/components/apitest.tsx | 119 + www/components/client_item.tsx | 12 + www/components/client_list.tsx | 13 + www/components/frpc_card.tsx | 116 + www/components/frpc_editor.tsx | 21 + www/components/frpc_form.tsx | 54 + www/components/frps_card.tsx | 84 + www/components/frps_editor.tsx | 13 + www/components/frps_form.tsx | 148 ++ www/components/layout.tsx | 10 + www/components/login.tsx | 108 + www/components/providers.tsx | 17 + www/components/proxy_form.tsx | 215 ++ www/components/register.tsx | 133 + www/components/server_item.tsx | 0 www/components/ui/alert.tsx | 59 + www/components/ui/button.tsx | 56 + www/components/ui/card.tsx | 79 + www/components/ui/form.tsx | 176 ++ www/components/ui/input.tsx | 25 + www/components/ui/label.tsx | 24 + www/components/ui/select.tsx | 158 ++ www/components/ui/separator.tsx | 29 + www/components/ui/switch.tsx | 27 + www/components/ui/table.tsx | 117 + www/components/ui/textarea.tsx | 24 + www/components/ui/toast.tsx | 127 + www/components/ui/toaster.tsx | 33 + www/components/ui/tooltip.tsx | 28 + www/components/ui/use-toast.ts | 192 ++ www/lib/consts.ts | 17 + www/lib/pb/api_auth.ts | 277 ++ www/lib/pb/api_client.ts | 752 ++++++ www/lib/pb/api_server.ts | 752 ++++++ www/lib/pb/api_user.ts | 220 ++ www/lib/pb/common.ts | 465 ++++ www/lib/utils.ts | 6 + www/next.config.js | 16 + www/package.json | 52 + www/pages/_app.tsx | 6 + www/pages/_document.tsx | 13 + www/pages/clients.tsx | 0 www/pages/index.tsx | 24 + www/pages/login.tsx | 46 + www/pages/register.tsx | 46 + www/pages/test.tsx | 28 + www/pnpm-lock.yaml | 3671 ++++++++++++++++++++++++++ www/postcss.config.js | 6 + www/public/favicon.ico | Bin 0 -> 25931 bytes www/public/next.svg | 1 + www/public/vercel.svg | 1 + www/store/user.ts | 6 + www/styles/globals.css | 76 + www/tailwind.config.js | 77 + www/tailwind.config.ts | 20 + www/tsconfig.json | 22 + www/types/api.ts | 9 + www/types/client.ts | 84 + www/types/common.ts | 64 + www/types/plugin.ts | 58 + www/types/proxy.ts | 106 + www/types/server.ts | 66 + www/types/visitor.ts | 41 + 175 files changed, 20826 insertions(+) create mode 100644 .env.sample create mode 100644 .gitignore create mode 100644 README.md create mode 100644 biz/client/remove_tunnel.go create mode 100644 biz/client/rpc_handler.go create mode 100644 biz/client/rpc_pull_config.go create mode 100644 biz/client/update_tunnel.go create mode 100644 biz/master/auth/handler.go create mode 100644 biz/master/auth/init.go create mode 100644 biz/master/auth/login.go create mode 100644 biz/master/auth/register.go create mode 100644 biz/master/client/create_client.go create mode 100644 biz/master/client/delete_client.go create mode 100644 biz/master/client/delete_tunnel.go create mode 100644 biz/master/client/get_client.go create mode 100644 biz/master/client/helper.go create mode 100644 biz/master/client/list_client.go create mode 100644 biz/master/client/rpc_pull_config.go create mode 100644 biz/master/client/sync_tunnel.go create mode 100644 biz/master/client/update_tunnel.go create mode 100644 biz/master/handler.go create mode 100644 biz/master/server/create_server.go create mode 100644 biz/master/server/delete_server.go create mode 100644 biz/master/server/delete_tunnel.go create mode 100644 biz/master/server/get_server.go create mode 100644 biz/master/server/helper.go create mode 100644 biz/master/server/list_server.go create mode 100644 biz/master/server/rpc_frp_auth.go create mode 100644 biz/master/server/rpc_pull_config.go create mode 100644 biz/master/server/update_tunnel.go create mode 100644 biz/master/user/get_user_info.go create mode 100644 biz/master/user/update_user_info.go create mode 100644 biz/server/auth_handler.go create mode 100644 biz/server/remove_tunnel.go create mode 100644 biz/server/rpc_handler.go create mode 100644 biz/server/rpc_pull_config.go create mode 100644 biz/server/update_tunnel.go create mode 100644 cache/freecache.go create mode 100644 cmd/client.go create mode 100644 cmd/cmd.go create mode 100644 cmd/main.go create mode 100644 cmd/master.go create mode 100644 cmd/server.go create mode 100644 cmd/test.go create mode 100755 codegen.sh create mode 100644 common/const.go create mode 100644 common/context.go create mode 100644 common/helper.go create mode 100644 common/request.go create mode 100644 common/response.go create mode 100644 common/result.go create mode 100644 conf/helper.go create mode 100644 conf/settings.go create mode 100644 dao/client.go create mode 100644 dao/server.go create mode 100644 dao/user.go create mode 100755 doc/callvis.gv create mode 100644 doc/callvis.svg create mode 100644 go.mod create mode 100644 go.sum create mode 100644 idl/api_auth.proto create mode 100644 idl/api_client.proto create mode 100644 idl/api_server.proto create mode 100644 idl/api_user.proto create mode 100644 idl/common.proto create mode 100644 idl/rpc_master.proto create mode 100644 middleware/auth.go create mode 100644 middleware/jwt.go create mode 100644 models/client.go create mode 100644 models/db.go create mode 100644 models/enums.go create mode 100644 models/init.go create mode 100644 models/server.go create mode 100644 models/user.go create mode 100644 pb/api_auth.pb.go create mode 100644 pb/api_client.pb.go create mode 100644 pb/api_server.pb.go create mode 100644 pb/api_user.pb.go create mode 100644 pb/common.pb.go create mode 100644 pb/rpc_master.pb.go create mode 100644 pb/rpc_master_grpc.pb.go create mode 100644 rpc/client.go create mode 100644 rpc/client_manager.go create mode 100644 rpc/init.go create mode 100644 rpc/master.go create mode 100644 services/api/service.go create mode 100644 services/client/frpc_service.go create mode 100644 services/master/grpc_server.go create mode 100644 services/master/grpc_service.go create mode 100644 services/rpcclient/rpc_handler.go create mode 100644 services/rpcclient/rpc_service.go create mode 100644 services/server/frps_service.go create mode 100644 tunnel/client.go create mode 100644 tunnel/master.go create mode 100644 tunnel/server.go create mode 100644 utils/conv.go create mode 100644 utils/ctx.go create mode 100644 utils/frp_config.go create mode 100644 utils/hash.go create mode 100644 utils/jwt.go create mode 100644 utils/load.go create mode 100644 watcher/client.go create mode 100644 www/.eslintrc.json create mode 100644 www/.gitignore create mode 100644 www/README.md create mode 100644 www/api/auth.ts create mode 100644 www/api/client.ts create mode 100644 www/api/frp.ts create mode 100644 www/api/http.ts create mode 100644 www/api/server.ts create mode 100644 www/api/user.ts create mode 100644 www/components.json create mode 100644 www/components/apitest.tsx create mode 100644 www/components/client_item.tsx create mode 100644 www/components/client_list.tsx create mode 100644 www/components/frpc_card.tsx create mode 100644 www/components/frpc_editor.tsx create mode 100644 www/components/frpc_form.tsx create mode 100644 www/components/frps_card.tsx create mode 100644 www/components/frps_editor.tsx create mode 100644 www/components/frps_form.tsx create mode 100644 www/components/layout.tsx create mode 100644 www/components/login.tsx create mode 100644 www/components/providers.tsx create mode 100644 www/components/proxy_form.tsx create mode 100644 www/components/register.tsx create mode 100644 www/components/server_item.tsx create mode 100644 www/components/ui/alert.tsx create mode 100644 www/components/ui/button.tsx create mode 100644 www/components/ui/card.tsx create mode 100644 www/components/ui/form.tsx create mode 100644 www/components/ui/input.tsx create mode 100644 www/components/ui/label.tsx create mode 100644 www/components/ui/select.tsx create mode 100644 www/components/ui/separator.tsx create mode 100644 www/components/ui/switch.tsx create mode 100644 www/components/ui/table.tsx create mode 100644 www/components/ui/textarea.tsx create mode 100644 www/components/ui/toast.tsx create mode 100644 www/components/ui/toaster.tsx create mode 100644 www/components/ui/tooltip.tsx create mode 100644 www/components/ui/use-toast.ts create mode 100644 www/lib/consts.ts create mode 100644 www/lib/pb/api_auth.ts create mode 100644 www/lib/pb/api_client.ts create mode 100644 www/lib/pb/api_server.ts create mode 100644 www/lib/pb/api_user.ts create mode 100644 www/lib/pb/common.ts create mode 100644 www/lib/utils.ts create mode 100644 www/next.config.js create mode 100644 www/package.json create mode 100644 www/pages/_app.tsx create mode 100644 www/pages/_document.tsx create mode 100644 www/pages/clients.tsx create mode 100644 www/pages/index.tsx create mode 100644 www/pages/login.tsx create mode 100644 www/pages/register.tsx create mode 100644 www/pages/test.tsx create mode 100644 www/pnpm-lock.yaml create mode 100644 www/postcss.config.js create mode 100644 www/public/favicon.ico create mode 100644 www/public/next.svg create mode 100644 www/public/vercel.svg create mode 100644 www/store/user.ts create mode 100644 www/styles/globals.css create mode 100644 www/tailwind.config.js create mode 100644 www/tailwind.config.ts create mode 100644 www/tsconfig.json create mode 100644 www/types/api.ts create mode 100644 www/types/client.ts create mode 100644 www/types/common.ts create mode 100644 www/types/plugin.ts create mode 100644 www/types/proxy.ts create mode 100644 www/types/server.ts create mode 100644 www/types/visitor.ts diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..fbee7ef --- /dev/null +++ b/.env.sample @@ -0,0 +1,2 @@ +APP_GLOBAL_SECRET="123" +MASTER_RPC_HOST=127.0.0.1 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..21c96fc --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.vscode +__debug* +.env +tmp +*.db +frp-panel \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..5092999 --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +项目如下 + +项目包含三个角色 +1. Master: 控制节点,接受来自前端的请求并负责管理Client和Server +2. Server: 服务端,受控制节点控制,负责对客户端提供服务,包含frps和rpc(用于连接Master)服务 +3. Client: 客户端,受控制节点控制,包含frpc和rpc(用于连接Master)服务 + +启动方式: + +- master: `go run cmd/*.go master` 或是 `frp-panel master` +- client: `go run cmd/*.go client -i -s ` 或是 `frp-panel client -i -s ` +- server: `go run cmd/*.go server -i -s ` 或是 `frp-panel server -i -s ` + +项目配置文件会默认读取当前文件夹下的.env文件,项目内置了样例配置文件,可以按照自己的需求进行修改 + +``` +. +|-- biz # 主要业务逻辑 +| |-- client # 客户端逻辑(这里指的是frp-panel的客户端) +| |-- master # frp-panel 控制平面,负责处理前端请求,并且使用rpc管理frp-panel的server和client +| | |-- auth # 认证模块,包含用户认证和客户端认证 +| | |-- client # 客户端模块,包含前端管理客户端的各种API +| | |-- server # 服务端模块,包含前端管理服务端的各种API +| | `-- user # 用户模块,包含用户管理、用户信息获取等 +| `-- server # 服务端逻辑(这里指的是frp-panel的服务端) +|-- cache # 缓存,用于存储frps的认证token +|-- cmd # 命令行入口,main函数的所在地,负责按需启动各个模块 +|-- common +|-- conf +|-- dao # data access object,任何和数据库相关的操作会调用这个库 +|-- doc # 文档 +|-- idl # idl定义 +|-- middleware # api的中间件,包含JWT和context相关,用于处理api请求,鉴权通过后会把用户信息注入到context,可以通过common包获取 +|-- models # 数据库模型,用于定义数据库表。同时包含实体定义 +|-- pb # protobuf生成的pb文件 +|-- rpc # 各种rpc的所在地,包含Client/Server调用Master的逻辑,也包含Master使用Stream调用Client和Server的逻辑 +|-- services # 各种需要在内存中持久运行的模块,这个包可以管理各个服务的运行/停止 +| |-- api # api服务,运行需要外部传入一个ginRouter +| |-- client # frp的客户端,即frpc,可以控制frpc的各种配置/开始与停止 +| |-- master # master服务,包含rpc的服务端定义,接收到rpc请求后会调用biz包处理逻辑 +| |-- rpcclient # 有状态的rpc客户端,因为rpc的client都没有公网ip,因此在rpc client启动时会调用master的stream长连接rpc,建立连接后Master和Client通过这个包通信 +| `-- server # frp的服务端,即frps,可以控制frps的各种配置/开始与停止 +|-- tunnel # tunnel模块,用于管理tunnel,也就是管理frpc和frps服务 +|-- utils +|-- watcher # 定时运行的任务,比如每30秒更新一次配置文件 +`-- www + |-- api + |-- components # 这里面有一个apitest组件用于测试 + | `-- ui + |-- lib + | `-- pb + |-- pages + |-- public + |-- store + |-- styles + `-- types +``` + +详细架构调用图 + +![structure](doc/callvis.svg) \ No newline at end of file diff --git a/biz/client/remove_tunnel.go b/biz/client/remove_tunnel.go new file mode 100644 index 0000000..743d322 --- /dev/null +++ b/biz/client/remove_tunnel.go @@ -0,0 +1,26 @@ +package client + +import ( + "context" + + "github.com/VaalaCat/frp-panel/pb" + "github.com/VaalaCat/frp-panel/tunnel" + "github.com/sirupsen/logrus" +) + +func RemoveFrpcHandler(ctx context.Context, req *pb.RemoveFRPCRequest) (*pb.RemoveFRPCResponse, error) { + logrus.Infof("remove frpc, req: [%+v]", req) + cli := tunnel.GetClientController().Get(req.GetClientId()) + if cli == nil { + logrus.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()) + + return &pb.RemoveFRPCResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + }, nil +} diff --git a/biz/client/rpc_handler.go b/biz/client/rpc_handler.go new file mode 100644 index 0000000..1bc6d60 --- /dev/null +++ b/biz/client/rpc_handler.go @@ -0,0 +1,23 @@ +package client + +import ( + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/pb" + "github.com/sirupsen/logrus" +) + +func HandleServerMessage(req *pb.ServerMessage) *pb.ClientMessage { + logrus.Infof("client get a server message, origin is: [%+v]", req) + switch req.Event { + case pb.Event_EVENT_UPDATE_FRPC: + return common.WrapperServerMsg(req, UpdateFrpcHander) + case pb.Event_EVENT_REMOVE_FRPC: + return common.WrapperServerMsg(req, RemoveFrpcHandler) + default: + } + + return &pb.ClientMessage{ + Event: pb.Event_EVENT_ERROR, + Data: []byte("unknown event"), + } +} diff --git a/biz/client/rpc_pull_config.go b/biz/client/rpc_pull_config.go new file mode 100644 index 0000000..33ee0fb --- /dev/null +++ b/biz/client/rpc_pull_config.go @@ -0,0 +1,78 @@ +package client + +import ( + "context" + "reflect" + + "github.com/VaalaCat/frp-panel/pb" + "github.com/VaalaCat/frp-panel/rpc" + "github.com/VaalaCat/frp-panel/services/client" + "github.com/VaalaCat/frp-panel/tunnel" + "github.com/VaalaCat/frp-panel/utils" + "github.com/sirupsen/logrus" +) + +func PullConfig(clientID, clientSecret string) error { + logrus.Infof("start to pull client config, clientID: [%s]", clientID) + ctx := context.Background() + cli, err := rpc.MasterCli(ctx) + if err != nil { + logrus.WithError(err).Error("cannot get master client") + return err + } + resp, err := cli.PullClientConfig(ctx, &pb.PullClientConfigReq{ + Base: &pb.ClientBase{ + ClientId: clientID, + ClientSecret: clientSecret, + }, + }) + if err != nil { + logrus.WithError(err).Error("cannot pull client config") + return err + } + + if len(resp.GetClient().GetConfig()) == 0 { + logrus.Infof("client [%s] config is empty, wait for server init", clientID) + return nil + } + + c, p, v, err := utils.LoadClientConfig([]byte(resp.GetClient().GetConfig()), true) + if err != nil { + logrus.WithError(err).Error("cannot load client config") + return err + } + + ctrl := tunnel.GetClientController() + + if t := ctrl.Get(clientID); t == nil { + ctrl.Add(clientID, client.NewClientHandler(c, p, v)) + ctrl.Run(clientID) + } else { + if !reflect.DeepEqual(t.GetCommonCfg(), c) { + logrus.Infof("client %s config changed, will recreate it", clientID) + tcli := ctrl.Get(clientID) + if tcli != nil { + tcli.Stop() + ctrl.Delete(clientID) + } + ctrl.Add(clientID, client.NewClientHandler(c, p, v)) + ctrl.Run(clientID) + } else { + logrus.Infof("client %s already exists, update if need", clientID) + tcli := ctrl.Get(clientID) + if tcli == nil || !tcli.Running() { + if tcli != nil { + tcli.Stop() + ctrl.Delete(clientID) + } + ctrl.Add(clientID, client.NewClientHandler(c, p, v)) + ctrl.Run(clientID) + } else { + tcli.Update(p, v) + } + } + } + + logrus.Infof("pull client config success, clientID: [%s]", clientID) + return nil +} diff --git a/biz/client/update_tunnel.go b/biz/client/update_tunnel.go new file mode 100644 index 0000000..fc32491 --- /dev/null +++ b/biz/client/update_tunnel.go @@ -0,0 +1,50 @@ +package client + +import ( + "context" + "fmt" + "reflect" + + "github.com/VaalaCat/frp-panel/pb" + "github.com/VaalaCat/frp-panel/services/client" + "github.com/VaalaCat/frp-panel/tunnel" + "github.com/VaalaCat/frp-panel/utils" + "github.com/sirupsen/logrus" +) + +func UpdateFrpcHander(ctx context.Context, req *pb.UpdateFRPCRequest) (*pb.UpdateFRPCResponse, error) { + logrus.Infof("update frpc, req: [%+v]", req) + content := req.GetConfig() + c, p, v, err := utils.LoadClientConfig(content, false) + if err != nil { + logrus.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()) + if cli == nil { + logrus.Errorf("cannot get client, id: [%s]", req.GetClientId()) + return &pb.UpdateFRPCResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "cannot get client"}, + }, fmt.Errorf("cannot get client") + } + + if reflect.DeepEqual(c, cli.GetCommonCfg()) { + logrus.Warnf("client config not changed") + cli.Update(p, v) + } else { + tcli := tunnel.GetClientController().Get(req.GetClientId()) + if tcli != nil { + tcli.Stop() + tunnel.GetClientController().Delete(req.GetClientId()) + } + tunnel.GetClientController().Add(req.GetClientId(), client.NewClientHandler(c, p, v)) + tunnel.GetClientController().Run(req.GetClientId()) + } + + return &pb.UpdateFRPCResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + }, nil +} diff --git a/biz/master/auth/handler.go b/biz/master/auth/handler.go new file mode 100644 index 0000000..5a94646 --- /dev/null +++ b/biz/master/auth/handler.go @@ -0,0 +1,84 @@ +package auth + +import ( + "net/http" + + "github.com/VaalaCat/frp-panel/cache" + "github.com/VaalaCat/frp-panel/dao" + plugin "github.com/fatedier/frp/pkg/plugin/server" + "github.com/gin-gonic/gin" + "github.com/sirupsen/logrus" +) + +type Response struct { + Msg string `json:"msg"` +} + +type HTTPError struct { + Code int + Err error +} + +func (e *HTTPError) Error() string { + return e.Err.Error() +} + +type HandlerFunc func(ctx *gin.Context) (interface{}, error) + +func MakeGinHandlerFunc(handler HandlerFunc) gin.HandlerFunc { + return func(ctx *gin.Context) { + res, err := handler(ctx) + if err != nil { + logrus.Infof("handle %s error: %v", ctx.Request.URL.Path, err) + switch e := err.(type) { + case *HTTPError: + ctx.JSON(e.Code, &Response{Msg: e.Err.Error()}) + default: + ctx.JSON(500, &Response{Msg: err.Error()}) + } + return + } + ctx.JSON(http.StatusOK, res) + } +} + +func HandleLogin(ctx *gin.Context) (interface{}, error) { + var r plugin.Request + var content plugin.LoginContent + r.Content = &content + if err := ctx.BindJSON(&r); err != nil { + return nil, &HTTPError{ + Code: http.StatusBadRequest, + Err: err, + } + } + + var res plugin.Response + token := content.Metas["token"] + if len(content.User) == 0 || len(token) == 0 { + res.Reject = true + res.RejectReason = "user or meta token can not be empty" + return res, nil + } + + userToken, err := cache.Get().Get([]byte(content.User)) + if err != nil { + u, err := dao.GetUserByUserName(content.User) + if err != nil || u == nil { + res.Reject = true + res.RejectReason = "invalid frp auth" + return res, nil + } + cache.Get().Set([]byte(u.GetUserName()), []byte(u.GetToken()), 0) + userToken = []byte(u.GetToken()) + } + + if string(userToken) == token { + res.Unchange = true + return res, nil + } + + res.Reject = true + res.RejectReason = "invalid meta token" + return res, nil +} diff --git a/biz/master/auth/init.go b/biz/master/auth/init.go new file mode 100644 index 0000000..32b5e71 --- /dev/null +++ b/biz/master/auth/init.go @@ -0,0 +1,24 @@ +package auth + +import ( + "github.com/VaalaCat/frp-panel/cache" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/models" + "github.com/samber/lo" + "github.com/sirupsen/logrus" +) + +func InitAuth() { + logrus.Info("start to init frp user auth token") + + u, err := dao.AdminGetAllUsers() + if err != nil { + logrus.WithError(err).Fatalf("init frp user auth token failed") + } + + lo.ForEach(u, func(user *models.UserEntity, _ int) { + cache.Get().Set([]byte(user.GetUserName()), []byte(user.GetToken()), 0) + }) + + logrus.Infof("init frp user auth token success, count: %d", len(u)) +} diff --git a/biz/master/auth/login.go b/biz/master/auth/login.go new file mode 100644 index 0000000..d728b86 --- /dev/null +++ b/biz/master/auth/login.go @@ -0,0 +1,37 @@ +package auth + +import ( + "context" + "fmt" + + "github.com/VaalaCat/frp-panel/conf" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/middleware" + "github.com/VaalaCat/frp-panel/pb" + "github.com/gin-gonic/gin" +) + +func LoginHandler(c context.Context, req *pb.LoginRequest) (*pb.LoginResponse, error) { + username := req.GetUsername() + password := req.GetPassword() + ok, user, err := dao.CheckUserPassword(username, password) + if err != nil { + return nil, err + } + + if !ok { + return &pb.LoginResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid username or password"}, + }, nil + } + + tokenStr := conf.GetCommonJWT(fmt.Sprint(user.GetUserID())) + + ginCtx := c.(*gin.Context) + middleware.PushTokenStr(ginCtx, tokenStr) + + return &pb.LoginResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + Token: &tokenStr, + }, nil +} diff --git a/biz/master/auth/register.go b/biz/master/auth/register.go new file mode 100644 index 0000000..c2f5790 --- /dev/null +++ b/biz/master/auth/register.go @@ -0,0 +1,51 @@ +package auth + +import ( + "context" + "fmt" + + "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" +) + +func RegisterHandler(c context.Context, req *pb.RegisterRequest) (*pb.RegisterResponse, error) { + username := req.GetUsername() + password := req.GetPassword() + email := req.GetEmail() + + if username == "" || password == "" || email == "" { + return &pb.RegisterResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid username or password or email"}, + }, fmt.Errorf("invalid username or password or email") + } + + hashedPassword, err := utils.HashPassword(password) + if err != nil { + return &pb.RegisterResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: err.Error()}, + }, err + } + + newUser := &models.UserEntity{ + UserName: username, + Password: hashedPassword, + Email: email, + Status: models.STATUS_NORMAL, + Role: models.ROLE_NORMAL, + Token: uuid.New().String(), + } + + err = dao.CreateUser(newUser) + if err != nil { + return &pb.RegisterResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: err.Error()}, + }, err + } + + return &pb.RegisterResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + }, nil +} diff --git a/biz/master/client/create_client.go b/biz/master/client/create_client.go new file mode 100644 index 0000000..abaaa68 --- /dev/null +++ b/biz/master/client/create_client.go @@ -0,0 +1,45 @@ +package client + +import ( + "context" + + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/models" + "github.com/VaalaCat/frp-panel/pb" + "github.com/google/uuid" +) + +func InitClientHandler(c context.Context, req *pb.InitClientRequest) (*pb.InitClientResponse, error) { + userClientID := req.GetClientId() + userInfo := common.GetUserInfo(c) + + if !userInfo.Valid() { + return &pb.InitClientResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid user"}, + }, nil + } + + if len(userClientID) == 0 { + return &pb.InitClientResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid client id"}, + }, nil + } + + globalClientID := common.GlobalClientID(userInfo.GetUserName(), userClientID) + + if err := dao.CreateClient(userInfo, + &models.ClientEntity{ + ClientID: globalClientID, + TenantID: userInfo.GetTenantID(), + UserID: userInfo.GetUserID(), + ConnectSecret: uuid.New().String(), + }); err != nil { + return nil, err + } + + return &pb.InitClientResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + ClientId: &globalClientID, + }, nil +} diff --git a/biz/master/client/delete_client.go b/biz/master/client/delete_client.go new file mode 100644 index 0000000..be7cd1e --- /dev/null +++ b/biz/master/client/delete_client.go @@ -0,0 +1,37 @@ +package client + +import ( + "context" + + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/pb" + "github.com/sirupsen/logrus" +) + +func DeleteClientHandler(ctx context.Context, req *pb.DeleteClientRequest) (*pb.DeleteClientResponse, error) { + logrus.Infof("delete client, req: [%+v]", req) + + userInfo := common.GetUserInfo(ctx) + clientID := req.GetClientId() + + if !userInfo.Valid() { + return &pb.DeleteClientResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid user"}, + }, nil + } + + if len(clientID) == 0 { + return &pb.DeleteClientResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid client id"}, + }, nil + } + + if err := dao.DeleteClient(userInfo, clientID); err != nil { + return nil, err + } + + return &pb.DeleteClientResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + }, nil +} diff --git a/biz/master/client/delete_tunnel.go b/biz/master/client/delete_tunnel.go new file mode 100644 index 0000000..749e451 --- /dev/null +++ b/biz/master/client/delete_tunnel.go @@ -0,0 +1,54 @@ +package client + +import ( + "context" + "fmt" + + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/pb" + "github.com/VaalaCat/frp-panel/rpc" + "github.com/sirupsen/logrus" +) + +func RemoveFrpcHandler(c context.Context, req *pb.RemoveFRPCRequest) (*pb.RemoveFRPCResponse, error) { + logrus.Infof("remove frpc, req: [%+v]", req) + + var ( + clientID = req.GetClientId() + userInfo = common.GetUserInfo(c) + ) + + if len(clientID) == 0 { + logrus.Errorf("invalid client id") + return nil, fmt.Errorf("invalid client id") + } + + _, err := dao.GetClientByClientID(userInfo, clientID) + if err != nil { + logrus.WithError(err).Errorf("cannot get client, id: [%s]", clientID) + return nil, err + } + + err = dao.DeleteClient(userInfo, clientID) + if err != nil { + logrus.WithError(err).Errorf("cannot delete client, id: [%s]", clientID) + return nil, err + } + + go func() { + resp, err := rpc.CallClient(c, req.GetClientId(), pb.Event_EVENT_REMOVE_FRPC, req) + if err != nil { + logrus.WithError(err).Errorf("remove event send to client error, client id: [%s]", req.GetClientId()) + } + + if resp == nil { + logrus.Errorf("cannot get response, client id: [%s]", req.GetClientId()) + } + }() + + logrus.Infof("remove frpc success, client id: [%s]", req.GetClientId()) + return &pb.RemoveFRPCResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + }, nil +} diff --git a/biz/master/client/get_client.go b/biz/master/client/get_client.go new file mode 100644 index 0000000..43d42ba --- /dev/null +++ b/biz/master/client/get_client.go @@ -0,0 +1,46 @@ +package client + +import ( + "context" + + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/pb" + "github.com/samber/lo" + "github.com/sirupsen/logrus" +) + +func GetClientHandler(ctx context.Context, req *pb.GetClientRequest) (*pb.GetClientResponse, error) { + logrus.Infof("get client, req: [%+v]", req) + + var ( + userInfo = common.GetUserInfo(ctx) + clientID = req.GetClientId() + ) + + if !userInfo.Valid() { + return &pb.GetClientResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid user"}, + }, nil + } + + if len(clientID) == 0 { + return &pb.GetClientResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid client id"}, + }, nil + } + + client, err := dao.GetClientByClientID(userInfo, clientID) + if err != nil { + return nil, err + } + + 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)), + }, + }, nil +} diff --git a/biz/master/client/helper.go b/biz/master/client/helper.go new file mode 100644 index 0000000..a7af4cf --- /dev/null +++ b/biz/master/client/helper.go @@ -0,0 +1,34 @@ +package client + +import ( + "fmt" + + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/models" +) + +type ValidateableClientRequest interface { + GetClientSecret() string + GetClientId() string +} + +func ValidateClientRequest(req ValidateableClientRequest) (*models.ClientEntity, error) { + if req == nil { + return nil, fmt.Errorf("invalid request") + } + + if req.GetClientId() == "" || req.GetClientSecret() == "" { + return nil, fmt.Errorf("invalid request") + } + + var ( + cli *models.ClientEntity + err error + ) + + if cli, err = dao.ValidateClientSecret(req.GetClientId(), req.GetClientSecret()); err != nil { + return nil, err + } + + return cli, nil +} diff --git a/biz/master/client/list_client.go b/biz/master/client/list_client.go new file mode 100644 index 0000000..7f28e3e --- /dev/null +++ b/biz/master/client/list_client.go @@ -0,0 +1,46 @@ +package client + +import ( + "context" + + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/models" + "github.com/VaalaCat/frp-panel/pb" + "github.com/samber/lo" + "github.com/sirupsen/logrus" +) + +func ListClientsHandler(ctx context.Context, req *pb.ListClientsRequest) (*pb.ListClientsResponse, error) { + logrus.Infof("list client, req: [%+v]", req) + + var ( + userInfo = common.GetUserInfo(ctx) + ) + + if !userInfo.Valid() { + return &pb.ListClientsResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid user"}, + }, nil + } + + page := int(req.GetPage()) + pageSize := int(req.GetPageSize()) + clients, err := dao.ListClients(userInfo, page, pageSize) + if err != nil { + return nil, err + } + + respClients := lo.Map(clients, func(c *models.ClientEntity, _ int) *pb.Client { + return &pb.Client{ + Id: lo.ToPtr(c.ClientID), + Secret: lo.ToPtr(c.ConnectSecret), + Config: lo.ToPtr(string(c.ConfigContent)), + } + }) + + return &pb.ListClientsResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + Clients: respClients, + }, nil +} diff --git a/biz/master/client/rpc_pull_config.go b/biz/master/client/rpc_pull_config.go new file mode 100644 index 0000000..6c79287 --- /dev/null +++ b/biz/master/client/rpc_pull_config.go @@ -0,0 +1,27 @@ +package client + +import ( + "context" + + "github.com/VaalaCat/frp-panel/models" + "github.com/VaalaCat/frp-panel/pb" + "github.com/samber/lo" +) + +func RPCPullConfig(ctx context.Context, req *pb.PullClientConfigReq) (*pb.PullClientConfigResp, error) { + var ( + err error + cli *models.ClientEntity + ) + + if cli, err = ValidateClientRequest(req.GetBase()); err != nil { + return nil, err + } + + return &pb.PullClientConfigResp{ + Client: &pb.Client{ + Id: lo.ToPtr(cli.ClientID), + Config: lo.ToPtr(string(cli.ConfigContent)), + }, + }, nil +} diff --git a/biz/master/client/sync_tunnel.go b/biz/master/client/sync_tunnel.go new file mode 100644 index 0000000..89b696a --- /dev/null +++ b/biz/master/client/sync_tunnel.go @@ -0,0 +1,41 @@ +package client + +import ( + "context" + + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/models" + "github.com/samber/lo" + "github.com/sirupsen/logrus" +) + +func SyncTunnel(ctx context.Context, userInfo models.UserInfo) error { + clis, err := dao.GetAllClients(userInfo) + if err != nil { + return err + } + lo.ForEach(clis, func(cli *models.ClientEntity, _ int) { + cfg, err := cli.GetConfigContent() + if err != nil { + logrus.WithError(err).Errorf("cannot get client config content, id: [%s]", cli.ClientID) + return + } + + cfg.User = userInfo.GetUserName() + cfg.Metadatas = map[string]string{ + common.FRPAuthTokenKey: userInfo.GetToken(), + } + if err := cli.SetConfigContent(*cfg); err != nil { + logrus.WithError(err).Errorf("cannot set client config content, id: [%s]", cli.ClientID) + return + } + + if err := dao.UpdateClient(userInfo, cli); err != nil { + logrus.WithError(err).Errorf("cannot update client, id: [%s]", cli.ClientID) + return + } + logrus.Infof("update client success, id: [%s]", cli.ClientID) + }) + return nil +} diff --git a/biz/master/client/update_tunnel.go b/biz/master/client/update_tunnel.go new file mode 100644 index 0000000..aaec240 --- /dev/null +++ b/biz/master/client/update_tunnel.go @@ -0,0 +1,113 @@ +package client + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/pb" + "github.com/VaalaCat/frp-panel/rpc" + "github.com/VaalaCat/frp-panel/utils" + v1 "github.com/fatedier/frp/pkg/config/v1" + "github.com/samber/lo" + "github.com/sirupsen/logrus" +) + +func UpdateFrpcHander(c context.Context, req *pb.UpdateFRPCRequest) (*pb.UpdateFRPCResponse, error) { + logrus.Infof("update frpc, req: [%+v]", req) + var ( + content = req.GetConfig() + serverID = req.GetServerId() + clientID = req.GetClientId() + userInfo = common.GetUserInfo(c) + ) + + cliCfg, err := utils.LoadClientConfigNormal(content, true) + if err != nil { + logrus.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()) + if err != nil { + logrus.WithError(err).Errorf("cannot get client, id: [%s]", req.GetClientId()) + return &pb.UpdateFRPCResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "cannot get client"}, + }, fmt.Errorf("cannot get client") + } + + srv, err := dao.GetServerByServerID(userInfo, req.GetServerId()) + if err != nil || srv == nil || len(srv.ServerIP) == 0 || len(srv.ConfigContent) == 0 { + logrus.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") + } + + srvConf, err := srv.GetConfigContent() + if srvConf == nil || err != nil { + logrus.WithError(err).Errorf("cannot get server, id: [%s]", serverID) + return nil, err + } + + cliCfg.ServerAddr = srv.ServerIP + cliCfg.ServerPort = srvConf.BindPort + cliCfg.User = userInfo.GetUserName() + cliCfg.Auth = v1.AuthClientConfig{} + cliCfg.Metadatas = map[string]string{ + common.FRPAuthTokenKey: userInfo.GetToken(), + } + + newCfg := struct { + v1.ClientCommonConfig + Proxies []v1.ProxyConfigurer `json:"proxies,omitempty"` + Visitors []v1.VisitorBaseConfig `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() + }), + } + + rawCliConf, err := json.Marshal(newCfg) + if err != nil { + logrus.WithError(err).Error("cannot marshal config") + return nil, err + } + + cli.ConfigContent = rawCliConf + + if err := dao.UpdateClient(userInfo, cli); err != nil { + logrus.WithError(err).Errorf("cannot update client, id: [%s]", clientID) + return nil, err + } + + cliReq := &pb.UpdateFRPCRequest{ + ClientId: lo.ToPtr(clientID), + ServerId: lo.ToPtr(serverID), + Config: rawCliConf, + } + + go func() { + resp, err := rpc.CallClient(c, req.GetClientId(), pb.Event_EVENT_UPDATE_FRPC, cliReq) + if err != nil { + logrus.WithError(err).Errorf("update event send to client error, server: [%s], client: [%s]", serverID, req.GetClientId()) + } + + if resp == nil { + logrus.Errorf("cannot get response, server: [%s], client: [%s]", serverID, req.GetClientId()) + } + }() + + logrus.Infof("update frpc success, client id: [%s]", req.GetClientId()) + return &pb.UpdateFRPCResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + }, nil +} diff --git a/biz/master/handler.go b/biz/master/handler.go new file mode 100644 index 0000000..9a800fa --- /dev/null +++ b/biz/master/handler.go @@ -0,0 +1,60 @@ +package master + +import ( + "github.com/VaalaCat/frp-panel/biz/master/auth" + "github.com/VaalaCat/frp-panel/biz/master/client" + "github.com/VaalaCat/frp-panel/biz/master/server" + "github.com/VaalaCat/frp-panel/biz/master/user" + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/middleware" + "github.com/gin-gonic/gin" +) + +func NewRouter() *gin.Engine { + router := gin.Default() + ConfigureRouter(router) + return router +} + +func ConfigureRouter(router *gin.Engine) { + router.POST("/auth", auth.MakeGinHandlerFunc(auth.HandleLogin)) + + api := router.Group("/api") + v1 := api.Group("/v1") + { + authRouter := v1.Group("/auth") + { + authRouter.POST("/login", common.Wrapper(auth.LoginHandler)) + authRouter.POST("/register", common.Wrapper(auth.RegisterHandler)) + } + userRouter := v1.Group("/user", middleware.JWTAuth, middleware.AuthCtx) + { + userRouter.POST("/get", common.Wrapper(user.GetUserInfoHandler)) + userRouter.POST("/update", common.Wrapper(user.UpdateUserInfoHander)) + } + clientRouter := v1.Group("/client", middleware.JWTAuth, middleware.AuthCtx) + { + clientRouter.POST("/get", common.Wrapper(client.GetClientHandler)) + clientRouter.POST("/init", common.Wrapper(client.InitClientHandler)) + clientRouter.POST("/delete", common.Wrapper(client.DeleteClientHandler)) + clientRouter.POST("/list", common.Wrapper(client.ListClientsHandler)) + } + serverRouter := v1.Group("/server", middleware.JWTAuth, middleware.AuthCtx) + { + serverRouter.POST("/get", common.Wrapper(server.GetServerHandler)) + serverRouter.POST("/init", common.Wrapper(server.InitServerHandler)) + serverRouter.POST("/delete", common.Wrapper(server.DeleteServerHandler)) + serverRouter.POST("/list", common.Wrapper(server.ListServersHandler)) + } + frpcRouter := v1.Group("/frpc", middleware.JWTAuth, middleware.AuthCtx) + { + frpcRouter.POST("/update", common.Wrapper(client.UpdateFrpcHander)) + frpcRouter.POST("/delete", common.Wrapper(client.RemoveFrpcHandler)) + } + frpsRouter := v1.Group("/frps", middleware.JWTAuth, middleware.AuthCtx) + { + frpsRouter.POST("/update", common.Wrapper(server.UpdateFrpsHander)) + frpsRouter.POST("/delete", common.Wrapper(server.RemoveFrpsHandler)) + } + } +} diff --git a/biz/master/server/create_server.go b/biz/master/server/create_server.go new file mode 100644 index 0000000..63e1ec9 --- /dev/null +++ b/biz/master/server/create_server.go @@ -0,0 +1,49 @@ +package server + +import ( + "context" + + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/models" + "github.com/VaalaCat/frp-panel/pb" + "github.com/google/uuid" +) + +func InitServerHandler(c context.Context, req *pb.InitServerRequest) (*pb.InitServerResponse, error) { + var ( + userServerID = req.GetServerId() + serverIP = req.GetServerIp() + userInfo = common.GetUserInfo(c) + ) + + if !userInfo.Valid() { + return &pb.InitServerResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid user"}, + }, nil + } + + if len(userServerID) == 0 || len(serverIP) == 0 { + return &pb.InitServerResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "request invalid"}, + }, nil + } + + globalServerID := common.GlobalClientID(userInfo.GetUserName(), userServerID) + + if err := dao.CreateServer(userInfo, + &models.ServerEntity{ + ServerID: globalServerID, + TenantID: userInfo.GetTenantID(), + UserID: userInfo.GetUserID(), + ConnectSecret: uuid.New().String(), + ServerIP: serverIP, + }); err != nil { + return nil, err + } + + return &pb.InitServerResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + ServerId: &globalServerID, + }, nil +} diff --git a/biz/master/server/delete_server.go b/biz/master/server/delete_server.go new file mode 100644 index 0000000..e005ae0 --- /dev/null +++ b/biz/master/server/delete_server.go @@ -0,0 +1,36 @@ +package server + +import ( + "context" + + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/pb" +) + +func DeleteServerHandler(c context.Context, req *pb.DeleteServerRequest) (*pb.DeleteServerResponse, error) { + var ( + userServerID = req.GetServerId() + userInfo = common.GetUserInfo(c) + ) + + if !userInfo.Valid() { + return &pb.DeleteServerResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid user"}, + }, nil + } + + if len(userServerID) == 0 { + return &pb.DeleteServerResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid client id"}, + }, nil + } + + if err := dao.DeleteServer(userInfo, userServerID); err != nil { + return nil, err + } + + return &pb.DeleteServerResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + }, nil +} diff --git a/biz/master/server/delete_tunnel.go b/biz/master/server/delete_tunnel.go new file mode 100644 index 0000000..63dc38f --- /dev/null +++ b/biz/master/server/delete_tunnel.go @@ -0,0 +1,46 @@ +package server + +import ( + "context" + + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/pb" + "github.com/VaalaCat/frp-panel/rpc" + "github.com/sirupsen/logrus" +) + +func RemoveFrpsHandler(c context.Context, req *pb.RemoveFRPSRequest) (*pb.RemoveFRPSResponse, error) { + logrus.Infof("remove frps, req: [%+v]", req) + + var ( + serverID = req.GetServerId() + userInfo = common.GetUserInfo(c) + ) + + srv, err := dao.GetServerByServerID(userInfo, serverID) + if srv == nil || err != nil { + logrus.WithError(err).Errorf("cannot get server, id: [%s]", serverID) + return nil, err + } + + if err = dao.DeleteServer(userInfo, serverID); err != nil { + logrus.WithError(err).Errorf("cannot delete server, id: [%s]", serverID) + return nil, err + } + + go func() { + resp, err := rpc.CallClient(c, req.GetServerId(), pb.Event_EVENT_REMOVE_FRPS, req) + if err != nil { + logrus.WithError(err).Errorf("remove event send to server error, server id: [%s]", req.GetServerId()) + } + + if resp == nil { + logrus.Errorf("cannot get response, server id: [%s]", req.GetServerId()) + } + }() + + return &pb.RemoveFRPSResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + }, nil +} diff --git a/biz/master/server/get_server.go b/biz/master/server/get_server.go new file mode 100644 index 0000000..2f7d3b1 --- /dev/null +++ b/biz/master/server/get_server.go @@ -0,0 +1,43 @@ +package server + +import ( + "context" + + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/pb" + "github.com/samber/lo" +) + +func GetServerHandler(c context.Context, req *pb.GetServerRequest) (*pb.GetServerResponse, error) { + var ( + userServerID = req.GetServerId() + userInfo = common.GetUserInfo(c) + ) + + if !userInfo.Valid() { + return &pb.GetServerResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid user"}, + }, nil + } + + if len(userServerID) == 0 { + return &pb.GetServerResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid client id"}, + }, nil + } + + serverEntity, err := dao.GetServerByServerID(userInfo, userServerID) + if err != nil { + return nil, err + } + + return &pb.GetServerResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + Server: &pb.Server{ + Id: lo.ToPtr(serverEntity.ServerID), + Config: lo.ToPtr(string(serverEntity.ConfigContent)), + Secret: lo.ToPtr(serverEntity.ConnectSecret), + }, + }, nil +} diff --git a/biz/master/server/helper.go b/biz/master/server/helper.go new file mode 100644 index 0000000..46108e8 --- /dev/null +++ b/biz/master/server/helper.go @@ -0,0 +1,34 @@ +package server + +import ( + "fmt" + + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/models" +) + +type ValidateableServerRequest interface { + GetServerSecret() string + GetServerId() string +} + +func ValidateServerRequest(req ValidateableServerRequest) (*models.ServerEntity, error) { + if req == nil { + return nil, fmt.Errorf("invalid request") + } + + if req.GetServerId() == "" || req.GetServerSecret() == "" { + return nil, fmt.Errorf("invalid request") + } + + var ( + cli *models.ServerEntity + err error + ) + + if cli, err = dao.ValidateServerSecret(req.GetServerId(), req.GetServerSecret()); err != nil { + return nil, err + } + + return cli, nil +} diff --git a/biz/master/server/list_server.go b/biz/master/server/list_server.go new file mode 100644 index 0000000..beb7aad --- /dev/null +++ b/biz/master/server/list_server.go @@ -0,0 +1,40 @@ +package server + +import ( + "context" + + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/models" + "github.com/VaalaCat/frp-panel/pb" + "github.com/samber/lo" +) + +func ListServersHandler(c context.Context, req *pb.ListServersRequest) (*pb.ListServersResponse, error) { + var ( + userInfo = common.GetUserInfo(c) + page = int(req.GetPage()) + pageSize = int(req.GetPageSize()) + ) + + if !userInfo.Valid() { + return &pb.ListServersResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid user"}, + }, nil + } + + servers, err := dao.ListServers(userInfo, page, pageSize) + if err != nil { + return nil, err + } + + return &pb.ListServersResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + Servers: lo.Map(servers, func(c *models.ServerEntity, _ int) *pb.Server { + return &pb.Server{ + Id: lo.ToPtr(c.ServerID), + Config: lo.ToPtr(string(c.ConfigContent)), + } + }), + }, nil +} diff --git a/biz/master/server/rpc_frp_auth.go b/biz/master/server/rpc_frp_auth.go new file mode 100644 index 0000000..9ea03d0 --- /dev/null +++ b/biz/master/server/rpc_frp_auth.go @@ -0,0 +1,31 @@ +package server + +import ( + "context" + + "github.com/VaalaCat/frp-panel/models" + "github.com/VaalaCat/frp-panel/pb" + "github.com/sirupsen/logrus" +) + +func FRPAuth(ctx context.Context, req *pb.FRPAuthRequest) (*pb.FRPAuthResponse, error) { + logrus.Infof("frpc auth, req: [%+v]", req) + var ( + err error + cli *models.ServerEntity + ) + + if cli, err = ValidateServerRequest(req.GetBase()); err != nil { + return &pb.FRPAuthResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: err.Error()}, + Ok: false, + }, err + } + + logrus.Infof("frpc auth success, server: [%+v]", cli.ServerID) + + return &pb.FRPAuthResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + Ok: true, + }, nil +} diff --git a/biz/master/server/rpc_pull_config.go b/biz/master/server/rpc_pull_config.go new file mode 100644 index 0000000..575b961 --- /dev/null +++ b/biz/master/server/rpc_pull_config.go @@ -0,0 +1,25 @@ +package server + +import ( + "context" + + "github.com/VaalaCat/frp-panel/models" + "github.com/VaalaCat/frp-panel/pb" + "github.com/samber/lo" +) + +func RPCPullConfig(ctx context.Context, req *pb.PullServerConfigReq) (*pb.PullServerConfigResp, error) { + var cli *models.ServerEntity + var err error + + if cli, err = ValidateServerRequest(req.GetBase()); err != nil { + return nil, err + } + + return &pb.PullServerConfigResp{ + Server: &pb.Server{ + Id: lo.ToPtr(cli.ServerID), + Config: lo.ToPtr(string(cli.ConfigContent)), + }, + }, nil +} diff --git a/biz/master/server/update_tunnel.go b/biz/master/server/update_tunnel.go new file mode 100644 index 0000000..255d405 --- /dev/null +++ b/biz/master/server/update_tunnel.go @@ -0,0 +1,63 @@ +package server + +import ( + "context" + "fmt" + + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/pb" + "github.com/VaalaCat/frp-panel/rpc" + "github.com/VaalaCat/frp-panel/utils" + "github.com/sirupsen/logrus" +) + +func UpdateFrpsHander(c context.Context, req *pb.UpdateFRPSRequest) (*pb.UpdateFRPSResponse, error) { + logrus.Infof("update frps, req: [%+v]", req) + var ( + serverID = req.GetServerId() + configStr = req.GetConfig() + userInfo = common.GetUserInfo(c) + ) + + if len(configStr) == 0 || len(serverID) == 0 { + return nil, fmt.Errorf("request invalid") + } + + srv, err := dao.GetServerByServerID(userInfo, serverID) + if srv == nil || err != nil { + logrus.WithError(err).Errorf("cannot get server, id: [%s]", serverID) + return nil, err + } + + srvCfg, err := utils.LoadServerConfig(configStr, true) + if srvCfg == nil || err != nil { + logrus.WithError(err).Errorf("cannot load server config") + return nil, err + } + + if err := srv.SetConfigContent(srvCfg); err != nil { + logrus.WithError(err).Errorf("cannot set server config") + return nil, err + } + + if err := dao.UpdateServer(userInfo, srv); err != nil { + logrus.WithError(err).Errorf("cannot update server, id: [%s]", serverID) + return nil, err + } + + go func() { + resp, err := rpc.CallClient(c, req.GetServerId(), pb.Event_EVENT_UPDATE_FRPS, req) + if err != nil { + logrus.WithError(err).Errorf("update event send to server error, server id: [%s]", req.GetServerId()) + } + if resp == nil { + logrus.Errorf("cannot get response, server id: [%s]", req.GetServerId()) + } + }() + + logrus.Infof("update frps success, id: [%s]", serverID) + return &pb.UpdateFRPSResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + }, nil +} diff --git a/biz/master/user/get_user_info.go b/biz/master/user/get_user_info.go new file mode 100644 index 0000000..cf2021f --- /dev/null +++ b/biz/master/user/get_user_info.go @@ -0,0 +1,26 @@ +package user + +import ( + "context" + "fmt" + + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/pb" + "github.com/samber/lo" +) + +func GetUserInfoHandler(c context.Context, req *pb.GetUserInfoRequest) (*pb.GetUserInfoResponse, error) { + userInfo := common.GetUserInfo(c) + return &pb.GetUserInfoResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + UserInfo: &pb.User{ + UserID: lo.ToPtr(int64(userInfo.GetUserID())), + TenantID: lo.ToPtr(int64(userInfo.GetTenantID())), + UserName: lo.ToPtr(userInfo.GetUserName()), + Email: lo.ToPtr(userInfo.GetEmail()), + Status: lo.ToPtr(fmt.Sprint(userInfo.GetStatus())), + Role: lo.ToPtr(userInfo.GetRole()), + Token: lo.ToPtr(userInfo.GetToken()), + }, + }, nil +} diff --git a/biz/master/user/update_user_info.go b/biz/master/user/update_user_info.go new file mode 100644 index 0000000..0266f10 --- /dev/null +++ b/biz/master/user/update_user_info.go @@ -0,0 +1,70 @@ +package user + +import ( + "context" + + "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/models" + "github.com/VaalaCat/frp-panel/pb" + "github.com/VaalaCat/frp-panel/utils" + "github.com/sirupsen/logrus" +) + +func UpdateUserInfoHander(c context.Context, req *pb.UpdateUserInfoRequest) (*pb.UpdateUserInfoResponse, error) { + var ( + userInfo = common.GetUserInfo(c) + ) + + if !userInfo.Valid() { + return &pb.UpdateUserInfoResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "invalid user"}, + }, nil + } + newUserEntity := userInfo.(*models.UserEntity) + newUserInfo := req.GetUserInfo() + + if newUserInfo.GetEmail() != "" { + newUserEntity.Email = newUserInfo.GetEmail() + } + + if newUserInfo.GetRawPassword() != "" { + hashedPassword, err := utils.HashPassword(newUserInfo.GetRawPassword()) + if err != nil { + logrus.WithError(err).Errorf("cannot hash password") + return nil, err + } + newUserEntity.Password = hashedPassword + } + + if newUserInfo.GetUserName() != "" { + newUserEntity.UserName = newUserInfo.GetUserName() + } + + if newUserInfo.GetToken() != "" { + newUserEntity.Token = newUserInfo.GetToken() + } + + if err := dao.UpdateUser(userInfo, newUserEntity); err != nil { + return &pb.UpdateUserInfoResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: err.Error()}, + }, err + } + + go func() { + newUser, err := dao.GetUserByUserID(userInfo.GetUserID()) + if err != nil { + logrus.WithError(err).Errorf("cannot get user") + return + } + + if err := client.SyncTunnel(c, newUser); err != nil { + logrus.WithError(err).Errorf("cannot sync tunnel, user need to retry update") + } + }() + + return &pb.UpdateUserInfoResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + }, nil +} diff --git a/biz/server/auth_handler.go b/biz/server/auth_handler.go new file mode 100644 index 0000000..f0a821d --- /dev/null +++ b/biz/server/auth_handler.go @@ -0,0 +1,91 @@ +package server + +import ( + "net/http" + + "github.com/VaalaCat/frp-panel/pb" + "github.com/VaalaCat/frp-panel/rpc" + plugin "github.com/fatedier/frp/pkg/plugin/server" + "github.com/gin-gonic/gin" + "github.com/sirupsen/logrus" +) + +func NewRouter() *gin.Engine { + router := gin.Default() + router.POST("/auth", MakeGinHandlerFunc(HandleLogin)) + return router +} + +type Response struct { + Msg string `json:"msg"` +} + +type HTTPError struct { + Code int + Err error +} + +func (e *HTTPError) Error() string { + return e.Err.Error() +} + +type HandlerFunc func(ctx *gin.Context) (interface{}, error) + +func MakeGinHandlerFunc(handler HandlerFunc) gin.HandlerFunc { + return func(ctx *gin.Context) { + res, err := handler(ctx) + if err != nil { + logrus.Infof("handle %s error: %v", ctx.Request.URL.Path, err) + switch e := err.(type) { + case *HTTPError: + ctx.JSON(e.Code, &Response{Msg: e.Err.Error()}) + default: + ctx.JSON(500, &Response{Msg: err.Error()}) + } + return + } + ctx.JSON(http.StatusOK, res) + } +} + +func HandleLogin(ctx *gin.Context) (interface{}, error) { + var r plugin.Request + var content plugin.LoginContent + r.Content = &content + if err := ctx.BindJSON(&r); err != nil { + return nil, &HTTPError{ + Code: http.StatusBadRequest, + Err: err, + } + } + + var res plugin.Response + token := content.Metas["token"] + if len(content.User) == 0 || len(token) == 0 { + res.Reject = true + res.RejectReason = "user or meta token can not be empty" + return res, nil + } + cli, err := rpc.MasterCli(ctx) + if err != nil { + res.Reject = true + res.RejectReason = "cannot connect to master, please check master is running" + return res, nil + } + + authResponse, err := cli.FRPCAuth(ctx, &pb.FRPAuthRequest{User: content.User, Token: token}) + if err != nil { + res.Reject = true + res.RejectReason = "invalid meta token" + return res, nil + } + + if authResponse.GetOk() { + res.Unchange = true + return res, nil + } + + res.Reject = true + res.RejectReason = "invalid meta token" + return res, nil +} diff --git a/biz/server/remove_tunnel.go b/biz/server/remove_tunnel.go new file mode 100644 index 0000000..2b33521 --- /dev/null +++ b/biz/server/remove_tunnel.go @@ -0,0 +1,35 @@ +package server + +import ( + "context" + "fmt" + + "github.com/VaalaCat/frp-panel/pb" + "github.com/VaalaCat/frp-panel/tunnel" + "github.com/sirupsen/logrus" +) + +func RemoveFrpsHandler(ctx context.Context, req *pb.RemoveFRPSRequest) (*pb.RemoveFRPSResponse, error) { + logrus.Infof("remove frps, req: [%+v]", req) + + if req.GetServerId() == "" { + return &pb.RemoveFRPSResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "server id cannot be empty"}, + }, fmt.Errorf("server id cannot be empty") + } + + srv := tunnel.GetServerController().Get(req.GetServerId()) + if srv == nil { + logrus.Infof("server not found, no need to remove") + return &pb.RemoveFRPSResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: "server not found"}, + }, nil + } + + srv.Stop() + tunnel.GetServerController().Delete(req.GetServerId()) + + return &pb.RemoveFRPSResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + }, nil +} diff --git a/biz/server/rpc_handler.go b/biz/server/rpc_handler.go new file mode 100644 index 0000000..0d53c71 --- /dev/null +++ b/biz/server/rpc_handler.go @@ -0,0 +1,23 @@ +package server + +import ( + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/pb" + "github.com/sirupsen/logrus" +) + +func HandleServerMessage(req *pb.ServerMessage) *pb.ClientMessage { + logrus.Infof("client get a server message, origin is: [%+v]", req) + switch req.Event { + case pb.Event_EVENT_UPDATE_FRPS: + return common.WrapperServerMsg(req, UpdateFrpsHander) + case pb.Event_EVENT_REMOVE_FRPS: + return common.WrapperServerMsg(req, RemoveFrpsHandler) + default: + } + + return &pb.ClientMessage{ + Event: pb.Event_EVENT_ERROR, + Data: []byte("unknown event"), + } +} diff --git a/biz/server/rpc_pull_config.go b/biz/server/rpc_pull_config.go new file mode 100644 index 0000000..95ebc8d --- /dev/null +++ b/biz/server/rpc_pull_config.go @@ -0,0 +1,65 @@ +package server + +import ( + "context" + "reflect" + + "github.com/VaalaCat/frp-panel/pb" + "github.com/VaalaCat/frp-panel/rpc" + "github.com/VaalaCat/frp-panel/services/server" + "github.com/VaalaCat/frp-panel/tunnel" + "github.com/VaalaCat/frp-panel/utils" + "github.com/sirupsen/logrus" +) + +func PullConfig(serverID, serverSecret string) error { + logrus.Infof("start to pull server config, serverID: [%s]", serverID) + ctx := context.Background() + cli, err := rpc.MasterCli(ctx) + if err != nil { + logrus.WithError(err).Error("cannot get master server") + return err + } + resp, err := cli.PullServerConfig(ctx, &pb.PullServerConfigReq{ + Base: &pb.ServerBase{ + ServerId: serverID, + ServerSecret: serverSecret, + }, + }) + if err != nil { + logrus.WithError(err).Error("cannot pull server config") + return err + } + + if len(resp.GetServer().GetConfig()) == 0 { + logrus.Infof("server [%s] config is empty, wait for server init", serverID) + return nil + } + + s, err := utils.LoadServerConfig([]byte(resp.GetServer().GetConfig()), true) + if err != nil { + logrus.WithError(err).Error("cannot load server config") + return err + } + + ctrl := tunnel.GetServerController() + + if t := ctrl.Get(serverID); t == nil { + ctrl.Add(serverID, server.NewServerHandler(s)) + ctrl.Run(serverID) + } else { + if !reflect.DeepEqual(t.GetCommonCfg(), s) { + logrus.Infof("server %s config changed, will recreate it", serverID) + srv := ctrl.Get(serverID) + if srv != nil { + srv.Stop() + ctrl.Delete(serverID) + } + ctrl.Add(serverID, server.NewServerHandler(s)) + ctrl.Run(serverID) + } + } + + logrus.Infof("pull server config success, serverID: [%s]", serverID) + return nil +} diff --git a/biz/server/update_tunnel.go b/biz/server/update_tunnel.go new file mode 100644 index 0000000..4f77802 --- /dev/null +++ b/biz/server/update_tunnel.go @@ -0,0 +1,37 @@ +package server + +import ( + "context" + + "github.com/VaalaCat/frp-panel/pb" + "github.com/VaalaCat/frp-panel/services/server" + "github.com/VaalaCat/frp-panel/tunnel" + "github.com/VaalaCat/frp-panel/utils" + "github.com/sirupsen/logrus" +) + +func UpdateFrpsHander(ctx context.Context, req *pb.UpdateFRPSRequest) (*pb.UpdateFRPSResponse, error) { + logrus.Infof("update frps, req: [%+v]", req) + + content := req.GetConfig() + + s, err := utils.LoadServerConfig(content, true) + if err != nil { + logrus.WithError(err).Errorf("cannot load config") + return &pb.UpdateFRPSResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: err.Error()}, + }, err + } + + serverID := req.GetServerId() + if cli := tunnel.GetServerController().Get(serverID); cli != nil { + cli.Stop() + tunnel.GetClientController().Delete(serverID) + } + tunnel.GetServerController().Add(serverID, server.NewServerHandler(s)) + tunnel.GetServerController().Run(serverID) + + return &pb.UpdateFRPSResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_SUCCESS, Message: "ok"}, + }, nil +} diff --git a/cache/freecache.go b/cache/freecache.go new file mode 100644 index 0000000..89d5a94 --- /dev/null +++ b/cache/freecache.go @@ -0,0 +1,21 @@ +package cache + +import ( + "github.com/VaalaCat/frp-panel/conf" + "github.com/coocood/freecache" + "github.com/sirupsen/logrus" +) + +var ( + cache *freecache.Cache +) + +func InitCache() { + cacheSize := conf.Get().Master.CacheSize * 1024 * 1024 // 100 MB + cache = freecache.NewCache(cacheSize) + logrus.Infof("init cache success, size: %d MB", cacheSize/1024/1024) +} + +func Get() *freecache.Cache { + return cache +} diff --git a/cmd/client.go b/cmd/client.go new file mode 100644 index 0000000..639d4cf --- /dev/null +++ b/cmd/client.go @@ -0,0 +1,47 @@ +package main + +import ( + bizclient "github.com/VaalaCat/frp-panel/biz/client" + "github.com/VaalaCat/frp-panel/pb" + "github.com/VaalaCat/frp-panel/services/rpcclient" + "github.com/VaalaCat/frp-panel/watcher" + "github.com/sirupsen/logrus" + "github.com/sourcegraph/conc" +) + +func runClient(clientID, clientSecret string) { + logrus.Infof("start to run client") + if len(clientSecret) == 0 { + logrus.Fatal("client secret cannot be empty") + } + + if len(clientID) == 0 { + logrus.Fatal("client id cannot be empty") + } + + rpcclient.MustInitClientRPCSerivce( + clientID, + clientSecret, + pb.Event_EVENT_REGISTER_CLIENT, + bizclient.HandleServerMessage, + ) + r := rpcclient.GetClientRPCSerivce() + defer r.Stop() + + w := watcher.NewClient(bizclient.PullConfig, clientID, clientSecret) + defer w.Stop() + + initClientOnce(clientID, clientSecret) + + var wg conc.WaitGroup + wg.Go(r.Run) + wg.Go(w.Run) + wg.Wait() +} + +func initClientOnce(clientID, clientSecret string) { + err := bizclient.PullConfig(clientID, clientSecret) + if err != nil { + logrus.WithError(err).Errorf("cannot pull client config, wait for retry") + } +} diff --git a/cmd/cmd.go b/cmd/cmd.go new file mode 100644 index 0000000..a9c4458 --- /dev/null +++ b/cmd/cmd.go @@ -0,0 +1,61 @@ +package main + +import ( + "fmt" + "os" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +var ( + clientSecret string + clientID string + clientCmd *cobra.Command + serverCmd *cobra.Command + masterCmd *cobra.Command + rootCmd *cobra.Command +) + +func initCommand() { + hostname, err := os.Hostname() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + clientCmd = &cobra.Command{ + Use: "client [-s client secret] [-i client id]", + Short: "run managed frpc", + Run: func(cmd *cobra.Command, args []string) { + runClient(clientID, clientSecret) + }, + } + serverCmd = &cobra.Command{ + Use: "server [-s client secret] [-i client id]", + Short: "run managed frps", + Run: func(cmd *cobra.Command, args []string) { + runServer(clientID, clientSecret) + }, + } + masterCmd = &cobra.Command{ + Use: "master", + Short: "run frp-panel manager", + Run: func(cmd *cobra.Command, args []string) { + runMaster() + }, + } + rootCmd = &cobra.Command{ + Use: "frp-panel", + Short: "frp-panel is a frp panel QwQ", + } + rootCmd.AddCommand(clientCmd, serverCmd, masterCmd) + clientCmd.Flags().StringVarP(&clientSecret, "secret", "s", "", "client secret") + serverCmd.Flags().StringVarP(&clientSecret, "secret", "s", "", "client secret") + clientCmd.Flags().StringVarP(&clientID, "id", "i", hostname, "client id") + serverCmd.Flags().StringVarP(&clientID, "id", "i", hostname, "client id") +} + +func initLogger() { + logrus.SetReportCaller(true) +} diff --git a/cmd/main.go b/cmd/main.go new file mode 100644 index 0000000..a7b474b --- /dev/null +++ b/cmd/main.go @@ -0,0 +1,18 @@ +package main + +import ( + "github.com/VaalaCat/frp-panel/conf" + "github.com/VaalaCat/frp-panel/rpc" + "github.com/VaalaCat/frp-panel/utils" + "github.com/fatedier/golib/crypto" +) + +func main() { + initLogger() + initCommand() + conf.InitConfig() + rpc.InitRPCClients() + + crypto.DefaultSalt = utils.MD5(conf.Get().App.GlobalSecret) + rootCmd.Execute() +} diff --git a/cmd/master.go b/cmd/master.go new file mode 100644 index 0000000..1d4023c --- /dev/null +++ b/cmd/master.go @@ -0,0 +1,64 @@ +package main + +import ( + bizmaster "github.com/VaalaCat/frp-panel/biz/master" + "github.com/VaalaCat/frp-panel/biz/master/auth" + "github.com/VaalaCat/frp-panel/cache" + "github.com/VaalaCat/frp-panel/conf" + "github.com/VaalaCat/frp-panel/models" + "github.com/VaalaCat/frp-panel/services/api" + "github.com/VaalaCat/frp-panel/services/master" + "github.com/VaalaCat/frp-panel/services/server" + "github.com/VaalaCat/frp-panel/utils" + v1 "github.com/fatedier/frp/pkg/config/v1" + "github.com/glebarez/sqlite" + "github.com/sirupsen/logrus" + "github.com/sourcegraph/conc" + "gorm.io/gorm" +) + +func runMaster() { + master.MustInitMasterService() + + router := bizmaster.NewRouter() + api.MustInitApiService(conf.MasterAPIListenAddr(), router) + + initDatabase() + cache.InitCache() + auth.InitAuth() + + logrus.Infof("start to run master") + m := master.GetMasterSerivce() + opt := utils.NewBaseFRPServerUserAuthConfig( + conf.Get().Master.InternalFRPServerPort, + []v1.HTTPPluginOptions{conf.FRPsAuthOption()}, + ) + + s := server.GetServerSerivce(opt) + a := api.GetAPIService() + + var wg conc.WaitGroup + wg.Go(s.Run) + wg.Go(m.Run) + wg.Go(a.Run) + wg.Wait() +} + +func initDatabase() { + logrus.Infof("start to init database, type: %s", conf.Get().DB.Type) + models.MustInitDBManager(nil, conf.Get().DB.Type) + + switch conf.Get().DB.Type { + case "sqlite3": + if sqlitedb, err := gorm.Open(sqlite.Open(conf.Get().DB.DSN), &gorm.Config{}); err != nil { + logrus.Panic(err) + } else { + models.GetDBManager().SetDB("sqlite3", sqlitedb) + logrus.Infof("init database success, data location: [%s]", conf.Get().DB.DSN) + } + default: + logrus.Panicf("currently unsupported database type: %s", conf.Get().DB.Type) + } + + models.GetDBManager().Init() +} diff --git a/cmd/server.go b/cmd/server.go new file mode 100644 index 0000000..07014b1 --- /dev/null +++ b/cmd/server.go @@ -0,0 +1,54 @@ +package main + +import ( + bizserver "github.com/VaalaCat/frp-panel/biz/server" + "github.com/VaalaCat/frp-panel/conf" + "github.com/VaalaCat/frp-panel/pb" + "github.com/VaalaCat/frp-panel/services/api" + "github.com/VaalaCat/frp-panel/services/rpcclient" + "github.com/VaalaCat/frp-panel/watcher" + "github.com/sirupsen/logrus" + "github.com/sourcegraph/conc" +) + +func runServer(clientID, clientSecret string) { + logrus.Infof("start to run server") + + if len(clientID) == 0 { + logrus.Fatal("client id cannot be empty") + } + + router := bizserver.NewRouter() + api.MustInitApiService(conf.ServerAPIListenAddr(), router) + + a := api.GetAPIService() + defer a.Stop() + + rpcclient.MustInitClientRPCSerivce( + clientID, + clientSecret, + pb.Event_EVENT_REGISTER_SERVER, + bizserver.HandleServerMessage, + ) + + r := rpcclient.GetClientRPCSerivce() + defer r.Stop() + + w := watcher.NewClient(bizserver.PullConfig, clientID, clientSecret) + defer w.Stop() + + initServerOnce(clientID, clientSecret) + + var wg conc.WaitGroup + wg.Go(r.Run) + wg.Go(w.Run) + wg.Go(a.Run) + wg.Wait() +} + +func initServerOnce(clientID, clientSecret string) { + err := bizserver.PullConfig(clientID, clientSecret) + if err != nil { + logrus.WithError(err).Errorf("cannot pull server config, wait for retry") + } +} diff --git a/cmd/test.go b/cmd/test.go new file mode 100644 index 0000000..cd955ee --- /dev/null +++ b/cmd/test.go @@ -0,0 +1,20 @@ +package main + +// func serverThings() { +// time.Sleep(5 * time.Second) +// p := pool.New().WithMaxGoroutines(500) +// for i := 0; i < 100000; i++ { +// cnt := i +// p.Go(func() { +// resp := rpc.CallClient(context.Background(), "test", &pb.ServerMessage{ +// Event: pb.Event_EVENT_DATA, +// Data: []byte(fmt.Sprint(cnt)), +// }) +// if string(resp.Data) != fmt.Sprint(cnt) { +// logrus.Panicf("resp: %+v", resp) +// } +// }) +// } +// p.Wait() +// logrus.Infof("finish server things") +// } diff --git a/codegen.sh b/codegen.sh new file mode 100755 index 0000000..1b9f488 --- /dev/null +++ b/codegen.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env /bin/bash + +cd idl && protoc *.proto --go_out=. --go-grpc_out=. && cd .. +cd www && npx protoc --ts_out ./lib/pb -I ../idl --proto_path ../idl/common.proto ../idl/common.proto ../idl/api*.proto && cd .. \ No newline at end of file diff --git a/common/const.go b/common/const.go new file mode 100644 index 0000000..5432132 --- /dev/null +++ b/common/const.go @@ -0,0 +1,47 @@ +package common + +import "time" + +const ( + AuthorizationKey = "authorization" + SetAuthorizationKey = "x-set-authorization" + MsgKey = "msg" + UserIDKey = "x-vaala-userid" + EndpointKey = "endpoint" + IpAddrKey = "ipaddr" + HeaderKey = "header" + MethodKey = "method" + UAKey = "User-Agent" + ContentTypeKey = "Content-Type" + TraceIDKey = "TraceID" + TokenKey = "token" + FRPAuthTokenKey = "token" + ErrKey = "err" + UserInfoKey = "x-vaala-userinfo" +) + +const ( + ErrInvalidRequest = "invalid request" + ErrUserInfoNotValid = "user info not valid" + ErrInternalError = "internal error" + ErrParamNotValid = "param not valid" + ErrDB = "database error" + ErrNotFound = "data not found" + ErrCodeNotFound = "code not found" + ErrCodeAlreadyUsed = "code already used" +) + +const ( + ReqSuccess = "success" +) + +const ( + TimeLayout = time.RFC3339 +) + +const ( + StatusPending = "pending" + StatusSuccess = "success" + StatusFailed = "failed" + StatusDone = "done" +) diff --git a/common/context.go b/common/context.go new file mode 100644 index 0000000..3281d35 --- /dev/null +++ b/common/context.go @@ -0,0 +1,21 @@ +package common + +import ( + "context" + + "github.com/VaalaCat/frp-panel/models" +) + +func GetUserInfo(c context.Context) models.UserInfo { + val := c.Value(UserInfoKey) + if val == nil { + return nil + } + + u, ok := val.(*models.UserEntity) + if !ok { + return nil + } + + return u +} diff --git a/common/helper.go b/common/helper.go new file mode 100644 index 0000000..eab5d25 --- /dev/null +++ b/common/helper.go @@ -0,0 +1,64 @@ +package common + +import ( + "context" + "fmt" + + "github.com/VaalaCat/frp-panel/pb" + "github.com/gin-gonic/gin" + "github.com/sirupsen/logrus" + "google.golang.org/protobuf/proto" +) + +func GlobalClientID(username, clientID string) string { + return fmt.Sprintf("%s.%s", username, clientID) +} + +func Wrapper[T CommonReq, U CommonResp](handler func(context.Context, *T) (*U, error)) func(c *gin.Context) { + return func(c *gin.Context) { + req, err := GetProtoRequest[T](c) + if err != nil { + ErrResp(c, &pb.CommonResponse{ + Status: &pb.Status{Code: pb.RespCode_RESP_CODE_INVALID, Message: err.Error()}, + }, err.Error()) + return + } + + resp, err := handler(c, req) + if err != nil { + ErrResp(c, resp, err.Error()) + return + } + + OKResp(c, resp) + } +} + +func WrapperServerMsg[T CommonReq, U CommonResp](req *pb.ServerMessage, handler func(context.Context, *T) (*U, error)) *pb.ClientMessage { + r := new(T) + GetServerMessageRequest(req.GetData(), r, proto.Unmarshal) + if err := GetServerMessageRequest(req.GetData(), r, proto.Unmarshal); err != nil { + logrus.WithError(err).Errorf("cannot unmarshal") + return nil + } + + ctx := context.Background() + resp, err := handler(ctx, r) + if err != nil { + logrus.WithError(err).Errorf("handler error") + return &pb.ClientMessage{ + Event: pb.Event_EVENT_ERROR, + Data: []byte(err.Error()), + } + } + + cliMsg, err := ProtoResp(resp) + if err != nil { + logrus.WithError(err).Errorf("cannot marshal") + return &pb.ClientMessage{ + Event: pb.Event_EVENT_ERROR, + Data: []byte(err.Error()), + } + } + return cliMsg +} diff --git a/common/request.go b/common/request.go new file mode 100644 index 0000000..76403a0 --- /dev/null +++ b/common/request.go @@ -0,0 +1,84 @@ +package common + +import ( + "fmt" + + "github.com/VaalaCat/frp-panel/pb" + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/reflect/protoreflect" +) + +type CommonReq interface { + pb.UpdateFRPCRequest | pb.RemoveFRPCRequest | + pb.UpdateFRPSRequest | pb.RemoveFRPSRequest | + pb.CommonResponse | pb.RegisterRequest | pb.LoginRequest | + pb.InitClientRequest | pb.ListClientsRequest | pb.GetClientRequest | + pb.DeleteClientRequest | + pb.InitServerRequest | pb.ListServersRequest | pb.GetServerRequest | + pb.DeleteServerRequest | + pb.GetUserInfoRequest | pb.UpdateUserInfoRequest +} + +func GetProtoRequest[T CommonReq](c *gin.Context) (r *T, err error) { + r = new(T) + if c.ContentType() == "application/x-protobuf" { + err = c.Copy().ShouldBindWith(r, binding.ProtoBuf) + if err != nil { + return nil, err + } + } else { + b, err := c.Copy().GetRawData() + if err != nil { + return nil, err + } + + err = GetServerMessageRequest(b, r, protojson.Unmarshal) + if err != nil { + return nil, err + } + } + return r, nil +} + +func GetServerMessageRequest[T CommonReq](b []byte, r *T, trans func(b []byte, m protoreflect.ProtoMessage) error) (err error) { + switch ptr := any(r).(type) { + case *pb.CommonResponse: + 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) + default: + } + return fmt.Errorf("cannot unmarshal unknown type: %T", r) +} diff --git a/common/response.go b/common/response.go new file mode 100644 index 0000000..6519d6a --- /dev/null +++ b/common/response.go @@ -0,0 +1,101 @@ +package common + +import ( + "fmt" + "net/http" + + "github.com/VaalaCat/frp-panel/pb" + "github.com/gin-gonic/gin" + "google.golang.org/protobuf/proto" +) + +type CommonResp interface { + pb.UpdateFRPCResponse | pb.RemoveFRPCResponse | + pb.UpdateFRPSResponse | pb.RemoveFRPSResponse | + pb.CommonResponse | pb.RegisterResponse | pb.LoginResponse | + pb.InitClientResponse | pb.ListClientsResponse | pb.GetClientResponse | + pb.DeleteClientResponse | + pb.InitServerResponse | pb.ListServersResponse | pb.GetServerResponse | + pb.DeleteServerResponse | + pb.GetUserInfoResponse | pb.UpdateUserInfoResponse +} + +func OKResp[T CommonResp](c *gin.Context, origin *T) { + c.Header(TraceIDKey, c.GetString(TraceIDKey)) + if c.ContentType() == "application/x-protobuf" { + c.ProtoBuf(http.StatusOK, origin) + } else { + c.JSON(http.StatusOK, OK(ReqSuccess).WithBody(origin)) + } +} + +func ErrResp[T CommonResp](c *gin.Context, origin *T, err string) { + c.Header(TraceIDKey, c.GetString(TraceIDKey)) + if c.ContentType() == "application/x-protobuf" { + c.ProtoBuf(http.StatusInternalServerError, origin) + } else { + c.JSON(http.StatusOK, Err(err).WithBody(origin)) + } +} + +func ErrUnAuthorized(c *gin.Context, err string) { + c.Header(TraceIDKey, c.GetString(TraceIDKey)) + if c.ContentType() == "application/x-protobuf" { + c.ProtoBuf(http.StatusUnauthorized, + &pb.CommonResponse{Status: &pb.Status{Code: pb.RespCode_RESP_CODE_UNAUTHORIZED, Message: err}}) + } else { + c.JSON(http.StatusOK, Err(err)) + } +} + +func ProtoResp[T CommonResp](origin *T) (*pb.ClientMessage, 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 + 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 + 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 + 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 + 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 + default: + } + return nil, fmt.Errorf("cannot unmarshal unknown type: %T", origin) +} diff --git a/common/result.go b/common/result.go new file mode 100644 index 0000000..b01a026 --- /dev/null +++ b/common/result.go @@ -0,0 +1,55 @@ +package common + +import ( + "github.com/gin-gonic/gin" +) + +type Result struct { + Code int `json:"code,omitempty"` + Msg string `json:"msg,omitempty"` + Data gin.H `json:"data,omitempty"` + Body interface{} `json:"body,omitempty"` +} + +func (r *Result) WithMsg(message string) *Result { + r.Msg = message + return r +} + +func (r *Result) WithData(data gin.H) *Result { + r.Data = data + return r +} + +func (r *Result) WithKeyValue(key string, value interface{}) *Result { + if r.Data == nil { + r.Data = gin.H{} + } + r.Data[key] = value + return r +} + +func (r *Result) WithBody(body interface{}) *Result { + r.Body = body + return r +} + +func newResult(code int, msg string) *Result { + return &Result{ + Code: code, + Msg: msg, + Data: nil, + } +} + +func OK(msg string) *Result { + return newResult(200, msg) +} + +func Err(msg string) *Result { + return newResult(500, msg) +} + +func UnAuth(msg string) *Result { + return newResult(401, msg) +} diff --git a/conf/helper.go b/conf/helper.go new file mode 100644 index 0000000..928c77d --- /dev/null +++ b/conf/helper.go @@ -0,0 +1,77 @@ +package conf + +import ( + "fmt" + "net/url" + "time" + + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/utils" + v1 "github.com/fatedier/frp/pkg/config/v1" + "github.com/sirupsen/logrus" +) + +func RPCListenAddr() string { + cfg := Get() + return fmt.Sprintf(":%d", cfg.Master.RPCPort) +} + +func RPCCallAddr() string { + cfg := Get() + return fmt.Sprintf("%s:%d", cfg.Master.RPCHost, cfg.Master.RPCPort) +} + +func InternalFRPServerToken() string { + cfg := Get() + return utils.MD5(fmt.Sprintf("%s:%d:%s", + cfg.Master.InternalFRPServerHost, + cfg.Master.InternalFRPServerPort, + cfg.App.GlobalSecret)) +} + +func JWTSecret() string { + cfg := Get() + return utils.SHA1(fmt.Sprintf("%s:%d:%s", cfg.Master.APIHost, cfg.Master.APIPort, cfg.App.GlobalSecret)) +} + +func MasterAPIListenAddr() string { + cfg := Get() + return fmt.Sprintf(":%d", cfg.Master.APIPort) +} + +func ServerAPIListenAddr() string { + cfg := Get() + return fmt.Sprintf(":%d", cfg.Server.APIPort) +} + +func FRPsAuthOption() v1.HTTPPluginOptions { + cfg := Get() + authUrl, err := url.Parse(fmt.Sprintf("http://%s:%d%s", cfg.Master.InternalFRPAuthServerHost, + cfg.Master.InternalFRPAuthServerPort, + cfg.Master.InternalFRPAuthServerPath)) + if err != nil { + logrus.WithError(err).Fatalf("parse auth url error") + } + return v1.HTTPPluginOptions{ + Name: "multiuser", + Ops: []string{"Login"}, + Addr: authUrl.Host, + Path: authUrl.Path, + } +} + +func GetCommonJWT(uid string) string { + token, _ := utils.GetJwtTokenFromMap(JWTSecret(), + time.Now().Unix(), + int64(Get().App.CookieAge), + map[string]string{common.UserIDKey: uid}) + return token +} + +func GetCommonJWTWithExpireTime(uid string, expSec int) string { + token, _ := utils.GetJwtTokenFromMap(JWTSecret(), + time.Now().Unix(), + int64(expSec), + map[string]string{common.UserIDKey: uid}) + return token +} diff --git a/conf/settings.go b/conf/settings.go new file mode 100644 index 0000000..398d699 --- /dev/null +++ b/conf/settings.go @@ -0,0 +1,74 @@ +package conf + +import ( + "github.com/ilyakaznacheev/cleanenv" + "github.com/joho/godotenv" + "github.com/sirupsen/logrus" +) + +type Config struct { + App struct { + GlobalSecret string `env:"GLOBAL_SECRET" env-required:"true" env-description:"global secret, used in manager gen secret, keep it safe"` + CookieAge int `env:"COOKIE_AGE" env-default:"86400" env-description:"cookie age in second, default is 1 day"` + CookieName string `env:"COOKIE_NAME" env-default:"frp-panel-cookie" env-description:"cookie name"` + CookiePath string `env:"COOKIE_PATH" env-default:"/" env-description:"cookie path"` + CookieDomain string `env:"COOKIE_DOMAIN" env-default:"" env-description:"cookie domain"` + CookieSecure bool `env:"COOKIE_SECURE" env-default:"false" env-description:"cookie secure"` + CookieHTTPOnly bool `env:"COOKIE_HTTP_ONLY" env-default:"true" env-description:"cookie http only"` + } `env-prefix:"APP_"` + Master struct { + APIPort int `env:"API_PORT" env-default:"9000" env-description:"master api port"` + APIHost string `env:"API_HOST" env-description:"master host, can behind proxy like cdn"` + CacheSize int `env:"CACHE_SIZE" env-default:"100" env-description:"cache size in MB"` + RPCHost string `env:"RPC_HOST" env-required:"true" env-description:"master host, is a public ip or domain"` + RPCPort int `env:"RPC_PORT" env-default:"9001" env-description:"master rpc port"` + InternalFRPServerHost string `env:"INTERNAL_FRP_SERVER_HOST" env-description:"internal frp server host, used for client connection"` + InternalFRPServerPort int `env:"INTERNAL_FRP_SERVER_PORT" env-default:"9002" env-description:"internal frp server port, used for client connection"` + InternalFRPAuthServerHost string `env:"INTERNAL_FRP_AUTH_SERVER_HOST" env-default:"127.0.0.1" env-description:"internal frp auth server host"` + InternalFRPAuthServerPort int `env:"INTERNAL_FRP_AUTH_SERVER_PORT" env-default:"9000" env-description:"internal frp auth server port"` + InternalFRPAuthServerPath string `env:"INTERNAL_FRP_AUTH_SERVER_PATH" env-default:"/auth" env-description:"internal frp auth server path"` + } `env-prefix:"MASTER_"` + Server struct { + APIPort int `env:"API_PORT" env-default:"8999" env-description:"server api port"` + } `env-prefix:"SERVER_"` + DB struct { + Type string `env:"TYPE" env-default:"sqlite3" env-description:"db type, mysql or sqlite3 and so on"` + DSN string `env:"DSN" env-default:"data.db" env-description:"db dsn, for sqlite is path, other is dsn, look at https://github.com/go-sql-driver/mysql#dsn-data-source-name"` + } `env-prefix:"DB_"` +} + +var ( + config *Config +) + +func Get() *Config { + return config +} + +func InitConfig() { + var ( + err error + ) + + if err = godotenv.Load(); err != nil { + logrus.Infof("Error loading .env file, will use runtime env") + } + + cfg := Config{} + if err = cleanenv.ReadEnv(&cfg); err != nil { + logrus.Panic(err) + } + cfg.Complete() + + config = &cfg +} + +func (cfg *Config) Complete() { + if len(cfg.Master.InternalFRPServerHost) == 0 { + cfg.Master.InternalFRPServerHost = cfg.Master.RPCHost + } + + if len(cfg.Master.APIHost) == 0 { + cfg.Master.APIHost = cfg.Master.RPCHost + } +} diff --git a/dao/client.go b/dao/client.go new file mode 100644 index 0000000..b13ada6 --- /dev/null +++ b/dao/client.go @@ -0,0 +1,147 @@ +package dao + +import ( + "fmt" + + "github.com/VaalaCat/frp-panel/models" + "github.com/samber/lo" +) + +func ValidateClientSecret(clientID, clientSecret string) (*models.ClientEntity, error) { + if clientID == "" || clientSecret == "" { + return nil, fmt.Errorf("invalid client id or client secret") + } + db := models.GetDBManager().GetDefaultDB() + c := &models.Client{} + err := db. + Where(&models.Client{ClientEntity: &models.ClientEntity{ + ClientID: clientID, + }}). + First(c).Error + if err != nil { + return nil, err + } + if c.ConnectSecret != clientSecret { + return nil, fmt.Errorf("invalid client secret") + } + return c.ClientEntity, nil +} + +func AdminGetClientByClientID(clientID string) (*models.ClientEntity, error) { + if clientID == "" { + return nil, fmt.Errorf("invalid client id") + } + db := models.GetDBManager().GetDefaultDB() + c := &models.Client{} + err := db. + Where(&models.Client{ClientEntity: &models.ClientEntity{ + ClientID: clientID, + }}). + First(c).Error + if err != nil { + return nil, err + } + return c.ClientEntity, nil +} + +func GetClientByClientID(userInfo models.UserInfo, clientID string) (*models.ClientEntity, error) { + if clientID == "" { + return nil, fmt.Errorf("invalid client id") + } + db := models.GetDBManager().GetDefaultDB() + c := &models.Client{} + err := db. + Where(&models.Client{ClientEntity: &models.ClientEntity{ + UserID: userInfo.GetUserID(), + TenantID: userInfo.GetTenantID(), + ClientID: clientID, + }}). + 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() + c := &models.Client{ + ClientEntity: client, + } + db := models.GetDBManager().GetDefaultDB() + return db.Create(c).Error +} + +func DeleteClient(userInfo models.UserInfo, clientID string) error { + if clientID == "" { + return fmt.Errorf("invalid client id") + } + db := models.GetDBManager().GetDefaultDB() + return db.Unscoped().Where(&models.Client{ + ClientEntity: &models.ClientEntity{ + ClientID: clientID, + UserID: userInfo.GetUserID(), + TenantID: userInfo.GetTenantID(), + }, + }).Delete(&models.Client{ + ClientEntity: &models.ClientEntity{ + ClientID: clientID, + }, + }).Error +} + +func UpdateClient(userInfo models.UserInfo, client *models.ClientEntity) error { + c := &models.Client{ + ClientEntity: client, + } + db := models.GetDBManager().GetDefaultDB() + return db.Where(&models.Client{ + ClientEntity: &models.ClientEntity{ + UserID: userInfo.GetUserID(), + TenantID: userInfo.GetTenantID(), + }, + }).Save(c).Error +} + +func ListClients(userInfo models.UserInfo, page, pageSize int) ([]*models.ClientEntity, error) { + if page < 1 || pageSize < 1 { + return nil, fmt.Errorf("invalid page or page size") + } + + db := models.GetDBManager().GetDefaultDB() + offset := (page - 1) * pageSize + + var clients []*models.Client + err := db.Where(&models.Client{ + ClientEntity: &models.ClientEntity{ + UserID: userInfo.GetUserID(), + TenantID: userInfo.GetTenantID(), + }, + }).Offset(offset).Limit(pageSize).Find(&clients).Error + if err != nil { + return nil, err + } + + return lo.Map(clients, func(c *models.Client, _ int) *models.ClientEntity { + return c.ClientEntity + }), nil +} + +func GetAllClients(userInfo models.UserInfo) ([]*models.ClientEntity, error) { + db := models.GetDBManager().GetDefaultDB() + var clients []*models.Client + err := db.Where(&models.Client{ + ClientEntity: &models.ClientEntity{ + UserID: userInfo.GetUserID(), + TenantID: userInfo.GetTenantID(), + }, + }).Find(&clients).Error + if err != nil { + return nil, err + } + + return lo.Map(clients, func(c *models.Client, _ int) *models.ClientEntity { + return c.ClientEntity + }), nil +} diff --git a/dao/server.go b/dao/server.go new file mode 100644 index 0000000..a74ee5c --- /dev/null +++ b/dao/server.go @@ -0,0 +1,134 @@ +package dao + +import ( + "fmt" + + "github.com/VaalaCat/frp-panel/models" + "github.com/samber/lo" +) + +func ValidateServerSecret(serverID string, secret string) (*models.ServerEntity, error) { + if serverID == "" || secret == "" { + return nil, fmt.Errorf("invalid request") + } + db := models.GetDBManager().GetDefaultDB() + c := &models.Server{} + err := db. + Where(&models.Server{ServerEntity: &models.ServerEntity{ + ServerID: serverID, + }}). + First(c).Error + if err != nil { + return nil, err + } + if c.ConnectSecret != secret { + return nil, fmt.Errorf("invalid secret") + } + return c.ServerEntity, nil +} + +func AdminGetServerByServerID(serverID string) (*models.ServerEntity, error) { + if serverID == "" { + return nil, fmt.Errorf("invalid server id") + } + db := models.GetDBManager().GetDefaultDB() + c := &models.Server{} + err := db. + Where(&models.Server{ServerEntity: &models.ServerEntity{ + ServerID: serverID, + }}). + First(c).Error + if err != nil { + return nil, err + } + return c.ServerEntity, nil +} + +func GetServerByServerID(userInfo models.UserInfo, serverID string) (*models.ServerEntity, error) { + if serverID == "" { + return nil, fmt.Errorf("invalid server id") + } + db := models.GetDBManager().GetDefaultDB() + c := &models.Server{} + err := db. + Where(&models.Server{ServerEntity: &models.ServerEntity{ + TenantID: userInfo.GetTenantID(), + UserID: userInfo.GetUserID(), + ServerID: serverID, + }}). + First(c).Error + if err != nil { + return nil, err + } + return c.ServerEntity, nil +} + +func CreateServer(userInfo models.UserInfo, server *models.ServerEntity) error { + server.UserID = userInfo.GetUserID() + server.TenantID = userInfo.GetTenantID() + c := &models.Server{ + ServerEntity: server, + } + db := models.GetDBManager().GetDefaultDB() + return db.Create(c).Error +} + +func DeleteServer(userInfo models.UserInfo, serverID string) error { + if serverID == "" { + return fmt.Errorf("invalid server id") + } + db := models.GetDBManager().GetDefaultDB() + return db.Unscoped().Where( + &models.Server{ + ServerEntity: &models.ServerEntity{ + TenantID: userInfo.GetTenantID(), + UserID: userInfo.GetUserID(), + }, + }, + ).Delete(&models.Server{ + ServerEntity: &models.ServerEntity{ + ServerID: serverID, + }, + }).Error +} + +func UpdateServer(userInfo models.UserInfo, server *models.ServerEntity) error { + c := &models.Server{ + ServerEntity: server, + } + db := models.GetDBManager().GetDefaultDB() + return db.Where( + &models.Server{ + ServerEntity: &models.ServerEntity{ + UserID: userInfo.GetUserID(), + TenantID: userInfo.GetTenantID(), + }, + }, + ).Save(c).Error +} + +func ListServers(userInfo models.UserInfo, page, pageSize int) ([]*models.ServerEntity, error) { + if page < 1 || pageSize < 1 { + return nil, fmt.Errorf("invalid page or page size") + } + + db := models.GetDBManager().GetDefaultDB() + offset := (page - 1) * pageSize + + var servers []*models.Server + err := db.Where( + &models.Server{ + ServerEntity: &models.ServerEntity{ + UserID: userInfo.GetUserID(), + TenantID: userInfo.GetTenantID(), + }, + }, + ).Offset(offset).Limit(pageSize).Find(&servers).Error + if err != nil { + return nil, err + } + + return lo.Map(servers, func(c *models.Server, _ int) *models.ServerEntity { + return c.ServerEntity + }), nil +} diff --git a/dao/user.go b/dao/user.go new file mode 100644 index 0000000..5a0e766 --- /dev/null +++ b/dao/user.go @@ -0,0 +1,114 @@ +package dao + +import ( + "fmt" + + "github.com/VaalaCat/frp-panel/models" + "github.com/VaalaCat/frp-panel/utils" + "github.com/samber/lo" +) + +func AdminGetAllUsers() ([]*models.UserEntity, error) { + db := models.GetDBManager().GetDefaultDB() + users := make([]*models.User, 0) + err := db.Find(&users).Error + if err != nil { + return nil, err + } + return lo.Map(users, + func(u *models.User, _ int) *models.UserEntity { + return u.UserEntity + }), nil +} + +func GetUserByUserID(userID int) (*models.UserEntity, error) { + if userID == 0 { + return nil, fmt.Errorf("invalid user id") + } + db := models.GetDBManager().GetDefaultDB() + u := &models.User{} + err := db.Where(&models.User{ + UserEntity: &models.UserEntity{ + UserID: userID, + }, + }).First(u).Error + if err != nil { + return nil, err + } + return u.UserEntity, nil +} + +func UpdateUser(userInfo models.UserInfo, user *models.UserEntity) error { + db := models.GetDBManager().GetDefaultDB() + user.UserID = userInfo.GetUserID() + return db.Model(&models.User{}).Where( + &models.User{ + UserEntity: &models.UserEntity{ + UserID: userInfo.GetUserID(), + }, + }, + ).Save(&models.User{ + UserEntity: user, + }).Error +} + +func GetUserByUserName(userName string) (*models.UserEntity, error) { + if userName == "" { + return nil, fmt.Errorf("invalid user name") + } + db := models.GetDBManager().GetDefaultDB() + u := &models.User{} + err := db.Where(&models.User{ + UserEntity: &models.UserEntity{ + UserName: userName, + }, + }).First(u).Error + if err != nil { + return nil, err + } + return u.UserEntity, nil +} + +func CheckUserPassword(userNameOrEmail, password string) (bool, models.UserInfo, error) { + var user models.User + db := models.GetDBManager().GetDefaultDB() + + if err := db.Where(&models.User{ + UserEntity: &models.UserEntity{ + UserName: userNameOrEmail, + }, + }).Or(&models.User{ + UserEntity: &models.UserEntity{ + Email: userNameOrEmail, + }, + }).First(&user).Error; err != nil { + return false, nil, err + } + return utils.CheckPasswordHash(password, user.Password), user, nil +} + +func CheckUserNameAndEmail(userName, email string) error { + var user models.User + db := models.GetDBManager().GetDefaultDB() + + if err := db.Where(&models.User{ + UserEntity: &models.UserEntity{ + UserName: userName, + }, + }).Or(&models.User{ + UserEntity: &models.UserEntity{ + Email: email, + }, + }).First(&user).Error; err != nil { + return err + } + return nil +} + +func CreateUser(user *models.UserEntity) error { + u := &models.User{ + UserEntity: user, + } + db := models.GetDBManager().GetDefaultDB() + return db.Create(u).Error +} diff --git a/doc/callvis.gv b/doc/callvis.gv new file mode 100755 index 0000000..2ac7df4 --- /dev/null +++ b/doc/callvis.gv @@ -0,0 +1,309 @@ +digraph gocallvis { + label="github.com/VaalaCat/frp-panel/cmd"; + labeljust="l"; + fontname="Arial"; + fontsize="14"; + rankdir="LR"; + bgcolor="lightgray"; + style="solid"; + penwidth="0.5"; + pad="0.0"; + nodesep="0.35"; + + node [shape="box" style="filled,rounded" fillcolor="honeydew" fontname="Verdana" penwidth="1.0" margin="0.05,0.0"]; + edge [minlen="2"] + + subgraph "cluster_focus" { + bgcolor="#e6ecfa"; +label="main"; +labelloc="t"; +labeljust="c"; +fontsize="18"; + + "github.com/VaalaCat/frp-panel/cmd.runClient" [ fillcolor="lightblue" label="runClient" penwidth="0.5" tooltip="github.com/VaalaCat/frp-panel/cmd.runClient | defined in client.go:12\nat client.go:31: calling [github.com/VaalaCat/frp-panel/watcher.NewClient]\nat client.go:34: calling [github.com/VaalaCat/frp-panel/cmd.initClientOnce]\nat client.go:28: calling [github.com/VaalaCat/frp-panel/services/rpcclient.GetClientRPCSerivce]\nat client.go:29: calling [(*github.com/VaalaCat/frp-panel/services/rpcclient.ClientRPC).Stop]\nat client.go:22: calling [github.com/VaalaCat/frp-panel/services/rpcclient.MustInitClientRPCSerivce]\nat client.go:32: calling [(*github.com/VaalaCat/frp-panel/watcher.client).Stop]" ] + "github.com/VaalaCat/frp-panel/cmd.initClientOnce" [ label="initClientOnce" penwidth="0.5" tooltip="github.com/VaalaCat/frp-panel/cmd.initClientOnce | defined in client.go:42\nat client.go:43: calling [github.com/VaalaCat/frp-panel/biz/client.PullConfig]" fillcolor="lightblue" ] + "github.com/VaalaCat/frp-panel/cmd.initCommand$1" [ fillcolor="lightblue" label="initCommand$1" style="dotted,filled" tooltip="github.com/VaalaCat/frp-panel/cmd.initCommand$1 | defined in cmd.go:30\nat cmd.go:31: calling [github.com/VaalaCat/frp-panel/cmd.runClient]" ] + "github.com/VaalaCat/frp-panel/cmd.runServer" [ penwidth="0.5" tooltip="github.com/VaalaCat/frp-panel/cmd.runServer | defined in server.go:14\nat server.go:38: calling [(*github.com/VaalaCat/frp-panel/watcher.client).Stop]\nat server.go:37: calling [github.com/VaalaCat/frp-panel/watcher.NewClient]\nat server.go:35: calling [(*github.com/VaalaCat/frp-panel/services/rpcclient.ClientRPC).Stop]\nat server.go:22: calling [github.com/VaalaCat/frp-panel/conf.ServerAPIListenAddr]\nat server.go:24: calling [github.com/VaalaCat/frp-panel/services/api.GetAPIService]\nat server.go:25: calling [(*github.com/VaalaCat/frp-panel/services/api.server).Stop]\nat server.go:21: calling [github.com/VaalaCat/frp-panel/biz/server.NewRouter]\nat server.go:22: calling [github.com/VaalaCat/frp-panel/services/api.MustInitApiService]\nat server.go:40: calling [github.com/VaalaCat/frp-panel/cmd.initServerOnce]\nat server.go:27: calling [github.com/VaalaCat/frp-panel/services/rpcclient.MustInitClientRPCSerivce]\nat server.go:34: calling [github.com/VaalaCat/frp-panel/services/rpcclient.GetClientRPCSerivce]" fillcolor="lightblue" label="runServer" ] + "github.com/VaalaCat/frp-panel/cmd.initServerOnce" [ fillcolor="lightblue" label="initServerOnce" penwidth="0.5" tooltip="github.com/VaalaCat/frp-panel/cmd.initServerOnce | defined in server.go:49\nat server.go:50: calling [github.com/VaalaCat/frp-panel/biz/server.PullConfig]" ] + "github.com/VaalaCat/frp-panel/cmd.initCommand$2" [ fillcolor="lightblue" label="initCommand$2" style="dotted,filled" tooltip="github.com/VaalaCat/frp-panel/cmd.initCommand$2 | defined in cmd.go:37\nat cmd.go:38: calling [github.com/VaalaCat/frp-panel/cmd.runServer]" ] + "github.com/VaalaCat/frp-panel/cmd.runMaster" [ tooltip="github.com/VaalaCat/frp-panel/cmd.runMaster | defined in master.go:20\nat master.go:34: calling [github.com/VaalaCat/frp-panel/conf.FRPsAuthOption]\nat master.go:28: calling [github.com/VaalaCat/frp-panel/biz/master/auth.InitAuth]\nat master.go:37: calling [github.com/VaalaCat/frp-panel/services/server.GetServerSerivce]\nat master.go:23: calling [github.com/VaalaCat/frp-panel/biz/master.NewRouter]\nat master.go:32: calling [github.com/VaalaCat/frp-panel/utils.NewBaseFRPServerUserAuthConfig]\nat master.go:21: calling [github.com/VaalaCat/frp-panel/services/master.MustInitMasterService]\nat master.go:24: calling [github.com/VaalaCat/frp-panel/services/api.MustInitApiService]\nat master.go:26: calling [github.com/VaalaCat/frp-panel/cmd.initDatabase]\nat master.go:33: calling [github.com/VaalaCat/frp-panel/conf.Get]\nat master.go:27: calling [github.com/VaalaCat/frp-panel/cache.InitCache]\nat master.go:24: calling [github.com/VaalaCat/frp-panel/conf.MasterAPIListenAddr]\nat master.go:31: calling [github.com/VaalaCat/frp-panel/services/master.GetMasterSerivce]\nat master.go:38: calling [github.com/VaalaCat/frp-panel/services/api.GetAPIService]" fillcolor="lightblue" label="runMaster" penwidth="0.5" ] + "github.com/VaalaCat/frp-panel/cmd.initDatabase" [ fillcolor="lightblue" label="initDatabase" penwidth="0.5" tooltip="github.com/VaalaCat/frp-panel/cmd.initDatabase | defined in master.go:47\nat master.go:48: calling [github.com/VaalaCat/frp-panel/conf.Get]\nat master.go:49: calling [github.com/VaalaCat/frp-panel/conf.Get]\nat master.go:51: calling [github.com/VaalaCat/frp-panel/conf.Get]\nat master.go:53: calling [github.com/VaalaCat/frp-panel/conf.Get]\nat master.go:60: calling [github.com/VaalaCat/frp-panel/conf.Get]\nat master.go:57: calling [github.com/VaalaCat/frp-panel/conf.Get]\nat master.go:63: calling [github.com/VaalaCat/frp-panel/models.GetDBManager]\nat master.go:56: calling [github.com/VaalaCat/frp-panel/models.GetDBManager]\nat master.go:49: calling [github.com/VaalaCat/frp-panel/models.MustInitDBManager]\nat master.go:56: calling [(*github.com/VaalaCat/frp-panel/models.dbManagerImpl).SetDB]\nat master.go:63: calling [(*github.com/VaalaCat/frp-panel/models.dbManagerImpl).Init]" ] + "github.com/VaalaCat/frp-panel/cmd.initCommand$3" [ style="dotted,filled" tooltip="github.com/VaalaCat/frp-panel/cmd.initCommand$3 | defined in cmd.go:44\nat cmd.go:45: calling [github.com/VaalaCat/frp-panel/cmd.runMaster]" fillcolor="lightblue" label="initCommand$3" ] + "github.com/VaalaCat/frp-panel/cmd.main" [ fillcolor="lightblue" label="main" penwidth="0.5" tooltip="github.com/VaalaCat/frp-panel/cmd.main | defined in main.go:10\nat main.go:16: calling [github.com/VaalaCat/frp-panel/utils.MD5]\nat main.go:13: calling [github.com/VaalaCat/frp-panel/conf.InitConfig]\nat main.go:14: calling [github.com/VaalaCat/frp-panel/rpc.InitRPCClients]\nat main.go:16: calling [github.com/VaalaCat/frp-panel/conf.Get]\nat main.go:12: calling [github.com/VaalaCat/frp-panel/cmd.initCommand]\nat main.go:11: calling [github.com/VaalaCat/frp-panel/cmd.initLogger]" ] + "github.com/VaalaCat/frp-panel/cmd.initLogger" [ fillcolor="lightblue" label="initLogger" penwidth="0.5" tooltip="github.com/VaalaCat/frp-panel/cmd.initLogger | defined in cmd.go:59" ] + "github.com/VaalaCat/frp-panel/cmd.initCommand" [ penwidth="0.5" tooltip="github.com/VaalaCat/frp-panel/cmd.initCommand | defined in cmd.go:20" fillcolor="lightblue" label="initCommand" ] + + subgraph "cluster_github.com/VaalaCat/frp-panel/biz/client" { + fontsize="16"; +URL="/?f=github.com/VaalaCat/frp-panel/biz/client"; +fontname="Tahoma bold"; +rank="sink"; +label="client"; +tooltip="package: github.com/VaalaCat/frp-panel/biz/client"; +penwidth="0.8"; +style="filled"; +fillcolor="lightyellow"; + + "github.com/VaalaCat/frp-panel/biz/client.PullConfig" [ fillcolor="moccasin" label="PullConfig" penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/biz/client.PullConfig | defined in rpc_pull_config.go:15" ] + + } + + subgraph "cluster_github.com/VaalaCat/frp-panel/biz/master" { + penwidth="0.8"; +style="filled"; +rank="sink"; +tooltip="package: github.com/VaalaCat/frp-panel/biz/master"; +fontsize="16"; +fillcolor="lightyellow"; +fontname="Tahoma bold"; +label="master"; +URL="/?f=github.com/VaalaCat/frp-panel/biz/master"; + + "github.com/VaalaCat/frp-panel/biz/master.NewRouter" [ penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/biz/master.NewRouter | defined in handler.go:13" fillcolor="moccasin" label="NewRouter" ] + + } + + subgraph "cluster_github.com/VaalaCat/frp-panel/biz/master/auth" { + fillcolor="lightyellow"; +label="auth"; +URL="/?f=github.com/VaalaCat/frp-panel/biz/master/auth"; +tooltip="package: github.com/VaalaCat/frp-panel/biz/master/auth"; +penwidth="0.8"; +style="filled"; +fontname="Tahoma bold"; +rank="sink"; +fontsize="16"; + + "github.com/VaalaCat/frp-panel/biz/master/auth.InitAuth" [ label="InitAuth" penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/biz/master/auth.InitAuth | defined in init.go:11" fillcolor="moccasin" ] + + } + + subgraph "cluster_github.com/VaalaCat/frp-panel/biz/server" { + fillcolor="lightyellow"; +fontname="Tahoma bold"; +URL="/?f=github.com/VaalaCat/frp-panel/biz/server"; +tooltip="package: github.com/VaalaCat/frp-panel/biz/server"; +penwidth="0.8"; +style="filled"; +label="server"; +fontsize="16"; +rank="sink"; + + "github.com/VaalaCat/frp-panel/biz/server.NewRouter" [ fillcolor="moccasin" label="NewRouter" penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/biz/server.NewRouter | defined in auth_handler.go:13" ] + "github.com/VaalaCat/frp-panel/biz/server.PullConfig" [ tooltip="github.com/VaalaCat/frp-panel/biz/server.PullConfig | defined in rpc_pull_config.go:15" fillcolor="moccasin" label="PullConfig" penwidth="1.5" ] + + } + + subgraph "cluster_github.com/VaalaCat/frp-panel/cache" { + tooltip="package: github.com/VaalaCat/frp-panel/cache"; +fontsize="16"; +style="filled"; +fillcolor="lightyellow"; +rank="sink"; +penwidth="0.8"; +fontname="Tahoma bold"; +label="cache"; +URL="/?f=github.com/VaalaCat/frp-panel/cache"; + + "github.com/VaalaCat/frp-panel/cache.InitCache" [ label="InitCache" penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/cache.InitCache | defined in freecache.go:13" fillcolor="moccasin" ] + + } + + subgraph "cluster_github.com/VaalaCat/frp-panel/conf" { + URL="/?f=github.com/VaalaCat/frp-panel/conf"; +tooltip="package: github.com/VaalaCat/frp-panel/conf"; +style="filled"; +rank="sink"; +fillcolor="lightyellow"; +fontname="Tahoma bold"; +label="conf"; +penwidth="0.8"; +fontsize="16"; + + "github.com/VaalaCat/frp-panel/conf.ServerAPIListenAddr" [ label="ServerAPIListenAddr" penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/conf.ServerAPIListenAddr | defined in helper.go:42" fillcolor="moccasin" ] + "github.com/VaalaCat/frp-panel/conf.MasterAPIListenAddr" [ tooltip="github.com/VaalaCat/frp-panel/conf.MasterAPIListenAddr | defined in helper.go:37" fillcolor="moccasin" label="MasterAPIListenAddr" penwidth="1.5" ] + "github.com/VaalaCat/frp-panel/conf.Get" [ tooltip="github.com/VaalaCat/frp-panel/conf.Get | defined in settings.go:44" fillcolor="moccasin" label="Get" penwidth="1.5" ] + "github.com/VaalaCat/frp-panel/conf.FRPsAuthOption" [ fillcolor="moccasin" label="FRPsAuthOption" penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/conf.FRPsAuthOption | defined in helper.go:47" ] + "github.com/VaalaCat/frp-panel/conf.InitConfig" [ label="InitConfig" penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/conf.InitConfig | defined in settings.go:48" fillcolor="moccasin" ] + + } + + subgraph "cluster_github.com/VaalaCat/frp-panel/models" { + fontsize="16"; +fillcolor="lightyellow"; +label="models"; +URL="/?f=github.com/VaalaCat/frp-panel/models"; +tooltip="package: github.com/VaalaCat/frp-panel/models"; +penwidth="0.8"; +style="filled"; +fontname="Tahoma bold"; +rank="sink"; + + "github.com/VaalaCat/frp-panel/models.MustInitDBManager" [ fillcolor="moccasin" label="MustInitDBManager" penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/models.MustInitDBManager | defined in db.go:39" ] + "github.com/VaalaCat/frp-panel/models.GetDBManager" [ fillcolor="moccasin" label="GetDBManager" penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/models.GetDBManager | defined in db.go:55" ] + "(*github.com/VaalaCat/frp-panel/models.dbManagerImpl).Init" [ fillcolor="moccasin" label="(*dbManagerImpl).Init" penwidth="1.5" tooltip="(*github.com/VaalaCat/frp-panel/models.dbManagerImpl).Init | defined in db.go:21" ] + "(*github.com/VaalaCat/frp-panel/models.dbManagerImpl).SetDB" [ fillcolor="moccasin" label="(*dbManagerImpl).SetDB" penwidth="1.5" tooltip="(*github.com/VaalaCat/frp-panel/models.dbManagerImpl).SetDB | defined in db.go:66" ] + + } + + subgraph "cluster_github.com/VaalaCat/frp-panel/rpc" { + style="filled"; +fontname="Tahoma bold"; +tooltip="package: github.com/VaalaCat/frp-panel/rpc"; +penwidth="0.8"; +fillcolor="lightyellow"; +rank="sink"; +label="rpc"; +URL="/?f=github.com/VaalaCat/frp-panel/rpc"; +fontsize="16"; + + "github.com/VaalaCat/frp-panel/rpc.InitRPCClients" [ penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/rpc.InitRPCClients | defined in init.go:3" fillcolor="moccasin" label="InitRPCClients" ] + + } + + subgraph "cluster_github.com/VaalaCat/frp-panel/services/api" { + URL="/?f=github.com/VaalaCat/frp-panel/services/api"; +penwidth="0.8"; +fontsize="16"; +rank="sink"; +label="api"; +style="filled"; +fillcolor="lightyellow"; +fontname="Tahoma bold"; +tooltip="package: github.com/VaalaCat/frp-panel/services/api"; + + "github.com/VaalaCat/frp-panel/services/api.MustInitApiService" [ tooltip="github.com/VaalaCat/frp-panel/services/api.MustInitApiService | defined in service.go:29" fillcolor="moccasin" label="MustInitApiService" penwidth="1.5" ] + "github.com/VaalaCat/frp-panel/services/api.GetAPIService" [ fillcolor="moccasin" label="GetAPIService" penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/services/api.GetAPIService | defined in service.go:33" ] + "(*github.com/VaalaCat/frp-panel/services/api.server).Stop" [ tooltip="(*github.com/VaalaCat/frp-panel/services/api.server).Stop | defined in service.go:41" fillcolor="moccasin" label="(*server).Stop" penwidth="1.5" ] + + } + + subgraph "cluster_github.com/VaalaCat/frp-panel/services/master" { + style="filled"; +fillcolor="lightyellow"; +rank="sink"; +label="master"; +penwidth="0.8"; +fontsize="16"; +fontname="Tahoma bold"; +URL="/?f=github.com/VaalaCat/frp-panel/services/master"; +tooltip="package: github.com/VaalaCat/frp-panel/services/master"; + + "github.com/VaalaCat/frp-panel/services/master.MustInitMasterService" [ fillcolor="moccasin" label="MustInitMasterService" penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/services/master.MustInitMasterService | defined in grpc_service.go:21" ] + "github.com/VaalaCat/frp-panel/services/master.GetMasterSerivce" [ fillcolor="moccasin" label="GetMasterSerivce" penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/services/master.GetMasterSerivce | defined in grpc_service.go:29" ] + + } + + subgraph "cluster_github.com/VaalaCat/frp-panel/services/rpcclient" { + fontsize="16"; +fontname="Tahoma bold"; +URL="/?f=github.com/VaalaCat/frp-panel/services/rpcclient"; +tooltip="package: github.com/VaalaCat/frp-panel/services/rpcclient"; +penwidth="0.8"; +fillcolor="lightyellow"; +rank="sink"; +label="rpcclient"; +style="filled"; + + "github.com/VaalaCat/frp-panel/services/rpcclient.MustInitClientRPCSerivce" [ penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/services/rpcclient.MustInitClientRPCSerivce | defined in rpc_service.go:27" fillcolor="moccasin" label="MustInitClientRPCSerivce" ] + "github.com/VaalaCat/frp-panel/services/rpcclient.GetClientRPCSerivce" [ tooltip="github.com/VaalaCat/frp-panel/services/rpcclient.GetClientRPCSerivce | defined in rpc_service.go:35" fillcolor="moccasin" label="GetClientRPCSerivce" penwidth="1.5" ] + "(*github.com/VaalaCat/frp-panel/services/rpcclient.ClientRPC).Stop" [ fillcolor="moccasin" label="(*ClientRPC).Stop" penwidth="1.5" tooltip="(*github.com/VaalaCat/frp-panel/services/rpcclient.ClientRPC).Stop | defined in rpc_service.go:62" ] + + } + + subgraph "cluster_github.com/VaalaCat/frp-panel/services/server" { + tooltip="package: github.com/VaalaCat/frp-panel/services/server"; +fontsize="16"; +style="filled"; +fontname="Tahoma bold"; +label="server"; +penwidth="0.8"; +fillcolor="lightyellow"; +rank="sink"; +URL="/?f=github.com/VaalaCat/frp-panel/services/server"; + + "github.com/VaalaCat/frp-panel/services/server.GetServerSerivce" [ penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/services/server.GetServerSerivce | defined in frps_service.go:45" fillcolor="moccasin" label="GetServerSerivce" ] + + } + + subgraph "cluster_github.com/VaalaCat/frp-panel/utils" { + penwidth="0.8"; +fontsize="16"; +style="filled"; +fillcolor="lightyellow"; +URL="/?f=github.com/VaalaCat/frp-panel/utils"; +fontname="Tahoma bold"; +rank="sink"; +label="utils"; +tooltip="package: github.com/VaalaCat/frp-panel/utils"; + + "github.com/VaalaCat/frp-panel/utils.NewBaseFRPServerUserAuthConfig" [ penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/utils.NewBaseFRPServerUserAuthConfig | defined in frp_config.go:19" fillcolor="moccasin" label="NewBaseFRPServerUserAuthConfig" ] + "github.com/VaalaCat/frp-panel/utils.MD5" [ label="MD5" penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/utils.MD5 | defined in hash.go:12" fillcolor="moccasin" ] + + } + + subgraph "cluster_github.com/VaalaCat/frp-panel/watcher" { + style="filled"; +fillcolor="lightyellow"; +fontname="Tahoma bold"; +rank="sink"; +label="watcher"; +penwidth="0.8"; +URL="/?f=github.com/VaalaCat/frp-panel/watcher"; +tooltip="package: github.com/VaalaCat/frp-panel/watcher"; +fontsize="16"; + + "github.com/VaalaCat/frp-panel/watcher.NewClient" [ fillcolor="moccasin" label="NewClient" penwidth="1.5" tooltip="github.com/VaalaCat/frp-panel/watcher.NewClient | defined in client.go:17" ] + "(*github.com/VaalaCat/frp-panel/watcher.client).Stop" [ fillcolor="moccasin" label="(*client).Stop" penwidth="1.5" tooltip="(*github.com/VaalaCat/frp-panel/watcher.client).Stop | defined in client.go:40" ] + + } + + } + + "github.com/VaalaCat/frp-panel/cmd.runClient" -> "github.com/VaalaCat/frp-panel/watcher.NewClient" [ color="saddlebrown" tooltip="at client.go:31: calling [github.com/VaalaCat/frp-panel/watcher.NewClient]" ] + "github.com/VaalaCat/frp-panel/cmd.initClientOnce" -> "github.com/VaalaCat/frp-panel/biz/client.PullConfig" [ color="saddlebrown" tooltip="at client.go:43: calling [github.com/VaalaCat/frp-panel/biz/client.PullConfig]" ] + "github.com/VaalaCat/frp-panel/cmd.runServer" -> "(*github.com/VaalaCat/frp-panel/watcher.client).Stop" [ color="saddlebrown" tooltip="at server.go:38: calling [(*github.com/VaalaCat/frp-panel/watcher.client).Stop]" style="dashed" arrowhead="normalnoneodiamond" ] + "github.com/VaalaCat/frp-panel/cmd.runMaster" -> "github.com/VaalaCat/frp-panel/conf.FRPsAuthOption" [ color="saddlebrown" tooltip="at master.go:34: calling [github.com/VaalaCat/frp-panel/conf.FRPsAuthOption]" ] + "github.com/VaalaCat/frp-panel/cmd.runClient" -> "github.com/VaalaCat/frp-panel/cmd.initClientOnce" [ tooltip="at client.go:34: calling [github.com/VaalaCat/frp-panel/cmd.initClientOnce]" ] + "github.com/VaalaCat/frp-panel/cmd.runServer" -> "github.com/VaalaCat/frp-panel/watcher.NewClient" [ color="saddlebrown" tooltip="at server.go:37: calling [github.com/VaalaCat/frp-panel/watcher.NewClient]" ] + "github.com/VaalaCat/frp-panel/cmd.initCommand$2" -> "github.com/VaalaCat/frp-panel/cmd.runServer" [ tooltip="at cmd.go:38: calling [github.com/VaalaCat/frp-panel/cmd.runServer]" ] + "github.com/VaalaCat/frp-panel/cmd.runMaster" -> "github.com/VaalaCat/frp-panel/biz/master/auth.InitAuth" [ color="saddlebrown" tooltip="at master.go:28: calling [github.com/VaalaCat/frp-panel/biz/master/auth.InitAuth]" ] + "github.com/VaalaCat/frp-panel/cmd.main" -> "github.com/VaalaCat/frp-panel/utils.MD5" [ color="saddlebrown" tooltip="at main.go:16: calling [github.com/VaalaCat/frp-panel/utils.MD5]" ] + "github.com/VaalaCat/frp-panel/cmd.runMaster" -> "github.com/VaalaCat/frp-panel/services/server.GetServerSerivce" [ color="saddlebrown" tooltip="at master.go:37: calling [github.com/VaalaCat/frp-panel/services/server.GetServerSerivce]" ] + "github.com/VaalaCat/frp-panel/cmd.main" -> "github.com/VaalaCat/frp-panel/conf.InitConfig" [ color="saddlebrown" tooltip="at main.go:13: calling [github.com/VaalaCat/frp-panel/conf.InitConfig]" ] + "github.com/VaalaCat/frp-panel/cmd.runClient" -> "github.com/VaalaCat/frp-panel/services/rpcclient.GetClientRPCSerivce" [ color="saddlebrown" tooltip="at client.go:28: calling [github.com/VaalaCat/frp-panel/services/rpcclient.GetClientRPCSerivce]" ] + "github.com/VaalaCat/frp-panel/cmd.runClient" -> "(*github.com/VaalaCat/frp-panel/services/rpcclient.ClientRPC).Stop" [ style="dashed" arrowhead="normalnoneodiamond" color="saddlebrown" tooltip="at client.go:29: calling [(*github.com/VaalaCat/frp-panel/services/rpcclient.ClientRPC).Stop]" ] + "github.com/VaalaCat/frp-panel/cmd.runServer" -> "(*github.com/VaalaCat/frp-panel/services/rpcclient.ClientRPC).Stop" [ style="dashed" arrowhead="normalnoneodiamond" color="saddlebrown" tooltip="at server.go:35: calling [(*github.com/VaalaCat/frp-panel/services/rpcclient.ClientRPC).Stop]" ] + "github.com/VaalaCat/frp-panel/cmd.runMaster" -> "github.com/VaalaCat/frp-panel/biz/master.NewRouter" [ color="saddlebrown" tooltip="at master.go:23: calling [github.com/VaalaCat/frp-panel/biz/master.NewRouter]" ] + "github.com/VaalaCat/frp-panel/cmd.initDatabase" -> "github.com/VaalaCat/frp-panel/conf.Get" [ tooltip="at master.go:48: calling [github.com/VaalaCat/frp-panel/conf.Get]\nat master.go:49: calling [github.com/VaalaCat/frp-panel/conf.Get]\nat master.go:51: calling [github.com/VaalaCat/frp-panel/conf.Get]\nat master.go:53: calling [github.com/VaalaCat/frp-panel/conf.Get]\nat master.go:60: calling [github.com/VaalaCat/frp-panel/conf.Get]\nat master.go:57: calling [github.com/VaalaCat/frp-panel/conf.Get]" color="saddlebrown" ] + "github.com/VaalaCat/frp-panel/cmd.initDatabase" -> "github.com/VaalaCat/frp-panel/models.GetDBManager" [ color="saddlebrown" tooltip="at master.go:63: calling [github.com/VaalaCat/frp-panel/models.GetDBManager]\nat master.go:56: calling [github.com/VaalaCat/frp-panel/models.GetDBManager]" ] + "github.com/VaalaCat/frp-panel/cmd.main" -> "github.com/VaalaCat/frp-panel/rpc.InitRPCClients" [ color="saddlebrown" tooltip="at main.go:14: calling [github.com/VaalaCat/frp-panel/rpc.InitRPCClients]" ] + "github.com/VaalaCat/frp-panel/cmd.main" -> "github.com/VaalaCat/frp-panel/conf.Get" [ tooltip="at main.go:16: calling [github.com/VaalaCat/frp-panel/conf.Get]" color="saddlebrown" ] + "github.com/VaalaCat/frp-panel/cmd.runMaster" -> "github.com/VaalaCat/frp-panel/utils.NewBaseFRPServerUserAuthConfig" [ color="saddlebrown" tooltip="at master.go:32: calling [github.com/VaalaCat/frp-panel/utils.NewBaseFRPServerUserAuthConfig]" ] + "github.com/VaalaCat/frp-panel/cmd.runClient" -> "github.com/VaalaCat/frp-panel/services/rpcclient.MustInitClientRPCSerivce" [ color="saddlebrown" tooltip="at client.go:22: calling [github.com/VaalaCat/frp-panel/services/rpcclient.MustInitClientRPCSerivce]" ] + "github.com/VaalaCat/frp-panel/cmd.runMaster" -> "github.com/VaalaCat/frp-panel/services/master.MustInitMasterService" [ color="saddlebrown" tooltip="at master.go:21: calling [github.com/VaalaCat/frp-panel/services/master.MustInitMasterService]" ] + "github.com/VaalaCat/frp-panel/cmd.runMaster" -> "github.com/VaalaCat/frp-panel/services/api.MustInitApiService" [ color="saddlebrown" tooltip="at master.go:24: calling [github.com/VaalaCat/frp-panel/services/api.MustInitApiService]" ] + "github.com/VaalaCat/frp-panel/cmd.initDatabase" -> "github.com/VaalaCat/frp-panel/models.MustInitDBManager" [ tooltip="at master.go:49: calling [github.com/VaalaCat/frp-panel/models.MustInitDBManager]" color="saddlebrown" ] + "github.com/VaalaCat/frp-panel/cmd.runMaster" -> "github.com/VaalaCat/frp-panel/cmd.initDatabase" [ tooltip="at master.go:26: calling [github.com/VaalaCat/frp-panel/cmd.initDatabase]" ] + "github.com/VaalaCat/frp-panel/cmd.runMaster" -> "github.com/VaalaCat/frp-panel/conf.Get" [ color="saddlebrown" tooltip="at master.go:33: calling [github.com/VaalaCat/frp-panel/conf.Get]" ] + "github.com/VaalaCat/frp-panel/cmd.initCommand$3" -> "github.com/VaalaCat/frp-panel/cmd.runMaster" [ tooltip="at cmd.go:45: calling [github.com/VaalaCat/frp-panel/cmd.runMaster]" ] + "github.com/VaalaCat/frp-panel/cmd.main" -> "github.com/VaalaCat/frp-panel/cmd.initCommand" [ tooltip="at main.go:12: calling [github.com/VaalaCat/frp-panel/cmd.initCommand]" ] + "github.com/VaalaCat/frp-panel/cmd.runServer" -> "github.com/VaalaCat/frp-panel/conf.ServerAPIListenAddr" [ color="saddlebrown" tooltip="at server.go:22: calling [github.com/VaalaCat/frp-panel/conf.ServerAPIListenAddr]" ] + "github.com/VaalaCat/frp-panel/cmd.runServer" -> "github.com/VaalaCat/frp-panel/services/api.GetAPIService" [ color="saddlebrown" tooltip="at server.go:24: calling [github.com/VaalaCat/frp-panel/services/api.GetAPIService]" ] + "github.com/VaalaCat/frp-panel/cmd.initServerOnce" -> "github.com/VaalaCat/frp-panel/biz/server.PullConfig" [ color="saddlebrown" tooltip="at server.go:50: calling [github.com/VaalaCat/frp-panel/biz/server.PullConfig]" ] + "github.com/VaalaCat/frp-panel/cmd.runServer" -> "(*github.com/VaalaCat/frp-panel/services/api.server).Stop" [ color="saddlebrown" tooltip="at server.go:25: calling [(*github.com/VaalaCat/frp-panel/services/api.server).Stop]" style="dashed" arrowhead="normalnoneodiamond" ] + "github.com/VaalaCat/frp-panel/cmd.initDatabase" -> "(*github.com/VaalaCat/frp-panel/models.dbManagerImpl).SetDB" [ style="dashed" color="saddlebrown" tooltip="at master.go:56: calling [(*github.com/VaalaCat/frp-panel/models.dbManagerImpl).SetDB]" ] + "github.com/VaalaCat/frp-panel/cmd.runMaster" -> "github.com/VaalaCat/frp-panel/cache.InitCache" [ color="saddlebrown" tooltip="at master.go:27: calling [github.com/VaalaCat/frp-panel/cache.InitCache]" ] + "github.com/VaalaCat/frp-panel/cmd.runClient" -> "(*github.com/VaalaCat/frp-panel/watcher.client).Stop" [ tooltip="at client.go:32: calling [(*github.com/VaalaCat/frp-panel/watcher.client).Stop]" style="dashed" arrowhead="normalnoneodiamond" color="saddlebrown" ] + "github.com/VaalaCat/frp-panel/cmd.runServer" -> "github.com/VaalaCat/frp-panel/biz/server.NewRouter" [ color="saddlebrown" tooltip="at server.go:21: calling [github.com/VaalaCat/frp-panel/biz/server.NewRouter]" ] + "github.com/VaalaCat/frp-panel/cmd.runServer" -> "github.com/VaalaCat/frp-panel/services/api.MustInitApiService" [ color="saddlebrown" tooltip="at server.go:22: calling [github.com/VaalaCat/frp-panel/services/api.MustInitApiService]" ] + "github.com/VaalaCat/frp-panel/cmd.initDatabase" -> "(*github.com/VaalaCat/frp-panel/models.dbManagerImpl).Init" [ tooltip="at master.go:63: calling [(*github.com/VaalaCat/frp-panel/models.dbManagerImpl).Init]" style="dashed" color="saddlebrown" ] + "github.com/VaalaCat/frp-panel/cmd.initCommand$1" -> "github.com/VaalaCat/frp-panel/cmd.runClient" [ tooltip="at cmd.go:31: calling [github.com/VaalaCat/frp-panel/cmd.runClient]" ] + "github.com/VaalaCat/frp-panel/cmd.runServer" -> "github.com/VaalaCat/frp-panel/cmd.initServerOnce" [ tooltip="at server.go:40: calling [github.com/VaalaCat/frp-panel/cmd.initServerOnce]" ] + "github.com/VaalaCat/frp-panel/cmd.runMaster" -> "github.com/VaalaCat/frp-panel/conf.MasterAPIListenAddr" [ color="saddlebrown" tooltip="at master.go:24: calling [github.com/VaalaCat/frp-panel/conf.MasterAPIListenAddr]" ] + "github.com/VaalaCat/frp-panel/cmd.main" -> "github.com/VaalaCat/frp-panel/cmd.initLogger" [ tooltip="at main.go:11: calling [github.com/VaalaCat/frp-panel/cmd.initLogger]" ] + "github.com/VaalaCat/frp-panel/cmd.runServer" -> "github.com/VaalaCat/frp-panel/services/rpcclient.MustInitClientRPCSerivce" [ color="saddlebrown" tooltip="at server.go:27: calling [github.com/VaalaCat/frp-panel/services/rpcclient.MustInitClientRPCSerivce]" ] + "github.com/VaalaCat/frp-panel/cmd.runServer" -> "github.com/VaalaCat/frp-panel/services/rpcclient.GetClientRPCSerivce" [ color="saddlebrown" tooltip="at server.go:34: calling [github.com/VaalaCat/frp-panel/services/rpcclient.GetClientRPCSerivce]" ] + "github.com/VaalaCat/frp-panel/cmd.runMaster" -> "github.com/VaalaCat/frp-panel/services/master.GetMasterSerivce" [ color="saddlebrown" tooltip="at master.go:31: calling [github.com/VaalaCat/frp-panel/services/master.GetMasterSerivce]" ] + "github.com/VaalaCat/frp-panel/cmd.runMaster" -> "github.com/VaalaCat/frp-panel/services/api.GetAPIService" [ color="saddlebrown" tooltip="at master.go:38: calling [github.com/VaalaCat/frp-panel/services/api.GetAPIService]" ] +} diff --git a/doc/callvis.svg b/doc/callvis.svg new file mode 100644 index 0000000..4cbba39 --- /dev/null +++ b/doc/callvis.svg @@ -0,0 +1,924 @@ + + + + + + +gocallvis + +github.com/VaalaCat/frp-panel/cmd + +cluster_focus + +main + + +cluster_github.com/VaalaCat/frp-panel/watcher + + +watcher + + + + +cluster_github.com/VaalaCat/frp-panel/utils + + +utils + + + + +cluster_github.com/VaalaCat/frp-panel/services/server + + +server + + + + +cluster_github.com/VaalaCat/frp-panel/services/rpcclient + + +rpcclient + + + + +cluster_github.com/VaalaCat/frp-panel/services/master + + +master + + + + +cluster_github.com/VaalaCat/frp-panel/services/api + + +api + + + + +cluster_github.com/VaalaCat/frp-panel/rpc + + +rpc + + + + +cluster_github.com/VaalaCat/frp-panel/models + + +models + + + + +cluster_github.com/VaalaCat/frp-panel/conf + + +conf + + + + +cluster_github.com/VaalaCat/frp-panel/cache + + +cache + + + + +cluster_github.com/VaalaCat/frp-panel/biz/server + + +server + + + + +cluster_github.com/VaalaCat/frp-panel/biz/master/auth + + +auth + + + + +cluster_github.com/VaalaCat/frp-panel/biz/master + + +master + + + + +cluster_github.com/VaalaCat/frp-panel/biz/client + + +client + + + + + +github.com/VaalaCat/frp-panel/cmd.runClient + + +runClient + + + + + +github.com/VaalaCat/frp-panel/cmd.initClientOnce + + +initClientOnce + + + + + +github.com/VaalaCat/frp-panel/cmd.runClient->github.com/VaalaCat/frp-panel/cmd.initClientOnce + + + + + + + + +github.com/VaalaCat/frp-panel/services/rpcclient.MustInitClientRPCSerivce + + +MustInitClientRPCSerivce + + + + + +github.com/VaalaCat/frp-panel/cmd.runClient->github.com/VaalaCat/frp-panel/services/rpcclient.MustInitClientRPCSerivce + + + + + + + + +github.com/VaalaCat/frp-panel/services/rpcclient.GetClientRPCSerivce + + +GetClientRPCSerivce + + + + + +github.com/VaalaCat/frp-panel/cmd.runClient->github.com/VaalaCat/frp-panel/services/rpcclient.GetClientRPCSerivce + + + + + + + + +(*github.com/VaalaCat/frp-panel/services/rpcclient.ClientRPC).Stop + + +(*ClientRPC).Stop + + + + + +github.com/VaalaCat/frp-panel/cmd.runClient->(*github.com/VaalaCat/frp-panel/services/rpcclient.ClientRPC).Stop + + + + + + + + + + +github.com/VaalaCat/frp-panel/watcher.NewClient + + +NewClient + + + + + +github.com/VaalaCat/frp-panel/cmd.runClient->github.com/VaalaCat/frp-panel/watcher.NewClient + + + + + + + + +(*github.com/VaalaCat/frp-panel/watcher.client).Stop + + +(*client).Stop + + + + + +github.com/VaalaCat/frp-panel/cmd.runClient->(*github.com/VaalaCat/frp-panel/watcher.client).Stop + + + + + + + + + + +github.com/VaalaCat/frp-panel/biz/client.PullConfig + + +PullConfig + + + + + +github.com/VaalaCat/frp-panel/cmd.initClientOnce->github.com/VaalaCat/frp-panel/biz/client.PullConfig + + + + + + + + +github.com/VaalaCat/frp-panel/cmd.initCommand$1 + + +initCommand$1 + + + + + +github.com/VaalaCat/frp-panel/cmd.initCommand$1->github.com/VaalaCat/frp-panel/cmd.runClient + + + + + + + + +github.com/VaalaCat/frp-panel/cmd.runServer + + +runServer + + + + + +github.com/VaalaCat/frp-panel/cmd.initServerOnce + + +initServerOnce + + + + + +github.com/VaalaCat/frp-panel/cmd.runServer->github.com/VaalaCat/frp-panel/cmd.initServerOnce + + + + + + + + +github.com/VaalaCat/frp-panel/biz/server.NewRouter + + +NewRouter + + + + + +github.com/VaalaCat/frp-panel/cmd.runServer->github.com/VaalaCat/frp-panel/biz/server.NewRouter + + + + + + + + +github.com/VaalaCat/frp-panel/conf.ServerAPIListenAddr + + +ServerAPIListenAddr + + + + + +github.com/VaalaCat/frp-panel/cmd.runServer->github.com/VaalaCat/frp-panel/conf.ServerAPIListenAddr + + + + + + + + +github.com/VaalaCat/frp-panel/services/api.MustInitApiService + + +MustInitApiService + + + + + +github.com/VaalaCat/frp-panel/cmd.runServer->github.com/VaalaCat/frp-panel/services/api.MustInitApiService + + + + + + + + +github.com/VaalaCat/frp-panel/services/api.GetAPIService + + +GetAPIService + + + + + +github.com/VaalaCat/frp-panel/cmd.runServer->github.com/VaalaCat/frp-panel/services/api.GetAPIService + + + + + + + + +(*github.com/VaalaCat/frp-panel/services/api.server).Stop + + +(*server).Stop + + + + + +github.com/VaalaCat/frp-panel/cmd.runServer->(*github.com/VaalaCat/frp-panel/services/api.server).Stop + + + + + + + + + + +github.com/VaalaCat/frp-panel/cmd.runServer->github.com/VaalaCat/frp-panel/services/rpcclient.MustInitClientRPCSerivce + + + + + + + + +github.com/VaalaCat/frp-panel/cmd.runServer->github.com/VaalaCat/frp-panel/services/rpcclient.GetClientRPCSerivce + + + + + + + + +github.com/VaalaCat/frp-panel/cmd.runServer->(*github.com/VaalaCat/frp-panel/services/rpcclient.ClientRPC).Stop + + + + + + + + + + +github.com/VaalaCat/frp-panel/cmd.runServer->github.com/VaalaCat/frp-panel/watcher.NewClient + + + + + + + + +github.com/VaalaCat/frp-panel/cmd.runServer->(*github.com/VaalaCat/frp-panel/watcher.client).Stop + + + + + + + + + + +github.com/VaalaCat/frp-panel/biz/server.PullConfig + + +PullConfig + + + + + +github.com/VaalaCat/frp-panel/cmd.initServerOnce->github.com/VaalaCat/frp-panel/biz/server.PullConfig + + + + + + + + +github.com/VaalaCat/frp-panel/cmd.initCommand$2 + + +initCommand$2 + + + + + +github.com/VaalaCat/frp-panel/cmd.initCommand$2->github.com/VaalaCat/frp-panel/cmd.runServer + + + + + + + + +github.com/VaalaCat/frp-panel/cmd.runMaster + + +runMaster + + + + + +github.com/VaalaCat/frp-panel/cmd.initDatabase + + +initDatabase + + + + + +github.com/VaalaCat/frp-panel/cmd.runMaster->github.com/VaalaCat/frp-panel/cmd.initDatabase + + + + + + + + +github.com/VaalaCat/frp-panel/biz/master.NewRouter + + +NewRouter + + + + + +github.com/VaalaCat/frp-panel/cmd.runMaster->github.com/VaalaCat/frp-panel/biz/master.NewRouter + + + + + + + + +github.com/VaalaCat/frp-panel/biz/master/auth.InitAuth + + +InitAuth + + + + + +github.com/VaalaCat/frp-panel/cmd.runMaster->github.com/VaalaCat/frp-panel/biz/master/auth.InitAuth + + + + + + + + +github.com/VaalaCat/frp-panel/cache.InitCache + + +InitCache + + + + + +github.com/VaalaCat/frp-panel/cmd.runMaster->github.com/VaalaCat/frp-panel/cache.InitCache + + + + + + + + +github.com/VaalaCat/frp-panel/conf.MasterAPIListenAddr + + +MasterAPIListenAddr + + + + + +github.com/VaalaCat/frp-panel/cmd.runMaster->github.com/VaalaCat/frp-panel/conf.MasterAPIListenAddr + + + + + + + + +github.com/VaalaCat/frp-panel/conf.Get + + +Get + + + + + +github.com/VaalaCat/frp-panel/cmd.runMaster->github.com/VaalaCat/frp-panel/conf.Get + + + + + + + + +github.com/VaalaCat/frp-panel/conf.FRPsAuthOption + + +FRPsAuthOption + + + + + +github.com/VaalaCat/frp-panel/cmd.runMaster->github.com/VaalaCat/frp-panel/conf.FRPsAuthOption + + + + + + + + +github.com/VaalaCat/frp-panel/cmd.runMaster->github.com/VaalaCat/frp-panel/services/api.MustInitApiService + + + + + + + + +github.com/VaalaCat/frp-panel/cmd.runMaster->github.com/VaalaCat/frp-panel/services/api.GetAPIService + + + + + + + + +github.com/VaalaCat/frp-panel/services/master.MustInitMasterService + + +MustInitMasterService + + + + + +github.com/VaalaCat/frp-panel/cmd.runMaster->github.com/VaalaCat/frp-panel/services/master.MustInitMasterService + + + + + + + + +github.com/VaalaCat/frp-panel/services/master.GetMasterSerivce + + +GetMasterSerivce + + + + + +github.com/VaalaCat/frp-panel/cmd.runMaster->github.com/VaalaCat/frp-panel/services/master.GetMasterSerivce + + + + + + + + +github.com/VaalaCat/frp-panel/services/server.GetServerSerivce + + +GetServerSerivce + + + + + +github.com/VaalaCat/frp-panel/cmd.runMaster->github.com/VaalaCat/frp-panel/services/server.GetServerSerivce + + + + + + + + +github.com/VaalaCat/frp-panel/utils.NewBaseFRPServerUserAuthConfig + + +NewBaseFRPServerUserAuthConfig + + + + + +github.com/VaalaCat/frp-panel/cmd.runMaster->github.com/VaalaCat/frp-panel/utils.NewBaseFRPServerUserAuthConfig + + + + + + + + +github.com/VaalaCat/frp-panel/cmd.initDatabase->github.com/VaalaCat/frp-panel/conf.Get + + + + + + + + +github.com/VaalaCat/frp-panel/models.MustInitDBManager + + +MustInitDBManager + + + + + +github.com/VaalaCat/frp-panel/cmd.initDatabase->github.com/VaalaCat/frp-panel/models.MustInitDBManager + + + + + + + + +github.com/VaalaCat/frp-panel/models.GetDBManager + + +GetDBManager + + + + + +github.com/VaalaCat/frp-panel/cmd.initDatabase->github.com/VaalaCat/frp-panel/models.GetDBManager + + + + + + + + +(*github.com/VaalaCat/frp-panel/models.dbManagerImpl).Init + + +(*dbManagerImpl).Init + + + + + +github.com/VaalaCat/frp-panel/cmd.initDatabase->(*github.com/VaalaCat/frp-panel/models.dbManagerImpl).Init + + + + + + + + +(*github.com/VaalaCat/frp-panel/models.dbManagerImpl).SetDB + + +(*dbManagerImpl).SetDB + + + + + +github.com/VaalaCat/frp-panel/cmd.initDatabase->(*github.com/VaalaCat/frp-panel/models.dbManagerImpl).SetDB + + + + + + + + +github.com/VaalaCat/frp-panel/cmd.initCommand$3 + + +initCommand$3 + + + + + +github.com/VaalaCat/frp-panel/cmd.initCommand$3->github.com/VaalaCat/frp-panel/cmd.runMaster + + + + + + + + +github.com/VaalaCat/frp-panel/cmd.main + + +main + + + + + +github.com/VaalaCat/frp-panel/cmd.initLogger + + +initLogger + + + + + +github.com/VaalaCat/frp-panel/cmd.main->github.com/VaalaCat/frp-panel/cmd.initLogger + + + + + + + + +github.com/VaalaCat/frp-panel/cmd.initCommand + + +initCommand + + + + + +github.com/VaalaCat/frp-panel/cmd.main->github.com/VaalaCat/frp-panel/cmd.initCommand + + + + + + + + +github.com/VaalaCat/frp-panel/cmd.main->github.com/VaalaCat/frp-panel/conf.Get + + + + + + + + +github.com/VaalaCat/frp-panel/conf.InitConfig + + +InitConfig + + + + + +github.com/VaalaCat/frp-panel/cmd.main->github.com/VaalaCat/frp-panel/conf.InitConfig + + + + + + + + +github.com/VaalaCat/frp-panel/rpc.InitRPCClients + + +InitRPCClients + + + + + +github.com/VaalaCat/frp-panel/cmd.main->github.com/VaalaCat/frp-panel/rpc.InitRPCClients + + + + + + + + +github.com/VaalaCat/frp-panel/utils.MD5 + + +MD5 + + + + + +github.com/VaalaCat/frp-panel/cmd.main->github.com/VaalaCat/frp-panel/utils.MD5 + + + + + + + + diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..e9481f8 --- /dev/null +++ b/go.mod @@ -0,0 +1,112 @@ +module github.com/VaalaCat/frp-panel + +go 1.21.5 + +require ( + github.com/coocood/freecache v1.2.4 + github.com/fatedier/frp v0.53.2 + github.com/fatedier/golib v0.1.1-0.20230725122706-dcbaee8eef40 + github.com/gin-gonic/gin v1.9.1 + github.com/glebarez/sqlite v1.10.0 + github.com/go-co-op/gocron/v2 v2.1.2 + github.com/golang-jwt/jwt/v5 v5.2.0 + github.com/google/uuid v1.5.0 + github.com/ilyakaznacheev/cleanenv v1.5.0 + github.com/joho/godotenv v1.5.1 + github.com/samber/lo v1.38.1 + github.com/sirupsen/logrus v1.9.3 + github.com/sourcegraph/conc v0.3.0 + github.com/spf13/cobra v1.8.0 + golang.org/x/crypto v0.16.0 + google.golang.org/grpc v1.60.1 + google.golang.org/protobuf v1.31.0 + gorm.io/gorm v1.25.5 + k8s.io/apimachinery v0.27.4 +) + +require ( + github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bytedance/sonic v1.9.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/coreos/go-oidc/v3 v3.6.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb // indirect + github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/glebarez/go-sqlite v1.21.2 // indirect + github.com/go-jose/go-jose/v3 v3.0.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.14.0 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 // indirect + github.com/gorilla/mux v1.8.0 // indirect + github.com/hashicorp/yamux v0.1.1 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/jonboulle/clockwork v0.4.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/klauspost/reedsolomon v1.9.15 // indirect + github.com/leodido/go-urn v1.2.4 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/onsi/ginkgo/v2 v2.11.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/pion/dtls/v2 v2.2.7 // indirect + github.com/pion/logging v0.2.2 // indirect + github.com/pion/stun v0.6.1 // indirect + github.com/pion/transport/v2 v2.2.1 // indirect + github.com/pires/go-proxyproto v0.7.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.16.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.10.1 // indirect + github.com/quic-go/qtls-go1-20 v0.3.1 // indirect + github.com/quic-go/quic-go v0.37.4 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/robfig/cron/v3 v3.0.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect + github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect + github.com/tjfoc/gmsm v1.4.1 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/arch v0.3.0 // indirect + golang.org/x/exp v0.0.0-20231219180239-dc181d75b848 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/oauth2 v0.15.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/tools v0.16.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + modernc.org/libc v1.22.5 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.5.0 // indirect + modernc.org/sqlite v1.23.1 // indirect + olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..66c8114 --- /dev/null +++ b/go.sum @@ -0,0 +1,380 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28= +github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= +github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/coocood/freecache v1.2.4 h1:UdR6Yz/X1HW4fZOuH0Z94KwG851GWOSknua5VUbb/5M= +github.com/coocood/freecache v1.2.4/go.mod h1:RBUWa/Cy+OHdfTGFEhEuE1pMCMX51Ncizj7rthiQ3vk= +github.com/coreos/go-oidc/v3 v3.6.0 h1:AKVxfYw1Gmkn/w96z0DbT/B/xFnzTd3MkZvWLjF4n/o= +github.com/coreos/go-oidc/v3 v3.6.0/go.mod h1:ZpHUsHBucTUj6WOkrP4E20UPynbLZzhTQ1XKCXkxyPc= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb h1:wCrNShQidLmvVWn/0PikGmpdP0vtQmnvyRg3ZBEhczw= +github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb/go.mod h1:wx3gB6dbIfBRcucp94PI9Bt3I0F2c/MyNEWuhzpWiwk= +github.com/fatedier/frp v0.53.2 h1:rbNcXJyKLrEnvurRfGDhSG3BERH7cfv1XRjIs6MSY4s= +github.com/fatedier/frp v0.53.2/go.mod h1:BNJZ9il1aazwhaLeiO2cQCBhY/c9Lq+HP73144bNUkk= +github.com/fatedier/golib v0.1.1-0.20230725122706-dcbaee8eef40 h1:BVdpWT6viE/mpuRa6txNyRNjtHa1Efrii9Du6/gHfJ0= +github.com/fatedier/golib v0.1.1-0.20230725122706-dcbaee8eef40/go.mod h1:Lmi9U4VfvdRvonSMh1FgXVy1hCXycVyJk4E9ktokknE= +github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible h1:ssXat9YXFvigNge/IkkZvFMn8yeYKFX+uI6wn2mLJ74= +github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible/go.mod h1:YpCOaxj7vvMThhIQ9AfTOPW2sfztQR5WDfs7AflSy4s= +github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= +github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= +github.com/glebarez/sqlite v1.10.0 h1:u4gt8y7OND/cCei/NMHmfbLxF6xP2wgKcT/BJf2pYkc= +github.com/glebarez/sqlite v1.10.0/go.mod h1:IJ+lfSOmiekhQsFTJRx/lHtGYmCdtAiTaf5wI9u5uHA= +github.com/go-co-op/gocron/v2 v2.1.2 h1:+6tTOA9aBaKXpDWExw07hYoGEBzT+4CkGSVAiJ7WSXs= +github.com/go-co-op/gocron/v2 v2.1.2/go.mod h1:0MfNAXEchzeSH1vtkZrTAcSMWqyL435kL6CA4b0bjrg= +github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= +github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= +github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= +github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/ilyakaznacheev/cleanenv v1.5.0 h1:0VNZXggJE2OYdXE87bfSSwGxeiGt9moSR2lOrsHHvr4= +github.com/ilyakaznacheev/cleanenv v1.5.0/go.mod h1:a5aDzaJrLCQZsazHol1w8InnDcOX0OColm64SlIi6gk= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= +github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/reedsolomon v1.9.15 h1:g2erWKD2M6rgnPf89fCji6jNlhMKMdXcuNHMW1SYCIo= +github.com/klauspost/reedsolomon v1.9.15/go.mod h1:eqPAcE7xar5CIzcdfwydOEdcmchAKAP/qs14y4GCBOk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= +github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8= +github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= +github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= +github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= +github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= +github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c= +github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= +github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs= +github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= +github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/quic-go/qtls-go1-20 v0.3.1 h1:O4BLOM3hwfVF3AcktIylQXyl7Yi2iBNVy5QsV+ySxbg= +github.com/quic-go/qtls-go1-20 v0.3.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= +github.com/quic-go/quic-go v0.37.4 h1:ke8B73yMCWGq9MfrCCAw0Uzdm7GaViC3i39dsIdDlH4= +github.com/quic-go/quic-go v0.37.4/go.mod h1:YsbH1r4mSHPJcLF4k4zruUkLBqctEMBDR6VPvcYjIsU= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= +github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU= +github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= +github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI= +github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= +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/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E= +github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= +golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20231219180239-dc181d75b848 h1:+iq7lrkxmFNBM7xx+Rae2W6uyPfhPeDWD+n+JgppptE= +golang.org/x/exp v0.0.0-20231219180239-dc181d75b848/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= +golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= +gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +k8s.io/apimachinery v0.27.4 h1:CdxflD4AF61yewuid0fLl6bM4a3q04jWel0IlP+aYjs= +k8s.io/apimachinery v0.27.4/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= +modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE= +modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= +modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM= +modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk= +olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 h1:slmdOY3vp8a7KQbHkL+FLbvbkgMqmXojpFUO/jENuqQ= +olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3/go.mod h1:oVgVk4OWVDi43qWBEyGhXgYxt7+ED4iYNpTngSLX2Iw= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/idl/api_auth.proto b/idl/api_auth.proto new file mode 100644 index 0000000..f78a8c2 --- /dev/null +++ b/idl/api_auth.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; +package api_auth; + +import "common.proto"; +option go_package="../pb"; + +message LoginRequest { + optional string username = 1; + optional string password = 2; +} + +message LoginResponse { + optional common.Status status = 1; + optional string token = 2; +} + +message RegisterRequest { + optional string username = 1; + optional string password = 2; + optional string email = 3; +} + +message RegisterResponse { + optional common.Status status = 1; +} \ No newline at end of file diff --git a/idl/api_client.proto b/idl/api_client.proto new file mode 100644 index 0000000..9d6e866 --- /dev/null +++ b/idl/api_client.proto @@ -0,0 +1,61 @@ +syntax = "proto3"; +package api_client; + +import "common.proto"; +option go_package="../pb"; + + +message InitClientRequest { + optional string client_id = 1; +} + +message InitClientResponse { + optional common.Status status = 1; + optional string client_id = 2; +} + +message ListClientsRequest { + optional int32 page = 1; + optional int32 page_size = 2; +} + +message ListClientsResponse { + optional common.Status status = 1; + optional int32 total = 2; + repeated common.Client clients = 3; +} + +message GetClientRequest { + optional string client_id = 1; +} + +message GetClientResponse { + optional common.Status status = 1; + optional common.Client client = 2; +} + +message DeleteClientRequest { + optional string client_id = 1; +} + +message DeleteClientResponse { + optional common.Status status = 1; +} + +message UpdateFRPCRequest { + optional string client_id = 1; + optional string server_id = 2; + optional bytes config = 3; +} + +message UpdateFRPCResponse { + optional common.Status status = 1; +} + +message RemoveFRPCRequest { + optional string client_id = 1; +} + +message RemoveFRPCResponse { + optional common.Status status = 1; +} \ No newline at end of file diff --git a/idl/api_server.proto b/idl/api_server.proto new file mode 100644 index 0000000..740d67c --- /dev/null +++ b/idl/api_server.proto @@ -0,0 +1,60 @@ +syntax = "proto3"; +package api_server; + +import "common.proto"; +option go_package="../pb"; + +message InitServerRequest { + optional string server_id = 1; + optional string server_ip = 2; +} + +message InitServerResponse { + optional common.Status status = 1; + optional string server_id = 2; +} + +message ListServersRequest { + optional int32 page = 1; + optional int32 page_size = 2; +} + +message ListServersResponse { + optional common.Status status = 1; + optional int32 total = 2; + repeated common.Server servers = 3; +} + +message GetServerRequest { + optional string server_id = 1; +} + +message GetServerResponse { + optional common.Status status = 1; + optional common.Server server = 2; +} + +message DeleteServerRequest { + optional string server_id = 1; +} + +message DeleteServerResponse { + optional common.Status status = 1; +} + +message UpdateFRPSRequest { + optional string server_id = 1; + optional bytes config = 2; +} + +message UpdateFRPSResponse { + optional common.Status status = 1; +} + +message RemoveFRPSRequest { + optional string server_id = 1; +} + +message RemoveFRPSResponse { + optional common.Status status = 1; +} \ No newline at end of file diff --git a/idl/api_user.proto b/idl/api_user.proto new file mode 100644 index 0000000..46ccd5f --- /dev/null +++ b/idl/api_user.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; +package api_user; + +import "common.proto"; +option go_package="../pb"; + +message GetUserInfoRequest {} + +message GetUserInfoResponse { + optional common.Status status = 1; + optional common.User user_info = 2; +} + +message UpdateUserInfoRequest { + optional common.User user_info = 1; +} + +message UpdateUserInfoResponse { + optional common.Status status = 1; +} \ No newline at end of file diff --git a/idl/common.proto b/idl/common.proto new file mode 100644 index 0000000..66f1bf9 --- /dev/null +++ b/idl/common.proto @@ -0,0 +1,47 @@ +syntax = "proto3"; + +package common; +option go_package="../pb"; + +enum RespCode { + RESP_CODE_UNSPECIFIED = 0; + RESP_CODE_SUCCESS = 1; + RESP_CODE_NOT_FOUND = 2; + RESP_CODE_ALREADY_EXISTS = 3; + RESP_CODE_INVALID = 4; + RESP_CODE_FINISH = 5; + RESP_CODE_UNAUTHORIZED = 6; +} + +message Status { + RespCode code = 1; + string message = 2; +} + +message CommonResponse { + optional Status status = 1; +} + +message Client { + optional string id = 1; + optional string secret = 2; + optional string config = 3; +} + +message Server { + optional string id = 1; + optional string secret = 2; + optional string ip = 3; + optional string config = 4; // 在定义上,ip和port只是为了方便使用 +} + +message User { + optional int64 UserID = 1; + optional int64 TenantID = 2; + optional string UserName = 3; + optional string Email = 4; + optional string Status = 5; + optional string Role = 6; + optional string Token = 7; + optional string RawPassword = 8; +} \ No newline at end of file diff --git a/idl/rpc_master.proto b/idl/rpc_master.proto new file mode 100644 index 0000000..e83f1d4 --- /dev/null +++ b/idl/rpc_master.proto @@ -0,0 +1,79 @@ +syntax = "proto3"; +package master; + +import "common.proto"; +option go_package="../pb"; + +enum Event { + EVENT_UNSPECIFIED = 0; + EVENT_REGISTER_CLIENT = 1; + EVENT_REGISTER_SERVER = 2; + EVENT_ERROR = 3; + EVENT_DATA = 4; + EVENT_UPDATE_FRPC = 5; + EVENT_REMOVE_FRPC = 6; + EVENT_UPDATE_FRPS = 7; + EVENT_REMOVE_FRPS = 8; +} + +message ServerBase { + string server_id = 1; + string server_secret = 2; +} + +message ClientBase { + string client_id = 1; + string client_secret = 2; +} + +message ServerMessage { + Event event = 1; + string client_id = 2; + string session_id = 3; + bytes data = 4; +} + +message ClientMessage { + Event event = 1; + string client_id = 2; + string session_id = 3; + string secret = 4; + bytes data = 5; +} + +message PullClientConfigReq { + ClientBase base = 255; +} + +message PullClientConfigResp { + common.Status status = 1; + common.Client client = 2; +} + +message PullServerConfigReq { + ServerBase base = 255; +} + +message PullServerConfigResp { + common.Status status = 1; + common.Server server = 2; +} + +message FRPAuthRequest { + string user = 1; + string token = 2; + + ServerBase base = 255; +} + +message FRPAuthResponse { + common.Status status = 1; + bool ok = 2; +} + +service Master { + rpc ServerSend(stream ClientMessage) returns(stream ServerMessage); + rpc PullClientConfig(PullClientConfigReq) returns(PullClientConfigResp); + rpc PullServerConfig(PullServerConfigReq) returns(PullServerConfigResp); + rpc FRPCAuth(FRPAuthRequest) returns(FRPAuthResponse); +} diff --git a/middleware/auth.go b/middleware/auth.go new file mode 100644 index 0000000..f28fa58 --- /dev/null +++ b/middleware/auth.go @@ -0,0 +1,65 @@ +package middleware + +import ( + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/models" + "github.com/VaalaCat/frp-panel/utils" + "github.com/gin-gonic/gin" + "github.com/sirupsen/logrus" +) + +func AuthCtx(c *gin.Context) { + var uid int64 + var err error + var u *models.UserEntity + + defer func() { + logrus.WithContext(c).Info("finish auth user middleware") + }() + + userID, ok := utils.GetValue[int](c, common.UserIDKey) + if !ok { + logrus.WithContext(c).Errorf("invalid user id") + common.ErrUnAuthorized(c, "token invalid") + c.Abort() + return + } + + u, err = dao.GetUserByUserID(userID) + if err != nil { + logrus.WithContext(c).Errorf("get user by user id failed: %v", err) + common.ErrUnAuthorized(c, "token invalid") + c.Abort() + return + } + + logrus.WithContext(c).Infof("auth middleware authed user is: [%+v]", u) + + if u.Valid() { + logrus.WithContext(c).Infof("set auth user to context, login success") + c.Set(common.UserInfoKey, u) + c.Next() + return + } else { + if uid == 1 { + logrus.WithContext(c).Infof("seems to be admin assign token login") + c.Next() + return + } + logrus.WithContext(c).Errorf("invalid authorization, auth ctx middleware login failed") + common.ErrUnAuthorized(c, "token invalid") + c.Abort() + return + } +} + +func AuthAdmin(c *gin.Context) { + u := common.GetUserInfo(c) + if u != nil && u.GetRole() == models.ROLE_ADMIN { + common.ErrUnAuthorized(c, "permission denied") + c.Abort() + return + } + c.Next() +} diff --git a/middleware/jwt.go b/middleware/jwt.go new file mode 100644 index 0000000..529d2ab --- /dev/null +++ b/middleware/jwt.go @@ -0,0 +1,157 @@ +package middleware + +import ( + "errors" + "strings" + "time" + + "github.com/VaalaCat/frp-panel/common" + "github.com/VaalaCat/frp-panel/conf" + "github.com/VaalaCat/frp-panel/utils" + "github.com/gin-gonic/gin" + "github.com/golang-jwt/jwt/v5" + "github.com/sirupsen/logrus" +) + +// JWTMAuth check if authed and set uid to context +func JWTAuth(c *gin.Context) { + defer func() { + logrus.WithContext(c).Info("finish jwt middleware") + }() + + var tokenStr string + + if tokenStr = c.Copy().Query(common.TokenKey); len(tokenStr) != 0 { + if t, err := utils.ParseToken(conf.JWTSecret(), tokenStr); err == nil { + for k, v := range t { + c.Set(k, v) + } + logrus.WithContext(c).Infof("query auth success") + if err = resignAndPatchCtxJWT(c, t, tokenStr); err != nil { + logrus.WithContext(c).WithError(err).Errorf("resign jwt error") + common.ErrUnAuthorized(c, "resign jwt error") + c.Abort() + return + } + c.Next() + SetToken(c, utils.ToStr(t[common.UserIDKey])) + return + } + logrus.WithContext(c).Infof("query auth failed") + } + + cookieToken, err := c.Cookie(conf.Get().App.CookieName) + if err == nil { + if t, err := utils.ParseToken(conf.JWTSecret(), cookieToken); err == nil { + for k, v := range t { + c.Set(k, v) + } + logrus.WithContext(c).Infof("cookie auth success") + if err = resignAndPatchCtxJWT(c, t, cookieToken); err != nil { + logrus.WithContext(c).WithError(err).Errorf("resign jwt error") + common.ErrUnAuthorized(c, "resign jwt error") + c.Abort() + return + } + c.Next() + return + } else { + logrus.WithContext(c).WithError(err).Errorf("jwt middleware parse token error") + common.ErrUnAuthorized(c, "invalid authorization") + c.Abort() + return + } + } + + tokenStr = c.Request.Header.Get(common.AuthorizationKey) + tokenStr = strings.TrimPrefix(tokenStr, "Bearer ") + if tokenStr == "" || tokenStr == "null" { + logrus.WithContext(c).WithError(errors.New("authorization is empty")).Infof("authorization is empty") + common.ErrUnAuthorized(c, "invalid authorization") + c.Abort() + return + } + + if t, err := utils.ParseToken(conf.JWTSecret(), tokenStr); err == nil { + for k, v := range t { + c.Set(k, v) + } + logrus.WithContext(c).Infof("header auth success") + if err = resignAndPatchCtxJWT(c, t, tokenStr); err != nil { + logrus.WithContext(c).WithError(err).Errorf("resign jwt error") + common.ErrUnAuthorized(c, "resign jwt error") + c.Abort() + return + } + c.Next() + return + } else { + logrus.WithContext(c).WithError(err).Errorf("jwt middleware parse token error") + } +} + +func resignAndPatchCtxJWT(c *gin.Context, t jwt.MapClaims, tokenStr string) error { + tokenExpire, _ := t.GetExpirationTime() + now := time.Now().Add(time.Duration(conf.Get().App.CookieAge/2) * time.Second) + if now.Before(tokenExpire.Time) { + logrus.WithContext(c).Infof("jwt not going to expire, continue to use old one") + c.Set(common.TokenKey, tokenStr) + return nil + } + + token, err := utils.GetJwtTokenFromMap(conf.JWTSecret(), + time.Now().Unix(), + int64(conf.Get().App.CookieAge), + map[string]string{common.UserIDKey: utils.ToStr(t[common.UserIDKey])}) + if err != nil { + c.Set(common.TokenKey, tokenStr) + logrus.WithContext(c).WithError(err).Errorf("resign jwt error") + return err + } + + logrus.WithContext(c).Infof("jwt going to expire, resigning token") + c.Header(common.SetAuthorizationKey, token) + c.SetCookie(conf.Get().App.CookieName, + token, + conf.Get().App.CookieAge, + conf.Get().App.CookiePath, + conf.Get().App.CookieDomain, + conf.Get().App.CookieSecure, + conf.Get().App.CookieHTTPOnly) + c.Set(common.TokenKey, token) + return nil +} + +func SetToken(c *gin.Context, uid string) (string, error) { + logrus.WithContext(c).Infof("set token for uid:[%s]", uid) + token, err := utils.GetJwtTokenFromMap(conf.JWTSecret(), + time.Now().Unix(), + int64(conf.Get().App.CookieAge), + map[string]string{common.UserIDKey: uid}) + if err != nil { + return "", err + } + c.SetCookie(conf.Get().App.CookieName, + token, + conf.Get().App.CookieAge, + conf.Get().App.CookiePath, + conf.Get().App.CookieDomain, + conf.Get().App.CookieSecure, + conf.Get().App.CookieHTTPOnly) + c.Set(common.TokenKey, token) + c.Header(common.SetAuthorizationKey, token) + return token, nil +} + +// PushTokenStr 推送token到客户端 +func PushTokenStr(c *gin.Context, tokenStr string) { + logrus.WithContext(c).Infof("push new token to client") + c.SetCookie(conf.Get().App.CookieName, + tokenStr, + conf.Get().App.CookieAge, + conf.Get().App.CookiePath, + conf.Get().App.CookieDomain, + conf.Get().App.CookieSecure, + conf.Get().App.CookieHTTPOnly) + c.Header(common.SetAuthorizationKey, tokenStr) +} diff --git a/models/client.go b/models/client.go new file mode 100644 index 0000000..ede6cc9 --- /dev/null +++ b/models/client.go @@ -0,0 +1,60 @@ +package models + +import ( + "encoding/json" + "time" + + "github.com/VaalaCat/frp-panel/utils" + v1 "github.com/fatedier/frp/pkg/config/v1" + "github.com/samber/lo" + "gorm.io/gorm" +) + +type Client struct { + *ClientEntity +} + +type ClientEntity struct { + ClientID string `json:"client_id" gorm:"uniqueIndex;not null;primaryKey"` + 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"` + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt gorm.DeletedAt `gorm:"index"` +} + +func (*Client) TableName() string { + return "clients" +} + +func (c *ClientEntity) SetConfigContent(cfg v1.ClientConfig) error { + newCfg := struct { + v1.ClientCommonConfig + Proxies []v1.ProxyConfigurer `json:"proxies,omitempty"` + Visitors []v1.VisitorBaseConfig `json:"visitors,omitempty"` + }{ + ClientCommonConfig: cfg.ClientCommonConfig, + Proxies: lo.Map(cfg.Proxies, func(item v1.TypedProxyConfig, _ int) v1.ProxyConfigurer { + return item.ProxyConfigurer + }), + Visitors: lo.Map(cfg.Visitors, func(item v1.TypedVisitorConfig, _ int) v1.VisitorBaseConfig { + return *item.GetBaseConfig() + }), + } + raw, err := json.Marshal(newCfg) + if err != nil { + return err + } + c.ConfigContent = raw + return nil +} + +func (c *ClientEntity) GetConfigContent() (*v1.ClientConfig, error) { + cliCfg, err := utils.LoadClientConfigNormal(c.ConfigContent, true) + if err != nil { + return nil, err + } + return cliCfg, err +} diff --git a/models/db.go b/models/db.go new file mode 100644 index 0000000..dea519c --- /dev/null +++ b/models/db.go @@ -0,0 +1,76 @@ +package models + +import ( + "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +type DBManager interface { + GetDB(dbType string) *gorm.DB + GetDefaultDB() *gorm.DB + SetDB(dbType string, db *gorm.DB) + RemoveDB(dbType string) + Init() +} + +type dbManagerImpl struct { + DBs map[string]*gorm.DB // key: db type + defaultDBType string +} + +func (dbm *dbManagerImpl) Init() { + for _, db := range dbm.DBs { + if err := db.AutoMigrate(&Client{}); err != nil { + logrus.WithError(err).Fatalf("cannot init db table [%s]", (&Client{}).TableName()) + } + if err := db.AutoMigrate(&User{}); err != nil { + logrus.WithError(err).Fatalf("cannot init db table [%s]", (&User{}).TableName()) + } + if err := db.AutoMigrate(&Server{}); err != nil { + logrus.WithError(err).Fatalf("cannot init db table [%s]", (&Server{}).TableName()) + } + } +} + +var ( + dbm *dbManagerImpl +) + +func MustInitDBManager(dbs map[string]*gorm.DB, defaultDBType string) { + if dbm == nil { + dbm = NewDBManager(dbs, defaultDBType) + } +} + +func NewDBManager(dbs map[string]*gorm.DB, defaultDBType string) *dbManagerImpl { + if dbs == nil { + dbs = make(map[string]*gorm.DB) + } + return &dbManagerImpl{ + DBs: dbs, + defaultDBType: defaultDBType, + } +} + +func GetDBManager() DBManager { + if dbm == nil { + dbm = NewDBManager(nil, "") + } + return dbm +} + +func (dbm *dbManagerImpl) GetDB(dbType string) *gorm.DB { + return dbm.DBs[dbType] +} + +func (dbm *dbManagerImpl) SetDB(dbType string, db *gorm.DB) { + dbm.DBs[dbType] = db +} + +func (dbm *dbManagerImpl) RemoveDB(dbType string) { + delete(dbm.DBs, dbType) +} + +func (dbm *dbManagerImpl) GetDefaultDB() *gorm.DB { + return dbm.DBs[dbm.defaultDBType] +} diff --git a/models/enums.go b/models/enums.go new file mode 100644 index 0000000..dc29fc4 --- /dev/null +++ b/models/enums.go @@ -0,0 +1,12 @@ +package models + +const ( + ROLE_ADMIN = "admin" + ROLE_NORMAL = "normal" +) + +const ( + STATUS_UNKNOWN = iota + STATUS_NORMAL + STATUS_BANED +) diff --git a/models/init.go b/models/init.go new file mode 100644 index 0000000..d6a05a4 --- /dev/null +++ b/models/init.go @@ -0,0 +1,2 @@ +package models + diff --git a/models/server.go b/models/server.go new file mode 100644 index 0000000..eed4faf --- /dev/null +++ b/models/server.go @@ -0,0 +1,49 @@ +package models + +import ( + "encoding/json" + "fmt" + "time" + + v1 "github.com/fatedier/frp/pkg/config/v1" + "gorm.io/gorm" +) + +type Server struct { + *ServerEntity +} + +type ServerEntity struct { + ServerID string `json:"client_id" gorm:"uniqueIndex;not null;primaryKey"` + TenantID int `json:"tenant_id" gorm:"not null"` + UserID int `json:"user_id" gorm:"not null"` + ServerIP string `json:"server_ip"` + ConfigContent []byte `json:"config_content"` + ConnectSecret string `json:"connect_secret" gorm:"not null"` + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt gorm.DeletedAt `gorm:"index"` +} + +func (*Server) TableName() string { + return "servers" +} + +func (s *ServerEntity) GetConfigContent() (*v1.ServerConfig, error) { + if len(s.ConfigContent) == 0 { + return nil, fmt.Errorf("config content is empty") + } + + var cfg v1.ServerConfig + err := json.Unmarshal(s.ConfigContent, &cfg) + return &cfg, err +} + +func (s *ServerEntity) SetConfigContent(cfg *v1.ServerConfig) error { + raw, err := json.Marshal(cfg) + if err != nil { + return err + } + s.ConfigContent = raw + return nil +} diff --git a/models/user.go b/models/user.go new file mode 100644 index 0000000..d5c1483 --- /dev/null +++ b/models/user.go @@ -0,0 +1,107 @@ +package models + +import ( + "fmt" + "time" + + "gorm.io/gorm" +) + +type User struct { + *UserEntity +} + +type UserInfo interface { + GetUserID() int + GetUserIDStr() string + GetUserName() string + GetEmail() string + GetHashedPassword() string + GetStatus() int + GetRole() string + GetToken() string + GetTenantID() int + GetSafeUserInfo() UserEntity + IsAdmin() bool + Valid() bool +} + +var _ UserInfo = (*UserEntity)(nil) + +type UserEntity struct { + UserID int `json:"user_id" gorm:"primaryKey"` + UserName string `json:"user_name" gorm:"uniqueIndex;not null"` + Password string `json:"password"` + Email string `json:"email" gorm:"uniqueIndex;not null"` + Status int `json:"status"` + Role string `json:"role"` + TenantID int `json:"tenant_id"` + Token string `json:"token"` + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt gorm.DeletedAt `gorm:"index"` +} + +func (u *UserEntity) GetUserID() int { + return u.UserID +} + +func (u *UserEntity) GetUserIDStr() string { + return fmt.Sprint(u.UserID) +} + +func (u *UserEntity) GetUserName() string { + return u.UserName +} + +func (u *UserEntity) GetEmail() string { + return u.Email +} + +func (u *UserEntity) GetHashedPassword() string { + return u.Password +} + +func (u *UserEntity) GetStatus() int { + return u.Status +} + +func (u *UserEntity) GetRole() string { + return u.Role +} + +func (u *UserEntity) GetTenantID() int { + return u.TenantID +} + +func (u *UserEntity) GetToken() string { + return u.Token +} + +func (u *UserEntity) GetSafeUserInfo() UserEntity { + return UserEntity{ + UserID: u.UserID, + UserName: u.UserName, + Email: u.Email, + Status: u.Status, + Role: u.Role, + } +} + +func (u *UserEntity) Valid() bool { + if u == nil { + return false + } + if u.Status == STATUS_BANED { + return false + } + return true +} + +func (u *UserEntity) IsAdmin() bool { + return u.Role == ROLE_ADMIN +} + +func (u *User) TableName() string { + return "users" +} diff --git a/pb/api_auth.pb.go b/pb/api_auth.pb.go new file mode 100644 index 0000000..a371ef9 --- /dev/null +++ b/pb/api_auth.pb.go @@ -0,0 +1,388 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.1 +// source: api_auth.proto + +package pb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type LoginRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Username *string `protobuf:"bytes,1,opt,name=username,proto3,oneof" json:"username,omitempty"` + Password *string `protobuf:"bytes,2,opt,name=password,proto3,oneof" json:"password,omitempty"` +} + +func (x *LoginRequest) Reset() { + *x = LoginRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_auth_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LoginRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoginRequest) ProtoMessage() {} + +func (x *LoginRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_auth_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LoginRequest.ProtoReflect.Descriptor instead. +func (*LoginRequest) Descriptor() ([]byte, []int) { + return file_api_auth_proto_rawDescGZIP(), []int{0} +} + +func (x *LoginRequest) GetUsername() string { + if x != nil && x.Username != nil { + return *x.Username + } + return "" +} + +func (x *LoginRequest) GetPassword() string { + if x != nil && x.Password != nil { + return *x.Password + } + return "" +} + +type LoginResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` + Token *string `protobuf:"bytes,2,opt,name=token,proto3,oneof" json:"token,omitempty"` +} + +func (x *LoginResponse) Reset() { + *x = LoginResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_auth_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LoginResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoginResponse) ProtoMessage() {} + +func (x *LoginResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_auth_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LoginResponse.ProtoReflect.Descriptor instead. +func (*LoginResponse) Descriptor() ([]byte, []int) { + return file_api_auth_proto_rawDescGZIP(), []int{1} +} + +func (x *LoginResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +func (x *LoginResponse) GetToken() string { + if x != nil && x.Token != nil { + return *x.Token + } + return "" +} + +type RegisterRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Username *string `protobuf:"bytes,1,opt,name=username,proto3,oneof" json:"username,omitempty"` + Password *string `protobuf:"bytes,2,opt,name=password,proto3,oneof" json:"password,omitempty"` + Email *string `protobuf:"bytes,3,opt,name=email,proto3,oneof" json:"email,omitempty"` +} + +func (x *RegisterRequest) Reset() { + *x = RegisterRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_auth_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RegisterRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterRequest) ProtoMessage() {} + +func (x *RegisterRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_auth_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegisterRequest.ProtoReflect.Descriptor instead. +func (*RegisterRequest) Descriptor() ([]byte, []int) { + return file_api_auth_proto_rawDescGZIP(), []int{2} +} + +func (x *RegisterRequest) GetUsername() string { + if x != nil && x.Username != nil { + return *x.Username + } + return "" +} + +func (x *RegisterRequest) GetPassword() string { + if x != nil && x.Password != nil { + return *x.Password + } + return "" +} + +func (x *RegisterRequest) GetEmail() string { + if x != nil && x.Email != nil { + return *x.Email + } + return "" +} + +type RegisterResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` +} + +func (x *RegisterResponse) Reset() { + *x = RegisterResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_auth_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RegisterResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterResponse) ProtoMessage() {} + +func (x *RegisterResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_auth_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegisterResponse.ProtoReflect.Descriptor instead. +func (*RegisterResponse) Descriptor() ([]byte, []int) { + return file_api_auth_proto_rawDescGZIP(), []int{3} +} + +func (x *RegisterResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +var File_api_auth_proto protoreflect.FileDescriptor + +var file_api_auth_proto_rawDesc = []byte{ + 0x0a, 0x0e, 0x61, 0x70, 0x69, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x12, 0x08, 0x61, 0x70, 0x69, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x1a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, + 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6a, 0x0a, 0x0c, 0x4c, 0x6f, 0x67, 0x69, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x75, 0x73, + 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x08, 0x70, + 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x75, + 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x22, 0x6c, 0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 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, 0x19, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x01, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, + 0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x22, 0x92, 0x01, 0x0a, 0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, + 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, + 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x08, 0x70, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, + 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, + 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, + 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x42, 0x08, 0x0a, + 0x06, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x4a, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x65, 0x72, 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, 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 ( + file_api_auth_proto_rawDescOnce sync.Once + file_api_auth_proto_rawDescData = file_api_auth_proto_rawDesc +) + +func file_api_auth_proto_rawDescGZIP() []byte { + file_api_auth_proto_rawDescOnce.Do(func() { + file_api_auth_proto_rawDescData = protoimpl.X.CompressGZIP(file_api_auth_proto_rawDescData) + }) + return file_api_auth_proto_rawDescData +} + +var file_api_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_api_auth_proto_goTypes = []interface{}{ + (*LoginRequest)(nil), // 0: api_auth.LoginRequest + (*LoginResponse)(nil), // 1: api_auth.LoginResponse + (*RegisterRequest)(nil), // 2: api_auth.RegisterRequest + (*RegisterResponse)(nil), // 3: api_auth.RegisterResponse + (*Status)(nil), // 4: common.Status +} +var file_api_auth_proto_depIdxs = []int32{ + 4, // 0: api_auth.LoginResponse.status:type_name -> common.Status + 4, // 1: api_auth.RegisterResponse.status:type_name -> common.Status + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_api_auth_proto_init() } +func file_api_auth_proto_init() { + if File_api_auth_proto != nil { + return + } + file_common_proto_init() + if !protoimpl.UnsafeEnabled { + file_api_auth_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_auth_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_auth_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegisterRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_auth_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegisterResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_api_auth_proto_msgTypes[0].OneofWrappers = []interface{}{} + file_api_auth_proto_msgTypes[1].OneofWrappers = []interface{}{} + file_api_auth_proto_msgTypes[2].OneofWrappers = []interface{}{} + file_api_auth_proto_msgTypes[3].OneofWrappers = []interface{}{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_api_auth_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_api_auth_proto_goTypes, + DependencyIndexes: file_api_auth_proto_depIdxs, + MessageInfos: file_api_auth_proto_msgTypes, + }.Build() + File_api_auth_proto = out.File + file_api_auth_proto_rawDesc = nil + file_api_auth_proto_goTypes = nil + file_api_auth_proto_depIdxs = nil +} diff --git a/pb/api_client.pb.go b/pb/api_client.pb.go new file mode 100644 index 0000000..9305597 --- /dev/null +++ b/pb/api_client.pb.go @@ -0,0 +1,954 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.1 +// source: api_client.proto + +package pb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type InitClientRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClientId *string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3,oneof" json:"client_id,omitempty"` +} + +func (x *InitClientRequest) Reset() { + *x = InitClientRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_client_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InitClientRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InitClientRequest) ProtoMessage() {} + +func (x *InitClientRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_client_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InitClientRequest.ProtoReflect.Descriptor instead. +func (*InitClientRequest) Descriptor() ([]byte, []int) { + return file_api_client_proto_rawDescGZIP(), []int{0} +} + +func (x *InitClientRequest) GetClientId() string { + if x != nil && x.ClientId != nil { + return *x.ClientId + } + return "" +} + +type InitClientResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` + ClientId *string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3,oneof" json:"client_id,omitempty"` +} + +func (x *InitClientResponse) Reset() { + *x = InitClientResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_client_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InitClientResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InitClientResponse) ProtoMessage() {} + +func (x *InitClientResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_client_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InitClientResponse.ProtoReflect.Descriptor instead. +func (*InitClientResponse) Descriptor() ([]byte, []int) { + return file_api_client_proto_rawDescGZIP(), []int{1} +} + +func (x *InitClientResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +func (x *InitClientResponse) GetClientId() string { + if x != nil && x.ClientId != nil { + return *x.ClientId + } + return "" +} + +type ListClientsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Page *int32 `protobuf:"varint,1,opt,name=page,proto3,oneof" json:"page,omitempty"` + PageSize *int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3,oneof" json:"page_size,omitempty"` +} + +func (x *ListClientsRequest) Reset() { + *x = ListClientsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_client_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListClientsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListClientsRequest) ProtoMessage() {} + +func (x *ListClientsRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_client_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListClientsRequest.ProtoReflect.Descriptor instead. +func (*ListClientsRequest) Descriptor() ([]byte, []int) { + return file_api_client_proto_rawDescGZIP(), []int{2} +} + +func (x *ListClientsRequest) GetPage() int32 { + if x != nil && x.Page != nil { + return *x.Page + } + return 0 +} + +func (x *ListClientsRequest) GetPageSize() int32 { + if x != nil && x.PageSize != nil { + return *x.PageSize + } + return 0 +} + +type ListClientsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` + Total *int32 `protobuf:"varint,2,opt,name=total,proto3,oneof" json:"total,omitempty"` + Clients []*Client `protobuf:"bytes,3,rep,name=clients,proto3" json:"clients,omitempty"` +} + +func (x *ListClientsResponse) Reset() { + *x = ListClientsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_client_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListClientsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListClientsResponse) ProtoMessage() {} + +func (x *ListClientsResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_client_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListClientsResponse.ProtoReflect.Descriptor instead. +func (*ListClientsResponse) Descriptor() ([]byte, []int) { + return file_api_client_proto_rawDescGZIP(), []int{3} +} + +func (x *ListClientsResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +func (x *ListClientsResponse) GetTotal() int32 { + if x != nil && x.Total != nil { + return *x.Total + } + return 0 +} + +func (x *ListClientsResponse) GetClients() []*Client { + if x != nil { + return x.Clients + } + return nil +} + +type GetClientRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClientId *string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3,oneof" json:"client_id,omitempty"` +} + +func (x *GetClientRequest) Reset() { + *x = GetClientRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_client_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetClientRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetClientRequest) ProtoMessage() {} + +func (x *GetClientRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_client_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetClientRequest.ProtoReflect.Descriptor instead. +func (*GetClientRequest) Descriptor() ([]byte, []int) { + return file_api_client_proto_rawDescGZIP(), []int{4} +} + +func (x *GetClientRequest) GetClientId() string { + if x != nil && x.ClientId != nil { + return *x.ClientId + } + return "" +} + +type GetClientResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` + Client *Client `protobuf:"bytes,2,opt,name=client,proto3,oneof" json:"client,omitempty"` +} + +func (x *GetClientResponse) Reset() { + *x = GetClientResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_client_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetClientResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetClientResponse) ProtoMessage() {} + +func (x *GetClientResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_client_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetClientResponse.ProtoReflect.Descriptor instead. +func (*GetClientResponse) Descriptor() ([]byte, []int) { + return file_api_client_proto_rawDescGZIP(), []int{5} +} + +func (x *GetClientResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +func (x *GetClientResponse) GetClient() *Client { + if x != nil { + return x.Client + } + return nil +} + +type DeleteClientRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClientId *string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3,oneof" json:"client_id,omitempty"` +} + +func (x *DeleteClientRequest) Reset() { + *x = DeleteClientRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_client_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteClientRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteClientRequest) ProtoMessage() {} + +func (x *DeleteClientRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_client_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteClientRequest.ProtoReflect.Descriptor instead. +func (*DeleteClientRequest) Descriptor() ([]byte, []int) { + return file_api_client_proto_rawDescGZIP(), []int{6} +} + +func (x *DeleteClientRequest) GetClientId() string { + if x != nil && x.ClientId != nil { + return *x.ClientId + } + return "" +} + +type DeleteClientResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` +} + +func (x *DeleteClientResponse) Reset() { + *x = DeleteClientResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_client_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteClientResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteClientResponse) ProtoMessage() {} + +func (x *DeleteClientResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_client_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteClientResponse.ProtoReflect.Descriptor instead. +func (*DeleteClientResponse) Descriptor() ([]byte, []int) { + return file_api_client_proto_rawDescGZIP(), []int{7} +} + +func (x *DeleteClientResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +type UpdateFRPCRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClientId *string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3,oneof" json:"client_id,omitempty"` + ServerId *string `protobuf:"bytes,2,opt,name=server_id,json=serverId,proto3,oneof" json:"server_id,omitempty"` + Config []byte `protobuf:"bytes,3,opt,name=config,proto3,oneof" json:"config,omitempty"` +} + +func (x *UpdateFRPCRequest) Reset() { + *x = UpdateFRPCRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_client_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateFRPCRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateFRPCRequest) ProtoMessage() {} + +func (x *UpdateFRPCRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_client_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateFRPCRequest.ProtoReflect.Descriptor instead. +func (*UpdateFRPCRequest) Descriptor() ([]byte, []int) { + return file_api_client_proto_rawDescGZIP(), []int{8} +} + +func (x *UpdateFRPCRequest) GetClientId() string { + if x != nil && x.ClientId != nil { + return *x.ClientId + } + return "" +} + +func (x *UpdateFRPCRequest) GetServerId() string { + if x != nil && x.ServerId != nil { + return *x.ServerId + } + return "" +} + +func (x *UpdateFRPCRequest) GetConfig() []byte { + if x != nil { + return x.Config + } + return nil +} + +type UpdateFRPCResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` +} + +func (x *UpdateFRPCResponse) Reset() { + *x = UpdateFRPCResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_client_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateFRPCResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateFRPCResponse) ProtoMessage() {} + +func (x *UpdateFRPCResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_client_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateFRPCResponse.ProtoReflect.Descriptor instead. +func (*UpdateFRPCResponse) Descriptor() ([]byte, []int) { + return file_api_client_proto_rawDescGZIP(), []int{9} +} + +func (x *UpdateFRPCResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +type RemoveFRPCRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClientId *string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3,oneof" json:"client_id,omitempty"` +} + +func (x *RemoveFRPCRequest) Reset() { + *x = RemoveFRPCRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_client_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveFRPCRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveFRPCRequest) ProtoMessage() {} + +func (x *RemoveFRPCRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_client_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveFRPCRequest.ProtoReflect.Descriptor instead. +func (*RemoveFRPCRequest) Descriptor() ([]byte, []int) { + return file_api_client_proto_rawDescGZIP(), []int{10} +} + +func (x *RemoveFRPCRequest) GetClientId() string { + if x != nil && x.ClientId != nil { + return *x.ClientId + } + return "" +} + +type RemoveFRPCResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` +} + +func (x *RemoveFRPCResponse) Reset() { + *x = RemoveFRPCResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_client_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveFRPCResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveFRPCResponse) ProtoMessage() {} + +func (x *RemoveFRPCResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_client_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveFRPCResponse.ProtoReflect.Descriptor instead. +func (*RemoveFRPCResponse) Descriptor() ([]byte, []int) { + return file_api_client_proto_rawDescGZIP(), []int{11} +} + +func (x *RemoveFRPCResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +var File_api_client_proto protoreflect.FileDescriptor + +var file_api_client_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x0a, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x1a, 0x0c, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x43, 0x0a, 0x11, + 0x49, 0x6e, 0x69, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x20, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, + 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, + 0x64, 0x22, 0x7c, 0x0a, 0x12, 0x49, 0x6e, 0x69, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 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, 0x20, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x22, + 0x66, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x20, + 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x05, 0x48, 0x01, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x88, 0x01, 0x01, + 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x61, + 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x9c, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, + 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 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, 0x19, 0x0a, 0x05, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x48, 0x01, 0x52, 0x05, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x28, 0x0a, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x73, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x08, 0x0a, 0x06, + 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0x42, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x09, 0x63, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, + 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, + 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x22, 0x83, 0x01, 0x0a, 0x11, 0x47, + 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 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, 0x2b, 0x0a, + 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, 0x01, 0x52, + 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x22, 0x45, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x22, 0x4e, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 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, 0x42, 0x09, 0x0a, 0x07, + 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x9b, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x46, 0x52, 0x50, 0x43, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, + 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x00, 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, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x01, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x88, 0x01, + 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0c, 0x48, 0x02, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x88, 0x01, 0x01, 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, 0x22, 0x4c, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, + 0x52, 0x50, 0x43, 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, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x22, 0x43, 0x0a, 0x11, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x46, 0x52, 0x50, + 0x43, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x22, 0x4c, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x46, 0x52, 0x50, 0x43, 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, 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 ( + file_api_client_proto_rawDescOnce sync.Once + file_api_client_proto_rawDescData = file_api_client_proto_rawDesc +) + +func file_api_client_proto_rawDescGZIP() []byte { + file_api_client_proto_rawDescOnce.Do(func() { + file_api_client_proto_rawDescData = protoimpl.X.CompressGZIP(file_api_client_proto_rawDescData) + }) + return file_api_client_proto_rawDescData +} + +var file_api_client_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_api_client_proto_goTypes = []interface{}{ + (*InitClientRequest)(nil), // 0: api_client.InitClientRequest + (*InitClientResponse)(nil), // 1: api_client.InitClientResponse + (*ListClientsRequest)(nil), // 2: api_client.ListClientsRequest + (*ListClientsResponse)(nil), // 3: api_client.ListClientsResponse + (*GetClientRequest)(nil), // 4: api_client.GetClientRequest + (*GetClientResponse)(nil), // 5: api_client.GetClientResponse + (*DeleteClientRequest)(nil), // 6: api_client.DeleteClientRequest + (*DeleteClientResponse)(nil), // 7: api_client.DeleteClientResponse + (*UpdateFRPCRequest)(nil), // 8: api_client.UpdateFRPCRequest + (*UpdateFRPCResponse)(nil), // 9: api_client.UpdateFRPCResponse + (*RemoveFRPCRequest)(nil), // 10: api_client.RemoveFRPCRequest + (*RemoveFRPCResponse)(nil), // 11: api_client.RemoveFRPCResponse + (*Status)(nil), // 12: common.Status + (*Client)(nil), // 13: common.Client +} +var file_api_client_proto_depIdxs = []int32{ + 12, // 0: api_client.InitClientResponse.status:type_name -> common.Status + 12, // 1: api_client.ListClientsResponse.status:type_name -> common.Status + 13, // 2: api_client.ListClientsResponse.clients:type_name -> common.Client + 12, // 3: api_client.GetClientResponse.status:type_name -> common.Status + 13, // 4: api_client.GetClientResponse.client:type_name -> common.Client + 12, // 5: api_client.DeleteClientResponse.status:type_name -> common.Status + 12, // 6: api_client.UpdateFRPCResponse.status:type_name -> common.Status + 12, // 7: api_client.RemoveFRPCResponse.status:type_name -> common.Status + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name +} + +func init() { file_api_client_proto_init() } +func file_api_client_proto_init() { + if File_api_client_proto != nil { + return + } + file_common_proto_init() + if !protoimpl.UnsafeEnabled { + file_api_client_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InitClientRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_client_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InitClientResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_client_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListClientsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_client_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListClientsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_client_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetClientRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_client_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetClientResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_client_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteClientRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_client_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteClientResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_client_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateFRPCRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_client_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateFRPCResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_client_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveFRPCRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_client_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveFRPCResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_api_client_proto_msgTypes[0].OneofWrappers = []interface{}{} + file_api_client_proto_msgTypes[1].OneofWrappers = []interface{}{} + file_api_client_proto_msgTypes[2].OneofWrappers = []interface{}{} + file_api_client_proto_msgTypes[3].OneofWrappers = []interface{}{} + file_api_client_proto_msgTypes[4].OneofWrappers = []interface{}{} + file_api_client_proto_msgTypes[5].OneofWrappers = []interface{}{} + file_api_client_proto_msgTypes[6].OneofWrappers = []interface{}{} + file_api_client_proto_msgTypes[7].OneofWrappers = []interface{}{} + file_api_client_proto_msgTypes[8].OneofWrappers = []interface{}{} + file_api_client_proto_msgTypes[9].OneofWrappers = []interface{}{} + file_api_client_proto_msgTypes[10].OneofWrappers = []interface{}{} + file_api_client_proto_msgTypes[11].OneofWrappers = []interface{}{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_api_client_proto_rawDesc, + NumEnums: 0, + NumMessages: 12, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_api_client_proto_goTypes, + DependencyIndexes: file_api_client_proto_depIdxs, + MessageInfos: file_api_client_proto_msgTypes, + }.Build() + File_api_client_proto = out.File + file_api_client_proto_rawDesc = nil + file_api_client_proto_goTypes = nil + file_api_client_proto_depIdxs = nil +} diff --git a/pb/api_server.pb.go b/pb/api_server.pb.go new file mode 100644 index 0000000..2ce471d --- /dev/null +++ b/pb/api_server.pb.go @@ -0,0 +1,954 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.1 +// source: api_server.proto + +package pb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type InitServerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ServerId *string `protobuf:"bytes,1,opt,name=server_id,json=serverId,proto3,oneof" json:"server_id,omitempty"` + ServerIp *string `protobuf:"bytes,2,opt,name=server_ip,json=serverIp,proto3,oneof" json:"server_ip,omitempty"` +} + +func (x *InitServerRequest) Reset() { + *x = InitServerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_server_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InitServerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InitServerRequest) ProtoMessage() {} + +func (x *InitServerRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_server_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InitServerRequest.ProtoReflect.Descriptor instead. +func (*InitServerRequest) Descriptor() ([]byte, []int) { + return file_api_server_proto_rawDescGZIP(), []int{0} +} + +func (x *InitServerRequest) GetServerId() string { + if x != nil && x.ServerId != nil { + return *x.ServerId + } + return "" +} + +func (x *InitServerRequest) GetServerIp() string { + if x != nil && x.ServerIp != nil { + return *x.ServerIp + } + return "" +} + +type InitServerResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` + ServerId *string `protobuf:"bytes,2,opt,name=server_id,json=serverId,proto3,oneof" json:"server_id,omitempty"` +} + +func (x *InitServerResponse) Reset() { + *x = InitServerResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_server_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InitServerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InitServerResponse) ProtoMessage() {} + +func (x *InitServerResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_server_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InitServerResponse.ProtoReflect.Descriptor instead. +func (*InitServerResponse) Descriptor() ([]byte, []int) { + return file_api_server_proto_rawDescGZIP(), []int{1} +} + +func (x *InitServerResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +func (x *InitServerResponse) GetServerId() string { + if x != nil && x.ServerId != nil { + return *x.ServerId + } + return "" +} + +type ListServersRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Page *int32 `protobuf:"varint,1,opt,name=page,proto3,oneof" json:"page,omitempty"` + PageSize *int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3,oneof" json:"page_size,omitempty"` +} + +func (x *ListServersRequest) Reset() { + *x = ListServersRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_server_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListServersRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListServersRequest) ProtoMessage() {} + +func (x *ListServersRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_server_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListServersRequest.ProtoReflect.Descriptor instead. +func (*ListServersRequest) Descriptor() ([]byte, []int) { + return file_api_server_proto_rawDescGZIP(), []int{2} +} + +func (x *ListServersRequest) GetPage() int32 { + if x != nil && x.Page != nil { + return *x.Page + } + return 0 +} + +func (x *ListServersRequest) GetPageSize() int32 { + if x != nil && x.PageSize != nil { + return *x.PageSize + } + return 0 +} + +type ListServersResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` + Total *int32 `protobuf:"varint,2,opt,name=total,proto3,oneof" json:"total,omitempty"` + Servers []*Server `protobuf:"bytes,3,rep,name=servers,proto3" json:"servers,omitempty"` +} + +func (x *ListServersResponse) Reset() { + *x = ListServersResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_server_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListServersResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListServersResponse) ProtoMessage() {} + +func (x *ListServersResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_server_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListServersResponse.ProtoReflect.Descriptor instead. +func (*ListServersResponse) Descriptor() ([]byte, []int) { + return file_api_server_proto_rawDescGZIP(), []int{3} +} + +func (x *ListServersResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +func (x *ListServersResponse) GetTotal() int32 { + if x != nil && x.Total != nil { + return *x.Total + } + return 0 +} + +func (x *ListServersResponse) GetServers() []*Server { + if x != nil { + return x.Servers + } + return nil +} + +type GetServerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ServerId *string `protobuf:"bytes,1,opt,name=server_id,json=serverId,proto3,oneof" json:"server_id,omitempty"` +} + +func (x *GetServerRequest) Reset() { + *x = GetServerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_server_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetServerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetServerRequest) ProtoMessage() {} + +func (x *GetServerRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_server_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetServerRequest.ProtoReflect.Descriptor instead. +func (*GetServerRequest) Descriptor() ([]byte, []int) { + return file_api_server_proto_rawDescGZIP(), []int{4} +} + +func (x *GetServerRequest) GetServerId() string { + if x != nil && x.ServerId != nil { + return *x.ServerId + } + return "" +} + +type GetServerResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` + Server *Server `protobuf:"bytes,2,opt,name=server,proto3,oneof" json:"server,omitempty"` +} + +func (x *GetServerResponse) Reset() { + *x = GetServerResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_server_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetServerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetServerResponse) ProtoMessage() {} + +func (x *GetServerResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_server_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetServerResponse.ProtoReflect.Descriptor instead. +func (*GetServerResponse) Descriptor() ([]byte, []int) { + return file_api_server_proto_rawDescGZIP(), []int{5} +} + +func (x *GetServerResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +func (x *GetServerResponse) GetServer() *Server { + if x != nil { + return x.Server + } + return nil +} + +type DeleteServerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ServerId *string `protobuf:"bytes,1,opt,name=server_id,json=serverId,proto3,oneof" json:"server_id,omitempty"` +} + +func (x *DeleteServerRequest) Reset() { + *x = DeleteServerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_server_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteServerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteServerRequest) ProtoMessage() {} + +func (x *DeleteServerRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_server_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteServerRequest.ProtoReflect.Descriptor instead. +func (*DeleteServerRequest) Descriptor() ([]byte, []int) { + return file_api_server_proto_rawDescGZIP(), []int{6} +} + +func (x *DeleteServerRequest) GetServerId() string { + if x != nil && x.ServerId != nil { + return *x.ServerId + } + return "" +} + +type DeleteServerResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` +} + +func (x *DeleteServerResponse) Reset() { + *x = DeleteServerResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_server_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteServerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteServerResponse) ProtoMessage() {} + +func (x *DeleteServerResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_server_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteServerResponse.ProtoReflect.Descriptor instead. +func (*DeleteServerResponse) Descriptor() ([]byte, []int) { + return file_api_server_proto_rawDescGZIP(), []int{7} +} + +func (x *DeleteServerResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +type UpdateFRPSRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ServerId *string `protobuf:"bytes,1,opt,name=server_id,json=serverId,proto3,oneof" json:"server_id,omitempty"` + Config []byte `protobuf:"bytes,2,opt,name=config,proto3,oneof" json:"config,omitempty"` +} + +func (x *UpdateFRPSRequest) Reset() { + *x = UpdateFRPSRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_server_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateFRPSRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateFRPSRequest) ProtoMessage() {} + +func (x *UpdateFRPSRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_server_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateFRPSRequest.ProtoReflect.Descriptor instead. +func (*UpdateFRPSRequest) Descriptor() ([]byte, []int) { + return file_api_server_proto_rawDescGZIP(), []int{8} +} + +func (x *UpdateFRPSRequest) GetServerId() string { + if x != nil && x.ServerId != nil { + return *x.ServerId + } + return "" +} + +func (x *UpdateFRPSRequest) GetConfig() []byte { + if x != nil { + return x.Config + } + return nil +} + +type UpdateFRPSResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` +} + +func (x *UpdateFRPSResponse) Reset() { + *x = UpdateFRPSResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_server_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateFRPSResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateFRPSResponse) ProtoMessage() {} + +func (x *UpdateFRPSResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_server_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateFRPSResponse.ProtoReflect.Descriptor instead. +func (*UpdateFRPSResponse) Descriptor() ([]byte, []int) { + return file_api_server_proto_rawDescGZIP(), []int{9} +} + +func (x *UpdateFRPSResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +type RemoveFRPSRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ServerId *string `protobuf:"bytes,1,opt,name=server_id,json=serverId,proto3,oneof" json:"server_id,omitempty"` +} + +func (x *RemoveFRPSRequest) Reset() { + *x = RemoveFRPSRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_server_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveFRPSRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveFRPSRequest) ProtoMessage() {} + +func (x *RemoveFRPSRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_server_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveFRPSRequest.ProtoReflect.Descriptor instead. +func (*RemoveFRPSRequest) Descriptor() ([]byte, []int) { + return file_api_server_proto_rawDescGZIP(), []int{10} +} + +func (x *RemoveFRPSRequest) GetServerId() string { + if x != nil && x.ServerId != nil { + return *x.ServerId + } + return "" +} + +type RemoveFRPSResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` +} + +func (x *RemoveFRPSResponse) Reset() { + *x = RemoveFRPSResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_server_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveFRPSResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveFRPSResponse) ProtoMessage() {} + +func (x *RemoveFRPSResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_server_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveFRPSResponse.ProtoReflect.Descriptor instead. +func (*RemoveFRPSResponse) Descriptor() ([]byte, []int) { + return file_api_server_proto_rawDescGZIP(), []int{11} +} + +func (x *RemoveFRPSResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +var File_api_server_proto protoreflect.FileDescriptor + +var file_api_server_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x61, 0x70, 0x69, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x0a, 0x61, 0x70, 0x69, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x1a, 0x0c, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x73, 0x0a, 0x11, + 0x49, 0x6e, 0x69, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 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, 0x12, 0x20, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x70, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x49, 0x70, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, + 0x70, 0x22, 0x7c, 0x0a, 0x12, 0x49, 0x6e, 0x69, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 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, 0x20, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x22, + 0x66, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x20, + 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x05, 0x48, 0x01, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x88, 0x01, 0x01, + 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x61, + 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x9c, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 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, 0x19, 0x0a, 0x05, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x48, 0x01, 0x52, 0x05, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x28, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x73, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x08, 0x0a, 0x06, + 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0x42, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 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, 0x11, 0x47, + 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 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, 0x2b, 0x0a, + 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x48, 0x01, 0x52, + 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x22, 0x45, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 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, 0x4e, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 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, 0x42, 0x09, 0x0a, 0x07, + 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x6b, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x46, 0x52, 0x50, 0x53, 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, 0x12, 0x1b, + 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x01, + 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x88, 0x01, 0x01, 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, 0x22, 0x4c, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x52, + 0x50, 0x53, 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, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x22, 0x43, 0x0a, 0x11, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x46, 0x52, 0x50, 0x53, + 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, 0x4c, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x46, 0x52, 0x50, 0x53, 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, 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 ( + file_api_server_proto_rawDescOnce sync.Once + file_api_server_proto_rawDescData = file_api_server_proto_rawDesc +) + +func file_api_server_proto_rawDescGZIP() []byte { + file_api_server_proto_rawDescOnce.Do(func() { + file_api_server_proto_rawDescData = protoimpl.X.CompressGZIP(file_api_server_proto_rawDescData) + }) + return file_api_server_proto_rawDescData +} + +var file_api_server_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_api_server_proto_goTypes = []interface{}{ + (*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 + (*Status)(nil), // 12: common.Status + (*Server)(nil), // 13: common.Server +} +var file_api_server_proto_depIdxs = []int32{ + 12, // 0: api_server.InitServerResponse.status:type_name -> common.Status + 12, // 1: api_server.ListServersResponse.status:type_name -> common.Status + 13, // 2: api_server.ListServersResponse.servers:type_name -> common.Server + 12, // 3: api_server.GetServerResponse.status:type_name -> common.Status + 13, // 4: api_server.GetServerResponse.server:type_name -> common.Server + 12, // 5: api_server.DeleteServerResponse.status:type_name -> common.Status + 12, // 6: api_server.UpdateFRPSResponse.status:type_name -> common.Status + 12, // 7: api_server.RemoveFRPSResponse.status:type_name -> common.Status + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name +} + +func init() { file_api_server_proto_init() } +func file_api_server_proto_init() { + if File_api_server_proto != nil { + return + } + file_common_proto_init() + if !protoimpl.UnsafeEnabled { + file_api_server_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InitServerRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_server_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InitServerResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_server_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListServersRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_server_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListServersResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_server_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetServerRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_server_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetServerResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_server_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteServerRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_server_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteServerResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_server_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateFRPSRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_server_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateFRPSResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_server_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveFRPSRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_server_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveFRPSResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_api_server_proto_msgTypes[0].OneofWrappers = []interface{}{} + file_api_server_proto_msgTypes[1].OneofWrappers = []interface{}{} + file_api_server_proto_msgTypes[2].OneofWrappers = []interface{}{} + file_api_server_proto_msgTypes[3].OneofWrappers = []interface{}{} + file_api_server_proto_msgTypes[4].OneofWrappers = []interface{}{} + file_api_server_proto_msgTypes[5].OneofWrappers = []interface{}{} + file_api_server_proto_msgTypes[6].OneofWrappers = []interface{}{} + file_api_server_proto_msgTypes[7].OneofWrappers = []interface{}{} + file_api_server_proto_msgTypes[8].OneofWrappers = []interface{}{} + file_api_server_proto_msgTypes[9].OneofWrappers = []interface{}{} + file_api_server_proto_msgTypes[10].OneofWrappers = []interface{}{} + file_api_server_proto_msgTypes[11].OneofWrappers = []interface{}{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_api_server_proto_rawDesc, + NumEnums: 0, + NumMessages: 12, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_api_server_proto_goTypes, + DependencyIndexes: file_api_server_proto_depIdxs, + MessageInfos: file_api_server_proto_msgTypes, + }.Build() + File_api_server_proto = out.File + file_api_server_proto_rawDesc = nil + file_api_server_proto_goTypes = nil + file_api_server_proto_depIdxs = nil +} diff --git a/pb/api_user.pb.go b/pb/api_user.pb.go new file mode 100644 index 0000000..06961c1 --- /dev/null +++ b/pb/api_user.pb.go @@ -0,0 +1,350 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.1 +// source: api_user.proto + +package pb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type GetUserInfoRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetUserInfoRequest) Reset() { + *x = GetUserInfoRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_user_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetUserInfoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetUserInfoRequest) ProtoMessage() {} + +func (x *GetUserInfoRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_user_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetUserInfoRequest.ProtoReflect.Descriptor instead. +func (*GetUserInfoRequest) Descriptor() ([]byte, []int) { + return file_api_user_proto_rawDescGZIP(), []int{0} +} + +type GetUserInfoResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` + UserInfo *User `protobuf:"bytes,2,opt,name=user_info,json=userInfo,proto3,oneof" json:"user_info,omitempty"` +} + +func (x *GetUserInfoResponse) Reset() { + *x = GetUserInfoResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_user_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetUserInfoResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetUserInfoResponse) ProtoMessage() {} + +func (x *GetUserInfoResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_user_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetUserInfoResponse.ProtoReflect.Descriptor instead. +func (*GetUserInfoResponse) Descriptor() ([]byte, []int) { + return file_api_user_proto_rawDescGZIP(), []int{1} +} + +func (x *GetUserInfoResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +func (x *GetUserInfoResponse) GetUserInfo() *User { + if x != nil { + return x.UserInfo + } + return nil +} + +type UpdateUserInfoRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserInfo *User `protobuf:"bytes,1,opt,name=user_info,json=userInfo,proto3,oneof" json:"user_info,omitempty"` +} + +func (x *UpdateUserInfoRequest) Reset() { + *x = UpdateUserInfoRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_user_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateUserInfoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateUserInfoRequest) ProtoMessage() {} + +func (x *UpdateUserInfoRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_user_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateUserInfoRequest.ProtoReflect.Descriptor instead. +func (*UpdateUserInfoRequest) Descriptor() ([]byte, []int) { + return file_api_user_proto_rawDescGZIP(), []int{2} +} + +func (x *UpdateUserInfoRequest) GetUserInfo() *User { + if x != nil { + return x.UserInfo + } + return nil +} + +type UpdateUserInfoResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` +} + +func (x *UpdateUserInfoResponse) Reset() { + *x = UpdateUserInfoResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_user_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateUserInfoResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateUserInfoResponse) ProtoMessage() {} + +func (x *UpdateUserInfoResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_user_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateUserInfoResponse.ProtoReflect.Descriptor instead. +func (*UpdateUserInfoResponse) Descriptor() ([]byte, []int) { + return file_api_user_proto_rawDescGZIP(), []int{3} +} + +func (x *UpdateUserInfoResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +var File_api_user_proto protoreflect.FileDescriptor + +var file_api_user_proto_rawDesc = []byte{ + 0x0a, 0x0e, 0x61, 0x70, 0x69, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x12, 0x08, 0x61, 0x70, 0x69, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x1a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, + 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x14, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8b, + 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 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, 0x2e, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x66, 0x6f, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, + 0x55, 0x73, 0x65, 0x72, 0x48, 0x01, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, + 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x0c, + 0x0a, 0x0a, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x55, 0x0a, 0x15, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, + 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x48, 0x00, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x49, 0x6e, + 0x66, 0x6f, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, + 0x6e, 0x66, 0x6f, 0x22, 0x50, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, + 0x72, 0x49, 0x6e, 0x66, 0x6f, 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, 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 ( + file_api_user_proto_rawDescOnce sync.Once + file_api_user_proto_rawDescData = file_api_user_proto_rawDesc +) + +func file_api_user_proto_rawDescGZIP() []byte { + file_api_user_proto_rawDescOnce.Do(func() { + file_api_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_api_user_proto_rawDescData) + }) + return file_api_user_proto_rawDescData +} + +var file_api_user_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_api_user_proto_goTypes = []interface{}{ + (*GetUserInfoRequest)(nil), // 0: api_user.GetUserInfoRequest + (*GetUserInfoResponse)(nil), // 1: api_user.GetUserInfoResponse + (*UpdateUserInfoRequest)(nil), // 2: api_user.UpdateUserInfoRequest + (*UpdateUserInfoResponse)(nil), // 3: api_user.UpdateUserInfoResponse + (*Status)(nil), // 4: common.Status + (*User)(nil), // 5: common.User +} +var file_api_user_proto_depIdxs = []int32{ + 4, // 0: api_user.GetUserInfoResponse.status:type_name -> common.Status + 5, // 1: api_user.GetUserInfoResponse.user_info:type_name -> common.User + 5, // 2: api_user.UpdateUserInfoRequest.user_info:type_name -> common.User + 4, // 3: api_user.UpdateUserInfoResponse.status:type_name -> common.Status + 4, // [4:4] is the sub-list for method output_type + 4, // [4:4] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name +} + +func init() { file_api_user_proto_init() } +func file_api_user_proto_init() { + if File_api_user_proto != nil { + return + } + file_common_proto_init() + if !protoimpl.UnsafeEnabled { + file_api_user_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetUserInfoRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_user_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetUserInfoResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_user_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateUserInfoRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_user_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateUserInfoResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_api_user_proto_msgTypes[1].OneofWrappers = []interface{}{} + file_api_user_proto_msgTypes[2].OneofWrappers = []interface{}{} + file_api_user_proto_msgTypes[3].OneofWrappers = []interface{}{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_api_user_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_api_user_proto_goTypes, + DependencyIndexes: file_api_user_proto_depIdxs, + MessageInfos: file_api_user_proto_msgTypes, + }.Build() + File_api_user_proto = out.File + file_api_user_proto_rawDesc = nil + file_api_user_proto_goTypes = nil + file_api_user_proto_depIdxs = nil +} diff --git a/pb/common.pb.go b/pb/common.pb.go new file mode 100644 index 0000000..f711c31 --- /dev/null +++ b/pb/common.pb.go @@ -0,0 +1,612 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.1 +// source: common.proto + +package pb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type RespCode int32 + +const ( + RespCode_RESP_CODE_UNSPECIFIED RespCode = 0 + RespCode_RESP_CODE_SUCCESS RespCode = 1 + RespCode_RESP_CODE_NOT_FOUND RespCode = 2 + RespCode_RESP_CODE_ALREADY_EXISTS RespCode = 3 + RespCode_RESP_CODE_INVALID RespCode = 4 + RespCode_RESP_CODE_FINISH RespCode = 5 + RespCode_RESP_CODE_UNAUTHORIZED RespCode = 6 +) + +// Enum value maps for RespCode. +var ( + RespCode_name = map[int32]string{ + 0: "RESP_CODE_UNSPECIFIED", + 1: "RESP_CODE_SUCCESS", + 2: "RESP_CODE_NOT_FOUND", + 3: "RESP_CODE_ALREADY_EXISTS", + 4: "RESP_CODE_INVALID", + 5: "RESP_CODE_FINISH", + 6: "RESP_CODE_UNAUTHORIZED", + } + RespCode_value = map[string]int32{ + "RESP_CODE_UNSPECIFIED": 0, + "RESP_CODE_SUCCESS": 1, + "RESP_CODE_NOT_FOUND": 2, + "RESP_CODE_ALREADY_EXISTS": 3, + "RESP_CODE_INVALID": 4, + "RESP_CODE_FINISH": 5, + "RESP_CODE_UNAUTHORIZED": 6, + } +) + +func (x RespCode) Enum() *RespCode { + p := new(RespCode) + *p = x + return p +} + +func (x RespCode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RespCode) Descriptor() protoreflect.EnumDescriptor { + return file_common_proto_enumTypes[0].Descriptor() +} + +func (RespCode) Type() protoreflect.EnumType { + return &file_common_proto_enumTypes[0] +} + +func (x RespCode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RespCode.Descriptor instead. +func (RespCode) EnumDescriptor() ([]byte, []int) { + return file_common_proto_rawDescGZIP(), []int{0} +} + +type Status struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Code RespCode `protobuf:"varint,1,opt,name=code,proto3,enum=common.RespCode" json:"code,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *Status) Reset() { + *x = Status{} + if protoimpl.UnsafeEnabled { + mi := &file_common_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Status) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Status) ProtoMessage() {} + +func (x *Status) ProtoReflect() protoreflect.Message { + mi := &file_common_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Status.ProtoReflect.Descriptor instead. +func (*Status) Descriptor() ([]byte, []int) { + return file_common_proto_rawDescGZIP(), []int{0} +} + +func (x *Status) GetCode() RespCode { + if x != nil { + return x.Code + } + return RespCode_RESP_CODE_UNSPECIFIED +} + +func (x *Status) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type CommonResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3,oneof" json:"status,omitempty"` +} + +func (x *CommonResponse) Reset() { + *x = CommonResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_common_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CommonResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CommonResponse) ProtoMessage() {} + +func (x *CommonResponse) ProtoReflect() protoreflect.Message { + mi := &file_common_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CommonResponse.ProtoReflect.Descriptor instead. +func (*CommonResponse) Descriptor() ([]byte, []int) { + return file_common_proto_rawDescGZIP(), []int{1} +} + +func (x *CommonResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +type Client struct { + state protoimpl.MessageState + 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"` +} + +func (x *Client) Reset() { + *x = Client{} + if protoimpl.UnsafeEnabled { + mi := &file_common_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Client) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Client) ProtoMessage() {} + +func (x *Client) ProtoReflect() protoreflect.Message { + mi := &file_common_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Client.ProtoReflect.Descriptor instead. +func (*Client) Descriptor() ([]byte, []int) { + return file_common_proto_rawDescGZIP(), []int{2} +} + +func (x *Client) GetId() string { + if x != nil && x.Id != nil { + return *x.Id + } + return "" +} + +func (x *Client) GetSecret() string { + if x != nil && x.Secret != nil { + return *x.Secret + } + return "" +} + +func (x *Client) GetConfig() string { + if x != nil && x.Config != nil { + return *x.Config + } + return "" +} + +type Server struct { + state protoimpl.MessageState + 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"` + Ip *string `protobuf:"bytes,3,opt,name=ip,proto3,oneof" json:"ip,omitempty"` + Config *string `protobuf:"bytes,4,opt,name=config,proto3,oneof" json:"config,omitempty"` // 在定义上,ip和port只是为了方便使用 +} + +func (x *Server) Reset() { + *x = Server{} + if protoimpl.UnsafeEnabled { + mi := &file_common_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Server) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Server) ProtoMessage() {} + +func (x *Server) ProtoReflect() protoreflect.Message { + mi := &file_common_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Server.ProtoReflect.Descriptor instead. +func (*Server) Descriptor() ([]byte, []int) { + return file_common_proto_rawDescGZIP(), []int{3} +} + +func (x *Server) GetId() string { + if x != nil && x.Id != nil { + return *x.Id + } + return "" +} + +func (x *Server) GetSecret() string { + if x != nil && x.Secret != nil { + return *x.Secret + } + return "" +} + +func (x *Server) GetIp() string { + if x != nil && x.Ip != nil { + return *x.Ip + } + return "" +} + +func (x *Server) GetConfig() string { + if x != nil && x.Config != nil { + return *x.Config + } + return "" +} + +type User struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserID *int64 `protobuf:"varint,1,opt,name=UserID,proto3,oneof" json:"UserID,omitempty"` + TenantID *int64 `protobuf:"varint,2,opt,name=TenantID,proto3,oneof" json:"TenantID,omitempty"` + UserName *string `protobuf:"bytes,3,opt,name=UserName,proto3,oneof" json:"UserName,omitempty"` + Email *string `protobuf:"bytes,4,opt,name=Email,proto3,oneof" json:"Email,omitempty"` + Status *string `protobuf:"bytes,5,opt,name=Status,proto3,oneof" json:"Status,omitempty"` + Role *string `protobuf:"bytes,6,opt,name=Role,proto3,oneof" json:"Role,omitempty"` + Token *string `protobuf:"bytes,7,opt,name=Token,proto3,oneof" json:"Token,omitempty"` + RawPassword *string `protobuf:"bytes,8,opt,name=RawPassword,proto3,oneof" json:"RawPassword,omitempty"` +} + +func (x *User) Reset() { + *x = User{} + if protoimpl.UnsafeEnabled { + mi := &file_common_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *User) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*User) ProtoMessage() {} + +func (x *User) ProtoReflect() protoreflect.Message { + mi := &file_common_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use User.ProtoReflect.Descriptor instead. +func (*User) Descriptor() ([]byte, []int) { + return file_common_proto_rawDescGZIP(), []int{4} +} + +func (x *User) GetUserID() int64 { + if x != nil && x.UserID != nil { + return *x.UserID + } + return 0 +} + +func (x *User) GetTenantID() int64 { + if x != nil && x.TenantID != nil { + return *x.TenantID + } + return 0 +} + +func (x *User) GetUserName() string { + if x != nil && x.UserName != nil { + return *x.UserName + } + return "" +} + +func (x *User) GetEmail() string { + if x != nil && x.Email != nil { + return *x.Email + } + return "" +} + +func (x *User) GetStatus() string { + if x != nil && x.Status != nil { + return *x.Status + } + return "" +} + +func (x *User) GetRole() string { + if x != nil && x.Role != nil { + return *x.Role + } + return "" +} + +func (x *User) GetToken() string { + if x != nil && x.Token != nil { + return *x.Token + } + return "" +} + +func (x *User) GetRawPassword() string { + if x != nil && x.RawPassword != nil { + return *x.RawPassword + } + return "" +} + +var File_common_proto protoreflect.FileDescriptor + +var file_common_proto_rawDesc = []byte{ + 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x22, 0x48, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x24, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, + 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x43, 0x6f, 0x64, 0x65, + 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x22, 0x48, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 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, 0x42, + 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x74, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 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, + 0x22, 0x90, 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, 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, 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, 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, 0x42, 0x07, 0x5a, 0x05, 0x2e, 0x2e, + 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_common_proto_rawDescOnce sync.Once + file_common_proto_rawDescData = file_common_proto_rawDesc +) + +func file_common_proto_rawDescGZIP() []byte { + file_common_proto_rawDescOnce.Do(func() { + file_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_common_proto_rawDescData) + }) + return file_common_proto_rawDescData +} + +var file_common_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_common_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_common_proto_goTypes = []interface{}{ + (RespCode)(0), // 0: common.RespCode + (*Status)(nil), // 1: common.Status + (*CommonResponse)(nil), // 2: common.CommonResponse + (*Client)(nil), // 3: common.Client + (*Server)(nil), // 4: common.Server + (*User)(nil), // 5: common.User +} +var file_common_proto_depIdxs = []int32{ + 0, // 0: common.Status.code:type_name -> common.RespCode + 1, // 1: common.CommonResponse.status:type_name -> common.Status + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_common_proto_init() } +func file_common_proto_init() { + if File_common_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_common_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Status); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_common_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CommonResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_common_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Client); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_common_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Server); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_common_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*User); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_common_proto_msgTypes[1].OneofWrappers = []interface{}{} + file_common_proto_msgTypes[2].OneofWrappers = []interface{}{} + file_common_proto_msgTypes[3].OneofWrappers = []interface{}{} + file_common_proto_msgTypes[4].OneofWrappers = []interface{}{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_common_proto_rawDesc, + NumEnums: 1, + NumMessages: 5, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_common_proto_goTypes, + DependencyIndexes: file_common_proto_depIdxs, + EnumInfos: file_common_proto_enumTypes, + MessageInfos: file_common_proto_msgTypes, + }.Build() + File_common_proto = out.File + file_common_proto_rawDesc = nil + file_common_proto_goTypes = nil + file_common_proto_depIdxs = nil +} diff --git a/pb/rpc_master.pb.go b/pb/rpc_master.pb.go new file mode 100644 index 0000000..6b384cc --- /dev/null +++ b/pb/rpc_master.pb.go @@ -0,0 +1,976 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.1 +// source: rpc_master.proto + +package pb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Event int32 + +const ( + Event_EVENT_UNSPECIFIED Event = 0 + Event_EVENT_REGISTER_CLIENT Event = 1 + Event_EVENT_REGISTER_SERVER Event = 2 + Event_EVENT_ERROR Event = 3 + Event_EVENT_DATA Event = 4 + Event_EVENT_UPDATE_FRPC Event = 5 + Event_EVENT_REMOVE_FRPC Event = 6 + Event_EVENT_UPDATE_FRPS Event = 7 + Event_EVENT_REMOVE_FRPS Event = 8 +) + +// Enum value maps for Event. +var ( + Event_name = map[int32]string{ + 0: "EVENT_UNSPECIFIED", + 1: "EVENT_REGISTER_CLIENT", + 2: "EVENT_REGISTER_SERVER", + 3: "EVENT_ERROR", + 4: "EVENT_DATA", + 5: "EVENT_UPDATE_FRPC", + 6: "EVENT_REMOVE_FRPC", + 7: "EVENT_UPDATE_FRPS", + 8: "EVENT_REMOVE_FRPS", + } + Event_value = map[string]int32{ + "EVENT_UNSPECIFIED": 0, + "EVENT_REGISTER_CLIENT": 1, + "EVENT_REGISTER_SERVER": 2, + "EVENT_ERROR": 3, + "EVENT_DATA": 4, + "EVENT_UPDATE_FRPC": 5, + "EVENT_REMOVE_FRPC": 6, + "EVENT_UPDATE_FRPS": 7, + "EVENT_REMOVE_FRPS": 8, + } +) + +func (x Event) Enum() *Event { + p := new(Event) + *p = x + return p +} + +func (x Event) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Event) Descriptor() protoreflect.EnumDescriptor { + return file_rpc_master_proto_enumTypes[0].Descriptor() +} + +func (Event) Type() protoreflect.EnumType { + return &file_rpc_master_proto_enumTypes[0] +} + +func (x Event) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Event.Descriptor instead. +func (Event) EnumDescriptor() ([]byte, []int) { + return file_rpc_master_proto_rawDescGZIP(), []int{0} +} + +type ServerBase struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ServerId string `protobuf:"bytes,1,opt,name=server_id,json=serverId,proto3" json:"server_id,omitempty"` + ServerSecret string `protobuf:"bytes,2,opt,name=server_secret,json=serverSecret,proto3" json:"server_secret,omitempty"` +} + +func (x *ServerBase) Reset() { + *x = ServerBase{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_master_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServerBase) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerBase) ProtoMessage() {} + +func (x *ServerBase) ProtoReflect() protoreflect.Message { + mi := &file_rpc_master_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServerBase.ProtoReflect.Descriptor instead. +func (*ServerBase) Descriptor() ([]byte, []int) { + return file_rpc_master_proto_rawDescGZIP(), []int{0} +} + +func (x *ServerBase) GetServerId() string { + if x != nil { + return x.ServerId + } + return "" +} + +func (x *ServerBase) GetServerSecret() string { + if x != nil { + return x.ServerSecret + } + return "" +} + +type ClientBase struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + ClientSecret string `protobuf:"bytes,2,opt,name=client_secret,json=clientSecret,proto3" json:"client_secret,omitempty"` +} + +func (x *ClientBase) Reset() { + *x = ClientBase{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_master_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClientBase) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClientBase) ProtoMessage() {} + +func (x *ClientBase) ProtoReflect() protoreflect.Message { + mi := &file_rpc_master_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClientBase.ProtoReflect.Descriptor instead. +func (*ClientBase) Descriptor() ([]byte, []int) { + return file_rpc_master_proto_rawDescGZIP(), []int{1} +} + +func (x *ClientBase) GetClientId() string { + if x != nil { + return x.ClientId + } + return "" +} + +func (x *ClientBase) GetClientSecret() string { + if x != nil { + return x.ClientSecret + } + return "" +} + +type ServerMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Event Event `protobuf:"varint,1,opt,name=event,proto3,enum=master.Event" json:"event,omitempty"` + ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + SessionId string `protobuf:"bytes,3,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *ServerMessage) Reset() { + *x = ServerMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_master_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServerMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerMessage) ProtoMessage() {} + +func (x *ServerMessage) ProtoReflect() protoreflect.Message { + mi := &file_rpc_master_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServerMessage.ProtoReflect.Descriptor instead. +func (*ServerMessage) Descriptor() ([]byte, []int) { + return file_rpc_master_proto_rawDescGZIP(), []int{2} +} + +func (x *ServerMessage) GetEvent() Event { + if x != nil { + return x.Event + } + return Event_EVENT_UNSPECIFIED +} + +func (x *ServerMessage) GetClientId() string { + if x != nil { + return x.ClientId + } + return "" +} + +func (x *ServerMessage) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +func (x *ServerMessage) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +type ClientMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Event Event `protobuf:"varint,1,opt,name=event,proto3,enum=master.Event" json:"event,omitempty"` + ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + SessionId string `protobuf:"bytes,3,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + Secret string `protobuf:"bytes,4,opt,name=secret,proto3" json:"secret,omitempty"` + Data []byte `protobuf:"bytes,5,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *ClientMessage) Reset() { + *x = ClientMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_master_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClientMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClientMessage) ProtoMessage() {} + +func (x *ClientMessage) ProtoReflect() protoreflect.Message { + mi := &file_rpc_master_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClientMessage.ProtoReflect.Descriptor instead. +func (*ClientMessage) Descriptor() ([]byte, []int) { + return file_rpc_master_proto_rawDescGZIP(), []int{3} +} + +func (x *ClientMessage) GetEvent() Event { + if x != nil { + return x.Event + } + return Event_EVENT_UNSPECIFIED +} + +func (x *ClientMessage) GetClientId() string { + if x != nil { + return x.ClientId + } + return "" +} + +func (x *ClientMessage) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +func (x *ClientMessage) GetSecret() string { + if x != nil { + return x.Secret + } + return "" +} + +func (x *ClientMessage) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +type PullClientConfigReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *ClientBase `protobuf:"bytes,255,opt,name=base,proto3" json:"base,omitempty"` +} + +func (x *PullClientConfigReq) Reset() { + *x = PullClientConfigReq{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_master_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PullClientConfigReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PullClientConfigReq) ProtoMessage() {} + +func (x *PullClientConfigReq) ProtoReflect() protoreflect.Message { + mi := &file_rpc_master_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PullClientConfigReq.ProtoReflect.Descriptor instead. +func (*PullClientConfigReq) Descriptor() ([]byte, []int) { + return file_rpc_master_proto_rawDescGZIP(), []int{4} +} + +func (x *PullClientConfigReq) GetBase() *ClientBase { + if x != nil { + return x.Base + } + return nil +} + +type PullClientConfigResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` + Client *Client `protobuf:"bytes,2,opt,name=client,proto3" json:"client,omitempty"` +} + +func (x *PullClientConfigResp) Reset() { + *x = PullClientConfigResp{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_master_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PullClientConfigResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PullClientConfigResp) ProtoMessage() {} + +func (x *PullClientConfigResp) ProtoReflect() protoreflect.Message { + mi := &file_rpc_master_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PullClientConfigResp.ProtoReflect.Descriptor instead. +func (*PullClientConfigResp) Descriptor() ([]byte, []int) { + return file_rpc_master_proto_rawDescGZIP(), []int{5} +} + +func (x *PullClientConfigResp) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +func (x *PullClientConfigResp) GetClient() *Client { + if x != nil { + return x.Client + } + return nil +} + +type PullServerConfigReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *ServerBase `protobuf:"bytes,255,opt,name=base,proto3" json:"base,omitempty"` +} + +func (x *PullServerConfigReq) Reset() { + *x = PullServerConfigReq{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_master_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PullServerConfigReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PullServerConfigReq) ProtoMessage() {} + +func (x *PullServerConfigReq) ProtoReflect() protoreflect.Message { + mi := &file_rpc_master_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PullServerConfigReq.ProtoReflect.Descriptor instead. +func (*PullServerConfigReq) Descriptor() ([]byte, []int) { + return file_rpc_master_proto_rawDescGZIP(), []int{6} +} + +func (x *PullServerConfigReq) GetBase() *ServerBase { + if x != nil { + return x.Base + } + return nil +} + +type PullServerConfigResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` + Server *Server `protobuf:"bytes,2,opt,name=server,proto3" json:"server,omitempty"` +} + +func (x *PullServerConfigResp) Reset() { + *x = PullServerConfigResp{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_master_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PullServerConfigResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PullServerConfigResp) ProtoMessage() {} + +func (x *PullServerConfigResp) ProtoReflect() protoreflect.Message { + mi := &file_rpc_master_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PullServerConfigResp.ProtoReflect.Descriptor instead. +func (*PullServerConfigResp) Descriptor() ([]byte, []int) { + return file_rpc_master_proto_rawDescGZIP(), []int{7} +} + +func (x *PullServerConfigResp) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +func (x *PullServerConfigResp) GetServer() *Server { + if x != nil { + return x.Server + } + return nil +} + +type FRPAuthRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` + Token string `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"` + Base *ServerBase `protobuf:"bytes,255,opt,name=base,proto3" json:"base,omitempty"` +} + +func (x *FRPAuthRequest) Reset() { + *x = FRPAuthRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_master_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FRPAuthRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FRPAuthRequest) ProtoMessage() {} + +func (x *FRPAuthRequest) ProtoReflect() protoreflect.Message { + mi := &file_rpc_master_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FRPAuthRequest.ProtoReflect.Descriptor instead. +func (*FRPAuthRequest) Descriptor() ([]byte, []int) { + return file_rpc_master_proto_rawDescGZIP(), []int{8} +} + +func (x *FRPAuthRequest) GetUser() string { + if x != nil { + return x.User + } + return "" +} + +func (x *FRPAuthRequest) GetToken() string { + if x != nil { + return x.Token + } + return "" +} + +func (x *FRPAuthRequest) GetBase() *ServerBase { + if x != nil { + return x.Base + } + return nil +} + +type FRPAuthResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status *Status `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` + Ok bool `protobuf:"varint,2,opt,name=ok,proto3" json:"ok,omitempty"` +} + +func (x *FRPAuthResponse) Reset() { + *x = FRPAuthResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_master_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FRPAuthResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FRPAuthResponse) ProtoMessage() {} + +func (x *FRPAuthResponse) ProtoReflect() protoreflect.Message { + mi := &file_rpc_master_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FRPAuthResponse.ProtoReflect.Descriptor instead. +func (*FRPAuthResponse) Descriptor() ([]byte, []int) { + return file_rpc_master_proto_rawDescGZIP(), []int{9} +} + +func (x *FRPAuthResponse) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +func (x *FRPAuthResponse) GetOk() bool { + if x != nil { + return x.Ok + } + return false +} + +var File_rpc_master_proto protoreflect.FileDescriptor + +var file_rpc_master_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x06, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x1a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, + 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4e, 0x0a, 0x0a, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x42, 0x61, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x65, + 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x22, 0x4e, 0x0a, 0x0a, 0x43, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x42, 0x61, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, + 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x22, 0x84, 0x01, 0x0a, 0x0d, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x6d, 0x61, 0x73, 0x74, + 0x65, 0x72, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, + 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, + 0x9c, 0x01, 0x0a, 0x0d, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x23, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x0d, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, + 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3e, + 0x0a, 0x13, 0x50, 0x75, 0x6c, 0x6c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x65, 0x71, 0x12, 0x27, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0xff, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x73, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x66, + 0x0a, 0x14, 0x50, 0x75, 0x6c, 0x6c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x12, 0x26, 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, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x26, + 0x0a, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, + 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x06, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x22, 0x3e, 0x0a, 0x13, 0x50, 0x75, 0x6c, 0x6c, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x12, 0x27, 0x0a, + 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0xff, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, + 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x42, 0x61, 0x73, 0x65, + 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x66, 0x0a, 0x14, 0x50, 0x75, 0x6c, 0x6c, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x12, 0x26, + 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, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x26, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x63, + 0x0a, 0x0e, 0x46, 0x52, 0x50, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x75, 0x73, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x27, 0x0a, 0x04, 0x62, 0x61, + 0x73, 0x65, 0x18, 0xff, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x61, 0x73, 0x74, + 0x65, 0x72, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x42, 0x61, 0x73, 0x65, 0x52, 0x04, 0x62, + 0x61, 0x73, 0x65, 0x22, 0x49, 0x0a, 0x0f, 0x46, 0x52, 0x50, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 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, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0e, + 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x2a, 0xd1, + 0x01, 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, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x45, 0x56, + 0x45, 0x4e, 0x54, 0x5f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x53, 0x45, 0x52, + 0x56, 0x45, 0x52, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, + 0x44, 0x41, 0x54, 0x41, 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, + 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x52, 0x50, 0x43, 0x10, 0x05, 0x12, 0x15, 0x0a, + 0x11, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x5f, 0x46, 0x52, + 0x50, 0x43, 0x10, 0x06, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x50, + 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x52, 0x50, 0x53, 0x10, 0x07, 0x12, 0x15, 0x0a, 0x11, 0x45, + 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x5f, 0x46, 0x52, 0x50, 0x53, + 0x10, 0x08, 0x32, 0xa3, 0x02, 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, 0x42, 0x07, 0x5a, 0x05, 0x2e, 0x2e, 0x2f, 0x70, + 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_rpc_master_proto_rawDescOnce sync.Once + file_rpc_master_proto_rawDescData = file_rpc_master_proto_rawDesc +) + +func file_rpc_master_proto_rawDescGZIP() []byte { + file_rpc_master_proto_rawDescOnce.Do(func() { + file_rpc_master_proto_rawDescData = protoimpl.X.CompressGZIP(file_rpc_master_proto_rawDescData) + }) + return file_rpc_master_proto_rawDescData +} + +var file_rpc_master_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_rpc_master_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_rpc_master_proto_goTypes = []interface{}{ + (Event)(0), // 0: master.Event + (*ServerBase)(nil), // 1: master.ServerBase + (*ClientBase)(nil), // 2: master.ClientBase + (*ServerMessage)(nil), // 3: master.ServerMessage + (*ClientMessage)(nil), // 4: master.ClientMessage + (*PullClientConfigReq)(nil), // 5: master.PullClientConfigReq + (*PullClientConfigResp)(nil), // 6: master.PullClientConfigResp + (*PullServerConfigReq)(nil), // 7: master.PullServerConfigReq + (*PullServerConfigResp)(nil), // 8: master.PullServerConfigResp + (*FRPAuthRequest)(nil), // 9: master.FRPAuthRequest + (*FRPAuthResponse)(nil), // 10: master.FRPAuthResponse + (*Status)(nil), // 11: common.Status + (*Client)(nil), // 12: common.Client + (*Server)(nil), // 13: common.Server +} +var file_rpc_master_proto_depIdxs = []int32{ + 0, // 0: master.ServerMessage.event:type_name -> master.Event + 0, // 1: master.ClientMessage.event:type_name -> master.Event + 2, // 2: master.PullClientConfigReq.base:type_name -> master.ClientBase + 11, // 3: master.PullClientConfigResp.status:type_name -> common.Status + 12, // 4: master.PullClientConfigResp.client:type_name -> common.Client + 1, // 5: master.PullServerConfigReq.base:type_name -> master.ServerBase + 11, // 6: master.PullServerConfigResp.status:type_name -> common.Status + 13, // 7: master.PullServerConfigResp.server:type_name -> common.Server + 1, // 8: master.FRPAuthRequest.base:type_name -> master.ServerBase + 11, // 9: master.FRPAuthResponse.status:type_name -> common.Status + 4, // 10: master.Master.ServerSend:input_type -> master.ClientMessage + 5, // 11: master.Master.PullClientConfig:input_type -> master.PullClientConfigReq + 7, // 12: master.Master.PullServerConfig:input_type -> master.PullServerConfigReq + 9, // 13: master.Master.FRPCAuth:input_type -> master.FRPAuthRequest + 3, // 14: master.Master.ServerSend:output_type -> master.ServerMessage + 6, // 15: master.Master.PullClientConfig:output_type -> master.PullClientConfigResp + 8, // 16: master.Master.PullServerConfig:output_type -> master.PullServerConfigResp + 10, // 17: master.Master.FRPCAuth:output_type -> master.FRPAuthResponse + 14, // [14:18] is the sub-list for method output_type + 10, // [10:14] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name +} + +func init() { file_rpc_master_proto_init() } +func file_rpc_master_proto_init() { + if File_rpc_master_proto != nil { + return + } + file_common_proto_init() + if !protoimpl.UnsafeEnabled { + file_rpc_master_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ServerBase); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_master_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClientBase); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_master_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ServerMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_master_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClientMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_master_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PullClientConfigReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_master_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PullClientConfigResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_master_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PullServerConfigReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_master_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PullServerConfigResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_master_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FRPAuthRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_master_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FRPAuthResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_rpc_master_proto_rawDesc, + NumEnums: 1, + NumMessages: 10, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_rpc_master_proto_goTypes, + DependencyIndexes: file_rpc_master_proto_depIdxs, + EnumInfos: file_rpc_master_proto_enumTypes, + MessageInfos: file_rpc_master_proto_msgTypes, + }.Build() + File_rpc_master_proto = out.File + file_rpc_master_proto_rawDesc = nil + file_rpc_master_proto_goTypes = nil + file_rpc_master_proto_depIdxs = nil +} diff --git a/pb/rpc_master_grpc.pb.go b/pb/rpc_master_grpc.pb.go new file mode 100644 index 0000000..50e5d8a --- /dev/null +++ b/pb/rpc_master_grpc.pb.go @@ -0,0 +1,253 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v4.25.1 +// source: rpc_master.proto + +package pb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + Master_ServerSend_FullMethodName = "/master.Master/ServerSend" + Master_PullClientConfig_FullMethodName = "/master.Master/PullClientConfig" + Master_PullServerConfig_FullMethodName = "/master.Master/PullServerConfig" + Master_FRPCAuth_FullMethodName = "/master.Master/FRPCAuth" +) + +// MasterClient is the client API for Master service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type MasterClient interface { + ServerSend(ctx context.Context, opts ...grpc.CallOption) (Master_ServerSendClient, error) + PullClientConfig(ctx context.Context, in *PullClientConfigReq, opts ...grpc.CallOption) (*PullClientConfigResp, error) + PullServerConfig(ctx context.Context, in *PullServerConfigReq, opts ...grpc.CallOption) (*PullServerConfigResp, error) + FRPCAuth(ctx context.Context, in *FRPAuthRequest, opts ...grpc.CallOption) (*FRPAuthResponse, error) +} + +type masterClient struct { + cc grpc.ClientConnInterface +} + +func NewMasterClient(cc grpc.ClientConnInterface) MasterClient { + return &masterClient{cc} +} + +func (c *masterClient) ServerSend(ctx context.Context, opts ...grpc.CallOption) (Master_ServerSendClient, error) { + stream, err := c.cc.NewStream(ctx, &Master_ServiceDesc.Streams[0], Master_ServerSend_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &masterServerSendClient{stream} + return x, nil +} + +type Master_ServerSendClient interface { + Send(*ClientMessage) error + Recv() (*ServerMessage, error) + grpc.ClientStream +} + +type masterServerSendClient struct { + grpc.ClientStream +} + +func (x *masterServerSendClient) Send(m *ClientMessage) error { + return x.ClientStream.SendMsg(m) +} + +func (x *masterServerSendClient) Recv() (*ServerMessage, error) { + m := new(ServerMessage) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *masterClient) PullClientConfig(ctx context.Context, in *PullClientConfigReq, opts ...grpc.CallOption) (*PullClientConfigResp, error) { + out := new(PullClientConfigResp) + err := c.cc.Invoke(ctx, Master_PullClientConfig_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *masterClient) PullServerConfig(ctx context.Context, in *PullServerConfigReq, opts ...grpc.CallOption) (*PullServerConfigResp, error) { + out := new(PullServerConfigResp) + err := c.cc.Invoke(ctx, Master_PullServerConfig_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *masterClient) FRPCAuth(ctx context.Context, in *FRPAuthRequest, opts ...grpc.CallOption) (*FRPAuthResponse, error) { + out := new(FRPAuthResponse) + err := c.cc.Invoke(ctx, Master_FRPCAuth_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MasterServer is the server API for Master service. +// All implementations must embed UnimplementedMasterServer +// for forward compatibility +type MasterServer interface { + ServerSend(Master_ServerSendServer) error + PullClientConfig(context.Context, *PullClientConfigReq) (*PullClientConfigResp, error) + PullServerConfig(context.Context, *PullServerConfigReq) (*PullServerConfigResp, error) + FRPCAuth(context.Context, *FRPAuthRequest) (*FRPAuthResponse, error) + mustEmbedUnimplementedMasterServer() +} + +// UnimplementedMasterServer must be embedded to have forward compatible implementations. +type UnimplementedMasterServer struct { +} + +func (UnimplementedMasterServer) ServerSend(Master_ServerSendServer) error { + return status.Errorf(codes.Unimplemented, "method ServerSend not implemented") +} +func (UnimplementedMasterServer) PullClientConfig(context.Context, *PullClientConfigReq) (*PullClientConfigResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method PullClientConfig not implemented") +} +func (UnimplementedMasterServer) PullServerConfig(context.Context, *PullServerConfigReq) (*PullServerConfigResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method PullServerConfig not implemented") +} +func (UnimplementedMasterServer) FRPCAuth(context.Context, *FRPAuthRequest) (*FRPAuthResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FRPCAuth not implemented") +} +func (UnimplementedMasterServer) mustEmbedUnimplementedMasterServer() {} + +// UnsafeMasterServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to MasterServer will +// result in compilation errors. +type UnsafeMasterServer interface { + mustEmbedUnimplementedMasterServer() +} + +func RegisterMasterServer(s grpc.ServiceRegistrar, srv MasterServer) { + s.RegisterService(&Master_ServiceDesc, srv) +} + +func _Master_ServerSend_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(MasterServer).ServerSend(&masterServerSendServer{stream}) +} + +type Master_ServerSendServer interface { + Send(*ServerMessage) error + Recv() (*ClientMessage, error) + grpc.ServerStream +} + +type masterServerSendServer struct { + grpc.ServerStream +} + +func (x *masterServerSendServer) Send(m *ServerMessage) error { + return x.ServerStream.SendMsg(m) +} + +func (x *masterServerSendServer) Recv() (*ClientMessage, error) { + m := new(ClientMessage) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _Master_PullClientConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PullClientConfigReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MasterServer).PullClientConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Master_PullClientConfig_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MasterServer).PullClientConfig(ctx, req.(*PullClientConfigReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Master_PullServerConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PullServerConfigReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MasterServer).PullServerConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Master_PullServerConfig_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MasterServer).PullServerConfig(ctx, req.(*PullServerConfigReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Master_FRPCAuth_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FRPAuthRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MasterServer).FRPCAuth(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Master_FRPCAuth_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MasterServer).FRPCAuth(ctx, req.(*FRPAuthRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Master_ServiceDesc is the grpc.ServiceDesc for Master service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Master_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "master.Master", + HandlerType: (*MasterServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "PullClientConfig", + Handler: _Master_PullClientConfig_Handler, + }, + { + MethodName: "PullServerConfig", + Handler: _Master_PullServerConfig_Handler, + }, + { + MethodName: "FRPCAuth", + Handler: _Master_FRPCAuth_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "ServerSend", + Handler: _Master_ServerSend_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "rpc_master.proto", +} diff --git a/rpc/client.go b/rpc/client.go new file mode 100644 index 0000000..331a2e4 --- /dev/null +++ b/rpc/client.go @@ -0,0 +1,106 @@ +package rpc + +import ( + "context" + "fmt" + "io" + "sync" + + "github.com/VaalaCat/frp-panel/pb" + "github.com/google/uuid" + "github.com/sirupsen/logrus" + "google.golang.org/protobuf/proto" +) + +func CallClient(c context.Context, clientID string, event pb.Event, msg proto.Message) (*pb.ClientMessage, error) { + sender := GetClientsManager().Get(clientID) + if sender == nil { + logrus.Errorf("cannot get client, id: [%s]", clientID) + return nil, fmt.Errorf("cannot get client, id: [%s]", clientID) + } + + data, err := proto.Marshal(msg) + if err != nil { + logrus.WithError(err).Errorf("cannot marshal") + return nil, err + } + + req := &pb.ServerMessage{ + Event: event, + Data: data, + SessionId: uuid.New().String(), + ClientId: clientID, + } + + recvMap.Store(req.SessionId, make(chan *pb.ClientMessage)) + err = sender.Send(req) + if err != nil { + logrus.WithError(err).Errorf("cannot send") + return nil, err + } + respChAny, ok := recvMap.Load(req.SessionId) + if !ok { + logrus.Fatalf("cannot load") + } + + respCh, ok := respChAny.(chan *pb.ClientMessage) + if !ok { + logrus.Fatalf("cannot cast") + } + + resp := <-respCh + if resp.Event == pb.Event_EVENT_ERROR { + return nil, fmt.Errorf("client return error: %s", resp.Data) + } + + close(respCh) + recvMap.Delete(req.SessionId) + return resp, nil +} + +var ( + recvMap *sync.Map +) + +func init() { + recvMap = &sync.Map{} +} + +func Recv(clientID string) chan bool { + done := make(chan bool) + go func() { + for { + reciver := GetClientsManager().Get(clientID) + if reciver == nil { + logrus.Errorf("cannot get client") + continue + } + resp, err := reciver.Recv() + if err == io.EOF { + logrus.Infof("finish client recv") + done <- true + return + } + if err != nil { + logrus.WithError(err).Errorf("cannot recv, usually means client disconnect") + done <- true + return + } + + respChAny, ok := recvMap.Load(resp.SessionId) + if !ok { + logrus.Errorf("cannot load") + continue + } + + respCh, ok := respChAny.(chan *pb.ClientMessage) + if !ok { + logrus.Errorf("cannot cast") + continue + } + logrus.Infof("recv success, resp: %+v", resp) + respCh <- resp + } + }() + return done +} diff --git a/rpc/client_manager.go b/rpc/client_manager.go new file mode 100644 index 0000000..7990b09 --- /dev/null +++ b/rpc/client_manager.go @@ -0,0 +1,63 @@ +package rpc + +import ( + "sync" + + "github.com/VaalaCat/frp-panel/pb" +) + +type ClientsManager interface { + Get(cliID string) pb.Master_ServerSendServer + Set(cliID string, sender pb.Master_ServerSendServer) + Remove(cliID string) +} + +type ClientsManagerImpl struct { + senders *sync.Map +} + +// Get implements ClientsManager. +func (c *ClientsManagerImpl) Get(cliID string) pb.Master_ServerSendServer { + cliAny, ok := c.senders.Load(cliID) + if !ok { + return nil + } + + cli, ok := cliAny.(pb.Master_ServerSendServer) + if !ok { + return nil + } + + return cli +} + +// Set implements ClientsManager. +func (c *ClientsManagerImpl) Set(cliID string, sender pb.Master_ServerSendServer) { + c.senders.Store(cliID, sender) +} + +func (c *ClientsManagerImpl) Remove(cliID string) { + c.senders.Delete(cliID) +} + +var ( + clientsManager *ClientsManagerImpl +) + +func NewClientsManager() *ClientsManagerImpl { + return &ClientsManagerImpl{ + senders: &sync.Map{}, + } +} + +func MustInitClientsManager() { + if clientsManager != nil { + return + } + + clientsManager = NewClientsManager() +} + +func GetClientsManager() ClientsManager { + return clientsManager +} diff --git a/rpc/init.go b/rpc/init.go new file mode 100644 index 0000000..337d403 --- /dev/null +++ b/rpc/init.go @@ -0,0 +1,5 @@ +package rpc + +func InitRPCClients() { + MustInitClientsManager() +} diff --git a/rpc/master.go b/rpc/master.go new file mode 100644 index 0000000..9f6dce5 --- /dev/null +++ b/rpc/master.go @@ -0,0 +1,23 @@ +package rpc + +import ( + "context" + + "github.com/VaalaCat/frp-panel/conf" + "github.com/VaalaCat/frp-panel/pb" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +func MasterCli(c context.Context) (pb.MasterClient, error) { + conn, err := grpc.Dial(conf.RPCCallAddr(), + grpc.WithTransportCredentials( + insecure.NewCredentials(), + )) + if err != nil { + return nil, err + } + + client := pb.NewMasterClient(conn) + return client, nil +} diff --git a/services/api/service.go b/services/api/service.go new file mode 100644 index 0000000..1fa4bb1 --- /dev/null +++ b/services/api/service.go @@ -0,0 +1,42 @@ +package api + +import ( + "github.com/gin-gonic/gin" +) + +type ApiService interface { + Run() + Stop() +} + +type server struct { + srv *gin.Engine + addr string +} + +var ( + _ ApiService = (*server)(nil) + apiService *server +) + +func NewApiService(listenAddr string, router *gin.Engine) *server { + return &server{ + srv: router, + addr: listenAddr, + } +} + +func MustInitApiService(listenAddr string, router *gin.Engine) { + apiService = NewApiService(listenAddr, router) +} + +func GetAPIService() ApiService { + return apiService +} + +func (s *server) Run() { + s.srv.Run(s.addr) +} + +func (s *server) Stop() { +} diff --git a/services/client/frpc_service.go b/services/client/frpc_service.go new file mode 100644 index 0000000..538b54a --- /dev/null +++ b/services/client/frpc_service.go @@ -0,0 +1,179 @@ +package client + +import ( + "context" + "os" + "os/signal" + "syscall" + "time" + + "github.com/VaalaCat/frp-panel/utils" + "github.com/fatedier/frp/client" + "github.com/fatedier/frp/client/proxy" + v1 "github.com/fatedier/frp/pkg/config/v1" + "github.com/fatedier/frp/pkg/config/v1/validation" + "github.com/fatedier/frp/pkg/util/log" + "github.com/samber/lo" + "github.com/sirupsen/logrus" +) + +type ClientHandler interface { + Run() + Stop() + Wait() + Running() bool + Update([]v1.ProxyConfigurer, []v1.VisitorConfigurer) + AddProxy(v1.ProxyConfigurer) + AddVisitor(v1.VisitorConfigurer) + RemoveProxy(v1.ProxyConfigurer) + RemoveVisitor(v1.VisitorConfigurer) + GetProxyStatus(string) (*proxy.WorkingStatus, error) + GetCommonCfg() *v1.ClientCommonConfig + GetProxyCfgs() map[string]v1.ProxyConfigurer + GetVisitorCfgs() map[string]v1.VisitorConfigurer +} + +type Client struct { + cli *client.Service + Common *v1.ClientCommonConfig + ProxyCfgs map[string]v1.ProxyConfigurer + VisitorCfgs map[string]v1.VisitorConfigurer + done chan bool + running bool +} + +var ( + cli *Client +) + +func InitGlobalClientService(commonCfg *v1.ClientCommonConfig, + proxyCfgs []v1.ProxyConfigurer, + visitorCfgs []v1.VisitorConfigurer) { + if cli != nil { + logrus.Warn("client has been initialized") + return + } + cli = NewClientHandler(commonCfg, proxyCfgs, visitorCfgs) +} + +func GetGlobalClientSerivce() ClientHandler { + if cli == nil { + logrus.Panic("client has not been initialized") + } + return cli +} + +func NewClientHandler(commonCfg *v1.ClientCommonConfig, + proxyCfgs []v1.ProxyConfigurer, + visitorCfgs []v1.VisitorConfigurer) *Client { + + warning, err := validation.ValidateAllClientConfig(commonCfg, proxyCfgs, visitorCfgs) + if warning != nil { + logrus.WithError(err).Warnf("validate client config warning: %+v", warning) + } + if err != nil { + logrus.Panic(err) + } + + log.InitLog(commonCfg.Log.To, commonCfg.Log.Level, commonCfg.Log.MaxDays, commonCfg.Log.DisablePrintColor) + cli, err := client.NewService(client.ServiceOptions{ + Common: commonCfg, + ProxyCfgs: proxyCfgs, + VisitorCfgs: visitorCfgs, + }) + if err != nil { + logrus.Panic(err) + } + + return &Client{ + cli: cli, + Common: commonCfg, + ProxyCfgs: lo.SliceToMap(proxyCfgs, utils.TransformProxyConfigurerToMap), + VisitorCfgs: lo.SliceToMap(visitorCfgs, utils.TransformVisitorConfigurerToMap), + } +} + +func (c *Client) Run() { + shouldGracefulClose := c.Common.Transport.Protocol == "kcp" || c.Common.Transport.Protocol == "quic" + if shouldGracefulClose { + go handleTermSignal(c.cli) + } + c.running = true + c.done = make(chan bool) + + defer func() { + c.running = false + close(c.done) + }() + + if err := c.cli.Run(context.Background()); err != nil { + logrus.Errorf("run client error: %v", err) + } +} + +func (c *Client) Stop() { + c.cli.Close() +} + +func (c *Client) Update(proxyCfgs []v1.ProxyConfigurer, visitorCfgs []v1.VisitorConfigurer) { + c.ProxyCfgs = lo.SliceToMap(proxyCfgs, utils.TransformProxyConfigurerToMap) + c.VisitorCfgs = lo.SliceToMap(visitorCfgs, utils.TransformVisitorConfigurerToMap) + c.cli.UpdateAllConfigurer(proxyCfgs, visitorCfgs) +} + +func (c *Client) AddProxy(proxyCfg v1.ProxyConfigurer) { + c.ProxyCfgs[proxyCfg.GetBaseConfig().Name] = proxyCfg + c.cli.UpdateAllConfigurer(lo.Values(c.ProxyCfgs), lo.Values(c.VisitorCfgs)) +} + +func (c *Client) AddVisitor(visitorCfg v1.VisitorConfigurer) { + c.VisitorCfgs[visitorCfg.GetBaseConfig().Name] = visitorCfg + c.cli.UpdateAllConfigurer(lo.Values(c.ProxyCfgs), lo.Values(c.VisitorCfgs)) +} + +func (c *Client) RemoveProxy(proxyCfg v1.ProxyConfigurer) { + old := c.ProxyCfgs + delete(old, proxyCfg.GetBaseConfig().Name) + + c.ProxyCfgs = old + c.cli.UpdateAllConfigurer(lo.Values(c.ProxyCfgs), lo.Values(c.VisitorCfgs)) +} + +func (c *Client) RemoveVisitor(visitorCfg v1.VisitorConfigurer) { + old := c.VisitorCfgs + delete(old, visitorCfg.GetBaseConfig().Name) + + c.VisitorCfgs = old + c.cli.UpdateAllConfigurer(lo.Values(c.ProxyCfgs), lo.Values(c.VisitorCfgs)) +} + +func (c *Client) GetProxyStatus(name string) (*proxy.WorkingStatus, error) { + return c.cli.GetProxyStatus(name) +} + +func (c *Client) GetCommonCfg() *v1.ClientCommonConfig { + return c.Common +} + +func (c *Client) GetProxyCfgs() map[string]v1.ProxyConfigurer { + return c.ProxyCfgs +} + +func (c *Client) GetVisitorCfgs() map[string]v1.VisitorConfigurer { + return c.VisitorCfgs +} + +func (c *Client) Running() bool { + return c.running +} + +func (c *Client) Wait() { + <-c.done +} + +func handleTermSignal(svr *client.Service) { + ch := make(chan os.Signal, 1) + signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) + <-ch + svr.GracefulClose(500 * time.Millisecond) +} diff --git a/services/master/grpc_server.go b/services/master/grpc_server.go new file mode 100644 index 0000000..c4b1523 --- /dev/null +++ b/services/master/grpc_server.go @@ -0,0 +1,132 @@ +package master + +import ( + "context" + "fmt" + "io" + "net" + + "github.com/VaalaCat/frp-panel/biz/master/client" + masterserver "github.com/VaalaCat/frp-panel/biz/master/server" + "github.com/VaalaCat/frp-panel/conf" + "github.com/VaalaCat/frp-panel/dao" + "github.com/VaalaCat/frp-panel/pb" + "github.com/VaalaCat/frp-panel/rpc" + "github.com/sirupsen/logrus" + "google.golang.org/grpc" +) + +type server struct { + pb.UnimplementedMasterServer +} + +func NewRpcServer() *grpc.Server { + s := grpc.NewServer() + pb.RegisterMasterServer(s, &server{}) + return s +} + +func RunRpcServer(s *grpc.Server) { + lis, err := net.Listen("tcp", conf.RPCListenAddr()) + if err != nil { + logrus.Fatalf("rpc server failed to listen: %v", err) + } + + logrus.Infof("start server") + if err := s.Serve(lis); err != nil { + logrus.Fatalf("failed to serve: %v", err) + } +} + +// PullClientConfig implements pb.MasterServer. +func (s *server) PullClientConfig(ctx context.Context, req *pb.PullClientConfigReq) (*pb.PullClientConfigResp, error) { + logrus.Infof("pull client config, req: [%+v]", req) + return client.RPCPullConfig(ctx, req) +} + +// PullServerConfig implements pb.MasterServer. +func (s *server) PullServerConfig(ctx context.Context, req *pb.PullServerConfigReq) (*pb.PullServerConfigResp, error) { + logrus.Infof("pull server config, req: [%+v]", req) + return masterserver.RPCPullConfig(ctx, req) +} + +// FRPCAuth implements pb.MasterServer. +func (*server) FRPCAuth(ctx context.Context, req *pb.FRPAuthRequest) (*pb.FRPAuthResponse, error) { + logrus.Infof("frpc auth, req: [%+v]", req) + return masterserver.FRPAuth(ctx, req) +} + +// ServerSend implements pb.MasterServer. +func (s *server) ServerSend(sender pb.Master_ServerSendServer) error { + logrus.Infof("server get a client connected") + var done chan bool + for { + req, err := sender.Recv() + if err == io.EOF { + logrus.Infof("finish server send, client id: [%s]", req.GetClientId()) + return nil + } + + if err != nil { + logrus.WithError(err).Errorf("cannot recv from client, id: [%s]", req.GetClientId()) + return err + } + + if req.GetEvent() == pb.Event_EVENT_REGISTER_CLIENT || req.GetEvent() == pb.Event_EVENT_REGISTER_SERVER { + if len(req.GetSecret()) == 0 { + logrus.Errorf("rpc auth token is empty") + sender.Send(&pb.ServerMessage{ + Event: req.GetEvent(), + Data: []byte("rpc auth token is invalid"), + }) + return fmt.Errorf("rpc auth token is invalid") + } + var secret string + switch req.GetEvent() { + case pb.Event_EVENT_REGISTER_CLIENT: + cli, err := dao.AdminGetClientByClientID(req.GetClientId()) + if err != nil { + logrus.WithError(err).Errorf("cannot get client, %s id: [%s]", req.GetEvent().String(), req.GetClientId()) + sender.Send(&pb.ServerMessage{ + Event: req.GetEvent(), + Data: []byte("rpc auth token is invalid"), + }) + return err + } + secret = cli.ConnectSecret + case pb.Event_EVENT_REGISTER_SERVER: + srv, err := dao.AdminGetServerByServerID(req.GetClientId()) + if err != nil { + logrus.WithError(err).Errorf("cannot get server, %s id: [%s]", req.GetEvent().String(), req.GetClientId()) + sender.Send(&pb.ServerMessage{ + Event: req.GetEvent(), + Data: []byte("rpc auth token is invalid"), + }) + return err + } + secret = srv.ConnectSecret + } + + if secret != req.GetSecret() { + logrus.Errorf("invalid secret, %s id: [%s]", req.GetEvent().String(), req.GetClientId()) + sender.Send(&pb.ServerMessage{ + Event: req.GetEvent(), + Data: []byte("rpc auth token is invalid"), + }) + return fmt.Errorf("invalid secret, %s id: [%s]", req.GetEvent().String(), req.GetClientId()) + } + + rpc.GetClientsManager().Set(req.GetClientId(), sender) + done = rpc.Recv(req.GetClientId()) + sender.Send(&pb.ServerMessage{ + Event: req.GetEvent(), + ClientId: req.GetClientId(), + SessionId: req.GetClientId(), + }) + logrus.Infof("register success, req: [%+v]", req) + break + } + } + <-done + return nil +} diff --git a/services/master/grpc_service.go b/services/master/grpc_service.go new file mode 100644 index 0000000..0e4c97a --- /dev/null +++ b/services/master/grpc_service.go @@ -0,0 +1,49 @@ +package master + +import ( + "github.com/sirupsen/logrus" + "google.golang.org/grpc" +) + +type MasterHandler interface { + Run() + Stop() +} + +type Master struct { + grpcServer *grpc.Server +} + +var ( + cli *Master +) + +func MustInitMasterService() { + if cli != nil { + logrus.Warn("server has been initialized") + return + } + cli = NewMasterHandler() +} + +func GetMasterSerivce() MasterHandler { + if cli == nil { + logrus.Panic("server has not been initialized") + } + return cli +} + +func NewMasterHandler() *Master { + s := NewRpcServer() + return &Master{ + grpcServer: s, + } +} + +func (s *Master) Run() { + RunRpcServer(s.grpcServer) +} + +func (s *Master) Stop() { + s.grpcServer.Stop() +} diff --git a/services/rpcclient/rpc_handler.go b/services/rpcclient/rpc_handler.go new file mode 100644 index 0000000..aaa47dd --- /dev/null +++ b/services/rpcclient/rpc_handler.go @@ -0,0 +1,113 @@ +package rpcclient + +import ( + "context" + "io" + "time" + + "github.com/VaalaCat/frp-panel/pb" + "github.com/VaalaCat/frp-panel/rpc" + "github.com/google/uuid" + "github.com/sirupsen/logrus" +) + +// func clientHandleServerSend(req *pb.ServerMessage) *pb.ClientMessage { +// logrus.Infof("client get a server message, origin is: [%+v]", req) +// return &pb.ClientMessage{ +// Event: pb.Event_EVENT_DATA, +// ClientId: req.ClientId, +// SessionId: req.SessionId, +// Data: req.Data, +// } +// } + +func NewMasterCli() (pb.MasterClient, error) { + return rpc.MasterCli(context.Background()) +} + +func RegistClientToMaster(recvStream pb.Master_ServerSendClient, event pb.Event, clientID, clientSecret string) { + logrus.Infof("start to regist client to master") + for { + err := recvStream.Send(&pb.ClientMessage{ + Event: event, + ClientId: clientID, + SessionId: uuid.New().String(), + Secret: clientSecret, + }) + if err != nil { + logrus.WithError(err).Warnf("cannot send, sleep 3s and retry") + time.Sleep(3 * time.Second) + continue + } + + resp, err := recvStream.Recv() + if err == io.EOF { + break + } + if err != nil { + logrus.Fatalf("cannot receive %v", err) + } + + if resp.GetEvent() == event { + logrus.Infof("client get server register envent success, clientID: %s", resp.GetClientId()) + break + } + } +} + +func RunRPCClient(recvStream pb.Master_ServerSendClient, done chan bool, clientID string, + clientHandleServerSend func(req *pb.ServerMessage) *pb.ClientMessage) { + for { + select { + case <-done: + logrus.Infof("finish rpc client") + recvStream.CloseSend() + return + default: + resp, err := recvStream.Recv() + if err == io.EOF { + break + } + if err != nil { + logrus.WithError(err).Errorf("cannot receive, sleep 3s and return") + time.Sleep(3 * time.Second) + return + } + if resp == nil { + continue + } + go func() { + msg := clientHandleServerSend(resp) + if msg == nil { + return + } + msg.ClientId = clientID + msg.SessionId = resp.SessionId + recvStream.Send(msg) + logrus.Infof("client resp received: %s", resp.GetClientId()) + }() + } + } +} + +func StartRPCClient(client pb.MasterClient, done chan bool, clientID, clientSecret string, event pb.Event, + clientHandleServerSend func(req *pb.ServerMessage) *pb.ClientMessage) { + logrus.Infof("start to run rpc client") + for { + select { + case <-done: + logrus.Infof("finish rpc client") + return + default: + recvStream, err := client.ServerSend(context.Background()) + if err != nil { + logrus.WithError(err).Errorf("cannot recv, sleep 3s and retry") + time.Sleep(3 * time.Second) + continue + } + + RegistClientToMaster(recvStream, event, clientID, clientSecret) + RunRPCClient(recvStream, done, clientID, clientHandleServerSend) + } + } +} diff --git a/services/rpcclient/rpc_service.go b/services/rpcclient/rpc_service.go new file mode 100644 index 0000000..2e65bf5 --- /dev/null +++ b/services/rpcclient/rpc_service.go @@ -0,0 +1,68 @@ +package rpcclient + +import ( + "github.com/VaalaCat/frp-panel/pb" + "github.com/sirupsen/logrus" +) + +type ClientRPCHandler interface { + Run() + Stop() + GetCli() pb.MasterClient +} + +type ClientRPC struct { + rpcClient pb.MasterClient + done chan bool + handerFunc func(req *pb.ServerMessage) *pb.ClientMessage + clientID string + clientSecret string + event pb.Event +} + +var ( + cliRpc *ClientRPC +) + +func MustInitClientRPCSerivce(clientID, clientSecret string, event pb.Event, handerFunc func(req *pb.ServerMessage) *pb.ClientMessage) { + if cliRpc != nil { + logrus.Warn("rpc client has been initialized") + return + } + cliRpc = NewClientRPCHandler(clientID, clientSecret, event, handerFunc) +} + +func GetClientRPCSerivce() ClientRPCHandler { + if cliRpc == nil { + logrus.Panic("rpc client has not been initialized") + } + return cliRpc +} + +func NewClientRPCHandler(clientID, clientSecret string, event pb.Event, handerFunc func(req *pb.ServerMessage) *pb.ClientMessage) *ClientRPC { + rpcCli, err := NewMasterCli() + if err != nil { + logrus.Fatalf("new rpc client failed: %v", err) + } + done := make(chan bool) + return &ClientRPC{ + rpcClient: rpcCli, + done: done, + handerFunc: handerFunc, + clientID: clientID, + clientSecret: clientSecret, + event: event, + } +} + +func (s *ClientRPC) Run() { + StartRPCClient(s.rpcClient, s.done, s.clientID, s.clientSecret, s.event, s.handerFunc) +} + +func (s *ClientRPC) Stop() { + close(s.done) +} + +func (s *ClientRPC) GetCli() pb.MasterClient { + return s.rpcClient +} diff --git a/services/server/frps_service.go b/services/server/frps_service.go new file mode 100644 index 0000000..5285eee --- /dev/null +++ b/services/server/frps_service.go @@ -0,0 +1,82 @@ +package server + +import ( + "context" + + v1 "github.com/fatedier/frp/pkg/config/v1" + "github.com/fatedier/frp/pkg/config/v1/validation" + "github.com/fatedier/frp/pkg/util/log" + "github.com/fatedier/frp/server" + "github.com/sirupsen/logrus" +) + +type ServerHandler interface { + Run() + Stop() + GetCommonCfg() *v1.ServerConfig +} + +type Server struct { + srv *server.Service + Common *v1.ServerConfig +} + +var ( + srv *Server +) + +func InitGlobalServerService(svrCfg *v1.ServerConfig) { + if srv != nil { + logrus.Warn("server has been initialized") + return + } + + svrCfg.Complete() + srv = NewServerHandler(svrCfg) +} + +func GetGlobalServerSerivce() ServerHandler { + if srv == nil { + logrus.Panic("server has not been initialized") + } + return srv +} + +func GetServerSerivce(svrCfg *v1.ServerConfig) ServerHandler { + svrCfg.Complete() + return NewServerHandler(svrCfg) +} + +func NewServerHandler(svrCfg *v1.ServerConfig) *Server { + warning, err := validation.ValidateServerConfig(svrCfg) + if warning != nil { + logrus.WithError(err).Warnf("validate server config warning: %+v", warning) + } + if err != nil { + logrus.Panic(err) + } + + log.InitLog(svrCfg.Log.To, svrCfg.Log.Level, svrCfg.Log.MaxDays, svrCfg.Log.DisablePrintColor) + + svr, err := server.NewService(svrCfg) + if err != nil { + logrus.Panic(err) + } + + return &Server{ + srv: svr, + Common: svrCfg, + } +} + +func (s *Server) Run() { + s.srv.Run(context.Background()) +} + +func (s *Server) Stop() { + s.srv.Close() +} + +func (s *Server) GetCommonCfg() *v1.ServerConfig { + return s.Common +} diff --git a/tunnel/client.go b/tunnel/client.go new file mode 100644 index 0000000..5ab6672 --- /dev/null +++ b/tunnel/client.go @@ -0,0 +1,83 @@ +package tunnel + +import ( + "sync" + + "github.com/VaalaCat/frp-panel/services/client" +) + +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) + List() []string +} + +type clientController struct { + clients *sync.Map +} + +var ( + clientControllerInstance *clientController +) + +func NewClientController() ClientController { + return &clientController{ + clients: &sync.Map{}, + } +} + +func GetClientController() ClientController { + if clientControllerInstance == nil { + clientControllerInstance = NewClientController().(*clientController) + } + return clientControllerInstance +} + +func (c *clientController) Add(clientID string, clientHandler client.ClientHandler) { + c.clients.Store(clientID, clientHandler) +} + +func (c *clientController) Get(clientID string) client.ClientHandler { + v, ok := c.clients.Load(clientID) + if !ok { + return nil + } + return v.(client.ClientHandler) +} + +func (c *clientController) Delete(clientID string) { + c.clients.Delete(clientID) +} + +func (c *clientController) Set(clientID string, clientHandler client.ClientHandler) { + c.clients.Store(clientID, clientHandler) +} + +func (c *clientController) Run(clientID string) { + v, ok := c.clients.Load(clientID) + if !ok { + return + } + go v.(client.ClientHandler).Run() +} + +func (c *clientController) Stop(clientID string) { + v, ok := c.clients.Load(clientID) + if !ok { + return + } + v.(client.ClientHandler).Stop() +} + +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 +} diff --git a/tunnel/master.go b/tunnel/master.go new file mode 100644 index 0000000..9af6f26 --- /dev/null +++ b/tunnel/master.go @@ -0,0 +1 @@ +package tunnel \ No newline at end of file diff --git a/tunnel/server.go b/tunnel/server.go new file mode 100644 index 0000000..3a85ecd --- /dev/null +++ b/tunnel/server.go @@ -0,0 +1,83 @@ +package tunnel + +import ( + "sync" + + "github.com/VaalaCat/frp-panel/services/server" +) + +type ServerController interface { + Add(serverID string, serverHandler server.ServerHandler) + Get(serverID string) server.ServerHandler + Delete(serverID string) + Set(serverID string, serverHandler server.ServerHandler) + Run(serverID string) // 不阻塞 + Stop(serverID string) + List() []string +} + +type serverController struct { + servers *sync.Map +} + +var ( + serverControllerInstance *serverController +) + +func NewServerController() ServerController { + return &serverController{ + servers: &sync.Map{}, + } +} + +func GetServerController() ServerController { + if serverControllerInstance == nil { + serverControllerInstance = NewServerController().(*serverController) + } + return serverControllerInstance +} + +func (c *serverController) Add(serverID string, serverHandler server.ServerHandler) { + c.servers.Store(serverID, serverHandler) +} + +func (c *serverController) Get(serverID string) server.ServerHandler { + v, ok := c.servers.Load(serverID) + if !ok { + return nil + } + return v.(server.ServerHandler) +} + +func (c *serverController) Delete(serverID string) { + c.servers.Delete(serverID) +} + +func (c *serverController) Set(serverID string, serverHandler server.ServerHandler) { + c.servers.Store(serverID, serverHandler) +} + +func (c *serverController) Run(serverID string) { + v, ok := c.servers.Load(serverID) + if !ok { + return + } + go v.(server.ServerHandler).Run() +} + +func (c *serverController) Stop(serverID string) { + v, ok := c.servers.Load(serverID) + if !ok { + return + } + v.(server.ServerHandler).Stop() +} + +func (c *serverController) List() []string { + keys := make([]string, 0) + c.servers.Range(func(key, value interface{}) bool { + keys = append(keys, key.(string)) + return true + }) + return keys +} diff --git a/utils/conv.go b/utils/conv.go new file mode 100644 index 0000000..157472f --- /dev/null +++ b/utils/conv.go @@ -0,0 +1,38 @@ +package utils + +import ( + "strconv" +) + +func Str2Int64(str string) int64 { + num, err := strconv.ParseInt(str, 10, 64) + if err != nil { + return 0 + } + return num +} + +func Str2Int64Default(str string, intVal int64) int64 { + num, err := strconv.ParseInt(str, 10, 64) + if err != nil { + return intVal + } + return num +} + +func ToStr(any interface{}) string { + if any == nil { + return "" + } + + if str, ok := any.(string); ok { + return str + } + + return "" +} + +func IsInteger(str string) bool { + _, err := strconv.Atoi(str) + return err == nil +} diff --git a/utils/ctx.go b/utils/ctx.go new file mode 100644 index 0000000..169f39c --- /dev/null +++ b/utils/ctx.go @@ -0,0 +1,60 @@ +package utils + +import ( + "context" + "reflect" + "strconv" +) + +func GetValue[T any](c context.Context, key string) (T, bool) { + val, ok := getValue[T](c, key) + if !ok { + return *new(T), false + } + v, ok := val.(T) + if !ok { + return *new(T), false + } + return v, true +} + +func getValue[T any](c context.Context, key string) (interface{}, bool) { + val := c.Value(key) + if val == nil { + return *new(T), false + } + + if reflect.TypeOf(*new(T)).Kind() == reflect.Int && reflect.TypeOf(val).Kind() == reflect.String { + strconvInt, err := strconv.Atoi(val.(string)) + if err != nil { + return *new(T), false + } + return strconvInt, true + } + + v, ok := val.(T) + if !ok { + return *new(T), false + } + + return v, true +} + +func GetIntValueFromStr(c context.Context, key string) (int, bool) { + val := c.Value(key) + if val == nil { + return 0, false + } + + v, ok := val.(string) + if !ok { + return 0, false + } + + strconvInt, err := strconv.Atoi(v) + if err != nil { + return 0, false + } + + return strconvInt, true +} diff --git a/utils/frp_config.go b/utils/frp_config.go new file mode 100644 index 0000000..2b4b10e --- /dev/null +++ b/utils/frp_config.go @@ -0,0 +1,64 @@ +package utils + +import ( + v1 "github.com/fatedier/frp/pkg/config/v1" +) + +func NewBaseFRPServerConfig(port int, token string) *v1.ServerConfig { + resp := &v1.ServerConfig{ + BindPort: port, + Auth: v1.AuthServerConfig{ + Method: v1.AuthMethodToken, + Token: token, + }, + } + resp.Complete() + return resp +} + +func NewBaseFRPServerUserAuthConfig(port int, opts []v1.HTTPPluginOptions) *v1.ServerConfig { + resp := &v1.ServerConfig{ + BindPort: port, + HTTPPlugins: opts, + } + resp.Complete() + return resp +} + +func NewBaseFRPClientConfig(serverAddr string, serverPort int, token string) *v1.ClientCommonConfig { + resp := &v1.ClientCommonConfig{ + Auth: v1.AuthClientConfig{ + Method: v1.AuthMethodToken, + Token: token, + }, + ServerAddr: serverAddr, + ServerPort: serverPort, + } + resp.Complete() + return resp +} + +func NewBaseFRPClientUserAuthConfig(serverAddr string, serverPort int, user, token string) *v1.ClientCommonConfig { + resp := &v1.ClientCommonConfig{ + User: user, + Metadatas: map[string]string{ + string(v1.AuthMethodToken): token, + }, + ServerAddr: serverAddr, + ServerPort: serverPort, + } + resp.Complete() + return resp +} + +func TransformProxyConfigurerToMap(origin v1.ProxyConfigurer) (key string, r v1.ProxyConfigurer) { + key = origin.GetBaseConfig().Name + r = origin + return +} + +func TransformVisitorConfigurerToMap(origin v1.VisitorConfigurer) (key string, r v1.VisitorConfigurer) { + key = origin.GetBaseConfig().Name + r = origin + return +} diff --git a/utils/hash.go b/utils/hash.go new file mode 100644 index 0000000..02eb488 --- /dev/null +++ b/utils/hash.go @@ -0,0 +1,32 @@ +package utils + +import ( + "crypto/md5" + "crypto/sha1" + "encoding/hex" + "fmt" + + "golang.org/x/crypto/bcrypt" +) + +func MD5(input string) string { + data := []byte(input) + hash := md5.Sum(data) + hashString := hex.EncodeToString(hash[:]) + return hashString +} + +func SHA1(input string) string { + hash := sha1.Sum([]byte(input)) + return fmt.Sprintf("%x", hash) +} + +func HashPassword(password string) (string, error) { + bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14) + return string(bytes), err +} + +func CheckPasswordHash(password, hash string) bool { + err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) + return err == nil +} diff --git a/utils/jwt.go b/utils/jwt.go new file mode 100644 index 0000000..c0d0ed4 --- /dev/null +++ b/utils/jwt.go @@ -0,0 +1,65 @@ +package utils + +import ( + "errors" + + "github.com/golang-jwt/jwt/v5" +) + +// @secretKey: JWT 加解密密钥 +// @iat: 时间戳 +// @seconds: 过期时间,单位秒 +// @payload: 数据载体 +func GetJwtToken(secretKey string, iat, seconds int64, payload string) (string, error) { + claims := make(jwt.MapClaims) + claims["exp"] = iat + seconds + claims["iat"] = iat + claims["payload"] = payload + token := jwt.New(jwt.SigningMethodHS256) + token.Claims = claims + return token.SignedString([]byte(secretKey)) +} + +// @secretKey: JWT 加解密密钥 +// @iat: 时间戳 +// @seconds: 过期时间,单位秒 +// @payload: 数据载体 +func GetJwtTokenFromMap(secretKey string, iat, seconds int64, payload map[string]string) (string, error) { + claims := make(jwt.MapClaims) + claims["exp"] = iat + seconds + claims["iat"] = iat + for k, v := range payload { + claims[k] = v + } + token := jwt.New(jwt.SigningMethodHS256) + token.Claims = claims + return token.SignedString([]byte(secretKey)) +} + +// @secretKey: JWT 加解密密钥 +// @token: JWT Token 的字符串 +func ValidateJwtToken(secretKey, token string) (bool, error) { + t, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) { + return []byte(secretKey), nil + }) + if err != nil { + return false, err + } + return t.Valid, nil +} + +func ParseToken(secretKey, tokenStr string) (u jwt.MapClaims, err error) { + token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) { + return []byte(secretKey), nil + }) + + if err != nil { + return nil, errors.New("couldn't handle this token") + } + + if t, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { + return t, nil + } + + return nil, errors.New("couldn't handle this token") +} diff --git a/utils/load.go b/utils/load.go new file mode 100644 index 0000000..6c20284 --- /dev/null +++ b/utils/load.go @@ -0,0 +1,94 @@ +package utils + +import ( + "github.com/fatedier/frp/pkg/config" + v1 "github.com/fatedier/frp/pkg/config/v1" + "github.com/samber/lo" + "k8s.io/apimachinery/pkg/util/sets" +) + +func LoadContentWithTemplate(content []byte, values *config.Values) ([]byte, error) { + return config.RenderWithTemplate(content, values) +} + +func LoadConfigureFromContent(content []byte, c any, strict bool) error { + ans, err := LoadContentWithTemplate(content, config.GetValues()) + if err != nil { + return err + } + return config.LoadConfigure(ans, c, strict) +} + +func LoadClientConfigNormal(content []byte, strict bool) (*v1.ClientConfig, error) { + var ( + cliCfg *v1.ClientCommonConfig + ) + + allCfg := v1.ClientConfig{} + if err := LoadConfigureFromContent(content, &allCfg, strict); err != nil { + return nil, err + } + cliCfg = &allCfg.ClientCommonConfig + cliCfg.Complete() + allCfg.ClientCommonConfig = *cliCfg + return &allCfg, nil +} + +func LoadClientConfig(content []byte, strict bool) ( + *v1.ClientCommonConfig, + []v1.ProxyConfigurer, + []v1.VisitorConfigurer, + error, +) { + var ( + cliCfg *v1.ClientCommonConfig + proxyCfgs = make([]v1.ProxyConfigurer, 0) + visitorCfgs = make([]v1.VisitorConfigurer, 0) + ) + + allCfg := v1.ClientConfig{} + if err := LoadConfigureFromContent(content, &allCfg, strict); err != nil { + return nil, nil, nil, err + } + cliCfg = &allCfg.ClientCommonConfig + for _, c := range allCfg.Proxies { + proxyCfgs = append(proxyCfgs, c.ProxyConfigurer) + } + for _, c := range allCfg.Visitors { + visitorCfgs = append(visitorCfgs, c.VisitorConfigurer) + } + + // Filter by start + if len(cliCfg.Start) > 0 { + startSet := sets.New(cliCfg.Start...) + proxyCfgs = lo.Filter(proxyCfgs, func(c v1.ProxyConfigurer, _ int) bool { + return startSet.Has(c.GetBaseConfig().Name) + }) + visitorCfgs = lo.Filter(visitorCfgs, func(c v1.VisitorConfigurer, _ int) bool { + return startSet.Has(c.GetBaseConfig().Name) + }) + } + + cliCfg.Complete() + + for _, c := range proxyCfgs { + c.Complete(cliCfg.User) + } + for _, c := range visitorCfgs { + c.Complete(cliCfg) + } + return cliCfg, proxyCfgs, visitorCfgs, nil +} + +func LoadServerConfig(content []byte, strict bool) (*v1.ServerConfig, error) { + var ( + svrCfg = &v1.ServerConfig{} + ) + if err := LoadConfigureFromContent(content, svrCfg, strict); err != nil { + return nil, err + } + + svrCfg.Complete() + + return svrCfg, nil +} diff --git a/watcher/client.go b/watcher/client.go new file mode 100644 index 0000000..6724290 --- /dev/null +++ b/watcher/client.go @@ -0,0 +1,44 @@ +package watcher + +import ( + "github.com/go-co-op/gocron/v2" + "github.com/sirupsen/logrus" +) + +type Client interface { + Run() + Stop() +} + +type client struct { + s gocron.Scheduler +} + +func NewClient(f func(clientID, clientSecret string) error, clientID, clientSecret string) Client { + s, err := gocron.NewScheduler() + if err != nil { + logrus.WithError(err).Fatalf("create scheduler error") + } + + _, err = s.NewJob( + gocron.CronJob("*/30 * * * * *", true), + gocron.NewTask(f, clientID, clientSecret), + ) + if err != nil { + logrus.WithError(err).Fatalf("create job error") + } + return &client{ + s: s, + } +} + +func (c *client) Run() { + logrus.Infof("start to run scheduler, interval: 30s") + c.s.Start() +} + +func (c *client) Stop() { + if err := c.s.Shutdown(); err != nil { + logrus.WithError(err).Errorf("shutdown scheduler error") + } +} diff --git a/www/.eslintrc.json b/www/.eslintrc.json new file mode 100644 index 0000000..bffb357 --- /dev/null +++ b/www/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next/core-web-vitals" +} diff --git a/www/.gitignore b/www/.gitignore new file mode 100644 index 0000000..fd3dbb5 --- /dev/null +++ b/www/.gitignore @@ -0,0 +1,36 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/www/README.md b/www/README.md new file mode 100644 index 0000000..a75ac52 --- /dev/null +++ b/www/README.md @@ -0,0 +1,40 @@ +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. + +[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. + +The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. + +This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/www/api/auth.ts b/www/api/auth.ts new file mode 100644 index 0000000..f1d638f --- /dev/null +++ b/www/api/auth.ts @@ -0,0 +1,17 @@ +import http from '@/api/http' +import { API_PATH } from '@/lib/consts' +import { + LoginRequest, LoginResponse, + RegisterRequest, RegisterResponse +} from '@/lib/pb/api_auth' +import { BaseResponse } from '@/types/api' + +export const login = async (req: LoginRequest) => { + const res = await http.post(API_PATH + '/auth/login', LoginRequest.toJson(req)) + return LoginResponse.fromJson((res.data as BaseResponse).body) +} + +export const register = async (req: RegisterRequest) => { + const res = await http.post(API_PATH + '/auth/register', RegisterRequest.toJson(req)) + return RegisterResponse.fromJson((res.data as BaseResponse).body) +} \ No newline at end of file diff --git a/www/api/client.ts b/www/api/client.ts new file mode 100644 index 0000000..cd9e14a --- /dev/null +++ b/www/api/client.ts @@ -0,0 +1,30 @@ +import http from '@/api/http' +import { API_PATH } from "@/lib/consts"; +import { + DeleteClientRequest, DeleteClientResponse, + GetClientRequest, GetClientResponse, + InitClientRequest, InitClientResponse, + ListClientsRequest, ListClientsResponse +} from '@/lib/pb/api_client'; +import { BaseResponse } from "@/types/api"; + +export const getClient = async (req: GetClientRequest) => { + const res = await http.post(API_PATH + '/client/get', GetClientRequest.toJson(req)) + return GetClientResponse.fromJson((res.data as BaseResponse).body) +} + +export const listClient = async (req: ListClientsRequest) => { + const res = await http.post(API_PATH + '/client/list', ListClientsRequest.toJson(req)) + return ListClientsResponse.fromJson((res.data as BaseResponse).body) +} + +export const deleteClient = async (req: DeleteClientRequest) => { + const res = await http.post(API_PATH + '/client/delete', DeleteClientRequest.toJson(req)) + return DeleteClientResponse.fromJson((res.data as BaseResponse).body) +} + +export const initClient = async (req: InitClientRequest) => { + console.log("attempting init client:", InitClientRequest.toJsonString(req)) + const res = await http.post(API_PATH + '/client/init', InitClientRequest.toJson(req)) + return InitClientResponse.fromJson((res.data as BaseResponse).body) +} \ No newline at end of file diff --git a/www/api/frp.ts b/www/api/frp.ts new file mode 100644 index 0000000..087a2ec --- /dev/null +++ b/www/api/frp.ts @@ -0,0 +1,35 @@ +import http from '@/api/http' +import { API_PATH } from "@/lib/consts"; +import { + RemoveFRPCRequest, + RemoveFRPCResponse, + UpdateFRPCRequest, + UpdateFRPCResponse +} from '@/lib/pb/api_client'; +import { + RemoveFRPSRequest, + RemoveFRPSResponse, + UpdateFRPSRequest, + UpdateFRPSResponse +} from '@/lib/pb/api_server'; +import { BaseResponse } from "@/types/api"; + +export const updateFRPS = async (req: UpdateFRPSRequest) => { + const res = await http.post(API_PATH + '/frps/update', UpdateFRPSRequest.toJson(req)) + return UpdateFRPSResponse.fromJson((res.data as BaseResponse).body) +} + +export const removeFRPS = async (req: RemoveFRPSRequest) => { + const res = await http.post(API_PATH + '/frps/remove', RemoveFRPSRequest.toJson(req)) + return RemoveFRPSResponse.fromJson((res.data as BaseResponse).body) +} + +export const updateFRPC = async (req: UpdateFRPCRequest) => { + const res = await http.post(API_PATH + '/frpc/update', UpdateFRPCRequest.toJson(req)) + return UpdateFRPCResponse.fromJson((res.data as BaseResponse).body) +} + +export const removeFRPC = async (req: RemoveFRPCRequest) => { + const res = await http.post(API_PATH + '/frpc/remove', RemoveFRPCRequest.toJson(req)) + return RemoveFRPCResponse.fromJson((res.data as BaseResponse).body) +} \ No newline at end of file diff --git a/www/api/http.ts b/www/api/http.ts new file mode 100644 index 0000000..322cb1f --- /dev/null +++ b/www/api/http.ts @@ -0,0 +1,29 @@ +import { LOCAL_STORAGE_TOKEN_KEY, SET_TOKEN_HEADER, X_CLIENT_REQUEST_ID } from '@/lib/consts'; +import { $token } from '@/store/user'; +import axios from 'axios' +import { v4 as uuidv4 } from 'uuid'; + +const instance = axios.create({}) + +instance.interceptors.request.use((request) => { + let token = 'Bearer ' + localStorage.getItem(LOCAL_STORAGE_TOKEN_KEY) + if (token) { + request.headers.Authorization = token + $token.set(token) + } + request.headers[X_CLIENT_REQUEST_ID] = uuidv4(); + return request +}) + +instance.interceptors.response.use((response) => { + if (response.headers?.[SET_TOKEN_HEADER]) { + localStorage.setItem(LOCAL_STORAGE_TOKEN_KEY, response.headers[SET_TOKEN_HEADER]) + $token.set(response.headers[SET_TOKEN_HEADER]) + } + if (response.data.code != 200) { + throw response.data.msg + } + return response +}) + +export default instance diff --git a/www/api/server.ts b/www/api/server.ts new file mode 100644 index 0000000..8901790 --- /dev/null +++ b/www/api/server.ts @@ -0,0 +1,31 @@ +import http from '@/api/http' +import { API_PATH } from "@/lib/consts"; +import { + DeleteServerRequest, + DeleteServerResponse, + GetServerRequest, GetServerResponse, + InitServerRequest, + InitServerResponse, + ListServersRequest, ListServersResponse +} from "@/lib/pb/api_server"; +import { BaseResponse } from "@/types/api"; + +export const getServer = async (req: GetServerRequest) => { + const res = await http.post(API_PATH + '/server/get', GetServerRequest.toJson(req)) + return GetServerResponse.fromJson((res.data as BaseResponse).body) +} + +export const listServer = async (req: ListServersRequest) => { + const res = await http.post(API_PATH + '/server/list', ListServersRequest.toJson(req)) + return ListServersResponse.fromJson((res.data as BaseResponse).body) +} + +export const deleteServer = async (req: DeleteServerRequest) => { + const res = await http.post(API_PATH + '/server/delete', DeleteServerRequest.toJson(req)) + return DeleteServerResponse.fromJson((res.data as BaseResponse).body) +} + +export const initServer = async (req: InitServerRequest) => { + const res = await http.post(API_PATH + '/server/init', InitServerRequest.toJson(req)) + return InitServerResponse.fromJson((res.data as BaseResponse).body) +} \ No newline at end of file diff --git a/www/api/user.ts b/www/api/user.ts new file mode 100644 index 0000000..911c71d --- /dev/null +++ b/www/api/user.ts @@ -0,0 +1,19 @@ +import http from '@/api/http' +import { API_PATH } from '@/lib/consts' +import { + GetUserInfoRequest, GetUserInfoResponse, + UpdateUserInfoRequest, UpdateUserInfoResponse +} from '@/lib/pb/api_user' +import { $userInfo } from '@/store/user' +import { BaseResponse } from '@/types/api' + +export const getUserInfo = async (req: GetUserInfoRequest) => { + const res = await http.post(API_PATH + '/user/get', GetUserInfoRequest.toJson(req)) + $userInfo.set(GetUserInfoResponse.fromJson((res.data as BaseResponse).body).userInfo) + return GetUserInfoResponse.fromJson((res.data as BaseResponse).body) +} + +export const updateUserInfo = async (req: UpdateUserInfoRequest) => { + const res = await http.post(API_PATH + '/user/update', UpdateUserInfoRequest.toJson(req)) + return UpdateUserInfoResponse.fromJson((res.data as BaseResponse).body) +} diff --git a/www/components.json b/www/components.json new file mode 100644 index 0000000..7c958bd --- /dev/null +++ b/www/components.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "tailwind.config.js", + "css": "styles/globals.css", + "baseColor": "slate", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils" + } +} \ No newline at end of file diff --git a/www/components/apitest.tsx b/www/components/apitest.tsx new file mode 100644 index 0000000..405f016 --- /dev/null +++ b/www/components/apitest.tsx @@ -0,0 +1,119 @@ +import { login, register } from "@/api/auth" +import { Button } from "./ui/button" +import { deleteClient, getClient, initClient, listClient } from "@/api/client" +import { deleteServer, getServer, initServer, listServer } from "@/api/server" +import { updateFRPC, updateFRPS } from "@/api/frp" +import { ClientConfig } from "@/types/client" +import { ServerConfig } from "@/types/server" +import { getUserInfo, updateUserInfo } from "@/api/user" +import { Separator } from "./ui/separator" +import { useState } from "react" +import { Input } from "./ui/input" +import { Label } from "@radix-ui/react-label" + +export const APITest = () => { + const [serverID, setServerID] = useState("admin.server") + const [clientID, setClientID] = useState("admin.client") + const [username, setUsername] = useState("admin") + const [password, setPassword] = useState("admin") + + return ( +
+
+
+ + setUsername(e.target.value)} /> +
+
+ + setPassword(e.target.value)} /> +
+
+ + setClientID(e.target.value)} /> +
+
+ + setServerID(e.target.value)} /> +
+
+
+ + + + +
+ +
+ + + + +
+ +
+ + +
+ +
+ + + + +
+ +
+ + +
+
+ ) +} \ No newline at end of file diff --git a/www/components/client_item.tsx b/www/components/client_item.tsx new file mode 100644 index 0000000..2278b0f --- /dev/null +++ b/www/components/client_item.tsx @@ -0,0 +1,12 @@ +import { Client } from "@/lib/pb/common" + +export interface ClientItemProps { + Client: Client +} +export const ClientItem: React.FC = ({ Client }) => { + return (<> +

+ {Client.id} +

+ ) +} \ No newline at end of file diff --git a/www/components/client_list.tsx b/www/components/client_list.tsx new file mode 100644 index 0000000..bbcb762 --- /dev/null +++ b/www/components/client_list.tsx @@ -0,0 +1,13 @@ +import { Client } from "@/lib/pb/common"; +import { ClientItem } from "./client_item"; + +export interface ClientListProps { + Clients: Client[] +} +export const ClientList: React.FC = ({ Clients }) => { + return ( + <> + + + ) +}; \ No newline at end of file diff --git a/www/components/frpc_card.tsx b/www/components/frpc_card.tsx new file mode 100644 index 0000000..b0e2c80 --- /dev/null +++ b/www/components/frpc_card.tsx @@ -0,0 +1,116 @@ +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 { useQuery } from '@tanstack/react-query' +import { listServer } from "@/api/server" +import { listClient } from "@/api/client" +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card" +import { Switch } from "./ui/switch" +import { FRPCEditor } from "./frpc_editor" +import { FRPCForm } from "./frpc_form" + +export interface FRPCFormCardProps { + clientID?: string + serverID?: string +} +export const FRPCFormCard: React.FC = ({ clientID: defaultClientID, serverID: defaultServerID }: FRPCFormCardProps) => { + const [advanceMode, setAdvanceMode] = useState(false) + const [clientID, setClientID] = useState() + const [serverID, setServerID] = useState() + const handleServerChange = (value: string) => { + setServerID(value) + } + + const handleClientChange = (value: string) => { + setClientID(value) + } + + useEffect(() => { + setClientID(defaultClientID) + setServerID(defaultServerID) + }, [defaultClientID, defaultServerID]) + + const { data: serverList, refetch: refetchServers } = useQuery({ + queryKey: ["listServer"], queryFn: () => { + return listServer({ page: 1, pageSize: 100 }) + } + }); + + const { data: clientList, refetch: refetchClients } = useQuery({ + queryKey: ["listClient"], queryFn: () => { + return listClient({ page: 1, pageSize: 100 }) + } + }) + + return ( + + + 创建隧道 + 选择客户端和服务端以创建隧道 + + +
+
+

+ 高级模式 +

+

+ 编辑客户端原始配置文件 +

+
+ +
+
+ + + + + +
+ {clientID && serverID && !advanceMode && } + {clientID && serverID && advanceMode && } +
+
+ ) +} \ No newline at end of file diff --git a/www/components/frpc_editor.tsx b/www/components/frpc_editor.tsx new file mode 100644 index 0000000..cb2a9cc --- /dev/null +++ b/www/components/frpc_editor.tsx @@ -0,0 +1,21 @@ +import { Label } from "@radix-ui/react-label" +import { Textarea } from "./ui/textarea" +import { FRPCFormProps } from "./frpc_form" +import { getClient } from "@/api/client"; +import { useQuery } from "@tanstack/react-query"; + +export const FRPCEditor: React.FC = ({ clientID }) => { + const { data: client, refetch: refetchClient } = useQuery({ + queryKey: ["getClient", clientID], queryFn: () => { + return getClient({ clientId: clientID }) + } + }); + + return (
+ +

+ 只需要配置proxies和visitors字段,认证信息和服务器连接信息会由系统补全 +

+