From 9dacd85a89ef0a5afa040979ee04f48af8bd7e05 Mon Sep 17 00:00:00 2001 From: shanshanzhong Date: Thu, 26 Feb 2026 04:12:43 -0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/deploy.yml | 226 +++++++++ .gitignore | 36 ++ Makefile | 83 ++++ apps/admin/admin.api | 22 + apps/admin/desc/announcement.api | 45 ++ apps/admin/desc/common.api | 14 + apps/admin/desc/console.api | 28 ++ apps/admin/desc/order.api | 45 ++ apps/admin/desc/server.api | 64 +++ apps/admin/desc/subscribe.api | 61 +++ apps/admin/desc/system.api | 54 +++ apps/admin/desc/ticket.api | 59 +++ apps/admin/desc/types.api | 11 + apps/admin/desc/user.api | 51 +++ apps/admin/etc/admin-dev.yaml | 32 ++ apps/admin/etc/admin-prod.yaml | 36 ++ apps/admin/etc/admin-test.yaml | 34 ++ apps/admin/etc/ppaneladmin.yaml | 3 + apps/admin/internal/config/config.go | 14 + .../announcement/createAnnouncementHandler.go | 31 ++ .../announcement/deleteAnnouncementHandler.go | 31 ++ .../announcement/updateAnnouncementHandler.go | 31 ++ .../internal/handler/common/healthHandler.go | 24 + .../handler/console/getConsoleStatsHandler.go | 24 + .../handler/order/getOrderListHandler.go | 31 ++ .../handler/order/updateOrderStatusHandler.go | 31 ++ apps/admin/internal/handler/routes.go | 215 +++++++++ .../handler/server/createServerHandler.go | 31 ++ .../handler/server/deleteServerHandler.go | 31 ++ .../handler/server/getServerListHandler.go | 31 ++ .../handler/server/updateServerHandler.go | 31 ++ .../subscribe/createSubscribeHandler.go | 31 ++ .../subscribe/deleteSubscribeHandler.go | 31 ++ .../subscribe/getSubscribeListHandler.go | 31 ++ .../subscribe/updateSubscribeHandler.go | 31 ++ .../system/getRegisterConfigHandler.go | 24 + .../handler/system/getSiteConfigHandler.go | 24 + .../system/updateRegisterConfigHandler.go | 31 ++ .../handler/system/updateSiteConfigHandler.go | 31 ++ .../ticket/createTicketFollowHandler.go | 31 ++ .../handler/ticket/getTicketDetailHandler.go | 31 ++ .../handler/ticket/getTicketListHandler.go | 31 ++ .../ticket/updateTicketStatusHandler.go | 31 ++ .../handler/user/deleteUserHandler.go | 31 ++ .../handler/user/getUserDetailHandler.go | 31 ++ .../handler/user/getUserListHandler.go | 31 ++ .../announcement/createAnnouncementLogic.go | 33 ++ .../announcement/deleteAnnouncementLogic.go | 33 ++ .../announcement/updateAnnouncementLogic.go | 33 ++ .../internal/logic/common/healthLogic.go | 33 ++ .../logic/console/getConsoleStatsLogic.go | 33 ++ .../internal/logic/order/getOrderListLogic.go | 33 ++ .../logic/order/updateOrderStatusLogic.go | 33 ++ .../logic/server/createServerLogic.go | 33 ++ .../logic/server/deleteServerLogic.go | 33 ++ .../logic/server/getServerListLogic.go | 33 ++ .../logic/server/updateServerLogic.go | 33 ++ .../logic/subscribe/createSubscribeLogic.go | 33 ++ .../logic/subscribe/deleteSubscribeLogic.go | 33 ++ .../logic/subscribe/getSubscribeListLogic.go | 33 ++ .../logic/subscribe/updateSubscribeLogic.go | 33 ++ .../logic/system/getRegisterConfigLogic.go | 33 ++ .../logic/system/getSiteConfigLogic.go | 33 ++ .../logic/system/updateRegisterConfigLogic.go | 33 ++ .../logic/system/updateSiteConfigLogic.go | 33 ++ .../logic/ticket/createTicketFollowLogic.go | 33 ++ .../logic/ticket/getTicketDetailLogic.go | 33 ++ .../logic/ticket/getTicketListLogic.go | 33 ++ .../logic/ticket/updateTicketStatusLogic.go | 33 ++ .../internal/logic/user/deleteUserLogic.go | 33 ++ .../internal/logic/user/getUserDetailLogic.go | 33 ++ .../internal/logic/user/getUserListLogic.go | 33 ++ apps/admin/internal/svc/serviceContext.go | 18 + apps/admin/internal/types/types.go | 228 +++++++++ apps/admin/ppaneladmin.go | 34 ++ apps/api/api.api | 18 + apps/api/desc/auth.api | 45 ++ apps/api/desc/common.api | 38 ++ apps/api/desc/order.api | 47 ++ apps/api/desc/ticket.api | 44 ++ apps/api/desc/types.api | 65 +++ apps/api/desc/user.api | 47 ++ apps/api/etc/api-dev.yaml | 38 ++ apps/api/etc/api-prod.yaml | 40 ++ apps/api/etc/api-test.yaml | 37 ++ apps/api/etc/ppanel-api.yaml | 3 + apps/api/internal/config/config.go | 18 + .../handler/auth/resetPasswordHandler.go | 31 ++ .../internal/handler/auth/userLoginHandler.go | 31 ++ .../handler/auth/userRegisterHandler.go | 31 ++ .../common/getAnnouncementListHandler.go | 24 + .../getAvailablePaymentMethodsHandler.go | 24 + .../common/getDocumentDetailHandler.go | 31 ++ .../handler/common/getDocumentListHandler.go | 24 + .../handler/common/getGlobalConfigHandler.go | 24 + .../common/getSubscribeGroupListHandler.go | 24 + .../handler/common/getSubscribeListHandler.go | 24 + .../internal/handler/common/healthHandler.go | 24 + .../handler/common/sendEmailCodeHandler.go | 31 ++ .../handler/order/closeOrderHandler.go | 31 ++ .../handler/order/createOrderHandler.go | 31 ++ .../handler/order/getOrderDetailHandler.go | 31 ++ apps/api/internal/handler/routes.go | 157 +++++++ .../ticket/createTicketFollowHandler.go | 31 ++ .../handler/ticket/createTicketHandler.go | 31 ++ .../handler/ticket/getTicketDetailHandler.go | 31 ++ .../handler/user/getUserInfoHandler.go | 24 + .../handler/user/getUserSubscribeHandler.go | 24 + .../handler/user/updateUserPasswordHandler.go | 31 ++ .../internal/logic/auth/resetPasswordLogic.go | 33 ++ .../api/internal/logic/auth/userLoginLogic.go | 33 ++ .../internal/logic/auth/userRegisterLogic.go | 33 ++ .../logic/common/getAnnouncementListLogic.go | 33 ++ .../common/getAvailablePaymentMethodsLogic.go | 33 ++ .../logic/common/getDocumentDetailLogic.go | 33 ++ .../logic/common/getDocumentListLogic.go | 33 ++ .../logic/common/getGlobalConfigLogic.go | 33 ++ .../common/getSubscribeGroupListLogic.go | 33 ++ .../logic/common/getSubscribeListLogic.go | 33 ++ apps/api/internal/logic/common/healthLogic.go | 44 ++ .../logic/common/sendEmailCodeLogic.go | 33 ++ .../internal/logic/order/closeOrderLogic.go | 33 ++ .../internal/logic/order/createOrderLogic.go | 33 ++ .../logic/order/getOrderDetailLogic.go | 33 ++ .../logic/ticket/createTicketFollowLogic.go | 33 ++ .../logic/ticket/createTicketLogic.go | 33 ++ .../logic/ticket/getTicketDetailLogic.go | 33 ++ .../internal/logic/user/getUserInfoLogic.go | 33 ++ .../logic/user/getUserSubscribeLogic.go | 33 ++ .../logic/user/updateUserPasswordLogic.go | 33 ++ apps/api/internal/svc/serviceContext.go | 22 + apps/api/internal/types/types.go | 154 +++++++ apps/api/ppanel.go | 34 ++ apps/node/desc/common.api | 14 + apps/node/desc/node.api | 70 +++ apps/node/desc/types.api | 11 + apps/node/etc/node-dev.yaml | 30 ++ apps/node/etc/node-prod.yaml | 34 ++ apps/node/etc/node-test.yaml | 32 ++ apps/node/etc/ppanelnode.yaml | 3 + apps/node/internal/config/config.go | 10 + .../internal/handler/common/healthHandler.go | 24 + .../handler/node/getServerConfigHandler.go | 24 + .../handler/node/getServerUserListHandler.go | 24 + .../handler/node/pushOnlineUsersHandler.go | 31 ++ .../handler/node/pushStatusHandler.go | 31 ++ .../handler/node/pushUserTrafficHandler.go | 31 ++ apps/node/internal/handler/routes.go | 61 +++ .../node/internal/logic/common/healthLogic.go | 33 ++ .../logic/node/getServerConfigLogic.go | 33 ++ .../logic/node/getServerUserListLogic.go | 33 ++ .../logic/node/pushOnlineUsersLogic.go | 33 ++ .../internal/logic/node/pushStatusLogic.go | 33 ++ .../logic/node/pushUserTrafficLogic.go | 33 ++ .../internal/middleware/nodeauthMiddleware.go | 22 + apps/node/internal/svc/serviceContext.go | 22 + apps/node/internal/types/types.go | 49 ++ apps/node/node.api | 15 + apps/node/ppanelnode.go | 34 ++ apps/queue/etc/queue-dev.yaml | 23 + apps/queue/etc/queue-prod.yaml | 28 ++ apps/queue/etc/queue-test.yaml | 25 + apps/queue/internal/config/config.go | 30 ++ apps/queue/internal/handler/routes.go | 15 + apps/queue/internal/logic/.gitkeep | 0 apps/queue/internal/svc/servicecontext.go | 15 + apps/queue/internal/types/types.go | 9 + apps/queue/queue.go | 49 ++ apps/rpc/core/core.go | 39 ++ apps/rpc/core/core.proto | 56 +++ apps/rpc/core/core/core.pb.go | 431 ++++++++++++++++++ apps/rpc/core/core/core_grpc.pb.go | 211 +++++++++ apps/rpc/core/coreClient/core.go | 60 +++ apps/rpc/core/etc/core-dev.yaml | 30 ++ apps/rpc/core/etc/core-prod.yaml | 30 ++ apps/rpc/core/etc/core-test.yaml | 30 ++ apps/rpc/core/internal/config/config.go | 15 + .../core/internal/logic/getNodeInfoLogic.go | 31 ++ .../core/internal/logic/getUserInfoLogic.go | 31 ++ apps/rpc/core/internal/logic/pingLogic.go | 35 ++ apps/rpc/core/internal/server/coreServer.go | 42 ++ apps/rpc/core/internal/svc/serviceContext.go | 13 + apps/scheduler/etc/scheduler-dev.yaml | 23 + apps/scheduler/etc/scheduler-prod.yaml | 28 ++ apps/scheduler/etc/scheduler-test.yaml | 25 + apps/scheduler/internal/config/config.go | 30 ++ apps/scheduler/internal/handler/.gitkeep | 0 apps/scheduler/internal/logic/.gitkeep | 0 apps/scheduler/internal/svc/servicecontext.go | 15 + apps/scheduler/internal/types/types.go | 8 + apps/scheduler/scheduler.go | 51 +++ deploy/Dockerfile.admin | 19 + deploy/Dockerfile.api | 19 + deploy/Dockerfile.node | 19 + deploy/Dockerfile.queue | 18 + deploy/Dockerfile.scheduler | 18 + deploy/docker-compose-env.yml | 55 +++ deploy/docker-compose.cloud.yml | 67 +++ deploy/docker-compose.yml | 119 +++++ deploy/prometheus.yml | 22 + go.mod | 94 ++++ go.sum | 287 ++++++++++++ pkg/constant/context_key.go | 8 + pkg/jwtx/jwt.go | 40 ++ pkg/result/errorhandler.go | 7 + pkg/result/response.go | 25 + pkg/xerr/errcode.go | 22 + pkg/xerr/errmsg.go | 29 ++ sql/001_init.down.sql | 7 + sql/001_init.up.sql | 40 ++ 210 files changed, 8261 insertions(+) create mode 100644 .gitea/workflows/deploy.yml create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 apps/admin/admin.api create mode 100644 apps/admin/desc/announcement.api create mode 100644 apps/admin/desc/common.api create mode 100644 apps/admin/desc/console.api create mode 100644 apps/admin/desc/order.api create mode 100644 apps/admin/desc/server.api create mode 100644 apps/admin/desc/subscribe.api create mode 100644 apps/admin/desc/system.api create mode 100644 apps/admin/desc/ticket.api create mode 100644 apps/admin/desc/types.api create mode 100644 apps/admin/desc/user.api create mode 100644 apps/admin/etc/admin-dev.yaml create mode 100644 apps/admin/etc/admin-prod.yaml create mode 100644 apps/admin/etc/admin-test.yaml create mode 100644 apps/admin/etc/ppaneladmin.yaml create mode 100644 apps/admin/internal/config/config.go create mode 100644 apps/admin/internal/handler/announcement/createAnnouncementHandler.go create mode 100644 apps/admin/internal/handler/announcement/deleteAnnouncementHandler.go create mode 100644 apps/admin/internal/handler/announcement/updateAnnouncementHandler.go create mode 100644 apps/admin/internal/handler/common/healthHandler.go create mode 100644 apps/admin/internal/handler/console/getConsoleStatsHandler.go create mode 100644 apps/admin/internal/handler/order/getOrderListHandler.go create mode 100644 apps/admin/internal/handler/order/updateOrderStatusHandler.go create mode 100644 apps/admin/internal/handler/routes.go create mode 100644 apps/admin/internal/handler/server/createServerHandler.go create mode 100644 apps/admin/internal/handler/server/deleteServerHandler.go create mode 100644 apps/admin/internal/handler/server/getServerListHandler.go create mode 100644 apps/admin/internal/handler/server/updateServerHandler.go create mode 100644 apps/admin/internal/handler/subscribe/createSubscribeHandler.go create mode 100644 apps/admin/internal/handler/subscribe/deleteSubscribeHandler.go create mode 100644 apps/admin/internal/handler/subscribe/getSubscribeListHandler.go create mode 100644 apps/admin/internal/handler/subscribe/updateSubscribeHandler.go create mode 100644 apps/admin/internal/handler/system/getRegisterConfigHandler.go create mode 100644 apps/admin/internal/handler/system/getSiteConfigHandler.go create mode 100644 apps/admin/internal/handler/system/updateRegisterConfigHandler.go create mode 100644 apps/admin/internal/handler/system/updateSiteConfigHandler.go create mode 100644 apps/admin/internal/handler/ticket/createTicketFollowHandler.go create mode 100644 apps/admin/internal/handler/ticket/getTicketDetailHandler.go create mode 100644 apps/admin/internal/handler/ticket/getTicketListHandler.go create mode 100644 apps/admin/internal/handler/ticket/updateTicketStatusHandler.go create mode 100644 apps/admin/internal/handler/user/deleteUserHandler.go create mode 100644 apps/admin/internal/handler/user/getUserDetailHandler.go create mode 100644 apps/admin/internal/handler/user/getUserListHandler.go create mode 100644 apps/admin/internal/logic/announcement/createAnnouncementLogic.go create mode 100644 apps/admin/internal/logic/announcement/deleteAnnouncementLogic.go create mode 100644 apps/admin/internal/logic/announcement/updateAnnouncementLogic.go create mode 100644 apps/admin/internal/logic/common/healthLogic.go create mode 100644 apps/admin/internal/logic/console/getConsoleStatsLogic.go create mode 100644 apps/admin/internal/logic/order/getOrderListLogic.go create mode 100644 apps/admin/internal/logic/order/updateOrderStatusLogic.go create mode 100644 apps/admin/internal/logic/server/createServerLogic.go create mode 100644 apps/admin/internal/logic/server/deleteServerLogic.go create mode 100644 apps/admin/internal/logic/server/getServerListLogic.go create mode 100644 apps/admin/internal/logic/server/updateServerLogic.go create mode 100644 apps/admin/internal/logic/subscribe/createSubscribeLogic.go create mode 100644 apps/admin/internal/logic/subscribe/deleteSubscribeLogic.go create mode 100644 apps/admin/internal/logic/subscribe/getSubscribeListLogic.go create mode 100644 apps/admin/internal/logic/subscribe/updateSubscribeLogic.go create mode 100644 apps/admin/internal/logic/system/getRegisterConfigLogic.go create mode 100644 apps/admin/internal/logic/system/getSiteConfigLogic.go create mode 100644 apps/admin/internal/logic/system/updateRegisterConfigLogic.go create mode 100644 apps/admin/internal/logic/system/updateSiteConfigLogic.go create mode 100644 apps/admin/internal/logic/ticket/createTicketFollowLogic.go create mode 100644 apps/admin/internal/logic/ticket/getTicketDetailLogic.go create mode 100644 apps/admin/internal/logic/ticket/getTicketListLogic.go create mode 100644 apps/admin/internal/logic/ticket/updateTicketStatusLogic.go create mode 100644 apps/admin/internal/logic/user/deleteUserLogic.go create mode 100644 apps/admin/internal/logic/user/getUserDetailLogic.go create mode 100644 apps/admin/internal/logic/user/getUserListLogic.go create mode 100644 apps/admin/internal/svc/serviceContext.go create mode 100644 apps/admin/internal/types/types.go create mode 100644 apps/admin/ppaneladmin.go create mode 100644 apps/api/api.api create mode 100644 apps/api/desc/auth.api create mode 100644 apps/api/desc/common.api create mode 100644 apps/api/desc/order.api create mode 100644 apps/api/desc/ticket.api create mode 100644 apps/api/desc/types.api create mode 100644 apps/api/desc/user.api create mode 100644 apps/api/etc/api-dev.yaml create mode 100644 apps/api/etc/api-prod.yaml create mode 100644 apps/api/etc/api-test.yaml create mode 100644 apps/api/etc/ppanel-api.yaml create mode 100644 apps/api/internal/config/config.go create mode 100644 apps/api/internal/handler/auth/resetPasswordHandler.go create mode 100644 apps/api/internal/handler/auth/userLoginHandler.go create mode 100644 apps/api/internal/handler/auth/userRegisterHandler.go create mode 100644 apps/api/internal/handler/common/getAnnouncementListHandler.go create mode 100644 apps/api/internal/handler/common/getAvailablePaymentMethodsHandler.go create mode 100644 apps/api/internal/handler/common/getDocumentDetailHandler.go create mode 100644 apps/api/internal/handler/common/getDocumentListHandler.go create mode 100644 apps/api/internal/handler/common/getGlobalConfigHandler.go create mode 100644 apps/api/internal/handler/common/getSubscribeGroupListHandler.go create mode 100644 apps/api/internal/handler/common/getSubscribeListHandler.go create mode 100644 apps/api/internal/handler/common/healthHandler.go create mode 100644 apps/api/internal/handler/common/sendEmailCodeHandler.go create mode 100644 apps/api/internal/handler/order/closeOrderHandler.go create mode 100644 apps/api/internal/handler/order/createOrderHandler.go create mode 100644 apps/api/internal/handler/order/getOrderDetailHandler.go create mode 100644 apps/api/internal/handler/routes.go create mode 100644 apps/api/internal/handler/ticket/createTicketFollowHandler.go create mode 100644 apps/api/internal/handler/ticket/createTicketHandler.go create mode 100644 apps/api/internal/handler/ticket/getTicketDetailHandler.go create mode 100644 apps/api/internal/handler/user/getUserInfoHandler.go create mode 100644 apps/api/internal/handler/user/getUserSubscribeHandler.go create mode 100644 apps/api/internal/handler/user/updateUserPasswordHandler.go create mode 100644 apps/api/internal/logic/auth/resetPasswordLogic.go create mode 100644 apps/api/internal/logic/auth/userLoginLogic.go create mode 100644 apps/api/internal/logic/auth/userRegisterLogic.go create mode 100644 apps/api/internal/logic/common/getAnnouncementListLogic.go create mode 100644 apps/api/internal/logic/common/getAvailablePaymentMethodsLogic.go create mode 100644 apps/api/internal/logic/common/getDocumentDetailLogic.go create mode 100644 apps/api/internal/logic/common/getDocumentListLogic.go create mode 100644 apps/api/internal/logic/common/getGlobalConfigLogic.go create mode 100644 apps/api/internal/logic/common/getSubscribeGroupListLogic.go create mode 100644 apps/api/internal/logic/common/getSubscribeListLogic.go create mode 100644 apps/api/internal/logic/common/healthLogic.go create mode 100644 apps/api/internal/logic/common/sendEmailCodeLogic.go create mode 100644 apps/api/internal/logic/order/closeOrderLogic.go create mode 100644 apps/api/internal/logic/order/createOrderLogic.go create mode 100644 apps/api/internal/logic/order/getOrderDetailLogic.go create mode 100644 apps/api/internal/logic/ticket/createTicketFollowLogic.go create mode 100644 apps/api/internal/logic/ticket/createTicketLogic.go create mode 100644 apps/api/internal/logic/ticket/getTicketDetailLogic.go create mode 100644 apps/api/internal/logic/user/getUserInfoLogic.go create mode 100644 apps/api/internal/logic/user/getUserSubscribeLogic.go create mode 100644 apps/api/internal/logic/user/updateUserPasswordLogic.go create mode 100644 apps/api/internal/svc/serviceContext.go create mode 100644 apps/api/internal/types/types.go create mode 100644 apps/api/ppanel.go create mode 100644 apps/node/desc/common.api create mode 100644 apps/node/desc/node.api create mode 100644 apps/node/desc/types.api create mode 100644 apps/node/etc/node-dev.yaml create mode 100644 apps/node/etc/node-prod.yaml create mode 100644 apps/node/etc/node-test.yaml create mode 100644 apps/node/etc/ppanelnode.yaml create mode 100644 apps/node/internal/config/config.go create mode 100644 apps/node/internal/handler/common/healthHandler.go create mode 100644 apps/node/internal/handler/node/getServerConfigHandler.go create mode 100644 apps/node/internal/handler/node/getServerUserListHandler.go create mode 100644 apps/node/internal/handler/node/pushOnlineUsersHandler.go create mode 100644 apps/node/internal/handler/node/pushStatusHandler.go create mode 100644 apps/node/internal/handler/node/pushUserTrafficHandler.go create mode 100644 apps/node/internal/handler/routes.go create mode 100644 apps/node/internal/logic/common/healthLogic.go create mode 100644 apps/node/internal/logic/node/getServerConfigLogic.go create mode 100644 apps/node/internal/logic/node/getServerUserListLogic.go create mode 100644 apps/node/internal/logic/node/pushOnlineUsersLogic.go create mode 100644 apps/node/internal/logic/node/pushStatusLogic.go create mode 100644 apps/node/internal/logic/node/pushUserTrafficLogic.go create mode 100644 apps/node/internal/middleware/nodeauthMiddleware.go create mode 100644 apps/node/internal/svc/serviceContext.go create mode 100644 apps/node/internal/types/types.go create mode 100644 apps/node/node.api create mode 100644 apps/node/ppanelnode.go create mode 100644 apps/queue/etc/queue-dev.yaml create mode 100644 apps/queue/etc/queue-prod.yaml create mode 100644 apps/queue/etc/queue-test.yaml create mode 100644 apps/queue/internal/config/config.go create mode 100644 apps/queue/internal/handler/routes.go create mode 100644 apps/queue/internal/logic/.gitkeep create mode 100644 apps/queue/internal/svc/servicecontext.go create mode 100644 apps/queue/internal/types/types.go create mode 100644 apps/queue/queue.go create mode 100644 apps/rpc/core/core.go create mode 100644 apps/rpc/core/core.proto create mode 100644 apps/rpc/core/core/core.pb.go create mode 100644 apps/rpc/core/core/core_grpc.pb.go create mode 100644 apps/rpc/core/coreClient/core.go create mode 100644 apps/rpc/core/etc/core-dev.yaml create mode 100644 apps/rpc/core/etc/core-prod.yaml create mode 100644 apps/rpc/core/etc/core-test.yaml create mode 100755 apps/rpc/core/internal/config/config.go create mode 100644 apps/rpc/core/internal/logic/getNodeInfoLogic.go create mode 100644 apps/rpc/core/internal/logic/getUserInfoLogic.go create mode 100644 apps/rpc/core/internal/logic/pingLogic.go create mode 100644 apps/rpc/core/internal/server/coreServer.go create mode 100644 apps/rpc/core/internal/svc/serviceContext.go create mode 100644 apps/scheduler/etc/scheduler-dev.yaml create mode 100644 apps/scheduler/etc/scheduler-prod.yaml create mode 100644 apps/scheduler/etc/scheduler-test.yaml create mode 100644 apps/scheduler/internal/config/config.go create mode 100644 apps/scheduler/internal/handler/.gitkeep create mode 100644 apps/scheduler/internal/logic/.gitkeep create mode 100644 apps/scheduler/internal/svc/servicecontext.go create mode 100644 apps/scheduler/internal/types/types.go create mode 100644 apps/scheduler/scheduler.go create mode 100644 deploy/Dockerfile.admin create mode 100644 deploy/Dockerfile.api create mode 100644 deploy/Dockerfile.node create mode 100644 deploy/Dockerfile.queue create mode 100644 deploy/Dockerfile.scheduler create mode 100644 deploy/docker-compose-env.yml create mode 100644 deploy/docker-compose.cloud.yml create mode 100644 deploy/docker-compose.yml create mode 100644 deploy/prometheus.yml create mode 100644 go.mod create mode 100644 go.sum create mode 100644 pkg/constant/context_key.go create mode 100644 pkg/jwtx/jwt.go create mode 100644 pkg/result/errorhandler.go create mode 100644 pkg/result/response.go create mode 100644 pkg/xerr/errcode.go create mode 100644 pkg/xerr/errmsg.go create mode 100644 sql/001_init.down.sql create mode 100644 sql/001_init.up.sql diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..c94539b --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,226 @@ +name: Build docker and publish +run-name: zero-ppanel Docker构建和部署 + +on: + push: + branches: + - main + - dev + pull_request: + branches: + - main + - dev + +env: + REPO: ${{ vars.REPO || 'registry.kxsw.us/vpn-server' }} + SSH_HOST: ${{ github.ref_name == 'main' && vars.SSH_HOST || vars.DEV_SSH_HOST }} + SSH_PORT: ${{ vars.SSH_PORT }} + SSH_USER: ${{ vars.SSH_USER }} + SSH_PASSWORD: ${{ github.ref_name == 'main' && vars.SSH_PASSWORD || vars.DEV_SSH_PASSWORD }} + TG_BOT_TOKEN: ${{ secrets.TG_BOT_TOKEN }} + TG_CHAT_ID: ${{ secrets.TG_CHAT_ID }} + VERSION: ${{ github.sha }} + BUILDTIME: ${{ github.event.head_commit.timestamp }} + +jobs: + # ============================================================ + # Job 1: 设置环境变量,供后续 jobs 共享 + # ============================================================ + prepare: + runs-on: ario-server + outputs: + docker_tag: ${{ steps.vars.outputs.docker_tag }} + container_suffix: ${{ steps.vars.outputs.container_suffix }} + deploy_path: ${{ steps.vars.outputs.deploy_path }} + steps: + - name: ⚙️ 计算部署变量 + id: vars + run: | + case "${{ github.ref_name }}" in + main) + echo "docker_tag=latest" >> $GITHUB_OUTPUT + echo "container_suffix=" >> $GITHUB_OUTPUT + echo "deploy_path=/root/bindbox" >> $GITHUB_OUTPUT + ;; + dev) + echo "docker_tag=dev" >> $GITHUB_OUTPUT + echo "container_suffix=-dev" >> $GITHUB_OUTPUT + echo "deploy_path=/root/bindbox-dev" >> $GITHUB_OUTPUT + ;; + *) + echo "docker_tag=${{ github.ref_name }}" >> $GITHUB_OUTPUT + echo "container_suffix=-${{ github.ref_name }}" >> $GITHUB_OUTPUT + echo "deploy_path=/root/vpn_server_other" >> $GITHUB_OUTPUT + ;; + esac + + # ============================================================ + # Job 2: 并行矩阵构建 5 个服务镜像 + # ============================================================ + build: + runs-on: ario-server + needs: prepare + strategy: + fail-fast: false + matrix: + service: + - name: api + dockerfile: deploy/Dockerfile.api + image_name: ppanel-api + - name: admin + dockerfile: deploy/Dockerfile.admin + image_name: ppanel-admin + - name: node + dockerfile: deploy/Dockerfile.node + image_name: ppanel-node + - name: queue + dockerfile: deploy/Dockerfile.queue + image_name: ppanel-queue + - name: scheduler + dockerfile: deploy/Dockerfile.scheduler + image_name: ppanel-scheduler + + steps: + - name: 📥 下载代码 + uses: actions/checkout@v4 + + - name: 🔧 安装 Docker CLI + run: | + set -e + export DEBIAN_FRONTEND=noninteractive + + # 等待 apt 锁释放 + for i in $(seq 1 60); do + if ! fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; then break; fi + echo "等待 apt 锁... ($i/60)"; sleep 5 + done + + apt-get update -y -o Dpkg::Lock::Timeout=300 + apt-get install -y -o Dpkg::Lock::Timeout=300 ca-certificates curl gnupg + + # 安装 Docker 官方 CLI (API >= 1.44) + install -m 0755 -d /etc/apt/keyrings + curl -fsSL https://download.docker.com/linux/debian/gpg \ + | gpg --dearmor -o /etc/apt/keyrings/docker.gpg + echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] \ + https://download.docker.com/linux/debian \ + $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \ + > /etc/apt/sources.list.d/docker.list + apt-get update -y -o Dpkg::Lock::Timeout=300 + apt-get install -y -o Dpkg::Lock::Timeout=300 docker-ce-cli docker-buildx-plugin + + echo "Docker CLI 版本: $(docker --version)" + echo "API 版本: $(docker version --format '{{.Client.APIVersion}}')" + + - name: 📤 构建并推送 ${{ matrix.service.name }} + run: | + DOCKER_TAG="${{ needs.prepare.outputs.docker_tag }}" + IMAGE_BASE="${{ env.REPO }}/${{ matrix.service.image_name }}" + + echo "构建服务: ${{ matrix.service.name }}" + echo "镜像: ${IMAGE_BASE}" + echo "标签: ${DOCKER_TAG} | ${{ env.VERSION }}" + + docker build \ + -f ${{ matrix.service.dockerfile }} \ + --platform linux/amd64 \ + --build-arg VERSION=${{ env.VERSION }} \ + --build-arg BUILDTIME=${{ env.BUILDTIME }} \ + -t ${IMAGE_BASE}:${{ env.VERSION }} \ + -t ${IMAGE_BASE}:${DOCKER_TAG} \ + . + + docker push ${IMAGE_BASE}:${{ env.VERSION }} + docker push ${IMAGE_BASE}:${DOCKER_TAG} + + echo "✅ ${{ matrix.service.name }} 镜像推送完成" + + # ============================================================ + # Job 3: 部署到服务器 + # ============================================================ + deploy: + runs-on: ario-server + needs: [prepare, build] + # PR 不触发部署,只有直接推送才部署 + if: github.event_name == 'push' + + steps: + - name: 📥 下载代码 (获取 docker-compose.cloud.yml) + uses: actions/checkout@v4 + + - name: 📂 传输 docker-compose.cloud.yml + uses: appleboy/scp-action@v0.1.7 + with: + host: ${{ env.SSH_HOST }} + username: ${{ env.SSH_USER }} + password: ${{ env.SSH_PASSWORD }} + port: ${{ env.SSH_PORT }} + source: "deploy/docker-compose.cloud.yml" + target: "${{ needs.prepare.outputs.deploy_path }}/" + strip_components: 1 + + - name: 🚀 部署服务 + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ env.SSH_HOST }} + username: ${{ env.SSH_USER }} + password: ${{ env.SSH_PASSWORD }} + port: ${{ env.SSH_PORT }} + timeout: 300s + command_timeout: 600s + script: | + set -e + DEPLOY_PATH="${{ needs.prepare.outputs.deploy_path }}" + DOCKER_TAG="${{ needs.prepare.outputs.docker_tag }}" + REPO="${{ env.REPO }}" + + echo "部署目录: ${DEPLOY_PATH}" + echo "镜像标签: ${DOCKER_TAG}" + + cd ${DEPLOY_PATH} + + # 写入环境变量供 docker-compose 使用 + cat > .env < RPC) + rpcResp, err := l.svcCtx.CoreRpc.Ping(l.ctx, &core.Empty{}) + + status := "ok" + if err != nil { + status = "rpc_error: " + err.Error() + } else if rpcResp.Msg != "" { + status = rpcResp.Msg + } + + return &types.HealthResp{ + Status: status, + }, nil +} diff --git a/apps/api/internal/logic/common/sendEmailCodeLogic.go b/apps/api/internal/logic/common/sendEmailCodeLogic.go new file mode 100644 index 0000000..d838d5d --- /dev/null +++ b/apps/api/internal/logic/common/sendEmailCodeLogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package common + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type SendEmailCodeLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewSendEmailCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SendEmailCodeLogic { + return &SendEmailCodeLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *SendEmailCodeLogic) SendEmailCode(req *types.SendEmailCodeReq) error { + // todo: add your logic here and delete this line + + return nil +} diff --git a/apps/api/internal/logic/order/closeOrderLogic.go b/apps/api/internal/logic/order/closeOrderLogic.go new file mode 100644 index 0000000..edffcfc --- /dev/null +++ b/apps/api/internal/logic/order/closeOrderLogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package order + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type CloseOrderLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewCloseOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CloseOrderLogic { + return &CloseOrderLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *CloseOrderLogic) CloseOrder(req *types.CloseOrderReq) error { + // todo: add your logic here and delete this line + + return nil +} diff --git a/apps/api/internal/logic/order/createOrderLogic.go b/apps/api/internal/logic/order/createOrderLogic.go new file mode 100644 index 0000000..69864ba --- /dev/null +++ b/apps/api/internal/logic/order/createOrderLogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package order + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type CreateOrderLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewCreateOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateOrderLogic { + return &CreateOrderLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *CreateOrderLogic) CreateOrder(req *types.CreateOrderReq) (resp *types.OrderResp, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/apps/api/internal/logic/order/getOrderDetailLogic.go b/apps/api/internal/logic/order/getOrderDetailLogic.go new file mode 100644 index 0000000..b11dd8e --- /dev/null +++ b/apps/api/internal/logic/order/getOrderDetailLogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package order + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetOrderDetailLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetOrderDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetOrderDetailLogic { + return &GetOrderDetailLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetOrderDetailLogic) GetOrderDetail(req *types.OrderDetailReq) (resp *types.OrderResp, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/apps/api/internal/logic/ticket/createTicketFollowLogic.go b/apps/api/internal/logic/ticket/createTicketFollowLogic.go new file mode 100644 index 0000000..aa6470e --- /dev/null +++ b/apps/api/internal/logic/ticket/createTicketFollowLogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package ticket + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type CreateTicketFollowLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewCreateTicketFollowLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateTicketFollowLogic { + return &CreateTicketFollowLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *CreateTicketFollowLogic) CreateTicketFollow(req *types.CreateTicketFollowReq) error { + // todo: add your logic here and delete this line + + return nil +} diff --git a/apps/api/internal/logic/ticket/createTicketLogic.go b/apps/api/internal/logic/ticket/createTicketLogic.go new file mode 100644 index 0000000..f284cf4 --- /dev/null +++ b/apps/api/internal/logic/ticket/createTicketLogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package ticket + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type CreateTicketLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewCreateTicketLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateTicketLogic { + return &CreateTicketLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *CreateTicketLogic) CreateTicket(req *types.CreateTicketReq) (resp *types.TicketResp, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/apps/api/internal/logic/ticket/getTicketDetailLogic.go b/apps/api/internal/logic/ticket/getTicketDetailLogic.go new file mode 100644 index 0000000..91abc4d --- /dev/null +++ b/apps/api/internal/logic/ticket/getTicketDetailLogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package ticket + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetTicketDetailLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetTicketDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetTicketDetailLogic { + return &GetTicketDetailLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetTicketDetailLogic) GetTicketDetail(req *types.TicketDetailReq) (resp *types.TicketResp, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/apps/api/internal/logic/user/getUserInfoLogic.go b/apps/api/internal/logic/user/getUserInfoLogic.go new file mode 100644 index 0000000..df3ad13 --- /dev/null +++ b/apps/api/internal/logic/user/getUserInfoLogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package user + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetUserInfoLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetUserInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserInfoLogic { + return &GetUserInfoLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetUserInfoLogic) GetUserInfo() (resp *types.UserInfoResp, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/apps/api/internal/logic/user/getUserSubscribeLogic.go b/apps/api/internal/logic/user/getUserSubscribeLogic.go new file mode 100644 index 0000000..8294c4d --- /dev/null +++ b/apps/api/internal/logic/user/getUserSubscribeLogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package user + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetUserSubscribeLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetUserSubscribeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserSubscribeLogic { + return &GetUserSubscribeLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetUserSubscribeLogic) GetUserSubscribe() (resp []types.UserSubscribeResp, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/apps/api/internal/logic/user/updateUserPasswordLogic.go b/apps/api/internal/logic/user/updateUserPasswordLogic.go new file mode 100644 index 0000000..72a3453 --- /dev/null +++ b/apps/api/internal/logic/user/updateUserPasswordLogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package user + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type UpdateUserPasswordLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewUpdateUserPasswordLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateUserPasswordLogic { + return &UpdateUserPasswordLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *UpdateUserPasswordLogic) UpdateUserPassword(req *types.UpdatePasswordReq) error { + // todo: add your logic here and delete this line + + return nil +} diff --git a/apps/api/internal/svc/serviceContext.go b/apps/api/internal/svc/serviceContext.go new file mode 100644 index 0000000..9ba211a --- /dev/null +++ b/apps/api/internal/svc/serviceContext.go @@ -0,0 +1,22 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package svc + +import ( + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/config" + "github.com/zero-ppanel/zero-ppanel/apps/rpc/core/coreclient" + "github.com/zeromicro/go-zero/zrpc" +) + +type ServiceContext struct { + Config config.Config + CoreRpc coreClient.Core +} + +func NewServiceContext(c config.Config) *ServiceContext { + return &ServiceContext{ + Config: c, + CoreRpc: coreClient.NewCore(zrpc.MustNewClient(c.CoreRpc)), + } +} diff --git a/apps/api/internal/types/types.go b/apps/api/internal/types/types.go new file mode 100644 index 0000000..1c7175c --- /dev/null +++ b/apps/api/internal/types/types.go @@ -0,0 +1,154 @@ +// Code generated by goctl. DO NOT EDIT. +// goctl 1.9.2 + +package types + +type AnnouncementResp struct { + Id int64 `json:"id"` + Title string `json:"title"` + Content string `json:"content"` + CreatedAt string `json:"created_at"` +} + +type AuthResp struct { + Token string `json:"token"` + Expire int64 `json:"expire"` +} + +type CloseOrderReq struct { + OrderNo string `path:"order_no"` +} + +type CreateOrderReq struct { + SubscribeId int64 `json:"subscribe_id"` + CouponCode string `json:"coupon_code,optional"` + PaymentId int64 `json:"payment_id"` + Period string `json:"period"` +} + +type CreateTicketFollowReq struct { + Id int64 `path:"id"` + Content string `json:"content"` +} + +type CreateTicketReq struct { + Title string `json:"title"` + Content string `json:"content"` +} + +type DocumentDetailReq struct { + Id int64 `path:"id"` +} + +type DocumentDetailResp struct { + Id int64 `json:"id"` + Title string `json:"title"` + Content string `json:"content"` +} + +type DocumentListResp struct { + Id int64 `json:"id"` + Title string `json:"title"` +} + +type GlobalConfigResp struct { + SiteName string `json:"site_name"` + SiteDesc string `json:"site_desc"` + SiteLogo string `json:"site_logo"` + ForceHttps bool `json:"force_https"` + StopRegister bool `json:"stop_register"` +} + +type HealthResp struct { + Status string `json:"status"` +} + +type OrderDetailReq struct { + OrderNo string `path:"order_no"` +} + +type OrderResp struct { + Id int64 `json:"id"` + OrderNo string `json:"order_no"` + Amount int64 `json:"amount"` + Status int `json:"status"` + PaymentUrl string `json:"payment_url,omitempty"` + CreatedAt string `json:"created_at"` +} + +type PaymentMethodResp struct { + Id int64 `json:"id"` + Name string `json:"name"` + Platform string `json:"platform"` + Icon string `json:"icon"` +} + +type ResetPasswordReq struct { + Email string `json:"email"` + Password string `json:"password"` + Code string `json:"code"` +} + +type SendEmailCodeReq struct { + Email string `json:"email"` +} + +type SubscribeGroupResp struct { + Id int64 `json:"id"` + Name string `json:"name"` +} + +type SubscribeResp struct { + Id int64 `json:"id"` + Name string `json:"name"` + Price int64 `json:"price"` + Traffic int64 `json:"traffic"` + GroupId int64 `json:"group_id"` +} + +type TicketDetailReq struct { + Id int64 `path:"id"` +} + +type TicketResp struct { + Id int64 `json:"id"` + Title string `json:"title"` + Status int `json:"status"` + CreatedAt string `json:"created_at"` +} + +type UpdatePasswordReq struct { + OldPassword string `json:"old_password"` + NewPassword string `json:"new_password"` +} + +type UserInfoResp struct { + Id int64 `json:"id"` + Email string `json:"email"` + Avatar string `json:"avatar"` + Balance int64 `json:"balance"` + Commission int64 `json:"commission"` + IsAdmin bool `json:"is_admin"` +} + +type UserLoginReq struct { + Email string `json:"email"` + Password string `json:"password"` +} + +type UserRegisterReq struct { + Email string `json:"email"` + Password string `json:"password"` + Code string `json:"code"` + ReferCode string `json:"refer_code,optional"` +} + +type UserSubscribeResp struct { + Id int64 `json:"id"` + SubscribeId int64 `json:"subscribe_id"` + Name string `json:"name"` + ExpireAt string `json:"expire_at"` + Traffic int64 `json:"traffic"` + UsedTraffic int64 `json:"used_traffic"` + Token string `json:"token"` +} diff --git a/apps/api/ppanel.go b/apps/api/ppanel.go new file mode 100644 index 0000000..90114f4 --- /dev/null +++ b/apps/api/ppanel.go @@ -0,0 +1,34 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package main + +import ( + "flag" + "fmt" + + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/config" + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/handler" + "github.com/zero-ppanel/zero-ppanel/apps/api/internal/svc" + + "github.com/zeromicro/go-zero/core/conf" + "github.com/zeromicro/go-zero/rest" +) + +var configFile = flag.String("f", "etc/api-dev.yaml", "the config file") + +func main() { + flag.Parse() + + var c config.Config + conf.MustLoad(*configFile, &c) + + server := rest.MustNewServer(c.RestConf) + defer server.Stop() + + ctx := svc.NewServiceContext(c) + handler.RegisterHandlers(server, ctx) + + fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port) + server.Start() +} diff --git a/apps/node/desc/common.api b/apps/node/desc/common.api new file mode 100644 index 0000000..e47f076 --- /dev/null +++ b/apps/node/desc/common.api @@ -0,0 +1,14 @@ +syntax = "v1" + +info ( + title: "节点服务公共接口" +) + +@server ( + prefix: /api/v1/node + group: common +) +service ppanelnode { + @handler HealthHandler + get /health returns (HealthResp) +} diff --git a/apps/node/desc/node.api b/apps/node/desc/node.api new file mode 100644 index 0000000..f305a5d --- /dev/null +++ b/apps/node/desc/node.api @@ -0,0 +1,70 @@ +syntax = "v1" + +info ( + title: "节点通信接口" +) + +type ( + PushStatusReq { + CPU float64 `json:"cpu"` + Mem float64 `json:"mem"` + Disk float64 `json:"disk"` + OnlineUsers int `json:"online_users"` + Uptime int64 `json:"uptime"` + } + + UserTraffic { + UserId int64 `json:"user_id"` + Upload int64 `json:"upload"` + Download int64 `json:"download"` + } + + PushUserTrafficReq { + Data []UserTraffic `json:"data"` + } + + OnlineUser { + UserId int64 `json:"user_id"` + IP string `json:"ip"` + } + + PushOnlineUsersReq { + Data []OnlineUser `json:"data"` + } + + ServerConfigResp { + Id int64 `json:"id"` + Name string `json:"name"` + Protocol string `json:"protocol"` + Config map[string]string `json:"config"` + } + + ServerUserResp { + Id int64 `json:"id"` + Token string `json:"token"` + Speed int64 `json:"speed"` + DeviceLimit int `json:"device_limit"` + } +) + +@server ( + prefix: /api/v1/node + group: node + middleware: NodeAuthMiddleware +) +service ppanelnode { + @handler GetServerConfigHandler + get /config returns (ServerConfigResp) + + @handler GetServerUserListHandler + get /users returns ([]ServerUserResp) + + @handler PushStatusHandler + post /status (PushStatusReq) + + @handler PushUserTrafficHandler + post /traffic (PushUserTrafficReq) + + @handler PushOnlineUsersHandler + post /online (PushOnlineUsersReq) +} diff --git a/apps/node/desc/types.api b/apps/node/desc/types.api new file mode 100644 index 0000000..a873a17 --- /dev/null +++ b/apps/node/desc/types.api @@ -0,0 +1,11 @@ +syntax = "v1" + +info ( + title: "节点服务公共类型" +) + +type ( + HealthResp { + Status string `json:"status"` + } +) diff --git a/apps/node/etc/node-dev.yaml b/apps/node/etc/node-dev.yaml new file mode 100644 index 0000000..06ac537 --- /dev/null +++ b/apps/node/etc/node-dev.yaml @@ -0,0 +1,30 @@ +Name: zero-ppanel-node +Host: 0.0.0.0 +Port: 8082 +Mode: dev + +Log: + Mode: console + Encoding: plain + Level: debug + +Telemetry: + Name: zero-ppanel-node + Endpoint: 127.0.0.1:4318 + Sampler: 1.0 + Batcher: otlphttp + +DevServer: + Enabled: true + Port: 6162 + EnableMetrics: true + EnablePprof: true + +NodeSecret: "dev-node-secret" + +MySQL: + DataSource: "root:password@tcp(127.0.0.1:3306)/ppanel?charset=utf8mb4&parseTime=true" + +Redis: + Host: 127.0.0.1:6379 + Type: node diff --git a/apps/node/etc/node-prod.yaml b/apps/node/etc/node-prod.yaml new file mode 100644 index 0000000..354a6a8 --- /dev/null +++ b/apps/node/etc/node-prod.yaml @@ -0,0 +1,34 @@ +Name: zero-ppanel-node +Host: 0.0.0.0 +Port: 8082 +Mode: pro + +Log: + Mode: file + Encoding: json + Level: info + Path: /var/log/zero-ppanel/node + KeepDays: 15 + Rotation: daily + +Telemetry: + Name: zero-ppanel-node + Endpoint: http://jaeger:4318/v1/traces + Sampler: 0.1 + Batcher: otlphttp + +DevServer: + Enabled: true + Port: 6162 + EnableMetrics: true + EnablePprof: false + +NodeSecret: "${NODE_SECRET}" + +MySQL: + DataSource: "${MYSQL_DSN}" + +Redis: + Host: "${REDIS_HOST}" + Type: node + Pass: "${REDIS_PASS}" diff --git a/apps/node/etc/node-test.yaml b/apps/node/etc/node-test.yaml new file mode 100644 index 0000000..77ca8aa --- /dev/null +++ b/apps/node/etc/node-test.yaml @@ -0,0 +1,32 @@ +Name: zero-ppanel-node +Host: 0.0.0.0 +Port: 8082 +Mode: test + +Log: + Mode: file + Encoding: json + Level: info + Path: logs/node + KeepDays: 7 + +Telemetry: + Name: zero-ppanel-node + Endpoint: http://jaeger:4318/v1/traces + Sampler: 0.5 + Batcher: otlphttp + +DevServer: + Enabled: true + Port: 6162 + EnableMetrics: true + EnablePprof: true + +NodeSecret: "test-node-secret" + +MySQL: + DataSource: "root:password@tcp(mysql:3306)/ppanel?charset=utf8mb4&parseTime=true" + +Redis: + Host: redis:6379 + Type: node diff --git a/apps/node/etc/ppanelnode.yaml b/apps/node/etc/ppanelnode.yaml new file mode 100644 index 0000000..6b912d9 --- /dev/null +++ b/apps/node/etc/ppanelnode.yaml @@ -0,0 +1,3 @@ +Name: ppanelnode +Host: 0.0.0.0 +Port: 8888 diff --git a/apps/node/internal/config/config.go b/apps/node/internal/config/config.go new file mode 100644 index 0000000..9b36470 --- /dev/null +++ b/apps/node/internal/config/config.go @@ -0,0 +1,10 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package config + +import "github.com/zeromicro/go-zero/rest" + +type Config struct { + rest.RestConf +} diff --git a/apps/node/internal/handler/common/healthHandler.go b/apps/node/internal/handler/common/healthHandler.go new file mode 100644 index 0000000..6349dfd --- /dev/null +++ b/apps/node/internal/handler/common/healthHandler.go @@ -0,0 +1,24 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package common + +import ( + "net/http" + + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/logic/common" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/svc" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func HealthHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + l := common.NewHealthLogic(r.Context(), svcCtx) + resp, err := l.Health() + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/apps/node/internal/handler/node/getServerConfigHandler.go b/apps/node/internal/handler/node/getServerConfigHandler.go new file mode 100644 index 0000000..ee6833d --- /dev/null +++ b/apps/node/internal/handler/node/getServerConfigHandler.go @@ -0,0 +1,24 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package node + +import ( + "net/http" + + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/logic/node" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/svc" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func GetServerConfigHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + l := node.NewGetServerConfigLogic(r.Context(), svcCtx) + resp, err := l.GetServerConfig() + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/apps/node/internal/handler/node/getServerUserListHandler.go b/apps/node/internal/handler/node/getServerUserListHandler.go new file mode 100644 index 0000000..c6e657d --- /dev/null +++ b/apps/node/internal/handler/node/getServerUserListHandler.go @@ -0,0 +1,24 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package node + +import ( + "net/http" + + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/logic/node" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/svc" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func GetServerUserListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + l := node.NewGetServerUserListLogic(r.Context(), svcCtx) + resp, err := l.GetServerUserList() + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/apps/node/internal/handler/node/pushOnlineUsersHandler.go b/apps/node/internal/handler/node/pushOnlineUsersHandler.go new file mode 100644 index 0000000..ebc7c2a --- /dev/null +++ b/apps/node/internal/handler/node/pushOnlineUsersHandler.go @@ -0,0 +1,31 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package node + +import ( + "net/http" + + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/logic/node" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func PushOnlineUsersHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.PushOnlineUsersReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := node.NewPushOnlineUsersLogic(r.Context(), svcCtx) + err := l.PushOnlineUsers(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.Ok(w) + } + } +} diff --git a/apps/node/internal/handler/node/pushStatusHandler.go b/apps/node/internal/handler/node/pushStatusHandler.go new file mode 100644 index 0000000..1c2745f --- /dev/null +++ b/apps/node/internal/handler/node/pushStatusHandler.go @@ -0,0 +1,31 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package node + +import ( + "net/http" + + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/logic/node" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func PushStatusHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.PushStatusReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := node.NewPushStatusLogic(r.Context(), svcCtx) + err := l.PushStatus(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.Ok(w) + } + } +} diff --git a/apps/node/internal/handler/node/pushUserTrafficHandler.go b/apps/node/internal/handler/node/pushUserTrafficHandler.go new file mode 100644 index 0000000..6985130 --- /dev/null +++ b/apps/node/internal/handler/node/pushUserTrafficHandler.go @@ -0,0 +1,31 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package node + +import ( + "net/http" + + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/logic/node" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func PushUserTrafficHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.PushUserTrafficReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := node.NewPushUserTrafficLogic(r.Context(), svcCtx) + err := l.PushUserTraffic(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.Ok(w) + } + } +} diff --git a/apps/node/internal/handler/routes.go b/apps/node/internal/handler/routes.go new file mode 100644 index 0000000..05dff0a --- /dev/null +++ b/apps/node/internal/handler/routes.go @@ -0,0 +1,61 @@ +// Code generated by goctl. DO NOT EDIT. +// goctl 1.9.2 + +package handler + +import ( + "net/http" + + common "github.com/zero-ppanel/zero-ppanel/apps/node/internal/handler/common" + node "github.com/zero-ppanel/zero-ppanel/apps/node/internal/handler/node" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/svc" + + "github.com/zeromicro/go-zero/rest" +) + +func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { + server.AddRoutes( + []rest.Route{ + { + Method: http.MethodGet, + Path: "/health", + Handler: common.HealthHandler(serverCtx), + }, + }, + rest.WithPrefix("/api/v1/node"), + ) + + server.AddRoutes( + rest.WithMiddlewares( + []rest.Middleware{serverCtx.NodeAuthMiddleware}, + []rest.Route{ + { + Method: http.MethodGet, + Path: "/config", + Handler: node.GetServerConfigHandler(serverCtx), + }, + { + Method: http.MethodPost, + Path: "/online", + Handler: node.PushOnlineUsersHandler(serverCtx), + }, + { + Method: http.MethodPost, + Path: "/status", + Handler: node.PushStatusHandler(serverCtx), + }, + { + Method: http.MethodPost, + Path: "/traffic", + Handler: node.PushUserTrafficHandler(serverCtx), + }, + { + Method: http.MethodGet, + Path: "/users", + Handler: node.GetServerUserListHandler(serverCtx), + }, + }..., + ), + rest.WithPrefix("/api/v1/node"), + ) +} diff --git a/apps/node/internal/logic/common/healthLogic.go b/apps/node/internal/logic/common/healthLogic.go new file mode 100644 index 0000000..4d493ec --- /dev/null +++ b/apps/node/internal/logic/common/healthLogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package common + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type HealthLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewHealthLogic(ctx context.Context, svcCtx *svc.ServiceContext) *HealthLogic { + return &HealthLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *HealthLogic) Health() (resp *types.HealthResp, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/apps/node/internal/logic/node/getServerConfigLogic.go b/apps/node/internal/logic/node/getServerConfigLogic.go new file mode 100644 index 0000000..fb36019 --- /dev/null +++ b/apps/node/internal/logic/node/getServerConfigLogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package node + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetServerConfigLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetServerConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetServerConfigLogic { + return &GetServerConfigLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetServerConfigLogic) GetServerConfig() (resp *types.ServerConfigResp, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/apps/node/internal/logic/node/getServerUserListLogic.go b/apps/node/internal/logic/node/getServerUserListLogic.go new file mode 100644 index 0000000..96b0cd4 --- /dev/null +++ b/apps/node/internal/logic/node/getServerUserListLogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package node + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetServerUserListLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetServerUserListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetServerUserListLogic { + return &GetServerUserListLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetServerUserListLogic) GetServerUserList() (resp []types.ServerUserResp, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/apps/node/internal/logic/node/pushOnlineUsersLogic.go b/apps/node/internal/logic/node/pushOnlineUsersLogic.go new file mode 100644 index 0000000..a78e061 --- /dev/null +++ b/apps/node/internal/logic/node/pushOnlineUsersLogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package node + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type PushOnlineUsersLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewPushOnlineUsersLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PushOnlineUsersLogic { + return &PushOnlineUsersLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *PushOnlineUsersLogic) PushOnlineUsers(req *types.PushOnlineUsersReq) error { + // todo: add your logic here and delete this line + + return nil +} diff --git a/apps/node/internal/logic/node/pushStatusLogic.go b/apps/node/internal/logic/node/pushStatusLogic.go new file mode 100644 index 0000000..2316e5d --- /dev/null +++ b/apps/node/internal/logic/node/pushStatusLogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package node + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type PushStatusLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewPushStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PushStatusLogic { + return &PushStatusLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *PushStatusLogic) PushStatus(req *types.PushStatusReq) error { + // todo: add your logic here and delete this line + + return nil +} diff --git a/apps/node/internal/logic/node/pushUserTrafficLogic.go b/apps/node/internal/logic/node/pushUserTrafficLogic.go new file mode 100644 index 0000000..7a24957 --- /dev/null +++ b/apps/node/internal/logic/node/pushUserTrafficLogic.go @@ -0,0 +1,33 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package node + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/svc" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type PushUserTrafficLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewPushUserTrafficLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PushUserTrafficLogic { + return &PushUserTrafficLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *PushUserTrafficLogic) PushUserTraffic(req *types.PushUserTrafficReq) error { + // todo: add your logic here and delete this line + + return nil +} diff --git a/apps/node/internal/middleware/nodeauthMiddleware.go b/apps/node/internal/middleware/nodeauthMiddleware.go new file mode 100644 index 0000000..1bc46bc --- /dev/null +++ b/apps/node/internal/middleware/nodeauthMiddleware.go @@ -0,0 +1,22 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package middleware + +import "net/http" + +type NodeAuthMiddleware struct { +} + +func NewNodeAuthMiddleware() *NodeAuthMiddleware { + return &NodeAuthMiddleware{} +} + +func (m *NodeAuthMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + // TODO generate middleware implement function, delete after code implementation + + // Passthrough to next handler if need + next(w, r) + } +} diff --git a/apps/node/internal/svc/serviceContext.go b/apps/node/internal/svc/serviceContext.go new file mode 100644 index 0000000..9ab11e3 --- /dev/null +++ b/apps/node/internal/svc/serviceContext.go @@ -0,0 +1,22 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package svc + +import ( + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/config" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/middleware" + "github.com/zeromicro/go-zero/rest" +) + +type ServiceContext struct { + Config config.Config + NodeAuthMiddleware rest.Middleware +} + +func NewServiceContext(c config.Config) *ServiceContext { + return &ServiceContext{ + Config: c, + NodeAuthMiddleware: middleware.NewNodeAuthMiddleware().Handle, + } +} diff --git a/apps/node/internal/types/types.go b/apps/node/internal/types/types.go new file mode 100644 index 0000000..2f0f2be --- /dev/null +++ b/apps/node/internal/types/types.go @@ -0,0 +1,49 @@ +// Code generated by goctl. DO NOT EDIT. +// goctl 1.9.2 + +package types + +type HealthResp struct { + Status string `json:"status"` +} + +type OnlineUser struct { + UserId int64 `json:"user_id"` + IP string `json:"ip"` +} + +type PushOnlineUsersReq struct { + Data []OnlineUser `json:"data"` +} + +type PushStatusReq struct { + CPU float64 `json:"cpu"` + Mem float64 `json:"mem"` + Disk float64 `json:"disk"` + OnlineUsers int `json:"online_users"` + Uptime int64 `json:"uptime"` +} + +type PushUserTrafficReq struct { + Data []UserTraffic `json:"data"` +} + +type ServerConfigResp struct { + Id int64 `json:"id"` + Name string `json:"name"` + Protocol string `json:"protocol"` + Config map[string]string `json:"config"` +} + +type ServerUserResp struct { + Id int64 `json:"id"` + Token string `json:"token"` + Speed int64 `json:"speed"` + DeviceLimit int `json:"device_limit"` +} + +type UserTraffic struct { + UserId int64 `json:"user_id"` + Upload int64 `json:"upload"` + Download int64 `json:"download"` +} diff --git a/apps/node/node.api b/apps/node/node.api new file mode 100644 index 0000000..dfc3e10 --- /dev/null +++ b/apps/node/node.api @@ -0,0 +1,15 @@ +syntax = "v1" + +info ( + title: "PPanel Node" + desc: "节点通信服务" + author: "ppanel" + version: "1.0" +) + +import ( + "desc/types.api" + "desc/common.api" + "desc/node.api" +) + diff --git a/apps/node/ppanelnode.go b/apps/node/ppanelnode.go new file mode 100644 index 0000000..1c5c48f --- /dev/null +++ b/apps/node/ppanelnode.go @@ -0,0 +1,34 @@ +// Code scaffolded by goctl. Safe to edit. +// goctl 1.9.2 + +package main + +import ( + "flag" + "fmt" + + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/config" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/handler" + "github.com/zero-ppanel/zero-ppanel/apps/node/internal/svc" + + "github.com/zeromicro/go-zero/core/conf" + "github.com/zeromicro/go-zero/rest" +) + +var configFile = flag.String("f", "etc/node-dev.yaml", "the config file") + +func main() { + flag.Parse() + + var c config.Config + conf.MustLoad(*configFile, &c) + + server := rest.MustNewServer(c.RestConf) + defer server.Stop() + + ctx := svc.NewServiceContext(c) + handler.RegisterHandlers(server, ctx) + + fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port) + server.Start() +} diff --git a/apps/queue/etc/queue-dev.yaml b/apps/queue/etc/queue-dev.yaml new file mode 100644 index 0000000..35120e8 --- /dev/null +++ b/apps/queue/etc/queue-dev.yaml @@ -0,0 +1,23 @@ +Name: zero-ppanel-queue +Mode: dev + +Log: + Mode: console + Encoding: plain + Level: debug + +Telemetry: + Name: zero-ppanel-queue + Endpoint: 127.0.0.1:4318 + Sampler: 1.0 + Batcher: otlphttp + +MySQL: + DataSource: "root:password@tcp(127.0.0.1:3306)/ppanel?charset=utf8mb4&parseTime=true" + +Redis: + Host: 127.0.0.1:6379 + Type: node + +Asynq: + Addr: 127.0.0.1:6379 diff --git a/apps/queue/etc/queue-prod.yaml b/apps/queue/etc/queue-prod.yaml new file mode 100644 index 0000000..79f0fc8 --- /dev/null +++ b/apps/queue/etc/queue-prod.yaml @@ -0,0 +1,28 @@ +Name: zero-ppanel-queue +Mode: pro + +Log: + Mode: file + Encoding: json + Level: info + Path: /var/log/zero-ppanel/queue + KeepDays: 15 + Rotation: daily + +Telemetry: + Name: zero-ppanel-queue + Endpoint: http://jaeger:4318/v1/traces + Sampler: 0.1 + Batcher: otlphttp + +MySQL: + DataSource: "${MYSQL_DSN}" + +Redis: + Host: "${REDIS_HOST}" + Type: node + Pass: "${REDIS_PASS}" + +Asynq: + Addr: "${REDIS_HOST}" + Pass: "${REDIS_PASS}" diff --git a/apps/queue/etc/queue-test.yaml b/apps/queue/etc/queue-test.yaml new file mode 100644 index 0000000..0fe42eb --- /dev/null +++ b/apps/queue/etc/queue-test.yaml @@ -0,0 +1,25 @@ +Name: zero-ppanel-queue +Mode: test + +Log: + Mode: file + Encoding: json + Level: info + Path: logs/queue + KeepDays: 7 + +Telemetry: + Name: zero-ppanel-queue + Endpoint: http://jaeger:4318/v1/traces + Sampler: 0.5 + Batcher: otlphttp + +MySQL: + DataSource: "root:password@tcp(mysql:3306)/ppanel?charset=utf8mb4&parseTime=true" + +Redis: + Host: redis:6379 + Type: node + +Asynq: + Addr: redis:6379 diff --git a/apps/queue/internal/config/config.go b/apps/queue/internal/config/config.go new file mode 100644 index 0000000..6ed8263 --- /dev/null +++ b/apps/queue/internal/config/config.go @@ -0,0 +1,30 @@ +package config + +import ( + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/core/trace" +) + +type Config struct { + Name string + Mode string `json:",default=pro"` + + Log logx.LogConf + + Telemetry trace.Config `json:",optional"` + + MySQL struct { + DataSource string + } + + Redis struct { + Host string + Type string + Pass string `json:",optional"` + } + + Asynq struct { + Addr string + Pass string `json:",optional"` + } +} diff --git a/apps/queue/internal/handler/routes.go b/apps/queue/internal/handler/routes.go new file mode 100644 index 0000000..7316faf --- /dev/null +++ b/apps/queue/internal/handler/routes.go @@ -0,0 +1,15 @@ +package handler + +import ( + "github.com/hibiken/asynq" + + "github.com/zero-ppanel/zero-ppanel/apps/queue/internal/svc" +) + +func RegisterHandlers(mux *asynq.ServeMux, svcCtx *svc.ServiceContext) { + // TODO: Register asynq task handlers + // mux.HandleFunc("task:send_email", logic.NewSendEmailLogic(svcCtx).Handle) + // mux.HandleFunc("task:send_sms", logic.NewSendSmsLogic(svcCtx).Handle) + // mux.HandleFunc("task:order_timeout", logic.NewOrderTimeoutLogic(svcCtx).Handle) + // mux.HandleFunc("task:telegram_notify", logic.NewTelegramNotifyLogic(svcCtx).Handle) +} diff --git a/apps/queue/internal/logic/.gitkeep b/apps/queue/internal/logic/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/apps/queue/internal/svc/servicecontext.go b/apps/queue/internal/svc/servicecontext.go new file mode 100644 index 0000000..26f4fdc --- /dev/null +++ b/apps/queue/internal/svc/servicecontext.go @@ -0,0 +1,15 @@ +package svc + +import ( + "github.com/zero-ppanel/zero-ppanel/apps/queue/internal/config" +) + +type ServiceContext struct { + Config config.Config +} + +func NewServiceContext(c config.Config) *ServiceContext { + return &ServiceContext{ + Config: c, + } +} diff --git a/apps/queue/internal/types/types.go b/apps/queue/internal/types/types.go new file mode 100644 index 0000000..8a820c5 --- /dev/null +++ b/apps/queue/internal/types/types.go @@ -0,0 +1,9 @@ +package types + +const ( + TaskSendEmail = "task:send_email" + TaskSendSms = "task:send_sms" + TaskOrderTimeout = "task:order_timeout" + TaskTelegramNotify = "task:telegram_notify" + TaskSendMessage = "task:send_message" +) diff --git a/apps/queue/queue.go b/apps/queue/queue.go new file mode 100644 index 0000000..30c3916 --- /dev/null +++ b/apps/queue/queue.go @@ -0,0 +1,49 @@ +package main + +import ( + "flag" + "fmt" + + "github.com/hibiken/asynq" + "github.com/zero-ppanel/zero-ppanel/apps/queue/internal/config" + "github.com/zero-ppanel/zero-ppanel/apps/queue/internal/handler" + "github.com/zero-ppanel/zero-ppanel/apps/queue/internal/svc" + "github.com/zeromicro/go-zero/core/conf" + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/core/trace" +) + +var configFile = flag.String("f", "etc/queue-dev.yaml", "the config file") + +func main() { + flag.Parse() + + var c config.Config + conf.MustLoad(*configFile, &c) + + logx.MustSetup(c.Log) + if c.Telemetry.Name != "" { + trace.StartAgent(c.Telemetry) + } + + svcCtx := svc.NewServiceContext(c) + + server := asynq.NewServer( + asynq.RedisClientOpt{Addr: c.Asynq.Addr, Password: c.Asynq.Pass}, + asynq.Config{ + Concurrency: 20, + IsFailure: func(err error) bool { + logx.Errorf("asynq task error: %v", err) + return true + }, + }, + ) + + mux := asynq.NewServeMux() + handler.RegisterHandlers(mux, svcCtx) + + fmt.Println("Starting zero-ppanel-queue worker...") + if err := server.Run(mux); err != nil { + logx.Must(err) + } +} diff --git a/apps/rpc/core/core.go b/apps/rpc/core/core.go new file mode 100644 index 0000000..d4954e0 --- /dev/null +++ b/apps/rpc/core/core.go @@ -0,0 +1,39 @@ +package main + +import ( + "flag" + "fmt" + + "github.com/zero-ppanel/zero-ppanel/apps/rpc/core/core" + "github.com/zero-ppanel/zero-ppanel/apps/rpc/core/internal/config" + "github.com/zero-ppanel/zero-ppanel/apps/rpc/core/internal/server" + "github.com/zero-ppanel/zero-ppanel/apps/rpc/core/internal/svc" + + "github.com/zeromicro/go-zero/core/conf" + "github.com/zeromicro/go-zero/core/service" + "github.com/zeromicro/go-zero/zrpc" + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" +) + +var configFile = flag.String("f", "etc/core.yaml", "the config file") + +func main() { + flag.Parse() + + var c config.Config + conf.MustLoad(*configFile, &c) + ctx := svc.NewServiceContext(c) + + s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) { + core.RegisterCoreServer(grpcServer, server.NewCoreServer(ctx)) + + if c.Mode == service.DevMode || c.Mode == service.TestMode { + reflection.Register(grpcServer) + } + }) + defer s.Stop() + + fmt.Printf("Starting rpc server at %s...\n", c.ListenOn) + s.Start() +} diff --git a/apps/rpc/core/core.proto b/apps/rpc/core/core.proto new file mode 100644 index 0000000..de1b351 --- /dev/null +++ b/apps/rpc/core/core.proto @@ -0,0 +1,56 @@ +syntax = "proto3"; + +package core; +option go_package = "./core"; + +// ---------------------------------------------------------------------------- +// 通用结构 +// ---------------------------------------------------------------------------- +message Empty {} + +message BasicResponse { + int32 code = 1; + string msg = 2; +} + +// ---------------------------------------------------------------------------- +// User 服务定义 +// ---------------------------------------------------------------------------- +message GetUserInfoReq { + int64 id = 1; +} + +message GetUserInfoResp { + int64 id = 1; + string email = 2; + string role = 3; + string uuid = 4; +} + +// ---------------------------------------------------------------------------- +// Node 服务定义 +// ---------------------------------------------------------------------------- +message GetNodeInfoReq { + int64 id = 1; +} + +message GetNodeInfoResp { + int64 id = 1; + string name = 2; + string server = 3; + string status = 4; +} + +// ---------------------------------------------------------------------------- +// 核心 RPC 服务接口 +// ---------------------------------------------------------------------------- +service Core { + // Ping 检查服务健康状态 + rpc Ping(Empty) returns(BasicResponse); + + // 用户相关 + rpc GetUserInfo(GetUserInfoReq) returns(GetUserInfoResp); + + // 节点相关 + rpc GetNodeInfo(GetNodeInfoReq) returns(GetNodeInfoResp); +} diff --git a/apps/rpc/core/core/core.pb.go b/apps/rpc/core/core/core.pb.go new file mode 100644 index 0000000..6af0c1d --- /dev/null +++ b/apps/rpc/core/core/core.pb.go @@ -0,0 +1,431 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc v6.33.4 +// source: core.proto + +package core + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +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 Empty struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Empty) Reset() { + *x = Empty{} + mi := &file_core_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Empty) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Empty) ProtoMessage() {} + +func (x *Empty) ProtoReflect() protoreflect.Message { + mi := &file_core_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Empty.ProtoReflect.Descriptor instead. +func (*Empty) Descriptor() ([]byte, []int) { + return file_core_proto_rawDescGZIP(), []int{0} +} + +type BasicResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Msg string `protobuf:"bytes,2,opt,name=msg,proto3" json:"msg,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BasicResponse) Reset() { + *x = BasicResponse{} + mi := &file_core_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BasicResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BasicResponse) ProtoMessage() {} + +func (x *BasicResponse) ProtoReflect() protoreflect.Message { + mi := &file_core_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BasicResponse.ProtoReflect.Descriptor instead. +func (*BasicResponse) Descriptor() ([]byte, []int) { + return file_core_proto_rawDescGZIP(), []int{1} +} + +func (x *BasicResponse) GetCode() int32 { + if x != nil { + return x.Code + } + return 0 +} + +func (x *BasicResponse) GetMsg() string { + if x != nil { + return x.Msg + } + return "" +} + +// ---------------------------------------------------------------------------- +// User 服务定义 +// ---------------------------------------------------------------------------- +type GetUserInfoReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetUserInfoReq) Reset() { + *x = GetUserInfoReq{} + mi := &file_core_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetUserInfoReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetUserInfoReq) ProtoMessage() {} + +func (x *GetUserInfoReq) ProtoReflect() protoreflect.Message { + mi := &file_core_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetUserInfoReq.ProtoReflect.Descriptor instead. +func (*GetUserInfoReq) Descriptor() ([]byte, []int) { + return file_core_proto_rawDescGZIP(), []int{2} +} + +func (x *GetUserInfoReq) GetId() int64 { + if x != nil { + return x.Id + } + return 0 +} + +type GetUserInfoResp struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` + Role string `protobuf:"bytes,3,opt,name=role,proto3" json:"role,omitempty"` + Uuid string `protobuf:"bytes,4,opt,name=uuid,proto3" json:"uuid,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetUserInfoResp) Reset() { + *x = GetUserInfoResp{} + mi := &file_core_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetUserInfoResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetUserInfoResp) ProtoMessage() {} + +func (x *GetUserInfoResp) ProtoReflect() protoreflect.Message { + mi := &file_core_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetUserInfoResp.ProtoReflect.Descriptor instead. +func (*GetUserInfoResp) Descriptor() ([]byte, []int) { + return file_core_proto_rawDescGZIP(), []int{3} +} + +func (x *GetUserInfoResp) GetId() int64 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *GetUserInfoResp) GetEmail() string { + if x != nil { + return x.Email + } + return "" +} + +func (x *GetUserInfoResp) GetRole() string { + if x != nil { + return x.Role + } + return "" +} + +func (x *GetUserInfoResp) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +// ---------------------------------------------------------------------------- +// Node 服务定义 +// ---------------------------------------------------------------------------- +type GetNodeInfoReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetNodeInfoReq) Reset() { + *x = GetNodeInfoReq{} + mi := &file_core_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetNodeInfoReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetNodeInfoReq) ProtoMessage() {} + +func (x *GetNodeInfoReq) ProtoReflect() protoreflect.Message { + mi := &file_core_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetNodeInfoReq.ProtoReflect.Descriptor instead. +func (*GetNodeInfoReq) Descriptor() ([]byte, []int) { + return file_core_proto_rawDescGZIP(), []int{4} +} + +func (x *GetNodeInfoReq) GetId() int64 { + if x != nil { + return x.Id + } + return 0 +} + +type GetNodeInfoResp struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Server string `protobuf:"bytes,3,opt,name=server,proto3" json:"server,omitempty"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetNodeInfoResp) Reset() { + *x = GetNodeInfoResp{} + mi := &file_core_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetNodeInfoResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetNodeInfoResp) ProtoMessage() {} + +func (x *GetNodeInfoResp) ProtoReflect() protoreflect.Message { + mi := &file_core_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetNodeInfoResp.ProtoReflect.Descriptor instead. +func (*GetNodeInfoResp) Descriptor() ([]byte, []int) { + return file_core_proto_rawDescGZIP(), []int{5} +} + +func (x *GetNodeInfoResp) GetId() int64 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *GetNodeInfoResp) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *GetNodeInfoResp) GetServer() string { + if x != nil { + return x.Server + } + return "" +} + +func (x *GetNodeInfoResp) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +var File_core_proto protoreflect.FileDescriptor + +const file_core_proto_rawDesc = "" + + "\n" + + "\n" + + "core.proto\x12\x04core\"\a\n" + + "\x05Empty\"5\n" + + "\rBasicResponse\x12\x12\n" + + "\x04code\x18\x01 \x01(\x05R\x04code\x12\x10\n" + + "\x03msg\x18\x02 \x01(\tR\x03msg\" \n" + + "\x0eGetUserInfoReq\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x03R\x02id\"_\n" + + "\x0fGetUserInfoResp\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x03R\x02id\x12\x14\n" + + "\x05email\x18\x02 \x01(\tR\x05email\x12\x12\n" + + "\x04role\x18\x03 \x01(\tR\x04role\x12\x12\n" + + "\x04uuid\x18\x04 \x01(\tR\x04uuid\" \n" + + "\x0eGetNodeInfoReq\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x03R\x02id\"e\n" + + "\x0fGetNodeInfoResp\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x03R\x02id\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x12\x16\n" + + "\x06server\x18\x03 \x01(\tR\x06server\x12\x16\n" + + "\x06status\x18\x04 \x01(\tR\x06status2\xa8\x01\n" + + "\x04Core\x12(\n" + + "\x04Ping\x12\v.core.Empty\x1a\x13.core.BasicResponse\x12:\n" + + "\vGetUserInfo\x12\x14.core.GetUserInfoReq\x1a\x15.core.GetUserInfoResp\x12:\n" + + "\vGetNodeInfo\x12\x14.core.GetNodeInfoReq\x1a\x15.core.GetNodeInfoRespB\bZ\x06./coreb\x06proto3" + +var ( + file_core_proto_rawDescOnce sync.Once + file_core_proto_rawDescData []byte +) + +func file_core_proto_rawDescGZIP() []byte { + file_core_proto_rawDescOnce.Do(func() { + file_core_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_core_proto_rawDesc), len(file_core_proto_rawDesc))) + }) + return file_core_proto_rawDescData +} + +var file_core_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_core_proto_goTypes = []any{ + (*Empty)(nil), // 0: core.Empty + (*BasicResponse)(nil), // 1: core.BasicResponse + (*GetUserInfoReq)(nil), // 2: core.GetUserInfoReq + (*GetUserInfoResp)(nil), // 3: core.GetUserInfoResp + (*GetNodeInfoReq)(nil), // 4: core.GetNodeInfoReq + (*GetNodeInfoResp)(nil), // 5: core.GetNodeInfoResp +} +var file_core_proto_depIdxs = []int32{ + 0, // 0: core.Core.Ping:input_type -> core.Empty + 2, // 1: core.Core.GetUserInfo:input_type -> core.GetUserInfoReq + 4, // 2: core.Core.GetNodeInfo:input_type -> core.GetNodeInfoReq + 1, // 3: core.Core.Ping:output_type -> core.BasicResponse + 3, // 4: core.Core.GetUserInfo:output_type -> core.GetUserInfoResp + 5, // 5: core.Core.GetNodeInfo:output_type -> core.GetNodeInfoResp + 3, // [3:6] is the sub-list for method output_type + 0, // [0:3] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_core_proto_init() } +func file_core_proto_init() { + if File_core_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_core_proto_rawDesc), len(file_core_proto_rawDesc)), + NumEnums: 0, + NumMessages: 6, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_core_proto_goTypes, + DependencyIndexes: file_core_proto_depIdxs, + MessageInfos: file_core_proto_msgTypes, + }.Build() + File_core_proto = out.File + file_core_proto_goTypes = nil + file_core_proto_depIdxs = nil +} diff --git a/apps/rpc/core/core/core_grpc.pb.go b/apps/rpc/core/core/core_grpc.pb.go new file mode 100644 index 0000000..2afd10f --- /dev/null +++ b/apps/rpc/core/core/core_grpc.pb.go @@ -0,0 +1,211 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.1 +// - protoc v6.33.4 +// source: core.proto + +package core + +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.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + Core_Ping_FullMethodName = "/core.Core/Ping" + Core_GetUserInfo_FullMethodName = "/core.Core/GetUserInfo" + Core_GetNodeInfo_FullMethodName = "/core.Core/GetNodeInfo" +) + +// CoreClient is the client API for Core 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. +// +// ---------------------------------------------------------------------------- +// 核心 RPC 服务接口 +// ---------------------------------------------------------------------------- +type CoreClient interface { + // Ping 检查服务健康状态 + Ping(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BasicResponse, error) + // 用户相关 + GetUserInfo(ctx context.Context, in *GetUserInfoReq, opts ...grpc.CallOption) (*GetUserInfoResp, error) + // 节点相关 + GetNodeInfo(ctx context.Context, in *GetNodeInfoReq, opts ...grpc.CallOption) (*GetNodeInfoResp, error) +} + +type coreClient struct { + cc grpc.ClientConnInterface +} + +func NewCoreClient(cc grpc.ClientConnInterface) CoreClient { + return &coreClient{cc} +} + +func (c *coreClient) Ping(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BasicResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(BasicResponse) + err := c.cc.Invoke(ctx, Core_Ping_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *coreClient) GetUserInfo(ctx context.Context, in *GetUserInfoReq, opts ...grpc.CallOption) (*GetUserInfoResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetUserInfoResp) + err := c.cc.Invoke(ctx, Core_GetUserInfo_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *coreClient) GetNodeInfo(ctx context.Context, in *GetNodeInfoReq, opts ...grpc.CallOption) (*GetNodeInfoResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetNodeInfoResp) + err := c.cc.Invoke(ctx, Core_GetNodeInfo_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// CoreServer is the server API for Core service. +// All implementations must embed UnimplementedCoreServer +// for forward compatibility. +// +// ---------------------------------------------------------------------------- +// 核心 RPC 服务接口 +// ---------------------------------------------------------------------------- +type CoreServer interface { + // Ping 检查服务健康状态 + Ping(context.Context, *Empty) (*BasicResponse, error) + // 用户相关 + GetUserInfo(context.Context, *GetUserInfoReq) (*GetUserInfoResp, error) + // 节点相关 + GetNodeInfo(context.Context, *GetNodeInfoReq) (*GetNodeInfoResp, error) + mustEmbedUnimplementedCoreServer() +} + +// UnimplementedCoreServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedCoreServer struct{} + +func (UnimplementedCoreServer) Ping(context.Context, *Empty) (*BasicResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Ping not implemented") +} +func (UnimplementedCoreServer) GetUserInfo(context.Context, *GetUserInfoReq) (*GetUserInfoResp, error) { + return nil, status.Error(codes.Unimplemented, "method GetUserInfo not implemented") +} +func (UnimplementedCoreServer) GetNodeInfo(context.Context, *GetNodeInfoReq) (*GetNodeInfoResp, error) { + return nil, status.Error(codes.Unimplemented, "method GetNodeInfo not implemented") +} +func (UnimplementedCoreServer) mustEmbedUnimplementedCoreServer() {} +func (UnimplementedCoreServer) testEmbeddedByValue() {} + +// UnsafeCoreServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to CoreServer will +// result in compilation errors. +type UnsafeCoreServer interface { + mustEmbedUnimplementedCoreServer() +} + +func RegisterCoreServer(s grpc.ServiceRegistrar, srv CoreServer) { + // If the following call panics, it indicates UnimplementedCoreServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&Core_ServiceDesc, srv) +} + +func _Core_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CoreServer).Ping(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Core_Ping_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CoreServer).Ping(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Core_GetUserInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetUserInfoReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CoreServer).GetUserInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Core_GetUserInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CoreServer).GetUserInfo(ctx, req.(*GetUserInfoReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Core_GetNodeInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetNodeInfoReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CoreServer).GetNodeInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Core_GetNodeInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CoreServer).GetNodeInfo(ctx, req.(*GetNodeInfoReq)) + } + return interceptor(ctx, in, info, handler) +} + +// Core_ServiceDesc is the grpc.ServiceDesc for Core service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Core_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "core.Core", + HandlerType: (*CoreServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Ping", + Handler: _Core_Ping_Handler, + }, + { + MethodName: "GetUserInfo", + Handler: _Core_GetUserInfo_Handler, + }, + { + MethodName: "GetNodeInfo", + Handler: _Core_GetNodeInfo_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "core.proto", +} diff --git a/apps/rpc/core/coreClient/core.go b/apps/rpc/core/coreClient/core.go new file mode 100644 index 0000000..46d1bbd --- /dev/null +++ b/apps/rpc/core/coreClient/core.go @@ -0,0 +1,60 @@ +// Code generated by goctl. DO NOT EDIT. +// goctl 1.9.2 +// Source: core.proto + +package coreClient + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/rpc/core/core" + + "github.com/zeromicro/go-zero/zrpc" + "google.golang.org/grpc" +) + +type ( + BasicResponse = core.BasicResponse + Empty = core.Empty + GetNodeInfoReq = core.GetNodeInfoReq + GetNodeInfoResp = core.GetNodeInfoResp + GetUserInfoReq = core.GetUserInfoReq + GetUserInfoResp = core.GetUserInfoResp + + Core interface { + // Ping 检查服务健康状态 + Ping(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BasicResponse, error) + // 用户相关 + GetUserInfo(ctx context.Context, in *GetUserInfoReq, opts ...grpc.CallOption) (*GetUserInfoResp, error) + // 节点相关 + GetNodeInfo(ctx context.Context, in *GetNodeInfoReq, opts ...grpc.CallOption) (*GetNodeInfoResp, error) + } + + defaultCore struct { + cli zrpc.Client + } +) + +func NewCore(cli zrpc.Client) Core { + return &defaultCore{ + cli: cli, + } +} + +// Ping 检查服务健康状态 +func (m *defaultCore) Ping(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BasicResponse, error) { + client := core.NewCoreClient(m.cli.Conn()) + return client.Ping(ctx, in, opts...) +} + +// 用户相关 +func (m *defaultCore) GetUserInfo(ctx context.Context, in *GetUserInfoReq, opts ...grpc.CallOption) (*GetUserInfoResp, error) { + client := core.NewCoreClient(m.cli.Conn()) + return client.GetUserInfo(ctx, in, opts...) +} + +// 节点相关 +func (m *defaultCore) GetNodeInfo(ctx context.Context, in *GetNodeInfoReq, opts ...grpc.CallOption) (*GetNodeInfoResp, error) { + client := core.NewCoreClient(m.cli.Conn()) + return client.GetNodeInfo(ctx, in, opts...) +} diff --git a/apps/rpc/core/etc/core-dev.yaml b/apps/rpc/core/etc/core-dev.yaml new file mode 100644 index 0000000..934e55c --- /dev/null +++ b/apps/rpc/core/etc/core-dev.yaml @@ -0,0 +1,30 @@ +Name: core.rpc +ListenOn: 0.0.0.0:8083 +Mode: dev + +Log: + Mode: console + Encoding: plain + Level: debug + +Telemetry: + Name: core.rpc + Endpoint: 127.0.0.1:4318 + Sampler: 1.0 + Batcher: otlphttp + +DevServer: + Enabled: true + Port: 6163 + EnableMetrics: true + EnablePprof: true + +MySQL: + DataSource: "root:password@tcp(127.0.0.1:3306)/ppanel?charset=utf8mb4&parseTime=true" + +CacheRedis: + Host: 127.0.0.1:6379 + Type: node + +# 注意:RPC 服务我们推荐直连注册中心 Etcd(生产环境),但本地开发为了省事可以使用直连(Direct) +# 目前暂不配置 Etcd,由调用方通过 target: "127.0.0.1:8083" 直连 diff --git a/apps/rpc/core/etc/core-prod.yaml b/apps/rpc/core/etc/core-prod.yaml new file mode 100644 index 0000000..934e55c --- /dev/null +++ b/apps/rpc/core/etc/core-prod.yaml @@ -0,0 +1,30 @@ +Name: core.rpc +ListenOn: 0.0.0.0:8083 +Mode: dev + +Log: + Mode: console + Encoding: plain + Level: debug + +Telemetry: + Name: core.rpc + Endpoint: 127.0.0.1:4318 + Sampler: 1.0 + Batcher: otlphttp + +DevServer: + Enabled: true + Port: 6163 + EnableMetrics: true + EnablePprof: true + +MySQL: + DataSource: "root:password@tcp(127.0.0.1:3306)/ppanel?charset=utf8mb4&parseTime=true" + +CacheRedis: + Host: 127.0.0.1:6379 + Type: node + +# 注意:RPC 服务我们推荐直连注册中心 Etcd(生产环境),但本地开发为了省事可以使用直连(Direct) +# 目前暂不配置 Etcd,由调用方通过 target: "127.0.0.1:8083" 直连 diff --git a/apps/rpc/core/etc/core-test.yaml b/apps/rpc/core/etc/core-test.yaml new file mode 100644 index 0000000..934e55c --- /dev/null +++ b/apps/rpc/core/etc/core-test.yaml @@ -0,0 +1,30 @@ +Name: core.rpc +ListenOn: 0.0.0.0:8083 +Mode: dev + +Log: + Mode: console + Encoding: plain + Level: debug + +Telemetry: + Name: core.rpc + Endpoint: 127.0.0.1:4318 + Sampler: 1.0 + Batcher: otlphttp + +DevServer: + Enabled: true + Port: 6163 + EnableMetrics: true + EnablePprof: true + +MySQL: + DataSource: "root:password@tcp(127.0.0.1:3306)/ppanel?charset=utf8mb4&parseTime=true" + +CacheRedis: + Host: 127.0.0.1:6379 + Type: node + +# 注意:RPC 服务我们推荐直连注册中心 Etcd(生产环境),但本地开发为了省事可以使用直连(Direct) +# 目前暂不配置 Etcd,由调用方通过 target: "127.0.0.1:8083" 直连 diff --git a/apps/rpc/core/internal/config/config.go b/apps/rpc/core/internal/config/config.go new file mode 100755 index 0000000..50a3e70 --- /dev/null +++ b/apps/rpc/core/internal/config/config.go @@ -0,0 +1,15 @@ +package config + +import ( + "github.com/zeromicro/go-zero/core/stores/redis" + "github.com/zeromicro/go-zero/zrpc" +) + +type Config struct { + zrpc.RpcServerConf + + MySQL struct { + DataSource string + } + CacheRedis redis.RedisConf +} diff --git a/apps/rpc/core/internal/logic/getNodeInfoLogic.go b/apps/rpc/core/internal/logic/getNodeInfoLogic.go new file mode 100644 index 0000000..1e88225 --- /dev/null +++ b/apps/rpc/core/internal/logic/getNodeInfoLogic.go @@ -0,0 +1,31 @@ +package logic + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/rpc/core/core" + "github.com/zero-ppanel/zero-ppanel/apps/rpc/core/internal/svc" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetNodeInfoLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewGetNodeInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetNodeInfoLogic { + return &GetNodeInfoLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +// 节点相关 +func (l *GetNodeInfoLogic) GetNodeInfo(in *core.GetNodeInfoReq) (*core.GetNodeInfoResp, error) { + // todo: add your logic here and delete this line + + return &core.GetNodeInfoResp{}, nil +} diff --git a/apps/rpc/core/internal/logic/getUserInfoLogic.go b/apps/rpc/core/internal/logic/getUserInfoLogic.go new file mode 100644 index 0000000..8a25f73 --- /dev/null +++ b/apps/rpc/core/internal/logic/getUserInfoLogic.go @@ -0,0 +1,31 @@ +package logic + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/rpc/core/core" + "github.com/zero-ppanel/zero-ppanel/apps/rpc/core/internal/svc" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetUserInfoLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewGetUserInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserInfoLogic { + return &GetUserInfoLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +// 用户相关 +func (l *GetUserInfoLogic) GetUserInfo(in *core.GetUserInfoReq) (*core.GetUserInfoResp, error) { + // todo: add your logic here and delete this line + + return &core.GetUserInfoResp{}, nil +} diff --git a/apps/rpc/core/internal/logic/pingLogic.go b/apps/rpc/core/internal/logic/pingLogic.go new file mode 100644 index 0000000..81959d8 --- /dev/null +++ b/apps/rpc/core/internal/logic/pingLogic.go @@ -0,0 +1,35 @@ +package logic + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/rpc/core/core" + "github.com/zero-ppanel/zero-ppanel/apps/rpc/core/internal/svc" + + "github.com/zeromicro/go-zero/core/logx" +) + +type PingLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewPingLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PingLogic { + return &PingLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +// Ping 检查服务健康状态 +func (l *PingLogic) Ping(in *core.Empty) (*core.BasicResponse, error) { + // 记录一行日志,这样我们能在 Jaeger 和控制台看到追踪信息 + l.Logger.Info("Received Ping request from BFF") + + return &core.BasicResponse{ + Code: 200, + Msg: "pong from core-rpc", + }, nil +} diff --git a/apps/rpc/core/internal/server/coreServer.go b/apps/rpc/core/internal/server/coreServer.go new file mode 100644 index 0000000..354144d --- /dev/null +++ b/apps/rpc/core/internal/server/coreServer.go @@ -0,0 +1,42 @@ +// Code generated by goctl. DO NOT EDIT. +// goctl 1.9.2 +// Source: core.proto + +package server + +import ( + "context" + + "github.com/zero-ppanel/zero-ppanel/apps/rpc/core/core" + "github.com/zero-ppanel/zero-ppanel/apps/rpc/core/internal/logic" + "github.com/zero-ppanel/zero-ppanel/apps/rpc/core/internal/svc" +) + +type CoreServer struct { + svcCtx *svc.ServiceContext + core.UnimplementedCoreServer +} + +func NewCoreServer(svcCtx *svc.ServiceContext) *CoreServer { + return &CoreServer{ + svcCtx: svcCtx, + } +} + +// Ping 检查服务健康状态 +func (s *CoreServer) Ping(ctx context.Context, in *core.Empty) (*core.BasicResponse, error) { + l := logic.NewPingLogic(ctx, s.svcCtx) + return l.Ping(in) +} + +// 用户相关 +func (s *CoreServer) GetUserInfo(ctx context.Context, in *core.GetUserInfoReq) (*core.GetUserInfoResp, error) { + l := logic.NewGetUserInfoLogic(ctx, s.svcCtx) + return l.GetUserInfo(in) +} + +// 节点相关 +func (s *CoreServer) GetNodeInfo(ctx context.Context, in *core.GetNodeInfoReq) (*core.GetNodeInfoResp, error) { + l := logic.NewGetNodeInfoLogic(ctx, s.svcCtx) + return l.GetNodeInfo(in) +} diff --git a/apps/rpc/core/internal/svc/serviceContext.go b/apps/rpc/core/internal/svc/serviceContext.go new file mode 100644 index 0000000..1a421b8 --- /dev/null +++ b/apps/rpc/core/internal/svc/serviceContext.go @@ -0,0 +1,13 @@ +package svc + +import "github.com/zero-ppanel/zero-ppanel/apps/rpc/core/internal/config" + +type ServiceContext struct { + Config config.Config +} + +func NewServiceContext(c config.Config) *ServiceContext { + return &ServiceContext{ + Config: c, + } +} diff --git a/apps/scheduler/etc/scheduler-dev.yaml b/apps/scheduler/etc/scheduler-dev.yaml new file mode 100644 index 0000000..9477cb5 --- /dev/null +++ b/apps/scheduler/etc/scheduler-dev.yaml @@ -0,0 +1,23 @@ +Name: zero-ppanel-scheduler +Mode: dev + +Log: + Mode: console + Encoding: plain + Level: debug + +Telemetry: + Name: zero-ppanel-scheduler + Endpoint: 127.0.0.1:4318 + Sampler: 1.0 + Batcher: otlphttp + +MySQL: + DataSource: "root:password@tcp(127.0.0.1:3306)/ppanel?charset=utf8mb4&parseTime=true" + +Redis: + Host: 127.0.0.1:6379 + Type: node + +Asynq: + Addr: 127.0.0.1:6379 diff --git a/apps/scheduler/etc/scheduler-prod.yaml b/apps/scheduler/etc/scheduler-prod.yaml new file mode 100644 index 0000000..89c4407 --- /dev/null +++ b/apps/scheduler/etc/scheduler-prod.yaml @@ -0,0 +1,28 @@ +Name: zero-ppanel-scheduler +Mode: pro + +Log: + Mode: file + Encoding: json + Level: info + Path: /var/log/zero-ppanel/scheduler + KeepDays: 15 + Rotation: daily + +Telemetry: + Name: zero-ppanel-scheduler + Endpoint: http://jaeger:4318/v1/traces + Sampler: 0.1 + Batcher: otlphttp + +MySQL: + DataSource: "${MYSQL_DSN}" + +Redis: + Host: "${REDIS_HOST}" + Type: node + Pass: "${REDIS_PASS}" + +Asynq: + Addr: "${REDIS_HOST}" + Pass: "${REDIS_PASS}" diff --git a/apps/scheduler/etc/scheduler-test.yaml b/apps/scheduler/etc/scheduler-test.yaml new file mode 100644 index 0000000..465160e --- /dev/null +++ b/apps/scheduler/etc/scheduler-test.yaml @@ -0,0 +1,25 @@ +Name: zero-ppanel-scheduler +Mode: test + +Log: + Mode: file + Encoding: json + Level: info + Path: logs/scheduler + KeepDays: 7 + +Telemetry: + Name: zero-ppanel-scheduler + Endpoint: http://jaeger:4318/v1/traces + Sampler: 0.5 + Batcher: otlphttp + +MySQL: + DataSource: "root:password@tcp(mysql:3306)/ppanel?charset=utf8mb4&parseTime=true" + +Redis: + Host: redis:6379 + Type: node + +Asynq: + Addr: redis:6379 diff --git a/apps/scheduler/internal/config/config.go b/apps/scheduler/internal/config/config.go new file mode 100644 index 0000000..6ed8263 --- /dev/null +++ b/apps/scheduler/internal/config/config.go @@ -0,0 +1,30 @@ +package config + +import ( + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/core/trace" +) + +type Config struct { + Name string + Mode string `json:",default=pro"` + + Log logx.LogConf + + Telemetry trace.Config `json:",optional"` + + MySQL struct { + DataSource string + } + + Redis struct { + Host string + Type string + Pass string `json:",optional"` + } + + Asynq struct { + Addr string + Pass string `json:",optional"` + } +} diff --git a/apps/scheduler/internal/handler/.gitkeep b/apps/scheduler/internal/handler/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/apps/scheduler/internal/logic/.gitkeep b/apps/scheduler/internal/logic/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/apps/scheduler/internal/svc/servicecontext.go b/apps/scheduler/internal/svc/servicecontext.go new file mode 100644 index 0000000..1578800 --- /dev/null +++ b/apps/scheduler/internal/svc/servicecontext.go @@ -0,0 +1,15 @@ +package svc + +import ( + "github.com/zero-ppanel/zero-ppanel/apps/scheduler/internal/config" +) + +type ServiceContext struct { + Config config.Config +} + +func NewServiceContext(c config.Config) *ServiceContext { + return &ServiceContext{ + Config: c, + } +} diff --git a/apps/scheduler/internal/types/types.go b/apps/scheduler/internal/types/types.go new file mode 100644 index 0000000..e4a5c50 --- /dev/null +++ b/apps/scheduler/internal/types/types.go @@ -0,0 +1,8 @@ +package types + +const ( + SchedulerTrafficStats = "scheduler:traffic_stats" + SchedulerExpireCheck = "scheduler:expire_check" + SchedulerExchangeRate = "scheduler:exchange_rate" + SchedulerCleanupLogs = "scheduler:cleanup_logs" +) diff --git a/apps/scheduler/scheduler.go b/apps/scheduler/scheduler.go new file mode 100644 index 0000000..27ef55f --- /dev/null +++ b/apps/scheduler/scheduler.go @@ -0,0 +1,51 @@ +package main + +import ( + "flag" + "fmt" + "time" + + "github.com/hibiken/asynq" + "github.com/zero-ppanel/zero-ppanel/apps/scheduler/internal/config" + "github.com/zero-ppanel/zero-ppanel/apps/scheduler/internal/types" + "github.com/zeromicro/go-zero/core/conf" + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/core/trace" +) + +var configFile = flag.String("f", "etc/scheduler-dev.yaml", "the config file") + +func main() { + flag.Parse() + + var c config.Config + conf.MustLoad(*configFile, &c) + + logx.MustSetup(c.Log) + if c.Telemetry.Name != "" { + trace.StartAgent(c.Telemetry) + } + + location, _ := time.LoadLocation("Asia/Shanghai") + scheduler := asynq.NewScheduler( + asynq.RedisClientOpt{Addr: c.Asynq.Addr, Password: c.Asynq.Pass}, + &asynq.SchedulerOpts{Location: location}, + ) + + // Traffic stats: every 5 minutes + scheduler.Register("*/5 * * * *", asynq.NewTask(types.SchedulerTrafficStats, nil)) + + // Expire check: every hour + scheduler.Register("0 * * * *", asynq.NewTask(types.SchedulerExpireCheck, nil)) + + // Exchange rate: every day at 01:00 + scheduler.Register("0 1 * * *", asynq.NewTask(types.SchedulerExchangeRate, nil), asynq.MaxRetry(3)) + + // Cleanup logs: every day at 03:00 + scheduler.Register("0 3 * * *", asynq.NewTask(types.SchedulerCleanupLogs, nil)) + + fmt.Println("Starting zero-ppanel-scheduler...") + if err := scheduler.Run(); err != nil { + logx.Must(err) + } +} diff --git a/deploy/Dockerfile.admin b/deploy/Dockerfile.admin new file mode 100644 index 0000000..db588d5 --- /dev/null +++ b/deploy/Dockerfile.admin @@ -0,0 +1,19 @@ +FROM golang:1.23-alpine AS builder + +WORKDIR /app +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . +RUN CGO_ENABLED=0 go build -trimpath -o /ppanel-admin ./apps/admin/admin.go + +FROM alpine:3.19 +RUN apk add --no-cache ca-certificates tzdata +ENV TZ=Asia/Shanghai + +WORKDIR /app +COPY --from=builder /ppanel-admin . +COPY apps/admin/etc /app/etc + +EXPOSE 8081 +CMD ["./ppanel-admin", "-f", "etc/admin.yaml"] diff --git a/deploy/Dockerfile.api b/deploy/Dockerfile.api new file mode 100644 index 0000000..6a97452 --- /dev/null +++ b/deploy/Dockerfile.api @@ -0,0 +1,19 @@ +FROM golang:1.23-alpine AS builder + +WORKDIR /app +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . +RUN CGO_ENABLED=0 go build -trimpath -o /ppanel-api ./apps/api/api.go + +FROM alpine:3.19 +RUN apk add --no-cache ca-certificates tzdata +ENV TZ=Asia/Shanghai + +WORKDIR /app +COPY --from=builder /ppanel-api . +COPY apps/api/etc /app/etc + +EXPOSE 8080 +CMD ["./ppanel-api", "-f", "etc/api.yaml"] diff --git a/deploy/Dockerfile.node b/deploy/Dockerfile.node new file mode 100644 index 0000000..17a9398 --- /dev/null +++ b/deploy/Dockerfile.node @@ -0,0 +1,19 @@ +FROM golang:1.23-alpine AS builder + +WORKDIR /app +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . +RUN CGO_ENABLED=0 go build -trimpath -o /ppanel-node ./apps/node/node.go + +FROM alpine:3.19 +RUN apk add --no-cache ca-certificates tzdata +ENV TZ=Asia/Shanghai + +WORKDIR /app +COPY --from=builder /ppanel-node . +COPY apps/node/etc /app/etc + +EXPOSE 8082 +CMD ["./ppanel-node", "-f", "etc/node.yaml"] diff --git a/deploy/Dockerfile.queue b/deploy/Dockerfile.queue new file mode 100644 index 0000000..07ed755 --- /dev/null +++ b/deploy/Dockerfile.queue @@ -0,0 +1,18 @@ +FROM golang:1.23-alpine AS builder + +WORKDIR /app +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . +RUN CGO_ENABLED=0 go build -trimpath -o /ppanel-queue ./apps/queue/queue.go + +FROM alpine:3.19 +RUN apk add --no-cache ca-certificates tzdata +ENV TZ=Asia/Shanghai + +WORKDIR /app +COPY --from=builder /ppanel-queue . +COPY apps/queue/etc /app/etc + +CMD ["./ppanel-queue", "-f", "etc/queue.yaml"] diff --git a/deploy/Dockerfile.scheduler b/deploy/Dockerfile.scheduler new file mode 100644 index 0000000..d7d4648 --- /dev/null +++ b/deploy/Dockerfile.scheduler @@ -0,0 +1,18 @@ +FROM golang:1.23-alpine AS builder + +WORKDIR /app +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . +RUN CGO_ENABLED=0 go build -trimpath -o /ppanel-scheduler ./apps/scheduler/scheduler.go + +FROM alpine:3.19 +RUN apk add --no-cache ca-certificates tzdata +ENV TZ=Asia/Shanghai + +WORKDIR /app +COPY --from=builder /ppanel-scheduler . +COPY apps/scheduler/etc /app/etc + +CMD ["./ppanel-scheduler", "-f", "etc/scheduler.yaml"] diff --git a/deploy/docker-compose-env.yml b/deploy/docker-compose-env.yml new file mode 100644 index 0000000..c8d7b7a --- /dev/null +++ b/deploy/docker-compose-env.yml @@ -0,0 +1,55 @@ +version: '3.8' + +services: + # Infrastructure + mysql: + image: mysql:8.0 + ports: + - "3306:3306" + environment: + MYSQL_ROOT_PASSWORD: password + MYSQL_DATABASE: ppanel + volumes: + - mysql_data:/var/lib/mysql + - ../sql:/docker-entrypoint-initdb.d + + redis: + image: redis:7-alpine + ports: + - "6379:6379" + volumes: + - redis_data:/data + + # Observability + jaeger: + image: jaegertracing/all-in-one:1.57 + ports: + - "16686:16686" + - "4317:4317" + - "4318:4318" + - "14268:14268" + environment: + COLLECTOR_OTLP_ENABLED: "true" + COLLECTOR_OTLP_HTTP_HOST_PORT: "0.0.0.0:4318" + COLLECTOR_OTLP_GRPC_HOST_PORT: "0.0.0.0:4317" + + prometheus: + image: prom/prometheus:v2.51.0 + ports: + - "9090:9090" + volumes: + - ./prometheus.yml:/etc/prometheus/prometheus.yml + + grafana: + image: grafana/grafana:10.4.0 + ports: + - "3000:3000" + environment: + GF_SECURITY_ADMIN_PASSWORD: admin + depends_on: + - prometheus + - jaeger + +volumes: + mysql_data: + redis_data: diff --git a/deploy/docker-compose.cloud.yml b/deploy/docker-compose.cloud.yml new file mode 100644 index 0000000..43a834e --- /dev/null +++ b/deploy/docker-compose.cloud.yml @@ -0,0 +1,67 @@ +# 云端部署用 docker-compose +# 镜像由 CI 预先构建并推送到镜像仓库 +# 本地基础设施 (mysql/redis) 需提前独立部署 + +version: '3.8' + +services: + ppanel-api: + image: ${PPANEL_REPO}/ppanel-api:${PPANEL_TAG:-latest} + restart: unless-stopped + ports: + - "8080:8080" + volumes: + - ./etc/api:/app/etc + logging: + driver: json-file + options: + max-size: "50m" + max-file: "3" + + ppanel-admin: + image: ${PPANEL_REPO}/ppanel-admin:${PPANEL_TAG:-latest} + restart: unless-stopped + ports: + - "8081:8081" + volumes: + - ./etc/admin:/app/etc + logging: + driver: json-file + options: + max-size: "50m" + max-file: "3" + + ppanel-node: + image: ${PPANEL_REPO}/ppanel-node:${PPANEL_TAG:-latest} + restart: unless-stopped + ports: + - "8082:8082" + volumes: + - ./etc/node:/app/etc + logging: + driver: json-file + options: + max-size: "50m" + max-file: "3" + + ppanel-queue: + image: ${PPANEL_REPO}/ppanel-queue:${PPANEL_TAG:-latest} + restart: unless-stopped + volumes: + - ./etc/queue:/app/etc + logging: + driver: json-file + options: + max-size: "50m" + max-file: "3" + + ppanel-scheduler: + image: ${PPANEL_REPO}/ppanel-scheduler:${PPANEL_TAG:-latest} + restart: unless-stopped + volumes: + - ./etc/scheduler:/app/etc + logging: + driver: json-file + options: + max-size: "50m" + max-file: "3" diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml new file mode 100644 index 0000000..066d753 --- /dev/null +++ b/deploy/docker-compose.yml @@ -0,0 +1,119 @@ +version: '3.8' + +services: + ppanel-api: + build: + context: .. + dockerfile: deploy/Dockerfile.api + ports: + - "8080:8080" + - "6160:6160" + depends_on: + - mysql + - redis + - jaeger + volumes: + - ../apps/api/etc:/app/etc + + ppanel-admin: + build: + context: .. + dockerfile: deploy/Dockerfile.admin + ports: + - "8081:8081" + - "6161:6161" + depends_on: + - mysql + - redis + - jaeger + volumes: + - ../apps/admin/etc:/app/etc + + ppanel-node: + build: + context: .. + dockerfile: deploy/Dockerfile.node + ports: + - "8082:8082" + - "6162:6162" + depends_on: + - mysql + - redis + - jaeger + volumes: + - ../apps/node/etc:/app/etc + deploy: + replicas: 2 + + ppanel-queue: + build: + context: .. + dockerfile: deploy/Dockerfile.queue + depends_on: + - mysql + - redis + - jaeger + volumes: + - ../apps/queue/etc:/app/etc + + ppanel-scheduler: + build: + context: .. + dockerfile: deploy/Dockerfile.scheduler + depends_on: + - mysql + - redis + - jaeger + volumes: + - ../apps/scheduler/etc:/app/etc + + # Infrastructure + mysql: + image: mysql:8.0 + ports: + - "3306:3306" + environment: + MYSQL_ROOT_PASSWORD: password + MYSQL_DATABASE: ppanel + volumes: + - mysql_data:/var/lib/mysql + - ../sql:/docker-entrypoint-initdb.d + + redis: + image: redis:7-alpine + ports: + - "6379:6379" + volumes: + - redis_data:/data + + # Observability + jaeger: + image: jaegertracing/all-in-one:1.57 + ports: + - "16686:16686" + - "4317:4317" + - "4318:4318" + - "14268:14268" + environment: + COLLECTOR_OTLP_ENABLED: "true" + + prometheus: + image: prom/prometheus:v2.51.0 + ports: + - "9090:9090" + volumes: + - ./prometheus.yml:/etc/prometheus/prometheus.yml + + grafana: + image: grafana/grafana:10.4.0 + ports: + - "3000:3000" + environment: + GF_SECURITY_ADMIN_PASSWORD: admin + depends_on: + - prometheus + - jaeger + +volumes: + mysql_data: + redis_data: diff --git a/deploy/prometheus.yml b/deploy/prometheus.yml new file mode 100644 index 0000000..054cb10 --- /dev/null +++ b/deploy/prometheus.yml @@ -0,0 +1,22 @@ +global: + scrape_interval: 15s + evaluation_interval: 15s + +scrape_configs: + # 注意:在 Docker-compose (Mac) 中访问宿主机的服务,请使用 host.docker.internal + # 因为我们开发时,服务是直接跑在宿主机的 go run 上 + - job_name: "zero-ppanel-api" + static_configs: + - targets: ["host.docker.internal:6160"] + + - job_name: "zero-ppanel-admin" + static_configs: + - targets: ["host.docker.internal:6161"] + + - job_name: "zero-ppanel-node" + static_configs: + - targets: ["host.docker.internal:6162"] + + - job_name: "zero-ppanel-rpc-core" + static_configs: + - targets: ["host.docker.internal:6163"] diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..3c06e77 --- /dev/null +++ b/go.mod @@ -0,0 +1,94 @@ +module github.com/zero-ppanel/zero-ppanel + +go 1.23 + +require ( + github.com/golang-jwt/jwt/v5 v5.2.1 + github.com/hibiken/asynq v0.25.1 + github.com/zeromicro/go-zero v1.7.6 + google.golang.org/grpc v1.65.0 + google.golang.org/protobuf v1.36.1 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/coreos/go-semver v0.3.1 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/fatih/color v1.18.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.4 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.1 // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/openzipkin/zipkin-go v0.4.3 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/prometheus/client_golang v1.20.5 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/redis/go-redis/v9 v9.7.0 // indirect + github.com/robfig/cron/v3 v3.0.1 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/spf13/cast v1.7.0 // indirect + go.etcd.io/etcd/api/v3 v3.5.15 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.15 // indirect + go.etcd.io/etcd/client/v3 v3.5.15 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/zipkin v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/atomic v1.10.0 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/term v0.27.0 // indirect + golang.org/x/text v0.21.0 // indirect + golang.org/x/time v0.8.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/api v0.29.3 // indirect + k8s.io/apimachinery v0.29.4 // indirect + k8s.io/client-go v0.29.3 // indirect + k8s.io/klog/v2 v2.110.1 // indirect + k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..4029aac --- /dev/null +++ b/go.sum @@ -0,0 +1,287 @@ +github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 h1:uvdUDbHQHO85qeSydJtItA4T55Pw6BtAejd0APRJOCE= +github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= +github.com/alicebob/miniredis/v2 v2.34.0 h1:mBFWMaJSNL9RwdGRyEDoAAv8OQc5UlEhLDQggTglU/0= +github.com/alicebob/miniredis/v2 v2.34.0/go.mod h1:kWShP4b58T1CW0Y5dViCd5ztzrDqRWqM3nksiyXk5s8= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +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/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +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/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= +github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +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.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= +github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= +github.com/hibiken/asynq v0.25.1 h1:phj028N0nm15n8O2ims+IvJ2gz4k2auvermngh9JhTw= +github.com/hibiken/asynq v0.25.1/go.mod h1:pazWNOLBu0FEynQRBvHA26qdIKRSmfdIfUm4HdsLmXg= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +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/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +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/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= +github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg= +github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= +github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= +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.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +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/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +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.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= +github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= +github.com/zeromicro/go-zero v1.7.6 h1:SArK4xecdrpVY3ZFJcbc0IZCx+NuWyHNjCv9f1+Gwrc= +github.com/zeromicro/go-zero v1.7.6/go.mod h1:SmGykRm5e0Z4CGNj+GaSKDffaHzQV56fel0FkymTLlE= +go.etcd.io/etcd/api/v3 v3.5.15 h1:3KpLJir1ZEBrYuV2v+Twaa/e2MdDCEZ/70H+lzEiwsk= +go.etcd.io/etcd/api/v3 v3.5.15/go.mod h1:N9EhGzXq58WuMllgH9ZvnEr7SI9pS0k0+DHZezGp7jM= +go.etcd.io/etcd/client/pkg/v3 v3.5.15 h1:fo0HpWz/KlHGMCC+YejpiCmyWDEuIpnTDzpJLB5fWlA= +go.etcd.io/etcd/client/pkg/v3 v3.5.15/go.mod h1:mXDI4NAOwEiszrHCb0aqfAYNCrZP4e9hRca3d1YK8EU= +go.etcd.io/etcd/client/v3 v3.5.15 h1:23M0eY4Fd/inNv1ZfU3AxrbbOdW79r9V9Rl62Nm6ip4= +go.etcd.io/etcd/client/v3 v3.5.15/go.mod h1:CLSJxrYjvLtHsrPKsy7LmZEE+DK2ktfd2bN4RhBMwlU= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4= +go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 h1:s0PHtIkN+3xrbDOpt2M8OTG92cWqUESvzh2MxiR5xY8= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0/go.mod h1:hZlFbDbRt++MMPCCfSJfmhkGIWnX1h3XjkfxZUjLrIA= +go.opentelemetry.io/otel/exporters/zipkin v1.24.0 h1:3evrL5poBuh1KF51D9gO/S+N/1msnm4DaBqs/rpXUqY= +go.opentelemetry.io/otel/exporters/zipkin v1.24.0/go.mod h1:0EHgD8R0+8yRhUYJOGR8Hfg2dpiJQxDOszd5smVO9wM= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +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/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +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-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +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-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.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.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +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.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +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/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= +google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= +google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +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/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY= +gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +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= +k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= +k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= +k8s.io/apimachinery v0.29.4 h1:RaFdJiDmuKs/8cm1M6Dh1Kvyh59YQFDcFuFTSmXes6Q= +k8s.io/apimachinery v0.29.4/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y= +k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= +k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= +k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= +k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +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/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/pkg/constant/context_key.go b/pkg/constant/context_key.go new file mode 100644 index 0000000..a598f11 --- /dev/null +++ b/pkg/constant/context_key.go @@ -0,0 +1,8 @@ +package constant + +const ( + KeyUserId = "user_id" + KeyLoginType = "login_type" + KeyIsAdmin = "is_admin" + KeyJwtUserId = "jwtUserId" +) diff --git a/pkg/jwtx/jwt.go b/pkg/jwtx/jwt.go new file mode 100644 index 0000000..2df41bd --- /dev/null +++ b/pkg/jwtx/jwt.go @@ -0,0 +1,40 @@ +package jwtx + +import ( + "time" + + "github.com/golang-jwt/jwt/v5" +) + +type Claims struct { + UserId int64 `json:"user_id"` + LoginType string `json:"login_type"` + IsAdmin bool `json:"is_admin"` + jwt.RegisteredClaims +} + +func GenerateToken(secret string, userId int64, isAdmin bool, expire int64) (string, error) { + claims := Claims{ + UserId: userId, + IsAdmin: isAdmin, + RegisteredClaims: jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(expire) * time.Second)), + IssuedAt: jwt.NewNumericDate(time.Now()), + }, + } + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + return token.SignedString([]byte(secret)) +} + +func ParseToken(tokenStr string, secret string) (*Claims, error) { + token, err := jwt.ParseWithClaims(tokenStr, &Claims{}, func(token *jwt.Token) (interface{}, error) { + return []byte(secret), nil + }) + if err != nil { + return nil, err + } + if claims, ok := token.Claims.(*Claims); ok && token.Valid { + return claims, nil + } + return nil, jwt.ErrSignatureInvalid +} diff --git a/pkg/result/errorhandler.go b/pkg/result/errorhandler.go new file mode 100644 index 0000000..250aedc --- /dev/null +++ b/pkg/result/errorhandler.go @@ -0,0 +1,7 @@ +package result + +import "net/http" + +func ErrorHandler(err error) (int, any) { + return http.StatusOK, Error(1001, err.Error()) +} diff --git a/pkg/result/response.go b/pkg/result/response.go new file mode 100644 index 0000000..d93d9f3 --- /dev/null +++ b/pkg/result/response.go @@ -0,0 +1,25 @@ +package result + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" +) + +type Response struct { + Code int `json:"code"` + Msg string `json:"msg"` + Data interface{} `json:"data"` +} + +func Success(data interface{}) *Response { + return &Response{Code: 0, Msg: "success", Data: data} +} + +func Error(code int, msg string) *Response { + return &Response{Code: code, Msg: msg, Data: nil} +} + +func OkJson(w http.ResponseWriter, data interface{}) { + httpx.OkJson(w, Success(data)) +} diff --git a/pkg/xerr/errcode.go b/pkg/xerr/errcode.go new file mode 100644 index 0000000..d37dbe6 --- /dev/null +++ b/pkg/xerr/errcode.go @@ -0,0 +1,22 @@ +package xerr + +const ( + OK = 0 + ServerError = 1001 + ParamError = 1002 + TokenExpire = 1003 + TokenEmpty = 1004 + InvalidAccess = 1005 + DatabaseQueryError = 1006 + DatabaseInsertError = 1007 + DatabaseUpdateError = 1008 + DatabaseDeleteError = 1009 + UserNotFound = 2001 + UserDisabled = 2002 + PasswordError = 2003 + OrderNotFound = 3001 + OrderExpired = 3002 + PaymentFailed = 4001 + SubscribeExpired = 5001 + NodeAuthFailed = 6001 +) diff --git a/pkg/xerr/errmsg.go b/pkg/xerr/errmsg.go new file mode 100644 index 0000000..eed3d84 --- /dev/null +++ b/pkg/xerr/errmsg.go @@ -0,0 +1,29 @@ +package xerr + +var codeText = map[int]string{ + OK: "success", + ServerError: "服务器错误", + ParamError: "参数错误", + TokenExpire: "Token已过期", + TokenEmpty: "Token为空", + InvalidAccess: "无效访问", + DatabaseQueryError: "数据库查询错误", + DatabaseInsertError: "数据库插入错误", + DatabaseUpdateError: "数据库更新错误", + DatabaseDeleteError: "数据库删除错误", + UserNotFound: "用户不存在", + UserDisabled: "用户已禁用", + PasswordError: "密码错误", + OrderNotFound: "订单不存在", + OrderExpired: "订单已过期", + PaymentFailed: "支付失败", + SubscribeExpired: "订阅已过期", + NodeAuthFailed: "节点认证失败", +} + +func MapErrMsg(code int) string { + if msg, ok := codeText[code]; ok { + return msg + } + return "未知错误" +} diff --git a/sql/001_init.down.sql b/sql/001_init.down.sql new file mode 100644 index 0000000..ccf0da7 --- /dev/null +++ b/sql/001_init.down.sql @@ -0,0 +1,7 @@ +-- PPanel Database Schema Rollback +-- Migration: 001_init +-- Description: Drop all tables from initial schema + +DROP TABLE IF EXISTS `user`; + +-- TODO: Add remaining DROP TABLE statements (in reverse order of creation) diff --git a/sql/001_init.up.sql b/sql/001_init.up.sql new file mode 100644 index 0000000..4e95c1f --- /dev/null +++ b/sql/001_init.up.sql @@ -0,0 +1,40 @@ +-- PPanel Database Schema +-- Migration: 001_init +-- Description: Initial database schema + +-- ============================================================ +-- User Domain +-- ============================================================ + +CREATE TABLE IF NOT EXISTS `user` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT, + `email` varchar(255) DEFAULT NULL, + `telephone` varchar(32) DEFAULT NULL, + `password` varchar(255) NOT NULL DEFAULT '', + `refer_code` varchar(32) DEFAULT NULL, + `refer_id` bigint unsigned DEFAULT 0, + `avatar` varchar(512) DEFAULT '', + `balance` bigint DEFAULT 0, + `commission` bigint DEFAULT 0, + `gift_amount` bigint DEFAULT 0, + `is_admin` tinyint(1) NOT NULL DEFAULT 0, + `is_staff` tinyint(1) NOT NULL DEFAULT 0, + `enable` tinyint(1) NOT NULL DEFAULT 1, + `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `idx_email` (`email`), + UNIQUE KEY `idx_telephone` (`telephone`), + UNIQUE KEY `idx_refer_code` (`refer_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- TODO: Add remaining tables +-- user_auth_methods, user_device, user_subscribe, user_balance_log, +-- user_commission_log, user_subscribe_log, user_login_log, +-- user_device_online_record, user_gift_amount_log, user_reset_subscribe_log +-- order, coupon, ticket, ticket_follow +-- payment, announcement, document +-- system, server, server_group, server_rule_group +-- subscribe, subscribe_group, subscribe_type, subscribe_application +-- ads, application, application_config, application_version +-- traffic_log, system_logs