From 4f1a56e66c747db13f2c21c3b5cee859506c53e1 Mon Sep 17 00:00:00 2001 From: ssongliu <73214554+ssongliu@users.noreply.github.com> Date: Tue, 21 Jan 2025 18:32:14 +0800 Subject: [PATCH] feat: merge code from dev (#7750) --- agent/app/api/v2/app.go | 19 +- agent/app/api/v2/app_install.go | 32 +- agent/app/api/v2/backup.go | 51 +- agent/app/api/v2/clam.go | 33 +- agent/app/api/v2/compose_template.go | 11 +- agent/app/api/v2/container.go | 69 +- agent/app/api/v2/cronjob.go | 25 +- agent/app/api/v2/dashboard.go | 11 +- agent/app/api/v2/database.go | 17 +- agent/app/api/v2/database_common.go | 7 +- agent/app/api/v2/database_mysql.go | 30 +- agent/app/api/v2/database_postgresql.go | 23 +- agent/app/api/v2/database_redis.go | 13 +- agent/app/api/v2/device.go | 30 +- agent/app/api/v2/docker.go | 18 +- agent/app/api/v2/fail2ban.go | 17 +- agent/app/api/v2/favorite.go | 7 +- agent/app/api/v2/file.go | 53 +- agent/app/api/v2/firewall.go | 30 +- agent/app/api/v2/ftp.go | 10 +- agent/app/api/v2/host_tool.go | 24 +- agent/app/api/v2/image.go | 22 +- agent/app/api/v2/image_repo.go | 14 +- agent/app/api/v2/logs.go | 6 +- agent/app/api/v2/monitor.go | 12 +- agent/app/api/v2/nginx.go | 16 +- agent/app/api/v2/php_extensions.go | 6 +- agent/app/api/v2/process.go | 1 + agent/app/api/v2/recycle_bin.go | 8 +- agent/app/api/v2/runtime.go | 46 +- agent/app/api/v2/setting.go | 8 +- agent/app/api/v2/snapshot.go | 25 +- agent/app/api/v2/ssh.go | 21 +- agent/app/api/v2/task.go | 2 + agent/app/api/v2/website.go | 90 +- agent/app/api/v2/website_acme_account.go | 5 +- agent/app/api/v2/website_ca.go | 7 + agent/app/api/v2/website_dns_account.go | 10 +- agent/app/api/v2/website_domain.go | 7 +- agent/app/api/v2/website_ssl.go | 22 +- agent/app/dto/alert.go | 20 + agent/app/dto/clam.go | 5 + agent/app/dto/cronjob.go | 9 + agent/app/service/clam.go | 70 +- agent/app/service/container.go | 3 +- agent/app/service/cronjob.go | 48 +- agent/app/service/cronjob_helper.go | 17 + agent/app/service/dashboard.go | 5 +- agent/app/service/docker.go | 17 + agent/app/service/file.go | 12 +- agent/app/service/monitor.go | 17 +- agent/constant/alert.go | 11 + agent/constant/errs.go | 10 + agent/i18n/i18n.go | 7 + agent/i18n/lang/en.yaml | 8 + agent/i18n/lang/fa.yaml | 63 + agent/i18n/lang/ja.yaml | 283 ++ agent/i18n/lang/ko.yaml | 286 ++ agent/i18n/lang/ms.yml | 285 ++ agent/i18n/lang/pt-BR.yaml | 283 ++ agent/i18n/lang/pt.yaml | 63 + agent/i18n/lang/ru.yaml | 286 ++ agent/i18n/lang/zh-Hant.yaml | 12 + agent/i18n/lang/zh.yaml | 109 +- agent/init/hook/hook.go | 39 +- agent/utils/common/common.go | 27 +- agent/utils/files/file_op.go | 3 + agent/utils/files/fileinfo.go | 45 +- agent/utils/files/tar.go | 2 +- agent/utils/files/tar_gz.go | 6 +- agent/utils/websocket/process_data.go | 39 +- agent/utils/xpack/xpack.go | 18 + core/app/api/v2/app_launcher.go | 3 +- core/app/api/v2/auth.go | 16 +- core/app/api/v2/backup.go | 12 +- core/app/api/v2/command.go | 12 +- core/app/api/v2/group.go | 10 +- core/app/api/v2/host.go | 20 +- core/app/api/v2/logs.go | 5 +- core/app/api/v2/setting.go | 92 +- core/app/api/v2/upgrade.go | 10 +- core/app/dto/auth.go | 2 +- core/app/dto/setting.go | 12 + core/app/service/setting.go | 31 + core/cmd/server/cmd/listen-ip.go | 40 +- core/cmd/server/cmd/reset.go | 61 +- core/cmd/server/cmd/restore.go | 73 +- core/cmd/server/cmd/root.go | 22 +- core/cmd/server/cmd/update.go | 100 +- core/cmd/server/cmd/user-info.go | 15 +- core/cmd/server/cmd/version.go | 16 +- core/cmd/server/conf/app.yaml | 1 + core/cmd/server/main.go | 26 +- core/configs/system.go | 7 + core/constant/errs.go | 23 +- core/global/global.go | 3 +- core/i18n/i18n.go | 49 + core/i18n/lang/en.yaml | 192 +- core/i18n/lang/fa.yaml | 63 + core/i18n/lang/ja.yaml | 157 + core/i18n/lang/ko.yaml | 157 + core/i18n/lang/ms.yml | 157 + core/i18n/lang/pt-BR.yaml | 157 + core/i18n/lang/pt.yaml | 157 + core/i18n/lang/ru.yaml | 286 ++ core/i18n/lang/zh-Hant.yaml | 114 +- core/i18n/lang/zh.yaml | 88 +- core/init/hook/hook.go | 23 + core/init/lang/lang.go | 134 + core/init/migration/migrations/init.go | 21 +- core/init/viper/viper.go | 8 +- core/middleware/session.go | 80 + core/router/ro_base.go | 1 + core/router/ro_setting.go | 2 + core/server/server.go | 2 + core/utils/files/files.go | 19 + frontend/package.json | 2 +- frontend/src/App.vue | 10 + frontend/src/api/index.ts | 2 +- frontend/src/api/interface/cronjob.ts | 3 + frontend/src/api/interface/file.ts | 2 +- frontend/src/api/interface/setting.ts | 15 + frontend/src/api/interface/toolbox.ts | 3 + frontend/src/api/modules/auth.ts | 4 + frontend/src/api/modules/files.ts | 2 +- frontend/src/api/modules/setting.ts | 8 + frontend/src/assets/images/menu-bg.svg | 1 + frontend/src/components/file-list/index.vue | 12 +- .../src/components/license-import/index.vue | 16 +- frontend/src/components/log-file/index.vue | 2 +- .../src/components/router-button/index.vue | 11 +- .../src/components/system-upgrade/index.vue | 59 +- .../system-upgrade/upgrade/index.vue | 15 +- frontend/src/components/terminal/index.vue | 6 +- .../components/v-charts/components/Line.vue | 17 +- .../components/v-charts/components/Pie.vue | 16 +- frontend/src/global/form-rules.ts | 18 + frontend/src/global/use-logo.ts | 20 + frontend/src/global/use-theme.ts | 31 +- frontend/src/lang/index.ts | 13 +- frontend/src/lang/modules/en.ts | 66 +- frontend/src/lang/modules/ja.ts | 2495 ++++++++++++++++ frontend/src/lang/modules/ko.ts | 2460 ++++++++++++++++ frontend/src/lang/modules/ms.ts | 2557 +++++++++++++++++ frontend/src/lang/modules/pt-br.ts | 2551 ++++++++++++++++ frontend/src/lang/modules/ru.ts | 2548 ++++++++++++++++ frontend/src/lang/modules/tw.ts | 61 +- frontend/src/lang/modules/zh.ts | 52 +- frontend/src/layout/components/AppFooter.vue | 8 +- .../Sidebar/components/Collapse.vue | 3 +- .../components/Sidebar/components/Logo.vue | 10 +- .../components/Sidebar/components/SubItem.vue | 2 +- .../src/layout/components/Sidebar/index.scss | 18 +- .../src/layout/components/Sidebar/index.vue | 59 +- frontend/src/layout/index.vue | 2 +- frontend/src/routers/index.ts | 6 + frontend/src/store/interface/index.ts | 3 +- frontend/src/store/modules/global.ts | 11 +- frontend/src/styles/common.scss | 28 +- frontend/src/styles/element-dark.scss | 690 +++-- frontend/src/styles/element.scss | 64 +- frontend/src/styles/moblie.scss | 1 - frontend/src/styles/reset.scss | 18 + frontend/src/utils/theme.ts | 8 + frontend/src/utils/util.ts | 30 +- frontend/src/utils/xpack.ts | 27 +- frontend/src/views/app-store/apps/index.vue | 16 +- frontend/src/views/app-store/detail/index.vue | 6 +- frontend/src/views/app-store/index.scss | 23 +- .../views/app-store/installed/check/index.vue | 15 +- .../src/views/app-store/installed/index.vue | 51 +- .../src/views/container/container/index.vue | 2 +- .../src/views/container/setting/index.vue | 6 +- .../views/container/setting/ipv6/index.vue | 4 +- frontend/src/views/cronjob/index.vue | 14 +- frontend/src/views/cronjob/operate/index.vue | 98 +- .../src/views/database/mysql/check/index.vue | 12 +- .../src/views/database/mysql/conn/index.vue | 2 +- frontend/src/views/database/mysql/index.vue | 28 +- .../views/database/postgresql/check/index.vue | 10 +- .../views/database/postgresql/conn/index.vue | 2 +- .../src/views/database/postgresql/index.vue | 28 +- .../src/views/database/redis/check/index.vue | 10 +- .../src/views/database/redis/conn/index.vue | 2 +- frontend/src/views/database/redis/index.vue | 17 +- frontend/src/views/home/app/index.vue | 2 +- frontend/src/views/home/index.vue | 4 +- frontend/src/views/home/status/index.vue | 2 + .../file-management/code-editor/index.vue | 7 +- .../host/file-management/delete/index.vue | 16 +- .../src/views/host/file-management/index.vue | 57 +- .../host/file-management/preview/index.vue | 4 +- .../src/views/host/firewall/forward/index.vue | 16 +- frontend/src/views/host/firewall/ip/index.vue | 16 +- .../src/views/host/firewall/port/index.vue | 16 +- frontend/src/views/log/operation/index.vue | 10 + .../src/views/login/components/login-form.vue | 122 +- frontend/src/views/setting/about/index.vue | 10 +- .../views/setting/backup-account/index.vue | 2 +- .../setting/backup-account/operate/index.vue | 10 +- frontend/src/views/setting/license/index.vue | 21 +- .../setting/panel/api-interface/index.vue | 190 ++ .../views/setting/panel/hidemenu/index.vue | 16 + frontend/src/views/setting/panel/index.vue | 247 +- .../src/views/setting/panel/name/index.vue | 2 +- .../src/views/setting/panel/proxy/index.vue | 101 +- .../views/setting/panel/theme-color/index.vue | 312 ++ frontend/src/views/terminal/command/index.vue | 2 +- .../src/views/terminal/terminal/index.vue | 22 +- frontend/src/views/toolbox/clam/index.vue | 6 +- .../src/views/toolbox/clam/operate/index.vue | 226 +- .../src/views/toolbox/clam/status/index.vue | 16 +- frontend/src/views/toolbox/clean/index.vue | 362 ++- frontend/src/views/toolbox/device/index.vue | 4 +- frontend/src/views/toolbox/fail2ban/index.vue | 16 +- frontend/src/views/toolbox/ftp/index.vue | 16 +- .../views/toolbox/supervisor/status/index.vue | 20 +- .../views/website/runtime/dotnet/index.vue | 6 +- .../src/views/website/runtime/go/index.vue | 6 +- .../src/views/website/runtime/java/index.vue | 6 +- .../src/views/website/runtime/node/index.vue | 6 +- .../views/website/runtime/php/check/index.vue | 14 +- .../website/runtime/php/create/index.vue | 48 +- .../php/extension-template/operate/index.vue | 4 +- .../views/website/runtime/python/index.vue | 6 +- frontend/src/views/website/ssl/index.vue | 14 +- frontend/src/views/website/website/index.vue | 4 +- frontend/vite.config.ts | 2 + 228 files changed, 20224 insertions(+), 1622 deletions(-) create mode 100644 agent/app/dto/alert.go create mode 100644 agent/constant/alert.go create mode 100644 agent/i18n/lang/fa.yaml create mode 100644 agent/i18n/lang/ja.yaml create mode 100644 agent/i18n/lang/ko.yaml create mode 100644 agent/i18n/lang/ms.yml create mode 100644 agent/i18n/lang/pt-BR.yaml create mode 100644 agent/i18n/lang/pt.yaml create mode 100644 agent/i18n/lang/ru.yaml create mode 100644 core/i18n/lang/fa.yaml create mode 100644 core/i18n/lang/ja.yaml create mode 100644 core/i18n/lang/ko.yaml create mode 100644 core/i18n/lang/ms.yml create mode 100644 core/i18n/lang/pt-BR.yaml create mode 100644 core/i18n/lang/pt.yaml create mode 100644 core/i18n/lang/ru.yaml create mode 100644 core/init/lang/lang.go create mode 100644 frontend/src/assets/images/menu-bg.svg create mode 100644 frontend/src/global/use-logo.ts create mode 100644 frontend/src/lang/modules/ja.ts create mode 100644 frontend/src/lang/modules/ko.ts create mode 100644 frontend/src/lang/modules/ms.ts create mode 100644 frontend/src/lang/modules/pt-br.ts create mode 100644 frontend/src/lang/modules/ru.ts create mode 100644 frontend/src/utils/theme.ts create mode 100644 frontend/src/views/setting/panel/api-interface/index.vue create mode 100644 frontend/src/views/setting/panel/theme-color/index.vue diff --git a/agent/app/api/v2/app.go b/agent/app/api/v2/app.go index 1eb24ba48..d9a06a9ed 100644 --- a/agent/app/api/v2/app.go +++ b/agent/app/api/v2/app.go @@ -12,8 +12,9 @@ import ( // @Summary List apps // @Accept json // @Param request body request.AppSearch true "request" -// @Success 200 +// @Success 200 {object} response.AppRes // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/search [post] func (b *BaseApi) SearchApp(c *gin.Context) { var req request.AppSearch @@ -32,6 +33,7 @@ func (b *BaseApi) SearchApp(c *gin.Context) { // @Summary Sync remote app list // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/sync/remote [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"应用商店同步","formatEN":"App store synchronization"} func (b *BaseApi) SyncApp(c *gin.Context) { @@ -56,13 +58,14 @@ func (b *BaseApi) SyncApp(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags App // @Summary Sync local app list // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/sync/local [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"应用商店同步","formatEN":"App store synchronization"} func (b *BaseApi) SyncLocalApp(c *gin.Context) { @@ -80,6 +83,7 @@ func (b *BaseApi) SyncLocalApp(c *gin.Context) { // @Param key path string true "app key" // @Success 200 {object} response.AppDTO // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/:key [get] func (b *BaseApi) GetApp(c *gin.Context) { appKey, err := helper.GetStrParamByKey(c, "key") @@ -103,6 +107,7 @@ func (b *BaseApi) GetApp(c *gin.Context) { // @Param version path string true "app 类型" // @Success 200 {object} response.AppDetailDTO // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/detail/:appId/:version/:type [get] func (b *BaseApi) GetAppDetail(c *gin.Context) { appID, err := helper.GetIntParamByKey(c, "appId") @@ -126,6 +131,7 @@ func (b *BaseApi) GetAppDetail(c *gin.Context) { // @Param appId path integer true "id" // @Success 200 {object} response.AppDetailDTO // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/details/:id [get] func (b *BaseApi) GetAppDetailByID(c *gin.Context) { appDetailID, err := helper.GetIntParamByKey(c, "id") @@ -144,8 +150,9 @@ func (b *BaseApi) GetAppDetailByID(c *gin.Context) { // @Tags App // @Summary Get Ignore App // @Accept json -// @Success 200 {object} response.IgnoredApp +// @Success 200 {array} response.IgnoredApp // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/ignored [get] func (b *BaseApi) GetIgnoredApp(c *gin.Context) { res, err := appService.GetIgnoredApp() @@ -162,6 +169,7 @@ func (b *BaseApi) GetIgnoredApp(c *gin.Context) { // @Param request body request.AppInstallCreate true "request" // @Success 200 {object} model.AppInstall // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/install [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"安装应用 [name]","formatEN":"Install app [name]"} func (b *BaseApi) InstallApp(c *gin.Context) { @@ -188,8 +196,9 @@ func (b *BaseApi) GetAppTags(c *gin.Context) { // @Tags App // @Summary Get app list update -// @Success 200 +// @Success 200 {object} response.AppUpdateRes // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/checkupdate [get] func (b *BaseApi) GetAppListUpdate(c *gin.Context) { res, err := appService.GetAppUpdate() @@ -206,6 +215,7 @@ func (b *BaseApi) GetAppListUpdate(c *gin.Context) { // @Param request body request.AppstoreUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/store/update [post] func (b *BaseApi) UpdateAppstoreConfig(c *gin.Context) { var req request.AppstoreUpdate @@ -224,6 +234,7 @@ func (b *BaseApi) UpdateAppstoreConfig(c *gin.Context) { // @Summary Get appstore config // @Success 200 {object} response.AppstoreConfig // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/store/config [get] func (b *BaseApi) GetAppstoreConfig(c *gin.Context) { res, err := appService.GetAppstoreConfig() diff --git a/agent/app/api/v2/app_install.go b/agent/app/api/v2/app_install.go index a41a9bc12..b5ff1c524 100644 --- a/agent/app/api/v2/app_install.go +++ b/agent/app/api/v2/app_install.go @@ -12,8 +12,9 @@ import ( // @Summary Page app installed // @Accept json // @Param request body request.AppInstalledSearch true "request" -// @Success 200 +// @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/installed/search [post] func (b *BaseApi) SearchAppInstalled(c *gin.Context) { var req request.AppInstalledSearch @@ -43,8 +44,9 @@ func (b *BaseApi) SearchAppInstalled(c *gin.Context) { // @Tags App // @Summary List app installed // @Accept json -// @Success 200 array dto.AppInstallInfo +// @Success 200 {array} dto.AppInstallInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/installed/list [get] func (b *BaseApi) ListAppInstalled(c *gin.Context) { list, err := appInstallService.GetInstallList() @@ -61,6 +63,7 @@ func (b *BaseApi) ListAppInstalled(c *gin.Context) { // @Param request body request.AppInstalledInfo true "request" // @Success 200 {object} response.AppInstalledCheck // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/installed/check [post] func (b *BaseApi) CheckAppInstalled(c *gin.Context) { var req request.AppInstalledInfo @@ -81,6 +84,7 @@ func (b *BaseApi) CheckAppInstalled(c *gin.Context) { // @Param request body dto.OperationWithNameAndType true "request" // @Success 200 {integer} port // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/installed/loadport [post] func (b *BaseApi) LoadPort(c *gin.Context) { var req dto.OperationWithNameAndType @@ -99,8 +103,9 @@ func (b *BaseApi) LoadPort(c *gin.Context) { // @Summary Search app password by key // @Accept json // @Param request body dto.OperationWithNameAndType true "request" -// @Success 200 {string} response.DatabaseConn +// @Success 200 {object} response.DatabaseConn // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/installed/conninfo/:key [get] func (b *BaseApi) LoadConnInfo(c *gin.Context) { var req dto.OperationWithNameAndType @@ -121,6 +126,7 @@ func (b *BaseApi) LoadConnInfo(c *gin.Context) { // @Param appInstallId path integer true "App install id" // @Success 200 {array} dto.AppResource // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/installed/delete/check/:appInstallId [get] func (b *BaseApi) DeleteCheck(c *gin.Context) { appInstallId, err := helper.GetIntParamByKey(c, "appInstallId") @@ -141,6 +147,7 @@ func (b *BaseApi) DeleteCheck(c *gin.Context) { // @Summary Sync app installed // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/installed/sync [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"同步已安装应用列表","formatEN":"Sync the list of installed apps"} func (b *BaseApi) SyncInstalled(c *gin.Context) { @@ -148,7 +155,7 @@ func (b *BaseApi) SyncInstalled(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, "") + helper.SuccessWithOutData(c) } // @Tags App @@ -157,6 +164,7 @@ func (b *BaseApi) SyncInstalled(c *gin.Context) { // @Param request body request.AppInstalledOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/installed/op [post] // @x-panel-log {"bodyKeys":["installId","operate"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"installId","isList":false,"db":"app_installs","output_column":"app_id","output_value":"appId"},{"input_column":"id","input_value":"installId","isList":false,"db":"app_installs","output_column":"name","output_value":"appName"},{"input_column":"id","input_value":"appId","isList":false,"db":"apps","output_column":"key","output_value":"appKey"}],"formatZH":"[operate] 应用 [appKey][appName]","formatEN":"[operate] App [appKey][appName]"} func (b *BaseApi) OperateInstalled(c *gin.Context) { @@ -168,7 +176,7 @@ func (b *BaseApi) OperateInstalled(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags App @@ -177,6 +185,7 @@ func (b *BaseApi) OperateInstalled(c *gin.Context) { // @Param key path string true "request" // @Success 200 {array} response.AppService // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/services/:key [get] func (b *BaseApi) GetServices(c *gin.Context) { key := c.Param("key") @@ -194,6 +203,7 @@ func (b *BaseApi) GetServices(c *gin.Context) { // @Param appInstallId path integer true "request" // @Success 200 {array} dto.AppVersion // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/installed/update/versions [post] func (b *BaseApi) GetUpdateVersions(c *gin.Context) { var req request.AppUpdateVersion @@ -214,6 +224,7 @@ func (b *BaseApi) GetUpdateVersions(c *gin.Context) { // @Param request body request.PortUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/installed/port/change [post] // @x-panel-log {"bodyKeys":["key","name","port"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"应用端口修改 [key]-[name] => [port]","formatEN":"Application port update [key]-[name] => [port]"} func (b *BaseApi) ChangeAppPort(c *gin.Context) { @@ -225,7 +236,7 @@ func (b *BaseApi) ChangeAppPort(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags App @@ -234,6 +245,7 @@ func (b *BaseApi) ChangeAppPort(c *gin.Context) { // @Param request body dto.OperationWithNameAndType true "request" // @Success 200 {string} content // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/installed/conf [post] func (b *BaseApi) GetDefaultConfig(c *gin.Context) { var req dto.OperationWithNameAndType @@ -253,8 +265,9 @@ func (b *BaseApi) GetDefaultConfig(c *gin.Context) { // @Summary Search params by appInstallId // @Accept json // @Param appInstallId path string true "request" -// @Success 200 {object} response.AppParam +// @Success 200 {object} response.AppConfig // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/installed/params/:appInstallId [get] func (b *BaseApi) GetParams(c *gin.Context) { appInstallId, err := helper.GetIntParamByKey(c, "appInstallId") @@ -276,6 +289,7 @@ func (b *BaseApi) GetParams(c *gin.Context) { // @Param request body request.AppInstalledUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/installed/params/update [post] // @x-panel-log {"bodyKeys":["installId"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"应用参数修改 [installId]","formatEN":"Application param update [installId]"} func (b *BaseApi) UpdateInstalled(c *gin.Context) { @@ -287,7 +301,7 @@ func (b *BaseApi) UpdateInstalled(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags App @@ -296,6 +310,7 @@ func (b *BaseApi) UpdateInstalled(c *gin.Context) { // @Param request body request.AppInstalledIgnoreUpgrade true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/installed/ignore [post] // @x-panel-log {"bodyKeys":["installId"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"忽略应用 [installId] 版本升级","formatEN":"Application param update [installId]"} func (b *BaseApi) IgnoreUpgrade(c *gin.Context) { @@ -316,6 +331,7 @@ func (b *BaseApi) IgnoreUpgrade(c *gin.Context) { // @Param request body request.AppConfigUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /apps/installed/config/update [post] // @x-panel-log {"bodyKeys":["installID","webUI"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"应用配置更新 [installID]","formatEN":"Application config update [installID]"} func (b *BaseApi) UpdateAppConfig(c *gin.Context) { diff --git a/agent/app/api/v2/backup.go b/agent/app/api/v2/backup.go index b4dfea21c..920d315d9 100644 --- a/agent/app/api/v2/backup.go +++ b/agent/app/api/v2/backup.go @@ -41,11 +41,11 @@ func (b *BaseApi) SyncBackupAccount(c *gin.Context) { // @Tags Backup Account // @Summary Create backup account -// @Description 创建备份账号 // @Accept json // @Param request body dto.BackupOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /backups [post] // @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建备份账号 [type]","formatEN":"create backup account [type]"} func (b *BaseApi) CreateBackup(c *gin.Context) { @@ -63,11 +63,11 @@ func (b *BaseApi) CreateBackup(c *gin.Context) { // @Tags Backup Account // @Summary Refresh token -// @Description 刷新 token // @Accept json // @Param request body dto.BackupOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /backups/refresh/token [post] func (b *BaseApi) RefreshToken(c *gin.Context) { var req dto.OperateByID @@ -83,11 +83,11 @@ func (b *BaseApi) RefreshToken(c *gin.Context) { // @Tags Backup Account // @Summary List buckets -// @Description 获取 bucket 列表 // @Accept json // @Param request body dto.ForBuckets true "request" -// @Success 200 {array} string +// @Success 200 {array} object // @Security ApiKeyAuth +// @Security Timestamp // @Router /buckets [post] func (b *BaseApi) ListBuckets(c *gin.Context) { var req dto.ForBuckets @@ -105,11 +105,11 @@ func (b *BaseApi) ListBuckets(c *gin.Context) { // @Tags Backup Account // @Summary Delete backup account -// @Description 删除备份账号 // @Accept json // @Param request body dto.OperateByID true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /backups/del [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"backup_accounts","output_column":"type","output_value":"types"}],"formatZH":"删除备份账号 [types]","formatEN":"delete backup account [types]"} func (b *BaseApi) DeleteBackup(c *gin.Context) { @@ -122,16 +122,16 @@ func (b *BaseApi) DeleteBackup(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Backup Account // @Summary Update backup account -// @Description 更新备份账号信息 // @Accept json // @Param request body dto.BackupOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /backups/update [post] // @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新备份账号 [types]","formatEN":"update backup account [types]"} func (b *BaseApi) UpdateBackup(c *gin.Context) { @@ -144,7 +144,7 @@ func (b *BaseApi) UpdateBackup(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Backup Account @@ -152,6 +152,7 @@ func (b *BaseApi) UpdateBackup(c *gin.Context) { // @Accept json // @Success 200 {array} dto.BackupOption // @Security ApiKeyAuth +// @Security Timestamp // @Router /backups/options [get] func (b *BaseApi) LoadBackupOptions(c *gin.Context) { list, err := backupService.LoadBackupOptions() @@ -164,11 +165,11 @@ func (b *BaseApi) LoadBackupOptions(c *gin.Context) { // @Tags Backup Account // @Summary Search backup accounts with page -// @Description 获取备份账号列表 // @Accept json // @Param request body dto.SearchPageWithType true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /backups/search [post] func (b *BaseApi) SearchBackup(c *gin.Context) { var req dto.SearchPageWithType @@ -190,9 +191,9 @@ func (b *BaseApi) SearchBackup(c *gin.Context) { // @Tags Backup Account // @Summary get local backup dir -// @Description 获取本地备份目录 -// @Success 200 +// @Success 200 {string} dir // @Security ApiKeyAuth +// @Security Timestamp // @Router /backups/local [get] func (b *BaseApi) GetLocalDir(c *gin.Context) { dir, err := backupService.GetLocalDir() @@ -205,12 +206,12 @@ func (b *BaseApi) GetLocalDir(c *gin.Context) { } // @Tags Backup Account -// @Summary Page backup records -// @Description 获取备份记录列表分页 +// @Summary Load backup record size // @Accept json // @Param request body dto.SearchForSize true "request" -// @Success 200 {object} dto.RecordFileSize +// @Success 200 {array} dto.RecordFileSize // @Security ApiKeyAuth +// @Security Timestamp // @Router /backups/record/size [post] func (b *BaseApi) LoadBackupRecordSize(c *gin.Context) { var req dto.SearchForSize @@ -231,8 +232,9 @@ func (b *BaseApi) LoadBackupRecordSize(c *gin.Context) { // @Summary Page backup records // @Accept json // @Param request body dto.RecordSearch true "request" -// @Success 200 +// @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /backups/record/search [post] func (b *BaseApi) SearchBackupRecords(c *gin.Context) { var req dto.RecordSearch @@ -256,8 +258,9 @@ func (b *BaseApi) SearchBackupRecords(c *gin.Context) { // @Summary Page backup records by cronjob // @Accept json // @Param request body dto.RecordSearchByCronjob true "request" -// @Success 200 +// @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /backups/record/search/bycronjob [post] func (b *BaseApi) SearchBackupRecordsByCronjob(c *gin.Context) { var req dto.RecordSearchByCronjob @@ -281,8 +284,9 @@ func (b *BaseApi) SearchBackupRecordsByCronjob(c *gin.Context) { // @Summary Download backup record // @Accept json // @Param request body dto.DownloadRecord true "request" -// @Success 200 +// @Success 200 {string} filePath // @Security ApiKeyAuth +// @Security Timestamp // @Router /backup/record/download [post] // @x-panel-log {"bodyKeys":["source","fileName"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"下载备份记录 [source][fileName]","formatEN":"download backup records [source][fileName]"} func (b *BaseApi) DownloadRecord(c *gin.Context) { @@ -305,6 +309,7 @@ func (b *BaseApi) DownloadRecord(c *gin.Context) { // @Param request body dto.BatchDeleteReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /record/del [post] // @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"backup_records","output_column":"file_name","output_value":"files"}],"formatZH":"删除备份记录 [files]","formatEN":"delete backup records [files]"} func (b *BaseApi) DeleteBackupRecord(c *gin.Context) { @@ -317,7 +322,7 @@ func (b *BaseApi) DeleteBackupRecord(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Backup Account @@ -326,6 +331,7 @@ func (b *BaseApi) DeleteBackupRecord(c *gin.Context) { // @Param request body dto.OperateByID true "request" // @Success 200 {array} string // @Security ApiKeyAuth +// @Security Timestamp // @Router /backups/search/files [post] func (b *BaseApi) LoadFilesFromBackup(c *gin.Context) { var req dto.OperateByID @@ -343,6 +349,7 @@ func (b *BaseApi) LoadFilesFromBackup(c *gin.Context) { // @Param request body dto.CommonBackup true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /backups/backup [post] // @x-panel-log {"bodyKeys":["type","name","detailName"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"备份 [type] 数据 [name][detailName]","formatEN":"backup [type] data [name][detailName]"} func (b *BaseApi) Backup(c *gin.Context) { @@ -378,7 +385,7 @@ func (b *BaseApi) Backup(c *gin.Context) { return } } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Backup Account @@ -387,6 +394,7 @@ func (b *BaseApi) Backup(c *gin.Context) { // @Param request body dto.CommonRecover true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /backups/recover [post] // @x-panel-log {"bodyKeys":["type","name","detailName","file"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"从 [file] 恢复 [type] 数据 [name][detailName]","formatEN":"recover [type] data [name][detailName] from [file]"} func (b *BaseApi) Recover(c *gin.Context) { @@ -432,7 +440,7 @@ func (b *BaseApi) Recover(c *gin.Context) { return } } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Backup Account @@ -441,6 +449,7 @@ func (b *BaseApi) Recover(c *gin.Context) { // @Param request body dto.CommonRecover true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /backups/recover/byupload [post] // @x-panel-log {"bodyKeys":["type","name","detailName","file"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"从 [file] 恢复 [type] 数据 [name][detailName]","formatEN":"recover [type] data [name][detailName] from [file]"} func (b *BaseApi) RecoverByUpload(c *gin.Context) { @@ -471,5 +480,5 @@ func (b *BaseApi) RecoverByUpload(c *gin.Context) { return } } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/clam.go b/agent/app/api/v2/clam.go index 6d3f08df0..f15783b3a 100644 --- a/agent/app/api/v2/clam.go +++ b/agent/app/api/v2/clam.go @@ -12,6 +12,7 @@ import ( // @Param request body dto.ClamCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/clam [post] // @x-panel-log {"bodyKeys":["name","path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建扫描规则 [name][path]","formatEN":"create clam [name][path]"} func (b *BaseApi) CreateClam(c *gin.Context) { @@ -24,7 +25,7 @@ func (b *BaseApi) CreateClam(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Clam @@ -33,6 +34,7 @@ func (b *BaseApi) CreateClam(c *gin.Context) { // @Param request body dto.ClamUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/clam/update [post] // @x-panel-log {"bodyKeys":["name","path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改扫描规则 [name][path]","formatEN":"update clam [name][path]"} func (b *BaseApi) UpdateClam(c *gin.Context) { @@ -45,7 +47,7 @@ func (b *BaseApi) UpdateClam(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Clam @@ -54,6 +56,7 @@ func (b *BaseApi) UpdateClam(c *gin.Context) { // @Param request body dto.ClamUpdateStatus true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/clam/status/update [post] // @x-panel-log {"bodyKeys":["id","status"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"clams","output_column":"name","output_value":"name"}],"formatZH":"修改扫描规则 [name] 状态为 [status]","formatEN":"change the status of clam [name] to [status]."} func (b *BaseApi) UpdateClamStatus(c *gin.Context) { @@ -66,7 +69,7 @@ func (b *BaseApi) UpdateClamStatus(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Clam @@ -75,6 +78,7 @@ func (b *BaseApi) UpdateClamStatus(c *gin.Context) { // @Param request body dto.SearchClamWithPage true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/clam/search [post] func (b *BaseApi) SearchClam(c *gin.Context) { var req dto.SearchClamWithPage @@ -99,6 +103,7 @@ func (b *BaseApi) SearchClam(c *gin.Context) { // @Accept json // @Success 200 {object} dto.ClamBaseInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/clam/base [get] func (b *BaseApi) LoadClamBaseInfo(c *gin.Context) { info, err := clamService.LoadBaseInfo() @@ -113,8 +118,10 @@ func (b *BaseApi) LoadClamBaseInfo(c *gin.Context) { // @Tags Clam // @Summary Operate Clam // @Accept json +// @Success 200 // @Param request body dto.Operate true "request" // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/clam/operate [post] // @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operation] Clam","formatEN":"[operation] FTP"} func (b *BaseApi) OperateClam(c *gin.Context) { @@ -128,14 +135,16 @@ func (b *BaseApi) OperateClam(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Clam // @Summary Clean clam record // @Accept json // @Param request body dto.OperateByID true "request" +// @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/clam/record/clean [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":true,"db":"clams","output_column":"name","output_value":"name"}],"formatZH":"清空扫描报告 [name]","formatEN":"clean clam record [name]"} func (b *BaseApi) CleanClamRecord(c *gin.Context) { @@ -148,7 +157,7 @@ func (b *BaseApi) CleanClamRecord(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Clam @@ -157,6 +166,7 @@ func (b *BaseApi) CleanClamRecord(c *gin.Context) { // @Param request body dto.ClamLogSearch true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/clam/record/search [post] func (b *BaseApi) SearchClamRecord(c *gin.Context) { var req dto.ClamLogSearch @@ -180,8 +190,9 @@ func (b *BaseApi) SearchClamRecord(c *gin.Context) { // @Summary Load clam record detail // @Accept json // @Param request body dto.ClamLogReq true "request" -// @Success 200 +// @Success 200 {string} content // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/clam/record/log [post] func (b *BaseApi) LoadClamRecordLog(c *gin.Context) { var req dto.ClamLogReq @@ -202,8 +213,9 @@ func (b *BaseApi) LoadClamRecordLog(c *gin.Context) { // @Summary Load clam file // @Accept json // @Param request body dto.ClamFileReq true "request" -// @Success 200 {object} dto.PageResult +// @Success 200 {string} content // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/clam/file/search [post] func (b *BaseApi) SearchClamFile(c *gin.Context) { var req dto.ClamFileReq @@ -226,6 +238,7 @@ func (b *BaseApi) SearchClamFile(c *gin.Context) { // @Param request body dto.UpdateByNameAndFile true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/clam/file/update [post] func (b *BaseApi) UpdateFile(c *gin.Context) { var req dto.UpdateByNameAndFile @@ -245,6 +258,7 @@ func (b *BaseApi) UpdateFile(c *gin.Context) { // @Param request body dto.ClamDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/clam/del [post] // @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"clams","output_column":"name","output_value":"names"}],"formatZH":"删除扫描规则 [names]","formatEN":"delete clam [names]"} func (b *BaseApi) DeleteClam(c *gin.Context) { @@ -257,7 +271,7 @@ func (b *BaseApi) DeleteClam(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Clam @@ -266,6 +280,7 @@ func (b *BaseApi) DeleteClam(c *gin.Context) { // @Param request body dto.OperateByID true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/clam/handle [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":true,"db":"clams","output_column":"name","output_value":"name"}],"formatZH":"执行病毒扫描 [name]","formatEN":"handle clam scan [name]"} func (b *BaseApi) HandleClamScan(c *gin.Context) { @@ -278,5 +293,5 @@ func (b *BaseApi) HandleClamScan(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/compose_template.go b/agent/app/api/v2/compose_template.go index 6b4c25dc9..f3265af1a 100644 --- a/agent/app/api/v2/compose_template.go +++ b/agent/app/api/v2/compose_template.go @@ -12,6 +12,7 @@ import ( // @Param request body dto.ComposeTemplateCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/template [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建 compose 模版 [name]","formatEN":"create compose template [name]"} func (b *BaseApi) CreateComposeTemplate(c *gin.Context) { @@ -24,7 +25,7 @@ func (b *BaseApi) CreateComposeTemplate(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container Compose-template @@ -34,6 +35,7 @@ func (b *BaseApi) CreateComposeTemplate(c *gin.Context) { // @Produce json // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/template/search [post] func (b *BaseApi) SearchComposeTemplate(c *gin.Context) { var req dto.SearchWithPage @@ -58,6 +60,7 @@ func (b *BaseApi) SearchComposeTemplate(c *gin.Context) { // @Produce json // @Success 200 {array} dto.ComposeTemplateInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/template [get] func (b *BaseApi) ListComposeTemplate(c *gin.Context) { list, err := composeTemplateService.List() @@ -75,6 +78,7 @@ func (b *BaseApi) ListComposeTemplate(c *gin.Context) { // @Param request body dto.BatchDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/template/del [post] // @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"compose_templates","output_column":"name","output_value":"names"}],"formatZH":"删除 compose 模版 [names]","formatEN":"delete compose template [names]"} func (b *BaseApi) DeleteComposeTemplate(c *gin.Context) { @@ -87,7 +91,7 @@ func (b *BaseApi) DeleteComposeTemplate(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container Compose-template @@ -96,6 +100,7 @@ func (b *BaseApi) DeleteComposeTemplate(c *gin.Context) { // @Param request body dto.ComposeTemplateUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/template/update [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"compose_templates","output_column":"name","output_value":"name"}],"formatZH":"更新 compose 模版 [name]","formatEN":"update compose template information [name]"} func (b *BaseApi) UpdateComposeTemplate(c *gin.Context) { @@ -111,5 +116,5 @@ func (b *BaseApi) UpdateComposeTemplate(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/container.go b/agent/app/api/v2/container.go index 810e86deb..bc70abdc1 100644 --- a/agent/app/api/v2/container.go +++ b/agent/app/api/v2/container.go @@ -16,6 +16,7 @@ import ( // @Produce json // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/search [post] func (b *BaseApi) SearchContainer(c *gin.Context) { var req dto.PageContainer @@ -38,8 +39,9 @@ func (b *BaseApi) SearchContainer(c *gin.Context) { // @Summary List containers // @Accept json // @Produce json -// @Success 200 +// @Success 200 {array} string // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/list [post] func (b *BaseApi) ListContainer(c *gin.Context) { list, err := containerService.List() @@ -54,8 +56,9 @@ func (b *BaseApi) ListContainer(c *gin.Context) { // @Summary Load containers status // @Accept json // @Produce json -// @Success 200 +// @Success 200 {object} dto.ContainerStatus // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/status [get] func (b *BaseApi) LoadContainerStatus(c *gin.Context) { data, err := containerService.LoadStatus() @@ -72,6 +75,7 @@ func (b *BaseApi) LoadContainerStatus(c *gin.Context) { // @Param request body dto.SearchWithPage true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/compose/search [post] func (b *BaseApi) SearchCompose(c *gin.Context) { var req dto.SearchWithPage @@ -94,8 +98,9 @@ func (b *BaseApi) SearchCompose(c *gin.Context) { // @Summary Test compose // @Accept json // @Param request body dto.ComposeCreate true "request" -// @Success 200 +// @Success 200 {boolean} isOK // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/compose/test [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"检测 compose [name] 格式","formatEN":"check compose [name]"} func (b *BaseApi) TestCompose(c *gin.Context) { @@ -118,6 +123,7 @@ func (b *BaseApi) TestCompose(c *gin.Context) { // @Param request body dto.ComposeCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/compose [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建 compose [name]","formatEN":"create compose [name]"} func (b *BaseApi) CreateCompose(c *gin.Context) { @@ -139,6 +145,7 @@ func (b *BaseApi) CreateCompose(c *gin.Context) { // @Param request body dto.ComposeOperation true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/compose/operate [post] // @x-panel-log {"bodyKeys":["name","operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"compose [operation] [name]","formatEN":"compose [operation] [name]"} func (b *BaseApi) OperatorCompose(c *gin.Context) { @@ -151,7 +158,7 @@ func (b *BaseApi) OperatorCompose(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container @@ -160,6 +167,7 @@ func (b *BaseApi) OperatorCompose(c *gin.Context) { // @Param request body dto.ContainerOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/update [post] // @x-panel-log {"bodyKeys":["name","image"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新容器 [name][image]","formatEN":"update container [name][image]"} func (b *BaseApi) ContainerUpdate(c *gin.Context) { @@ -172,7 +180,7 @@ func (b *BaseApi) ContainerUpdate(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container @@ -181,6 +189,7 @@ func (b *BaseApi) ContainerUpdate(c *gin.Context) { // @Param request body dto.OperationWithName true "request" // @Success 200 {object} dto.ContainerOperate // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/info [post] func (b *BaseApi) ContainerInfo(c *gin.Context) { var req dto.OperationWithName @@ -199,6 +208,7 @@ func (b *BaseApi) ContainerInfo(c *gin.Context) { // @Summary Load container limits // @Success 200 {object} dto.ResourceLimit // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/limit [get] func (b *BaseApi) LoadResourceLimit(c *gin.Context) { data, err := containerService.LoadResourceLimit() @@ -212,6 +222,7 @@ func (b *BaseApi) LoadResourceLimit(c *gin.Context) { // @Summary Load container stats // @Success 200 {array} dto.ContainerListStats // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/list/stats [get] func (b *BaseApi) ContainerListStats(c *gin.Context) { data, err := containerService.ContainerListStats() @@ -228,6 +239,7 @@ func (b *BaseApi) ContainerListStats(c *gin.Context) { // @Param request body dto.ContainerOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers [post] // @x-panel-log {"bodyKeys":["name","image"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建容器 [name][image]","formatEN":"create container [name][image]"} func (b *BaseApi) ContainerCreate(c *gin.Context) { @@ -240,7 +252,7 @@ func (b *BaseApi) ContainerCreate(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container @@ -249,6 +261,7 @@ func (b *BaseApi) ContainerCreate(c *gin.Context) { // @Param request body dto.ContainerCreateByCommand true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/command [post] func (b *BaseApi) ContainerCreateByCommand(c *gin.Context) { var req dto.ContainerCreateByCommand @@ -260,7 +273,7 @@ func (b *BaseApi) ContainerCreateByCommand(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container @@ -269,6 +282,7 @@ func (b *BaseApi) ContainerCreateByCommand(c *gin.Context) { // @Param request body dto.ContainerUpgrade true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/upgrade [post] // @x-panel-log {"bodyKeys":["name","image"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新容器镜像 [name][image]","formatEN":"upgrade container image [name][image]"} func (b *BaseApi) ContainerUpgrade(c *gin.Context) { @@ -281,7 +295,7 @@ func (b *BaseApi) ContainerUpgrade(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container @@ -290,6 +304,7 @@ func (b *BaseApi) ContainerUpgrade(c *gin.Context) { // @Param request body dto.ContainerPrune true "request" // @Success 200 {object} dto.ContainerPruneReport // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/prune [post] // @x-panel-log {"bodyKeys":["pruneType"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理容器 [pruneType]","formatEN":"clean container [pruneType]"} func (b *BaseApi) ContainerPrune(c *gin.Context) { @@ -312,6 +327,7 @@ func (b *BaseApi) ContainerPrune(c *gin.Context) { // @Param request body dto.OperationWithName true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/clean/log [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理容器 [name] 日志","formatEN":"clean container [name] logs"} func (b *BaseApi) CleanContainerLog(c *gin.Context) { @@ -324,15 +340,16 @@ func (b *BaseApi) CleanContainerLog(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container // @Summary Load container log // @Accept json // @Param request body dto.OperationWithNameAndType true "request" -// @Success 200 +// @Success 200 {string} content // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/load/log [post] func (b *BaseApi) LoadContainerLog(c *gin.Context) { var req dto.OperationWithNameAndType @@ -350,6 +367,7 @@ func (b *BaseApi) LoadContainerLog(c *gin.Context) { // @Param request body dto.ContainerRename true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/rename [post] // @x-panel-log {"bodyKeys":["name","newName"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"容器重命名 [name] => [newName]","formatEN":"rename container [name] => [newName]"} func (b *BaseApi) ContainerRename(c *gin.Context) { @@ -362,7 +380,7 @@ func (b *BaseApi) ContainerRename(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container @@ -370,6 +388,8 @@ func (b *BaseApi) ContainerRename(c *gin.Context) { // @Accept json // @Param request body dto.ContainerCommit true "request" // @Success 200 +// @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/commit [post] func (b *BaseApi) ContainerCommit(c *gin.Context) { var req dto.ContainerCommit @@ -381,7 +401,7 @@ func (b *BaseApi) ContainerCommit(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container @@ -390,6 +410,7 @@ func (b *BaseApi) ContainerCommit(c *gin.Context) { // @Param request body dto.ContainerOperation true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/operate [post] // @x-panel-log {"bodyKeys":["names","operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"容器 [names] 执行 [operation]","formatEN":"container [operation] [names]"} func (b *BaseApi) ContainerOperation(c *gin.Context) { @@ -402,7 +423,7 @@ func (b *BaseApi) ContainerOperation(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container @@ -410,6 +431,7 @@ func (b *BaseApi) ContainerOperation(c *gin.Context) { // @Param id path integer true "容器id" // @Success 200 {object} dto.ContainerStats // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/stats/:id [get] func (b *BaseApi) ContainerStats(c *gin.Context) { containerID, ok := c.Params.Get("id") @@ -432,6 +454,7 @@ func (b *BaseApi) ContainerStats(c *gin.Context) { // @Param request body dto.InspectReq true "request" // @Success 200 {string} result // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/inspect [post] func (b *BaseApi) Inspect(c *gin.Context) { var req dto.InspectReq @@ -466,6 +489,7 @@ func (b *BaseApi) DownloadContainerLogs(c *gin.Context) { // @Produce json // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/network/search [post] func (b *BaseApi) SearchNetwork(c *gin.Context) { var req dto.SearchWithPage @@ -490,6 +514,7 @@ func (b *BaseApi) SearchNetwork(c *gin.Context) { // @Produce json // @Success 200 {array} dto.Options // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/network [get] func (b *BaseApi) ListNetwork(c *gin.Context) { list, err := containerService.ListNetwork() @@ -506,6 +531,7 @@ func (b *BaseApi) ListNetwork(c *gin.Context) { // @Param request body dto.BatchDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/network/del [post] // @x-panel-log {"bodyKeys":["names"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除容器网络 [names]","formatEN":"delete container network [names]"} func (b *BaseApi) DeleteNetwork(c *gin.Context) { @@ -518,7 +544,7 @@ func (b *BaseApi) DeleteNetwork(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container Network @@ -527,6 +553,7 @@ func (b *BaseApi) DeleteNetwork(c *gin.Context) { // @Param request body dto.NetworkCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/network [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建容器网络 name","formatEN":"create container network [name]"} func (b *BaseApi) CreateNetwork(c *gin.Context) { @@ -539,7 +566,7 @@ func (b *BaseApi) CreateNetwork(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container Volume @@ -549,6 +576,7 @@ func (b *BaseApi) CreateNetwork(c *gin.Context) { // @Produce json // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/volume/search [post] func (b *BaseApi) SearchVolume(c *gin.Context) { var req dto.SearchWithPage @@ -573,6 +601,7 @@ func (b *BaseApi) SearchVolume(c *gin.Context) { // @Produce json // @Success 200 {array} dto.Options // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/volume [get] func (b *BaseApi) ListVolume(c *gin.Context) { list, err := containerService.ListVolume() @@ -589,6 +618,7 @@ func (b *BaseApi) ListVolume(c *gin.Context) { // @Param request body dto.BatchDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/volume/del [post] // @x-panel-log {"bodyKeys":["names"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除容器存储卷 [names]","formatEN":"delete container volume [names]"} func (b *BaseApi) DeleteVolume(c *gin.Context) { @@ -601,7 +631,7 @@ func (b *BaseApi) DeleteVolume(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container Volume @@ -610,6 +640,7 @@ func (b *BaseApi) DeleteVolume(c *gin.Context) { // @Param request body dto.VolumeCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/volume [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建容器存储卷 [name]","formatEN":"create container volume [name]"} func (b *BaseApi) CreateVolume(c *gin.Context) { @@ -622,7 +653,7 @@ func (b *BaseApi) CreateVolume(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container Compose @@ -631,6 +662,7 @@ func (b *BaseApi) CreateVolume(c *gin.Context) { // @Param request body dto.ComposeUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/compose/update [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 compose [name]","formatEN":"update compose information [name]"} func (b *BaseApi) ComposeUpdate(c *gin.Context) { @@ -643,7 +675,7 @@ func (b *BaseApi) ComposeUpdate(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container @@ -653,6 +685,7 @@ func (b *BaseApi) ComposeUpdate(c *gin.Context) { // @Param follow query string false "是否追踪" // @Param tail query string false "显示行号" // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/search/log [post] func (b *BaseApi) ContainerStreamLogs(c *gin.Context) { c.Header("Content-Type", "text/event-stream") diff --git a/agent/app/api/v2/cronjob.go b/agent/app/api/v2/cronjob.go index e2ccc7bbe..2844abcf3 100644 --- a/agent/app/api/v2/cronjob.go +++ b/agent/app/api/v2/cronjob.go @@ -15,6 +15,7 @@ import ( // @Param request body dto.CronjobCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /cronjobs [post] // @x-panel-log {"bodyKeys":["type","name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建计划任务 [type][name]","formatEN":"create cronjob [type][name]"} func (b *BaseApi) CreateCronjob(c *gin.Context) { @@ -27,7 +28,7 @@ func (b *BaseApi) CreateCronjob(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Cronjob @@ -36,6 +37,7 @@ func (b *BaseApi) CreateCronjob(c *gin.Context) { // @Param request body dto.CronjobSpec true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /cronjobs/next [post] func (b *BaseApi) LoadNextHandle(c *gin.Context) { var req dto.CronjobSpec @@ -57,6 +59,7 @@ func (b *BaseApi) LoadNextHandle(c *gin.Context) { // @Param request body dto.PageCronjob true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /cronjobs/search [post] func (b *BaseApi) SearchCronjob(c *gin.Context) { var req dto.PageCronjob @@ -82,6 +85,7 @@ func (b *BaseApi) SearchCronjob(c *gin.Context) { // @Param request body dto.SearchRecord true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /cronjobs/search/records [post] func (b *BaseApi) SearchJobRecords(c *gin.Context) { var req dto.SearchRecord @@ -109,8 +113,9 @@ func (b *BaseApi) SearchJobRecords(c *gin.Context) { // @Summary Load Cronjob record log // @Accept json // @Param request body dto.OperateByID true "request" -// @Success 200 +// @Success 200 {string} content // @Security ApiKeyAuth +// @Security Timestamp // @Router /cronjobs/records/log [post] func (b *BaseApi) LoadRecordLog(c *gin.Context) { var req dto.OperateByID @@ -127,6 +132,7 @@ func (b *BaseApi) LoadRecordLog(c *gin.Context) { // @Param request body dto.CronjobClean true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /cronjobs/records/clean [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"清空计划任务记录 [name]","formatEN":"clean cronjob [name] records"} func (b *BaseApi) CleanRecord(c *gin.Context) { @@ -140,7 +146,7 @@ func (b *BaseApi) CleanRecord(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Cronjob @@ -149,6 +155,7 @@ func (b *BaseApi) CleanRecord(c *gin.Context) { // @Param request body dto.CronjobBatchDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /cronjobs/del [post] // @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"cronjobs","output_column":"name","output_value":"names"}],"formatZH":"删除计划任务 [names]","formatEN":"delete cronjob [names]"} func (b *BaseApi) DeleteCronjob(c *gin.Context) { @@ -161,7 +168,7 @@ func (b *BaseApi) DeleteCronjob(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Cronjob @@ -170,6 +177,7 @@ func (b *BaseApi) DeleteCronjob(c *gin.Context) { // @Param request body dto.CronjobUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /cronjobs/update [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"更新计划任务 [name]","formatEN":"update cronjob [name]"} func (b *BaseApi) UpdateCronjob(c *gin.Context) { @@ -182,7 +190,7 @@ func (b *BaseApi) UpdateCronjob(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Cronjob @@ -191,6 +199,7 @@ func (b *BaseApi) UpdateCronjob(c *gin.Context) { // @Param request body dto.CronjobUpdateStatus true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /cronjobs/status [post] // @x-panel-log {"bodyKeys":["id","status"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"修改计划任务 [name] 状态为 [status]","formatEN":"change the status of cronjob [name] to [status]."} func (b *BaseApi) UpdateCronjobStatus(c *gin.Context) { @@ -203,7 +212,7 @@ func (b *BaseApi) UpdateCronjobStatus(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Cronjob @@ -212,6 +221,7 @@ func (b *BaseApi) UpdateCronjobStatus(c *gin.Context) { // @Param request body dto.CronjobDownload true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /cronjobs/download [post] // @x-panel-log {"bodyKeys":["recordID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"recordID","isList":false,"db":"job_records","output_column":"file","output_value":"file"}],"formatZH":"下载计划任务记录 [file]","formatEN":"download the cronjob record [file]"} func (b *BaseApi) TargetDownload(c *gin.Context) { @@ -235,6 +245,7 @@ func (b *BaseApi) TargetDownload(c *gin.Context) { // @Param request body dto.OperateByID true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /cronjobs/handle [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"手动执行计划任务 [name]","formatEN":"manually execute the cronjob [name]"} func (b *BaseApi) HandleOnce(c *gin.Context) { @@ -247,5 +258,5 @@ func (b *BaseApi) HandleOnce(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/dashboard.go b/agent/app/api/v2/dashboard.go index 5ef823fa8..a5b5b04a1 100644 --- a/agent/app/api/v2/dashboard.go +++ b/agent/app/api/v2/dashboard.go @@ -14,6 +14,7 @@ import ( // @Accept json // @Success 200 {object} dto.OsInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /dashboard/base/os [get] func (b *BaseApi) LoadDashboardOsInfo(c *gin.Context) { data, err := dashboardService.LoadOsInfo() @@ -27,8 +28,9 @@ func (b *BaseApi) LoadDashboardOsInfo(c *gin.Context) { // @Tags Dashboard // @Summary Load app launcher // @Accept json -// @Success 200 {Array} dto.dto.AppLauncher +// @Success 200 {Array} dto.AppLauncher // @Security ApiKeyAuth +// @Security Timestamp // @Router /dashboard/app/launcher [get] func (b *BaseApi) LoadAppLauncher(c *gin.Context) { data, err := dashboardService.LoadAppLauncher() @@ -45,6 +47,7 @@ func (b *BaseApi) LoadAppLauncher(c *gin.Context) { // @Param request body dto.SearchByFilter true "request" // @Success 200 {Array} dto.LauncherOption // @Security ApiKeyAuth +// @Security Timestamp // @Router /dashboard/app/launcher/option [post] func (b *BaseApi) LoadAppLauncherOption(c *gin.Context) { var req dto.SearchByFilter @@ -66,6 +69,7 @@ func (b *BaseApi) LoadAppLauncherOption(c *gin.Context) { // @Param netOption path string true "request" // @Success 200 {object} dto.DashboardBase // @Security ApiKeyAuth +// @Security Timestamp // @Router /dashboard/base/:ioOption/:netOption [get] func (b *BaseApi) LoadDashboardBaseInfo(c *gin.Context) { ioOption, ok := c.Params.Get("ioOption") @@ -90,6 +94,7 @@ func (b *BaseApi) LoadDashboardBaseInfo(c *gin.Context) { // @Summary Load dashboard current info for node // @Success 200 {object} dto.NodeCurrent // @Security ApiKeyAuth +// @Security Timestamp // @Router /dashboard/current/node [get] func (b *BaseApi) LoadCurrentInfoForNode(c *gin.Context) { data := dashboardService.LoadCurrentInfoForNode() @@ -103,6 +108,7 @@ func (b *BaseApi) LoadCurrentInfoForNode(c *gin.Context) { // @Param netOption path string true "request" // @Success 200 {object} dto.DashboardCurrent // @Security ApiKeyAuth +// @Security Timestamp // @Router /dashboard/current/:ioOption/:netOption [get] func (b *BaseApi) LoadDashboardCurrentInfo(c *gin.Context) { ioOption, ok := c.Params.Get("ioOption") @@ -126,6 +132,7 @@ func (b *BaseApi) LoadDashboardCurrentInfo(c *gin.Context) { // @Param operation path string true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /dashboard/system/restart/:operation [post] func (b *BaseApi) SystemRestart(c *gin.Context) { operation, ok := c.Params.Get("operation") @@ -137,5 +144,5 @@ func (b *BaseApi) SystemRestart(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/database.go b/agent/app/api/v2/database.go index c2eb67b16..edb849cd7 100644 --- a/agent/app/api/v2/database.go +++ b/agent/app/api/v2/database.go @@ -14,6 +14,7 @@ import ( // @Param request body dto.DatabaseCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/db [post] // @x-panel-log {"bodyKeys":["name", "type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建远程数据库 [name][type]","formatEN":"create database [name][type]"} func (b *BaseApi) CreateDatabase(c *gin.Context) { @@ -34,15 +35,16 @@ func (b *BaseApi) CreateDatabase(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database // @Summary Check database // @Accept json // @Param request body dto.DatabaseCreate true "request" -// @Success 200 +// @Success 200 {boolean} isOk // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/db/check [post] // @x-panel-log {"bodyKeys":["name", "type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"检测远程数据库 [name][type] 连接性","formatEN":"check if database [name][type] is connectable"} func (b *BaseApi) CheckDatabase(c *gin.Context) { @@ -68,6 +70,7 @@ func (b *BaseApi) CheckDatabase(c *gin.Context) { // @Param request body dto.DatabaseSearch true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/db/search [post] func (b *BaseApi) SearchDatabase(c *gin.Context) { var req dto.DatabaseSearch @@ -91,6 +94,7 @@ func (b *BaseApi) SearchDatabase(c *gin.Context) { // @Summary List databases // @Success 200 {array} dto.DatabaseOption // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/db/list/:type [get] func (b *BaseApi) ListDatabase(c *gin.Context) { dbType, err := helper.GetStrParamByKey(c, "type") @@ -111,6 +115,7 @@ func (b *BaseApi) ListDatabase(c *gin.Context) { // @Summary List databases // @Success 200 {array} dto.DatabaseItem // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/db/item/:type [get] func (b *BaseApi) LoadDatabaseItems(c *gin.Context) { dbType, err := helper.GetStrParamByKey(c, "type") @@ -131,6 +136,7 @@ func (b *BaseApi) LoadDatabaseItems(c *gin.Context) { // @Summary Get databases // @Success 200 {object} dto.DatabaseInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/db/:name [get] func (b *BaseApi) GetDatabase(c *gin.Context) { name, err := helper.GetStrParamByKey(c, "name") @@ -153,6 +159,7 @@ func (b *BaseApi) GetDatabase(c *gin.Context) { // @Param request body dto.OperateByID true "request" // @Success 200 {array} string // @Security ApiKeyAuth +// @Security Timestamp // @Router /db/remote/del/check [post] func (b *BaseApi) DeleteCheckDatabase(c *gin.Context) { var req dto.OperateByID @@ -174,6 +181,7 @@ func (b *BaseApi) DeleteCheckDatabase(c *gin.Context) { // @Param request body dto.DatabaseDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/db/del [post] // @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"databases","output_column":"name","output_value":"names"}],"formatZH":"删除远程数据库 [names]","formatEN":"delete database [names]"} func (b *BaseApi) DeleteDatabase(c *gin.Context) { @@ -186,7 +194,7 @@ func (b *BaseApi) DeleteDatabase(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database @@ -195,6 +203,7 @@ func (b *BaseApi) DeleteDatabase(c *gin.Context) { // @Param request body dto.DatabaseUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/db/update [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新远程数据库 [name]","formatEN":"update database [name]"} func (b *BaseApi) UpdateDatabase(c *gin.Context) { @@ -215,5 +224,5 @@ func (b *BaseApi) UpdateDatabase(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/database_common.go b/agent/app/api/v2/database_common.go index 45ac9b898..8ae18a62b 100644 --- a/agent/app/api/v2/database_common.go +++ b/agent/app/api/v2/database_common.go @@ -12,6 +12,7 @@ import ( // @Param request body dto.OperationWithNameAndType true "request" // @Success 200 {object} dto.DBBaseInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/common/info [post] func (b *BaseApi) LoadDBBaseInfo(c *gin.Context) { var req dto.OperationWithNameAndType @@ -32,8 +33,9 @@ func (b *BaseApi) LoadDBBaseInfo(c *gin.Context) { // @Summary Load Database conf // @Accept json // @Param request body dto.OperationWithNameAndType true "request" -// @Success 200 +// @Success 200 {string} content // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/common/load/file [post] func (b *BaseApi) LoadDBFile(c *gin.Context) { var req dto.OperationWithNameAndType @@ -54,6 +56,7 @@ func (b *BaseApi) LoadDBFile(c *gin.Context) { // @Param request body dto.DBConfUpdateByFile true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/common/update/conf [post] // @x-panel-log {"bodyKeys":["type","database"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 [type] 数据库 [database] 配置信息","formatEN":"update the [type] [database] database configuration information"} func (b *BaseApi) UpdateDBConfByFile(c *gin.Context) { @@ -67,5 +70,5 @@ func (b *BaseApi) UpdateDBConfByFile(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/database_mysql.go b/agent/app/api/v2/database_mysql.go index a70fc0bbb..8ecf83f75 100644 --- a/agent/app/api/v2/database_mysql.go +++ b/agent/app/api/v2/database_mysql.go @@ -15,6 +15,7 @@ import ( // @Param request body dto.MysqlDBCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建 mysql 数据库 [name]","formatEN":"create mysql database [name]"} func (b *BaseApi) CreateMysql(c *gin.Context) { @@ -36,7 +37,7 @@ func (b *BaseApi) CreateMysql(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database Mysql @@ -45,6 +46,7 @@ func (b *BaseApi) CreateMysql(c *gin.Context) { // @Param request body dto.BindUser true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/bind [post] // @x-panel-log {"bodyKeys":["database", "username"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"绑定 mysql 数据库名 [database] [username]","formatEN":"bind mysql database [database] [username]"} func (b *BaseApi) BindUser(c *gin.Context) { @@ -66,7 +68,7 @@ func (b *BaseApi) BindUser(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database Mysql @@ -75,6 +77,7 @@ func (b *BaseApi) BindUser(c *gin.Context) { // @Param request body dto.UpdateDescription true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/description/update [post] // @x-panel-log {"bodyKeys":["id","description"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_mysqls","output_column":"name","output_value":"name"}],"formatZH":"mysql 数据库 [name] 描述信息修改 [description]","formatEN":"The description of the mysql database [name] is modified => [description]"} func (b *BaseApi) UpdateMysqlDescription(c *gin.Context) { @@ -87,7 +90,7 @@ func (b *BaseApi) UpdateMysqlDescription(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database Mysql @@ -96,6 +99,7 @@ func (b *BaseApi) UpdateMysqlDescription(c *gin.Context) { // @Param request body dto.ChangeDBInfo true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/change/password [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_mysqls","output_column":"name","output_value":"name"}],"formatZH":"更新数据库 [name] 密码","formatEN":"Update database [name] password"} func (b *BaseApi) ChangeMysqlPassword(c *gin.Context) { @@ -117,7 +121,7 @@ func (b *BaseApi) ChangeMysqlPassword(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database Mysql @@ -126,6 +130,7 @@ func (b *BaseApi) ChangeMysqlPassword(c *gin.Context) { // @Param request body dto.ChangeDBInfo true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/change/access [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_mysqls","output_column":"name","output_value":"name"}],"formatZH":"更新数据库 [name] 访问权限","formatEN":"Update database [name] access"} func (b *BaseApi) ChangeMysqlAccess(c *gin.Context) { @@ -138,7 +143,7 @@ func (b *BaseApi) ChangeMysqlAccess(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database Mysql @@ -147,6 +152,7 @@ func (b *BaseApi) ChangeMysqlAccess(c *gin.Context) { // @Param request body dto.MysqlVariablesUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/variables/update [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"调整 mysql 数据库性能参数","formatEN":"adjust mysql database performance parameters"} func (b *BaseApi) UpdateMysqlVariables(c *gin.Context) { @@ -159,7 +165,7 @@ func (b *BaseApi) UpdateMysqlVariables(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database Mysql @@ -168,6 +174,7 @@ func (b *BaseApi) UpdateMysqlVariables(c *gin.Context) { // @Param request body dto.MysqlDBSearch true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/search [post] func (b *BaseApi) SearchMysql(c *gin.Context) { var req dto.MysqlDBSearch @@ -193,6 +200,7 @@ func (b *BaseApi) SearchMysql(c *gin.Context) { // @Param request body dto.PageInfo true "request" // @Success 200 {array} dto.MysqlOption // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/options [get] func (b *BaseApi) ListDBName(c *gin.Context) { list, err := mysqlService.ListDBOption() @@ -209,6 +217,7 @@ func (b *BaseApi) ListDBName(c *gin.Context) { // @Accept json // @Param request body dto.MysqlLoadDB true "request" // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/load [post] func (b *BaseApi) LoadDBFromRemote(c *gin.Context) { var req dto.MysqlLoadDB @@ -221,7 +230,7 @@ func (b *BaseApi) LoadDBFromRemote(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database Mysql @@ -230,6 +239,7 @@ func (b *BaseApi) LoadDBFromRemote(c *gin.Context) { // @Param request body dto.MysqlDBDeleteCheck true "request" // @Success 200 {array} string // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/del/check [post] func (b *BaseApi) DeleteCheckMysql(c *gin.Context) { var req dto.MysqlDBDeleteCheck @@ -251,6 +261,7 @@ func (b *BaseApi) DeleteCheckMysql(c *gin.Context) { // @Param request body dto.MysqlDBDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/del [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_mysqls","output_column":"name","output_value":"name"}],"formatZH":"删除 mysql 数据库 [name]","formatEN":"delete mysql database [name]"} func (b *BaseApi) DeleteMysql(c *gin.Context) { @@ -266,7 +277,7 @@ func (b *BaseApi) DeleteMysql(c *gin.Context) { return } tx.Commit() - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database Mysql @@ -275,6 +286,7 @@ func (b *BaseApi) DeleteMysql(c *gin.Context) { // @Param request body dto.OperationWithNameAndType true "request" // @Success 200 {boolean} isRemote // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/remote [post] func (b *BaseApi) LoadRemoteAccess(c *gin.Context) { var req dto.OperationWithNameAndType @@ -296,6 +308,7 @@ func (b *BaseApi) LoadRemoteAccess(c *gin.Context) { // @Param request body dto.OperationWithNameAndType true "request" // @Success 200 {object} dto.MysqlStatus // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/status [post] func (b *BaseApi) LoadStatus(c *gin.Context) { var req dto.OperationWithNameAndType @@ -318,6 +331,7 @@ func (b *BaseApi) LoadStatus(c *gin.Context) { // @Param request body dto.OperationWithNameAndType true "request" // @Success 200 {object} dto.MysqlVariables // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/variables [post] func (b *BaseApi) LoadVariables(c *gin.Context) { var req dto.OperationWithNameAndType diff --git a/agent/app/api/v2/database_postgresql.go b/agent/app/api/v2/database_postgresql.go index a9e061c5f..5926a850c 100644 --- a/agent/app/api/v2/database_postgresql.go +++ b/agent/app/api/v2/database_postgresql.go @@ -15,6 +15,7 @@ import ( // @Param request body dto.PostgresqlDBCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/pg [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建 postgresql 数据库 [name]","formatEN":"create postgresql database [name]"} func (b *BaseApi) CreatePostgresql(c *gin.Context) { @@ -36,7 +37,7 @@ func (b *BaseApi) CreatePostgresql(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database Postgresql @@ -45,6 +46,7 @@ func (b *BaseApi) CreatePostgresql(c *gin.Context) { // @Param request body dto.PostgresqlBindUser true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/pg/bind [post] // @x-panel-log {"bodyKeys":["name", "username"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"绑定 postgresql 数据库 [name] 用户 [username]","formatEN":"bind postgresql database [name] user [username]"} func (b *BaseApi) BindPostgresqlUser(c *gin.Context) { @@ -57,7 +59,7 @@ func (b *BaseApi) BindPostgresqlUser(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database Postgresql @@ -66,6 +68,7 @@ func (b *BaseApi) BindPostgresqlUser(c *gin.Context) { // @Param request body dto.UpdateDescription true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/pg/description [post] // @x-panel-log {"bodyKeys":["id","description"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_postgresqls","output_column":"name","output_value":"name"}],"formatZH":"postgresql 数据库 [name] 描述信息修改 [description]","formatEN":"The description of the postgresql database [name] is modified => [description]"} func (b *BaseApi) UpdatePostgresqlDescription(c *gin.Context) { @@ -78,7 +81,7 @@ func (b *BaseApi) UpdatePostgresqlDescription(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database Postgresql @@ -87,6 +90,7 @@ func (b *BaseApi) UpdatePostgresqlDescription(c *gin.Context) { // @Param request body dto.ChangeDBInfo true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/pg/privileges [post] // @x-panel-log {"bodyKeys":["database", "username"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新数据库 [database] 用户 [username] 权限","formatEN":"Update [user] privileges of database [database]"} func (b *BaseApi) ChangePostgresqlPrivileges(c *gin.Context) { @@ -99,7 +103,7 @@ func (b *BaseApi) ChangePostgresqlPrivileges(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database Postgresql @@ -108,6 +112,7 @@ func (b *BaseApi) ChangePostgresqlPrivileges(c *gin.Context) { // @Param request body dto.ChangeDBInfo true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/pg/password [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_postgresqls","output_column":"name","output_value":"name"}],"formatZH":"更新数据库 [name] 密码","formatEN":"Update database [name] password"} func (b *BaseApi) ChangePostgresqlPassword(c *gin.Context) { @@ -129,7 +134,7 @@ func (b *BaseApi) ChangePostgresqlPassword(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database Postgresql @@ -138,6 +143,7 @@ func (b *BaseApi) ChangePostgresqlPassword(c *gin.Context) { // @Param request body dto.PostgresqlDBSearch true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/pg/search [post] func (b *BaseApi) SearchPostgresql(c *gin.Context) { var req dto.PostgresqlDBSearch @@ -162,6 +168,7 @@ func (b *BaseApi) SearchPostgresql(c *gin.Context) { // @Accept json // @Param request body dto.PostgresqlLoadDB true "request" // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/pg/:database/load [post] func (b *BaseApi) LoadPostgresqlDBFromRemote(c *gin.Context) { database, err := helper.GetStrParamByKey(c, "database") @@ -175,7 +182,7 @@ func (b *BaseApi) LoadPostgresqlDBFromRemote(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database Postgresql @@ -184,6 +191,7 @@ func (b *BaseApi) LoadPostgresqlDBFromRemote(c *gin.Context) { // @Param request body dto.PostgresqlDBDeleteCheck true "request" // @Success 200 {array} string // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/pg/del/check [post] func (b *BaseApi) DeleteCheckPostgresql(c *gin.Context) { var req dto.PostgresqlDBDeleteCheck @@ -205,6 +213,7 @@ func (b *BaseApi) DeleteCheckPostgresql(c *gin.Context) { // @Param request body dto.PostgresqlDBDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/pg/del [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_postgresqls","output_column":"name","output_value":"name"}],"formatZH":"删除 postgresql 数据库 [name]","formatEN":"delete postgresql database [name]"} func (b *BaseApi) DeletePostgresql(c *gin.Context) { @@ -219,5 +228,5 @@ func (b *BaseApi) DeletePostgresql(c *gin.Context) { return } tx.Commit() - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/database_redis.go b/agent/app/api/v2/database_redis.go index ee599e423..ac1d47b51 100644 --- a/agent/app/api/v2/database_redis.go +++ b/agent/app/api/v2/database_redis.go @@ -14,6 +14,7 @@ import ( // @Param request body dto.OperationWithName true "request" // @Success 200 {object} dto.RedisStatus // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/redis/status [post] func (b *BaseApi) LoadRedisStatus(c *gin.Context) { var req dto.OperationWithName @@ -35,6 +36,7 @@ func (b *BaseApi) LoadRedisStatus(c *gin.Context) { // @Param request body dto.OperationWithName true "request" // @Success 200 {object} dto.RedisConf // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/redis/conf [post] func (b *BaseApi) LoadRedisConf(c *gin.Context) { var req dto.OperationWithName @@ -56,6 +58,7 @@ func (b *BaseApi) LoadRedisConf(c *gin.Context) { // @Param request body dto.OperationWithName true "request" // @Success 200 {object} dto.RedisPersistence // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/redis/persistence/conf [post] func (b *BaseApi) LoadPersistenceConf(c *gin.Context) { var req dto.OperationWithName @@ -79,6 +82,7 @@ func (b *BaseApi) CheckHasCli(c *gin.Context) { // @Summary Install redis-cli // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/redis/install/cli [post] func (b *BaseApi) InstallCli(c *gin.Context) { if err := redisService.InstallCli(); err != nil { @@ -95,6 +99,7 @@ func (b *BaseApi) InstallCli(c *gin.Context) { // @Param request body dto.RedisConfUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/redis/conf/update [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 redis 数据库配置信息","formatEN":"update the redis database configuration information"} func (b *BaseApi) UpdateRedisConf(c *gin.Context) { @@ -107,7 +112,7 @@ func (b *BaseApi) UpdateRedisConf(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database Redis @@ -116,6 +121,7 @@ func (b *BaseApi) UpdateRedisConf(c *gin.Context) { // @Param request body dto.ChangeRedisPass true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/redis/password [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 redis 数据库密码","formatEN":"change the password of the redis database"} func (b *BaseApi) ChangeRedisPassword(c *gin.Context) { @@ -137,7 +143,7 @@ func (b *BaseApi) ChangeRedisPassword(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Database Redis @@ -146,6 +152,7 @@ func (b *BaseApi) ChangeRedisPassword(c *gin.Context) { // @Param request body dto.RedisConfPersistenceUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /databases/redis/persistence/update [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"redis 数据库持久化配置更新","formatEN":"redis database persistence configuration update"} func (b *BaseApi) UpdateRedisPersistenceConf(c *gin.Context) { @@ -158,5 +165,5 @@ func (b *BaseApi) UpdateRedisPersistenceConf(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/device.go b/agent/app/api/v2/device.go index 473c39d3f..4a1e81f78 100644 --- a/agent/app/api/v2/device.go +++ b/agent/app/api/v2/device.go @@ -12,6 +12,7 @@ import ( // @Summary Load device base info // @Success 200 {object} dto.DeviceBaseInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/device/base [post] func (b *BaseApi) LoadDeviceBaseInfo(c *gin.Context) { data, err := deviceService.LoadBaseInfo() @@ -28,6 +29,7 @@ func (b *BaseApi) LoadDeviceBaseInfo(c *gin.Context) { // @Accept json // @Success 200 {Array} string // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/device/zone/options [get] func (b *BaseApi) LoadTimeOption(c *gin.Context) { list, err := deviceService.LoadTimeZone() @@ -43,8 +45,9 @@ func (b *BaseApi) LoadTimeOption(c *gin.Context) { // @Summary load conf // @Accept json // @Param request body dto.OperationWithName true "request" -// @Success 200 +// @Success 200 {array} string // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/device/conf [post] func (b *BaseApi) LoadDeviceConf(c *gin.Context) { var req dto.OperationWithName @@ -67,6 +70,7 @@ func (b *BaseApi) LoadDeviceConf(c *gin.Context) { // @Param request body dto.UpdateByNameAndFile true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/device/update/byconf [post] func (b *BaseApi) UpdateDeviceByFile(c *gin.Context) { var req dto.UpdateByNameAndFile @@ -78,13 +82,14 @@ func (b *BaseApi) UpdateDeviceByFile(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Device // @Summary Load user list // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/device/users [get] func (b *BaseApi) LoadUsers(c *gin.Context) { users, err := deviceService.LoadUsers() @@ -101,6 +106,7 @@ func (b *BaseApi) LoadUsers(c *gin.Context) { // @Param request body dto.SettingUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/device/update/conf [post] // @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改主机参数 [key] => [value]","formatEN":"update device conf [key] => [value]"} func (b *BaseApi) UpdateDeviceConf(c *gin.Context) { @@ -114,13 +120,14 @@ func (b *BaseApi) UpdateDeviceConf(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Device // @Summary Update device hosts // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/device/update/host [post] // @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改主机 Host [key] => [value]","formatEN":"update device host [key] => [value]"} func (b *BaseApi) UpdateDeviceHost(c *gin.Context) { @@ -134,7 +141,7 @@ func (b *BaseApi) UpdateDeviceHost(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Device @@ -143,6 +150,7 @@ func (b *BaseApi) UpdateDeviceHost(c *gin.Context) { // @Param request body dto.ChangePasswd true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/device/update/passwd [post] func (b *BaseApi) UpdateDevicePasswd(c *gin.Context) { var req dto.ChangePasswd @@ -162,7 +170,7 @@ func (b *BaseApi) UpdateDevicePasswd(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Device @@ -171,6 +179,7 @@ func (b *BaseApi) UpdateDevicePasswd(c *gin.Context) { // @Param request body dto.SwapHelper true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/device/update/swap [post] // @x-panel-log {"bodyKeys":["operate","path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] 主机 swap [path]","formatEN":"[operate] device swap [path]"} func (b *BaseApi) UpdateDeviceSwap(c *gin.Context) { @@ -183,15 +192,16 @@ func (b *BaseApi) UpdateDeviceSwap(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Device // @Summary Check device DNS conf // @Accept json // @Param request body dto.SettingUpdate true "request" -// @Success 200 +// @Success 200 {boolean} data // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/device/check/dns [post] func (b *BaseApi) CheckDNS(c *gin.Context) { var req dto.SettingUpdate @@ -210,8 +220,9 @@ func (b *BaseApi) CheckDNS(c *gin.Context) { // @Tags Device // @Summary Scan system -// @Success 200 +// @Success 200 {object} dto.CleanData // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/scan [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"扫描系统垃圾文件","formatEN":"scan System Junk Files"} func (b *BaseApi) ScanSystem(c *gin.Context) { @@ -224,6 +235,7 @@ func (b *BaseApi) ScanSystem(c *gin.Context) { // @Param request body []dto.Clean true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/clean [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理系统垃圾文件","formatEN":"Clean system junk files"} func (b *BaseApi) SystemClean(c *gin.Context) { @@ -234,5 +246,5 @@ func (b *BaseApi) SystemClean(c *gin.Context) { deviceService.Clean(req) - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/docker.go b/agent/app/api/v2/docker.go index 09fa94267..9b22de872 100644 --- a/agent/app/api/v2/docker.go +++ b/agent/app/api/v2/docker.go @@ -14,6 +14,7 @@ import ( // @Produce json // @Success 200 {string} status // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/docker/status [get] func (b *BaseApi) LoadDockerStatus(c *gin.Context) { status := dockerService.LoadDockerStatus() @@ -25,6 +26,7 @@ func (b *BaseApi) LoadDockerStatus(c *gin.Context) { // @Produce json // @Success 200 {object} string // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/daemonjson/file [get] func (b *BaseApi) LoadDaemonJsonFile(c *gin.Context) { if _, err := os.Stat(constant.DaemonJsonPath); err != nil { @@ -44,6 +46,7 @@ func (b *BaseApi) LoadDaemonJsonFile(c *gin.Context) { // @Produce json // @Success 200 {object} dto.DaemonJsonConf // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/daemonjson [get] func (b *BaseApi) LoadDaemonJson(c *gin.Context) { conf := dockerService.LoadDockerConf() @@ -56,6 +59,7 @@ func (b *BaseApi) LoadDaemonJson(c *gin.Context) { // @Param request body dto.SettingUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/daemonjson/update [post] // @x-panel-log {"bodyKeys":["key", "value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新配置 [key]","formatEN":"Updated configuration [key]"} func (b *BaseApi) UpdateDaemonJson(c *gin.Context) { @@ -69,7 +73,7 @@ func (b *BaseApi) UpdateDaemonJson(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container Docker @@ -78,6 +82,7 @@ func (b *BaseApi) UpdateDaemonJson(c *gin.Context) { // @Param request body dto.LogOption true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/logoption/update [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新日志配置","formatEN":"Updated the log option"} func (b *BaseApi) UpdateLogOption(c *gin.Context) { @@ -91,7 +96,7 @@ func (b *BaseApi) UpdateLogOption(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container Docker @@ -100,6 +105,7 @@ func (b *BaseApi) UpdateLogOption(c *gin.Context) { // @Param request body dto.LogOption true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/ipv6option/update [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 ipv6 配置","formatEN":"Updated the ipv6 option"} func (b *BaseApi) UpdateIpv6Option(c *gin.Context) { @@ -113,7 +119,7 @@ func (b *BaseApi) UpdateIpv6Option(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container Docker @@ -122,6 +128,7 @@ func (b *BaseApi) UpdateIpv6Option(c *gin.Context) { // @Param request body dto.DaemonJsonUpdateByFile true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/daemonjson/update/byfile [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新配置文件","formatEN":"Updated configuration file"} func (b *BaseApi) UpdateDaemonJsonByFile(c *gin.Context) { @@ -135,7 +142,7 @@ func (b *BaseApi) UpdateDaemonJsonByFile(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container Docker @@ -144,6 +151,7 @@ func (b *BaseApi) UpdateDaemonJsonByFile(c *gin.Context) { // @Param request body dto.DockerOperation true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/docker/operate [post] // @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"docker 服务 [operation]","formatEN":"[operation] docker service"} func (b *BaseApi) OperateDocker(c *gin.Context) { @@ -157,5 +165,5 @@ func (b *BaseApi) OperateDocker(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/fail2ban.go b/agent/app/api/v2/fail2ban.go index c1eb05381..780e90c48 100644 --- a/agent/app/api/v2/fail2ban.go +++ b/agent/app/api/v2/fail2ban.go @@ -12,6 +12,7 @@ import ( // @Summary Load fail2ban base info // @Success 200 {object} dto.Fail2BanBaseInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/fail2ban/base [get] func (b *BaseApi) LoadFail2BanBaseInfo(c *gin.Context) { data, err := fail2banService.LoadBaseInfo() @@ -29,6 +30,7 @@ func (b *BaseApi) LoadFail2BanBaseInfo(c *gin.Context) { // @Param request body dto.Fail2BanSearch true "request" // @Success 200 {Array} string // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/fail2ban/search [post] func (b *BaseApi) SearchFail2Ban(c *gin.Context) { var req dto.Fail2BanSearch @@ -50,6 +52,7 @@ func (b *BaseApi) SearchFail2Ban(c *gin.Context) { // @Accept json // @Param request body dto.Operate true "request" // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/fail2ban/operate [post] // @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operation] Fail2ban","formatEN":"[operation] Fail2ban"} func (b *BaseApi) OperateFail2Ban(c *gin.Context) { @@ -63,7 +66,7 @@ func (b *BaseApi) OperateFail2Ban(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Fail2ban @@ -71,6 +74,7 @@ func (b *BaseApi) OperateFail2Ban(c *gin.Context) { // @Accept json // @Param request body dto.Operate true "request" // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/fail2ban/operate/sshd [post] func (b *BaseApi) OperateSSHD(c *gin.Context) { var req dto.Fail2BanSet @@ -83,7 +87,7 @@ func (b *BaseApi) OperateSSHD(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Fail2ban @@ -92,6 +96,7 @@ func (b *BaseApi) OperateSSHD(c *gin.Context) { // @Param request body dto.Fail2BanUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/fail2ban/update [post] // @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 Fail2ban 配置 [key] => [value]","formatEN":"update fail2ban conf [key] => [value]"} func (b *BaseApi) UpdateFail2BanConf(c *gin.Context) { @@ -104,14 +109,15 @@ func (b *BaseApi) UpdateFail2BanConf(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Fail2ban // @Summary Load fail2ban conf // @Accept json -// @Success 200 +// @Success 200 {string} file // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/fail2ban/load/conf [get] func (b *BaseApi) LoadFail2BanConf(c *gin.Context) { path := "/etc/fail2ban/jail.local" @@ -130,6 +136,7 @@ func (b *BaseApi) LoadFail2BanConf(c *gin.Context) { // @Param request body dto.UpdateByFile true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/fail2ban/update/byconf [post] func (b *BaseApi) UpdateFail2BanConfByFile(c *gin.Context) { var req dto.UpdateByFile @@ -141,5 +148,5 @@ func (b *BaseApi) UpdateFail2BanConfByFile(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/favorite.go b/agent/app/api/v2/favorite.go index 0161a5b4c..b82301323 100644 --- a/agent/app/api/v2/favorite.go +++ b/agent/app/api/v2/favorite.go @@ -11,8 +11,9 @@ import ( // @Summary List favorites // @Accept json // @Param request body dto.PageInfo true "request" -// @Success 200 +// @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/favorite/search [post] func (b *BaseApi) SearchFavorite(c *gin.Context) { var req dto.PageInfo @@ -34,8 +35,9 @@ func (b *BaseApi) SearchFavorite(c *gin.Context) { // @Summary Create favorite // @Accept json // @Param request body request.FavoriteCreate true "request" -// @Success 200 +// @Success 200 {object} model.Favorite // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/favorite [post] // @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"收藏文件/文件夹 [path]","formatEN":"收藏文件/文件夹 [path]"} func (b *BaseApi) CreateFavorite(c *gin.Context) { @@ -57,6 +59,7 @@ func (b *BaseApi) CreateFavorite(c *gin.Context) { // @Param request body request.FavoriteDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/favorite/del [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"favorites","output_column":"path","output_value":"path"}],"formatZH":"删除收藏 [path]","formatEN":"delete avorite [path]"} func (b *BaseApi) DeleteFavorite(c *gin.Context) { diff --git a/agent/app/api/v2/file.go b/agent/app/api/v2/file.go index 3160b205f..31e184166 100644 --- a/agent/app/api/v2/file.go +++ b/agent/app/api/v2/file.go @@ -32,26 +32,28 @@ import ( // @Param request body request.FileOption true "request" // @Success 200 {object} response.FileInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/search [post] func (b *BaseApi) ListFiles(c *gin.Context) { var req request.FileOption if err := helper.CheckBindAndValidate(&req, c); err != nil { return } - files, err := fileService.GetFileList(req) + fileList, err := fileService.GetFileList(req) if err != nil { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, files) + helper.SuccessWithData(c, fileList) } // @Tags File // @Summary Page file // @Accept json // @Param request body request.SearchUploadWithPage true "request" -// @Success 200 {array} response.FileInfo +// @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/upload/search [post] func (b *BaseApi) SearchUploadWithPage(c *gin.Context) { var req request.SearchUploadWithPage @@ -75,6 +77,7 @@ func (b *BaseApi) SearchUploadWithPage(c *gin.Context) { // @Param request body request.FileOption true "request" // @Success 200 {array} response.FileTree // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/tree [post] func (b *BaseApi) GetFileTree(c *gin.Context) { var req request.FileOption @@ -95,6 +98,7 @@ func (b *BaseApi) GetFileTree(c *gin.Context) { // @Param request body request.FileCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files [post] // @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建文件/文件夹 [path]","formatEN":"Create dir or file [path]"} func (b *BaseApi) CreateFile(c *gin.Context) { @@ -107,7 +111,7 @@ func (b *BaseApi) CreateFile(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags File @@ -116,6 +120,7 @@ func (b *BaseApi) CreateFile(c *gin.Context) { // @Param request body request.FileDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/del [post] // @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除文件/文件夹 [path]","formatEN":"Delete dir or file [path]"} func (b *BaseApi) DeleteFile(c *gin.Context) { @@ -128,7 +133,7 @@ func (b *BaseApi) DeleteFile(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags File @@ -137,6 +142,7 @@ func (b *BaseApi) DeleteFile(c *gin.Context) { // @Param request body request.FileBatchDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/batch/del [post] // @x-panel-log {"bodyKeys":["paths"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"批量删除文件/文件夹 [paths]","formatEN":"Batch delete dir or file [paths]"} func (b *BaseApi) BatchDeleteFile(c *gin.Context) { @@ -149,7 +155,7 @@ func (b *BaseApi) BatchDeleteFile(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags File @@ -158,6 +164,7 @@ func (b *BaseApi) BatchDeleteFile(c *gin.Context) { // @Param request body request.FileCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/mode [post] // @x-panel-log {"bodyKeys":["path","mode"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改权限 [paths] => [mode]","formatEN":"Change mode [paths] => [mode]"} func (b *BaseApi) ChangeFileMode(c *gin.Context) { @@ -179,6 +186,7 @@ func (b *BaseApi) ChangeFileMode(c *gin.Context) { // @Param request body request.FileRoleUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/owner [post] // @x-panel-log {"bodyKeys":["path","user","group"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改用户/组 [paths] => [user]/[group]","formatEN":"Change owner [paths] => [user]/[group]"} func (b *BaseApi) ChangeFileOwner(c *gin.Context) { @@ -199,6 +207,7 @@ func (b *BaseApi) ChangeFileOwner(c *gin.Context) { // @Param request body request.FileCompress true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/compress [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"压缩文件 [name]","formatEN":"Compress file [name]"} func (b *BaseApi) CompressFile(c *gin.Context) { @@ -211,7 +220,7 @@ func (b *BaseApi) CompressFile(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags File @@ -220,6 +229,7 @@ func (b *BaseApi) CompressFile(c *gin.Context) { // @Param request body request.FileDeCompress true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/decompress [post] // @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"解压 [path]","formatEN":"Decompress file [path]"} func (b *BaseApi) DeCompressFile(c *gin.Context) { @@ -232,7 +242,7 @@ func (b *BaseApi) DeCompressFile(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags File @@ -241,6 +251,7 @@ func (b *BaseApi) DeCompressFile(c *gin.Context) { // @Param request body request.FileContentReq true "request" // @Success 200 {object} response.FileInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/content [post] // @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"获取文件内容 [path]","formatEN":"Load file content [path]"} func (b *BaseApi) GetContent(c *gin.Context) { @@ -262,6 +273,7 @@ func (b *BaseApi) GetContent(c *gin.Context) { // @Param request body request.FileEdit true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/save [post] // @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新文件内容 [path]","formatEN":"Update file content [path]"} func (b *BaseApi) SaveContent(c *gin.Context) { @@ -273,7 +285,7 @@ func (b *BaseApi) SaveContent(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags File @@ -281,6 +293,7 @@ func (b *BaseApi) SaveContent(c *gin.Context) { // @Param file formData file true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/upload [post] // @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"上传文件 [path]","formatEN":"Upload file [path]"} func (b *BaseApi) UploadFiles(c *gin.Context) { @@ -387,8 +400,9 @@ func (b *BaseApi) UploadFiles(c *gin.Context) { // @Summary Check file exist // @Accept json // @Param request body request.FilePathCheck true "request" -// @Success 200 +// @Success 200 {boolean} isOk // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/check [post] func (b *BaseApi) CheckFile(c *gin.Context) { var req request.FilePathCheck @@ -408,6 +422,7 @@ func (b *BaseApi) CheckFile(c *gin.Context) { // @Param request body request.FileRename true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/rename [post] // @x-panel-log {"bodyKeys":["oldName","newName"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"重命名 [oldName] => [newName]","formatEN":"Rename [oldName] => [newName]"} func (b *BaseApi) ChangeFileName(c *gin.Context) { @@ -419,15 +434,16 @@ func (b *BaseApi) ChangeFileName(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags File // @Summary Wget file // @Accept json // @Param request body request.FileWget true "request" -// @Success 200 +// @Success 200 {object} response.FileWgetRes // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/wget [post] // @x-panel-log {"bodyKeys":["url","path","name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"下载 url => [path]/[name]","formatEN":"Download url => [path]/[name]"} func (b *BaseApi) WgetFile(c *gin.Context) { @@ -451,6 +467,7 @@ func (b *BaseApi) WgetFile(c *gin.Context) { // @Param request body request.FileMove true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/move [post] // @x-panel-log {"bodyKeys":["oldPaths","newPath"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"移动文件 [oldPaths] => [newPath]","formatEN":"Move [oldPaths] => [newPath]"} func (b *BaseApi) MoveFile(c *gin.Context) { @@ -462,7 +479,7 @@ func (b *BaseApi) MoveFile(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags File @@ -470,6 +487,7 @@ func (b *BaseApi) MoveFile(c *gin.Context) { // @Accept json // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/download [get] func (b *BaseApi) Download(c *gin.Context) { filePath := c.Query("path") @@ -490,6 +508,7 @@ func (b *BaseApi) Download(c *gin.Context) { // @Param request body request.FileDownload true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/chunkdownload [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"下载文件 [name]","formatEN":"Download file [name]"} func (b *BaseApi) DownloadChunkFiles(c *gin.Context) { @@ -564,8 +583,9 @@ func (b *BaseApi) DownloadChunkFiles(c *gin.Context) { // @Summary Load file size // @Accept json // @Param request body request.DirSizeReq true "request" -// @Success 200 +// @Success 200 {object} response.DirSizeRes // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/size [post] // @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"获取文件夹大小 [path]","formatEN":"Load file size [path]"} func (b *BaseApi) Size(c *gin.Context) { @@ -633,6 +653,7 @@ func mergeChunks(fileName string, fileDir string, dstDir string, chunkCount int, // @Param file formData file true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/chunkupload [post] func (b *BaseApi) UploadChunkFiles(c *gin.Context) { var err error @@ -747,8 +768,9 @@ func (b *BaseApi) Keys(c *gin.Context) { // @Tags File // @Summary Read file by Line // @Param request body request.FileReadByLineReq true "request" -// @Success 200 +// @Success 200 {object} response.FileLineContent // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/read [post] func (b *BaseApi) ReadFileByLine(c *gin.Context) { var req request.FileReadByLineReq @@ -769,6 +791,7 @@ func (b *BaseApi) ReadFileByLine(c *gin.Context) { // @Param request body request.FileRoleReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/batch/role [post] // @x-panel-log {"bodyKeys":["paths","mode","user","group"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"批量修改文件权限和用户/组 [paths] => [mode]/[user]/[group]","formatEN":"Batch change file mode and owner [paths] => [mode]/[user]/[group]"} func (b *BaseApi) BatchChangeModeAndOwner(c *gin.Context) { diff --git a/agent/app/api/v2/firewall.go b/agent/app/api/v2/firewall.go index 9e8781c0c..cba6b4e9c 100644 --- a/agent/app/api/v2/firewall.go +++ b/agent/app/api/v2/firewall.go @@ -10,6 +10,7 @@ import ( // @Summary Load firewall base info // @Success 200 {object} dto.FirewallBaseInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /hosts/firewall/base [get] func (b *BaseApi) LoadFirewallBaseInfo(c *gin.Context) { data, err := firewallService.LoadBaseInfo() @@ -27,6 +28,7 @@ func (b *BaseApi) LoadFirewallBaseInfo(c *gin.Context) { // @Param request body dto.RuleSearch true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /hosts/firewall/search [post] func (b *BaseApi) SearchFirewallRule(c *gin.Context) { var req dto.RuleSearch @@ -47,11 +49,12 @@ func (b *BaseApi) SearchFirewallRule(c *gin.Context) { } // @Tags Firewall -// @Summary Page firewall status +// @Summary Operate firewall // @Accept json // @Param request body dto.FirewallOperation true "request" -// @Success 200 {object} dto.PageResult +// @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /hosts/firewall/operate [post] // @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operation] 防火墙","formatEN":"[operation] firewall"} func (b *BaseApi) OperateFirewall(c *gin.Context) { @@ -65,7 +68,7 @@ func (b *BaseApi) OperateFirewall(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Firewall @@ -74,6 +77,7 @@ func (b *BaseApi) OperateFirewall(c *gin.Context) { // @Param request body dto.PortRuleOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /hosts/firewall/port [post] // @x-panel-log {"bodyKeys":["port","strategy"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加端口规则 [strategy] [port]","formatEN":"create port rules [strategy][port]"} func (b *BaseApi) OperatePortRule(c *gin.Context) { @@ -86,7 +90,7 @@ func (b *BaseApi) OperatePortRule(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // OperateForwardRule @@ -96,6 +100,7 @@ func (b *BaseApi) OperatePortRule(c *gin.Context) { // @Param request body dto.ForwardRuleOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /hosts/firewall/forward [post] // @x-panel-log {"bodyKeys":["source_port"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新端口转发规则 [source_port]","formatEN":"update port forward rules [source_port]"} func (b *BaseApi) OperateForwardRule(c *gin.Context) { @@ -108,7 +113,7 @@ func (b *BaseApi) OperateForwardRule(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Firewall @@ -117,6 +122,7 @@ func (b *BaseApi) OperateForwardRule(c *gin.Context) { // @Param request body dto.AddrRuleOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /hosts/firewall/ip [post] // @x-panel-log {"bodyKeys":["strategy","address"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加 ip 规则 [strategy] [address]","formatEN":"create address rules [strategy][address]"} func (b *BaseApi) OperateIPRule(c *gin.Context) { @@ -129,7 +135,7 @@ func (b *BaseApi) OperateIPRule(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Firewall @@ -138,6 +144,7 @@ func (b *BaseApi) OperateIPRule(c *gin.Context) { // @Param request body dto.BatchRuleOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /hosts/firewall/batch [post] func (b *BaseApi) BatchOperateRule(c *gin.Context) { var req dto.BatchRuleOperate @@ -149,7 +156,7 @@ func (b *BaseApi) BatchOperateRule(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Firewall @@ -158,6 +165,7 @@ func (b *BaseApi) BatchOperateRule(c *gin.Context) { // @Param request body dto.UpdateFirewallDescription true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /hosts/firewall/update/description [post] func (b *BaseApi) UpdateFirewallDescription(c *gin.Context) { var req dto.UpdateFirewallDescription @@ -169,7 +177,7 @@ func (b *BaseApi) UpdateFirewallDescription(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Firewall @@ -178,6 +186,7 @@ func (b *BaseApi) UpdateFirewallDescription(c *gin.Context) { // @Param request body dto.PortRuleUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /hosts/firewall/update/port [post] func (b *BaseApi) UpdatePortRule(c *gin.Context) { var req dto.PortRuleUpdate @@ -189,7 +198,7 @@ func (b *BaseApi) UpdatePortRule(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Firewall @@ -198,6 +207,7 @@ func (b *BaseApi) UpdatePortRule(c *gin.Context) { // @Param request body dto.AddrRuleUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /hosts/firewall/update/addr [post] func (b *BaseApi) UpdateAddrRule(c *gin.Context) { var req dto.AddrRuleUpdate @@ -209,5 +219,5 @@ func (b *BaseApi) UpdateAddrRule(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/ftp.go b/agent/app/api/v2/ftp.go index 28db4e5a4..308f41695 100644 --- a/agent/app/api/v2/ftp.go +++ b/agent/app/api/v2/ftp.go @@ -13,6 +13,7 @@ import ( // @Summary Load FTP base info // @Success 200 {object} dto.FtpBaseInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/ftp/base [get] func (b *BaseApi) LoadFtpBaseInfo(c *gin.Context) { data, err := ftpService.LoadBaseInfo() @@ -30,6 +31,7 @@ func (b *BaseApi) LoadFtpBaseInfo(c *gin.Context) { // @Param request body dto.FtpLogSearch true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/ftp/log/search [post] func (b *BaseApi) LoadFtpLogInfo(c *gin.Context) { var req dto.FtpLogSearch @@ -54,6 +56,7 @@ func (b *BaseApi) LoadFtpLogInfo(c *gin.Context) { // @Accept json // @Param request body dto.Operate true "request" // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/ftp/operate [post] // @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operation] FTP","formatEN":"[operation] FTP"} func (b *BaseApi) OperateFtp(c *gin.Context) { @@ -67,7 +70,7 @@ func (b *BaseApi) OperateFtp(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags FTP @@ -76,6 +79,7 @@ func (b *BaseApi) OperateFtp(c *gin.Context) { // @Param request body dto.SearchWithPage true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/ftp/search [post] func (b *BaseApi) SearchFtp(c *gin.Context) { var req dto.SearchWithPage @@ -101,6 +105,7 @@ func (b *BaseApi) SearchFtp(c *gin.Context) { // @Param request body dto.FtpCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/ftp [post] // @x-panel-log {"bodyKeys":["user", "path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建 FTP 账户 [user][path]","formatEN":"create FTP [user][path]"} func (b *BaseApi) CreateFtp(c *gin.Context) { @@ -130,6 +135,7 @@ func (b *BaseApi) CreateFtp(c *gin.Context) { // @Param request body dto.BatchDeleteReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/ftp/del [post] // @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"ftps","output_column":"user","output_value":"users"}],"formatZH":"删除 FTP 账户 [users]","formatEN":"delete FTP users [users]"} func (b *BaseApi) DeleteFtp(c *gin.Context) { @@ -151,6 +157,7 @@ func (b *BaseApi) DeleteFtp(c *gin.Context) { // @Param request body dto.BatchDeleteReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/ftp/sync [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"同步 FTP 账户","formatEN":"sync FTP users"} func (b *BaseApi) SyncFtp(c *gin.Context) { @@ -167,6 +174,7 @@ func (b *BaseApi) SyncFtp(c *gin.Context) { // @Param request body dto.FtpUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /toolbox/ftp/update [post] // @x-panel-log {"bodyKeys":["user", "path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 FTP 账户 [user][path]","formatEN":"update FTP [user][path]"} func (b *BaseApi) UpdateFtp(c *gin.Context) { diff --git a/agent/app/api/v2/host_tool.go b/agent/app/api/v2/host_tool.go index 1bb17882f..010b15261 100644 --- a/agent/app/api/v2/host_tool.go +++ b/agent/app/api/v2/host_tool.go @@ -7,11 +7,12 @@ import ( ) // @Tags Host tool -// @Summary Get tool +// @Summary Get tool status // @Accept json // @Param request body request.HostToolReq true "request" -// @Success 200 +// @Success 200 {object} response.HostToolRes // @Security ApiKeyAuth +// @Security Timestamp // @Router /host/tool [post] func (b *BaseApi) GetToolStatus(c *gin.Context) { var req request.HostToolReq @@ -33,6 +34,7 @@ func (b *BaseApi) GetToolStatus(c *gin.Context) { // @Param request body request.HostToolCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /host/tool/create [post] // @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建 [type] 配置","formatEN":"create [type] config"} func (b *BaseApi) InitToolConfig(c *gin.Context) { @@ -54,6 +56,7 @@ func (b *BaseApi) InitToolConfig(c *gin.Context) { // @Param request body request.HostToolReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /host/tool/operate [post] // @x-panel-log {"bodyKeys":["operate","type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] [type] ","formatEN":"[operate] [type]"} func (b *BaseApi) OperateTool(c *gin.Context) { @@ -73,8 +76,9 @@ func (b *BaseApi) OperateTool(c *gin.Context) { // @Summary Get tool config // @Accept json // @Param request body request.HostToolConfig true "request" -// @Success 200 +// @Success 200 {object} response.HostToolConfig // @Security ApiKeyAuth +// @Security Timestamp // @Router /host/tool/config [post] // @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] 主机工具配置文件 ","formatEN":"[operate] tool config"} func (b *BaseApi) OperateToolConfig(c *gin.Context) { @@ -92,11 +96,12 @@ func (b *BaseApi) OperateToolConfig(c *gin.Context) { } // @Tags Host tool -// @Summary Get tool +// @Summary Get tool logs // @Accept json // @Param request body request.HostToolLogReq true "request" -// @Success 200 +// @Success 200 {string} logContent // @Security ApiKeyAuth +// @Security Timestamp // @Router /host/tool/log [post] func (b *BaseApi) GetToolLog(c *gin.Context) { var req request.HostToolLogReq @@ -118,6 +123,7 @@ func (b *BaseApi) GetToolLog(c *gin.Context) { // @Param request body request.SupervisorProcessConfig true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /host/tool/supervisor/process [post] // @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] 守护进程 ","formatEN":"[operate] process"} func (b *BaseApi) OperateProcess(c *gin.Context) { @@ -137,8 +143,9 @@ func (b *BaseApi) OperateProcess(c *gin.Context) { // @Tags Host tool // @Summary Get Supervisor process config // @Accept json -// @Success 200 +// @Success 200 {object} response.SupervisorProcessConfig // @Security ApiKeyAuth +// @Security Timestamp // @Router /host/tool/supervisor/process [get] func (b *BaseApi) GetProcess(c *gin.Context) { configs, err := hostToolService.GetSupervisorProcessConfig() @@ -150,11 +157,12 @@ func (b *BaseApi) GetProcess(c *gin.Context) { } // @Tags Host tool -// @Summary Get Supervisor process config +// @Summary Get Supervisor process config file // @Accept json // @Param request body request.SupervisorProcessFileReq true "request" -// @Success 200 +// @Success 200 {string} content // @Security ApiKeyAuth +// @Security Timestamp // @Router /host/tool/supervisor/process/file [post] // @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] Supervisor 进程文件 ","formatEN":"[operate] Supervisor Process Config file"} func (b *BaseApi) GetProcessFile(c *gin.Context) { diff --git a/agent/app/api/v2/image.go b/agent/app/api/v2/image.go index 3812f0531..b5eab841d 100644 --- a/agent/app/api/v2/image.go +++ b/agent/app/api/v2/image.go @@ -13,6 +13,7 @@ import ( // @Produce json // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/image/search [post] func (b *BaseApi) SearchImage(c *gin.Context) { var req dto.SearchWithPage @@ -37,6 +38,7 @@ func (b *BaseApi) SearchImage(c *gin.Context) { // @Produce json // @Success 200 {array} dto.ImageInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/image/all [get] func (b *BaseApi) ListAllImage(c *gin.Context) { list, err := imageService.ListAll() @@ -52,6 +54,7 @@ func (b *BaseApi) ListAllImage(c *gin.Context) { // @Produce json // @Success 200 {array} dto.Options // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/image [get] func (b *BaseApi) ListImage(c *gin.Context) { list, err := imageService.List() @@ -68,6 +71,7 @@ func (b *BaseApi) ListImage(c *gin.Context) { // @Param request body dto.ImageBuild true "request" // @Success 200 {string} log // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/image/build [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"构建镜像 [name]","formatEN":"build image [name]"} func (b *BaseApi) ImageBuild(c *gin.Context) { @@ -88,8 +92,9 @@ func (b *BaseApi) ImageBuild(c *gin.Context) { // @Summary Pull image // @Accept json // @Param request body dto.ImagePull true "request" -// @Success 200 {string} log +// @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/image/pull [post] // @x-panel-log {"bodyKeys":["repoID","imageName"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"repoID","isList":false,"db":"image_repos","output_column":"name","output_value":"reponame"}],"formatZH":"镜像拉取 [reponame][imageName]","formatEN":"image pull [reponame][imageName]"} func (b *BaseApi) ImagePull(c *gin.Context) { @@ -110,8 +115,9 @@ func (b *BaseApi) ImagePull(c *gin.Context) { // @Summary Push image // @Accept json // @Param request body dto.ImagePush true "request" -// @Success 200 {string} log +// @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/image/push [post] // @x-panel-log {"bodyKeys":["repoID","tagName","name"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"repoID","isList":false,"db":"image_repos","output_column":"name","output_value":"reponame"}],"formatZH":"[tagName] 推送到 [reponame][name]","formatEN":"push [tagName] to [reponame][name]"} func (b *BaseApi) ImagePush(c *gin.Context) { @@ -132,8 +138,9 @@ func (b *BaseApi) ImagePush(c *gin.Context) { // @Summary Delete image // @Accept json // @Param request body dto.BatchDelete true "request" -// @Success 200 +// @Success 200 {object} dto.ContainerPruneReport // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/image/remove [post] // @x-panel-log {"bodyKeys":["names"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"移除镜像 [names]","formatEN":"remove image [names]"} func (b *BaseApi) ImageRemove(c *gin.Context) { @@ -157,6 +164,7 @@ func (b *BaseApi) ImageRemove(c *gin.Context) { // @Param request body dto.ImageSave true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/image/save [post] // @x-panel-log {"bodyKeys":["tagName","path","name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"保留 [tagName] 为 [path]/[name]","formatEN":"save [tagName] as [path]/[name]"} func (b *BaseApi) ImageSave(c *gin.Context) { @@ -170,7 +178,7 @@ func (b *BaseApi) ImageSave(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container Image @@ -179,6 +187,7 @@ func (b *BaseApi) ImageSave(c *gin.Context) { // @Param request body dto.ImageTag true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/image/tag [post] // @x-panel-log {"bodyKeys":["repoID","targetName"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"repoID","isList":false,"db":"image_repos","output_column":"name","output_value":"reponame"}],"formatZH":"tag 镜像 [reponame][targetName]","formatEN":"tag image [reponame][targetName]"} func (b *BaseApi) ImageTag(c *gin.Context) { @@ -192,7 +201,7 @@ func (b *BaseApi) ImageTag(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container Image @@ -201,6 +210,7 @@ func (b *BaseApi) ImageTag(c *gin.Context) { // @Param request body dto.ImageLoad true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/image/load [post] // @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"从 [path] 加载镜像","formatEN":"load image from [path]"} func (b *BaseApi) ImageLoad(c *gin.Context) { @@ -214,5 +224,5 @@ func (b *BaseApi) ImageLoad(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/image_repo.go b/agent/app/api/v2/image_repo.go index 152a3ad47..65f49eaed 100644 --- a/agent/app/api/v2/image_repo.go +++ b/agent/app/api/v2/image_repo.go @@ -13,6 +13,7 @@ import ( // @Produce json // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/repo/search [post] func (b *BaseApi) SearchRepo(c *gin.Context) { var req dto.SearchWithPage @@ -37,6 +38,7 @@ func (b *BaseApi) SearchRepo(c *gin.Context) { // @Produce json // @Success 200 {array} dto.ImageRepoOption // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/repo [get] func (b *BaseApi) ListRepo(c *gin.Context) { list, err := imageRepoService.List() @@ -55,6 +57,7 @@ func (b *BaseApi) ListRepo(c *gin.Context) { // @Produce json // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/repo/status [get] func (b *BaseApi) CheckRepoStatus(c *gin.Context) { var req dto.OperateByID @@ -66,7 +69,7 @@ func (b *BaseApi) CheckRepoStatus(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container Image-repo @@ -76,6 +79,7 @@ func (b *BaseApi) CheckRepoStatus(c *gin.Context) { // @Produce json // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/repo [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建镜像仓库 [name]","formatEN":"create image repo [name]"} func (b *BaseApi) CreateRepo(c *gin.Context) { @@ -88,7 +92,7 @@ func (b *BaseApi) CreateRepo(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container Image-repo @@ -98,6 +102,7 @@ func (b *BaseApi) CreateRepo(c *gin.Context) { // @Produce json // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/repo/del [post] // @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"image_repos","output_column":"name","output_value":"names"}],"formatZH":"删除镜像仓库 [names]","formatEN":"delete image repo [names]"} func (b *BaseApi) DeleteRepo(c *gin.Context) { @@ -110,7 +115,7 @@ func (b *BaseApi) DeleteRepo(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Container Image-repo @@ -120,6 +125,7 @@ func (b *BaseApi) DeleteRepo(c *gin.Context) { // @Produce json // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /containers/repo/update [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"image_repos","output_column":"name","output_value":"name"}],"formatZH":"更新镜像仓库 [name]","formatEN":"update image repo information [name]"} func (b *BaseApi) UpdateRepo(c *gin.Context) { @@ -132,5 +138,5 @@ func (b *BaseApi) UpdateRepo(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/logs.go b/agent/app/api/v2/logs.go index 2563cac5e..c1b88c877 100644 --- a/agent/app/api/v2/logs.go +++ b/agent/app/api/v2/logs.go @@ -8,8 +8,9 @@ import ( // @Tags Logs // @Summary Load system log files -// @Success 200 +// @Success 200 {array} string // @Security ApiKeyAuth +// @Security Timestamp // @Router /logs/system/files [get] func (b *BaseApi) GetSystemFiles(c *gin.Context) { data, err := logService.ListSystemLogFile() @@ -23,8 +24,9 @@ func (b *BaseApi) GetSystemFiles(c *gin.Context) { // @Tags Logs // @Summary Load system logs -// @Success 200 +// @Success 200 {string} data // @Security ApiKeyAuth +// @Security Timestamp // @Router /logs/system [post] func (b *BaseApi) GetSystemLogs(c *gin.Context) { var req dto.OperationWithName diff --git a/agent/app/api/v2/monitor.go b/agent/app/api/v2/monitor.go index f874a8ce5..e8d177704 100644 --- a/agent/app/api/v2/monitor.go +++ b/agent/app/api/v2/monitor.go @@ -13,8 +13,9 @@ import ( // @Tags Monitor // @Summary Load monitor data // @Param request body dto.MonitorSearch true "request" -// @Success 200 +// @Success 200 {array} dto.MonitorData // @Security ApiKeyAuth +// @Security Timestamp // @Router /hosts/monitor/search [post] func (b *BaseApi) LoadMonitor(c *gin.Context) { var req dto.MonitorSearch @@ -34,6 +35,7 @@ func (b *BaseApi) LoadMonitor(c *gin.Context) { // @Summary Clean monitor data // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /hosts/monitor/clean [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清空监控数据","formatEN":"clean monitor datas"} func (b *BaseApi) CleanMonitor(c *gin.Context) { @@ -42,13 +44,14 @@ func (b *BaseApi) CleanMonitor(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Monitor // @Summary Load monitor setting -// @Success 200 +// @Success 200 {object} dto.MonitorSetting // @Security ApiKeyAuth +// @Security Timestamp // @Router /hosts/monitor/setting [get] func (b *BaseApi) LoadMonitorSetting(c *gin.Context) { setting, err := monitorService.LoadSetting() @@ -65,6 +68,7 @@ func (b *BaseApi) LoadMonitorSetting(c *gin.Context) { // @Param request body dto.MonitorSettingUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /hosts/monitor/setting/update [post] // @x-panel-log {"bodyKeys":["key", "value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改默认监控网卡 [name]-[value]","formatEN":"update default monitor [name]-[value]"} func (b *BaseApi) UpdateMonitorSetting(c *gin.Context) { @@ -77,7 +81,7 @@ func (b *BaseApi) UpdateMonitorSetting(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } func (b *BaseApi) GetNetworkOptions(c *gin.Context) { diff --git a/agent/app/api/v2/nginx.go b/agent/app/api/v2/nginx.go index 4b499022c..25559002f 100644 --- a/agent/app/api/v2/nginx.go +++ b/agent/app/api/v2/nginx.go @@ -8,8 +8,9 @@ import ( // @Tags OpenResty // @Summary Load OpenResty conf -// @Success 200 {object} response.FileInfo +// @Success 200 {object} response.NginxFile // @Security ApiKeyAuth +// @Security Timestamp // @Router /openresty [get] func (b *BaseApi) GetNginx(c *gin.Context) { fileInfo, err := nginxService.GetNginxConfig() @@ -26,6 +27,7 @@ func (b *BaseApi) GetNginx(c *gin.Context) { // @Param request body request.NginxScopeReq true "request" // @Success 200 {array} response.NginxParam // @Security ApiKeyAuth +// @Security Timestamp // @Router /openresty/scope [post] func (b *BaseApi) GetNginxConfigByScope(c *gin.Context) { var req request.NginxScopeReq @@ -47,6 +49,7 @@ func (b *BaseApi) GetNginxConfigByScope(c *gin.Context) { // @Param request body request.NginxConfigUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /openresty/update [post] // @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新 nginx 配置 [domain]","formatEN":"Update nginx conf [domain]"} func (b *BaseApi) UpdateNginxConfigByScope(c *gin.Context) { @@ -58,13 +61,14 @@ func (b *BaseApi) UpdateNginxConfigByScope(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags OpenResty // @Summary Load OpenResty status info // @Success 200 {object} response.NginxStatus // @Security ApiKeyAuth +// @Security Timestamp // @Router /openresty/status [get] func (b *BaseApi) GetNginxStatus(c *gin.Context) { res, err := nginxService.GetStatus() @@ -81,6 +85,7 @@ func (b *BaseApi) GetNginxStatus(c *gin.Context) { // @Param request body request.NginxConfigFileUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /openresty/file [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 nginx 配置","formatEN":"Update nginx conf"} func (b *BaseApi) UpdateNginxFile(c *gin.Context) { @@ -93,7 +98,7 @@ func (b *BaseApi) UpdateNginxFile(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags OpenResty @@ -102,6 +107,7 @@ func (b *BaseApi) UpdateNginxFile(c *gin.Context) { // @Param request body request.NginxBuildReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /openresty/build [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"构建 OpenResty","formatEN":"Build OpenResty"} func (b *BaseApi) BuildNginx(c *gin.Context) { @@ -122,6 +128,7 @@ func (b *BaseApi) BuildNginx(c *gin.Context) { // @Param request body request.NginxModuleUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /openresty/module/update [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 OpenResty 模块","formatEN":"Update OpenResty module"} func (b *BaseApi) UpdateNginxModule(c *gin.Context) { @@ -138,8 +145,9 @@ func (b *BaseApi) UpdateNginxModule(c *gin.Context) { // @Tags OpenResty // @Summary Get OpenResty modules -// @Success 200 {array} response.NginxModule +// @Success 200 {object} response.NginxBuildConfig // @Security ApiKeyAuth +// @Security Timestamp // @Router /openresty/modules [get] func (b *BaseApi) GetNginxModules(c *gin.Context) { modules, err := nginxService.GetModules() diff --git a/agent/app/api/v2/php_extensions.go b/agent/app/api/v2/php_extensions.go index 5e86079a0..72305b514 100644 --- a/agent/app/api/v2/php_extensions.go +++ b/agent/app/api/v2/php_extensions.go @@ -11,8 +11,9 @@ import ( // @Summary Page Extensions // @Accept json // @Param request body request.PHPExtensionsSearch true "request" -// @Success 200 {array} response.PHPExtensionsDTO +// @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/php/extensions/search [post] func (b *BaseApi) PagePHPExtensions(c *gin.Context) { var req request.PHPExtensionsSearch @@ -46,6 +47,7 @@ func (b *BaseApi) PagePHPExtensions(c *gin.Context) { // @Param request body request.PHPExtensionsCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/php/extensions [post] func (b *BaseApi) CreatePHPExtensions(c *gin.Context) { var req request.PHPExtensionsCreate @@ -65,6 +67,7 @@ func (b *BaseApi) CreatePHPExtensions(c *gin.Context) { // @Param request body request.PHPExtensionsUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/php/extensions/update [post] func (b *BaseApi) UpdatePHPExtensions(c *gin.Context) { var req request.PHPExtensionsUpdate @@ -84,6 +87,7 @@ func (b *BaseApi) UpdatePHPExtensions(c *gin.Context) { // @Param request body request.PHPExtensionsDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/php/extensions/del [post] func (b *BaseApi) DeletePHPExtensions(c *gin.Context) { var req request.PHPExtensionsDelete diff --git a/agent/app/api/v2/process.go b/agent/app/api/v2/process.go index 920b1eb26..8e77a2978 100644 --- a/agent/app/api/v2/process.go +++ b/agent/app/api/v2/process.go @@ -22,6 +22,7 @@ func (b *BaseApi) ProcessWs(c *gin.Context) { // @Param request body request.ProcessReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /process/stop [post] // @x-panel-log {"bodyKeys":["PID"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"结束进程 [PID]","formatEN":"结束进程 [PID]"} func (b *BaseApi) StopProcess(c *gin.Context) { diff --git a/agent/app/api/v2/recycle_bin.go b/agent/app/api/v2/recycle_bin.go index dda4fe508..da735072e 100644 --- a/agent/app/api/v2/recycle_bin.go +++ b/agent/app/api/v2/recycle_bin.go @@ -11,8 +11,9 @@ import ( // @Summary List RecycleBin files // @Accept json // @Param request body dto.PageInfo true "request" -// @Success 200 +// @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/recycle/search [post] func (b *BaseApi) SearchRecycleBinFile(c *gin.Context) { var req dto.PageInfo @@ -36,6 +37,7 @@ func (b *BaseApi) SearchRecycleBinFile(c *gin.Context) { // @Param request body request.RecycleBinReduce true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/recycle/reduce [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"还原回收站文件 [name]","formatEN":"Reduce RecycleBin file [name]"} func (b *BaseApi) ReduceRecycleBinFile(c *gin.Context) { @@ -55,6 +57,7 @@ func (b *BaseApi) ReduceRecycleBinFile(c *gin.Context) { // @Accept json // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/recycle/clear [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清空回收站","formatEN":"清空回收站"} func (b *BaseApi) ClearRecycleBinFile(c *gin.Context) { @@ -68,8 +71,9 @@ func (b *BaseApi) ClearRecycleBinFile(c *gin.Context) { // @Tags File // @Summary Get RecycleBin status // @Accept json -// @Success 200 +// @Success 200 {string} content // @Security ApiKeyAuth +// @Security Timestamp // @Router /files/recycle/status [get] func (b *BaseApi) GetRecycleStatus(c *gin.Context) { settingInfo, err := settingService.GetSettingInfo() diff --git a/agent/app/api/v2/runtime.go b/agent/app/api/v2/runtime.go index 60d25386f..2116e4705 100644 --- a/agent/app/api/v2/runtime.go +++ b/agent/app/api/v2/runtime.go @@ -11,8 +11,9 @@ import ( // @Summary List runtimes // @Accept json // @Param request body request.RuntimeSearch true "request" -// @Success 200 +// @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/search [post] func (b *BaseApi) SearchRuntimes(c *gin.Context) { var req request.RuntimeSearch @@ -34,8 +35,9 @@ func (b *BaseApi) SearchRuntimes(c *gin.Context) { // @Summary Create runtime // @Accept json // @Param request body request.RuntimeCreate true "request" -// @Success 200 +// @Success 200 {object} model.Runtime // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建运行环境 [name]","formatEN":"Create runtime [name]"} func (b *BaseApi) CreateRuntime(c *gin.Context) { @@ -57,6 +59,7 @@ func (b *BaseApi) CreateRuntime(c *gin.Context) { // @Param request body request.RuntimeDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/del [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除运行环境 [name]","formatEN":"Delete runtime [name]"} func (b *BaseApi) DeleteRuntime(c *gin.Context) { @@ -75,8 +78,9 @@ func (b *BaseApi) DeleteRuntime(c *gin.Context) { // @Tags Website // @Summary Delete runtime // @Accept json -// @Success 200 +// @Success 200 {array} dto.AppResource // @Security ApiKeyAuth +// @Security Timestamp // @Router /installed/delete/check/:id [get] func (b *BaseApi) DeleteRuntimeCheck(c *gin.Context) { runTimeId, err := helper.GetIntParamByKey(c, "id") @@ -98,6 +102,7 @@ func (b *BaseApi) DeleteRuntimeCheck(c *gin.Context) { // @Param request body request.RuntimeUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/update [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新运行环境 [name]","formatEN":"Update runtime [name]"} func (b *BaseApi) UpdateRuntime(c *gin.Context) { @@ -116,8 +121,9 @@ func (b *BaseApi) UpdateRuntime(c *gin.Context) { // @Summary Get runtime // @Accept json // @Param id path string true "request" -// @Success 200 +// @Success 200 {object} response.RuntimeDTO // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/:id [get] func (b *BaseApi) GetRuntime(c *gin.Context) { id, err := helper.GetIntParamByKey(c, "id") @@ -137,8 +143,9 @@ func (b *BaseApi) GetRuntime(c *gin.Context) { // @Summary Get Node package scripts // @Accept json // @Param request body request.NodePackageReq true "request" -// @Success 200 +// @Success 200 {array} response.PackageScripts // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/node/package [post] func (b *BaseApi) GetNodePackageRunScript(c *gin.Context) { var req request.NodePackageReq @@ -159,6 +166,7 @@ func (b *BaseApi) GetNodePackageRunScript(c *gin.Context) { // @Param request body request.RuntimeOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/operate [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"操作运行环境 [name]","formatEN":"Operate runtime [name]"} func (b *BaseApi) OperateRuntime(c *gin.Context) { @@ -178,8 +186,9 @@ func (b *BaseApi) OperateRuntime(c *gin.Context) { // @Summary Get Node modules // @Accept json // @Param request body request.NodeModuleReq true "request" -// @Success 200 +// @Success 200 {array} response.NodeModule // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/node/modules [post] func (b *BaseApi) GetNodeModules(c *gin.Context) { var req request.NodeModuleReq @@ -200,6 +209,7 @@ func (b *BaseApi) GetNodeModules(c *gin.Context) { // @Param request body request.NodeModuleReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/node/modules/operate [post] func (b *BaseApi) OperateNodeModules(c *gin.Context) { var req request.NodeModuleOperateReq @@ -233,8 +243,9 @@ func (b *BaseApi) SyncStatus(c *gin.Context) { // @Summary Get php runtime extension // @Accept json // @Param id path string true "request" -// @Success 200 +// @Success 200 {object} response.PHPExtensionRes // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/php/:id/extensions [get] func (b *BaseApi) GetRuntimeExtension(c *gin.Context) { id, err := helper.GetIntParamByKey(c, "id") @@ -256,6 +267,7 @@ func (b *BaseApi) GetRuntimeExtension(c *gin.Context) { // @Param request body request.PHPExtensionInstallReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/php/extensions/install [post] func (b *BaseApi) InstallPHPExtension(c *gin.Context) { var req request.PHPExtensionInstallReq @@ -276,6 +288,7 @@ func (b *BaseApi) InstallPHPExtension(c *gin.Context) { // @Param request body request.PHPExtensionInstallReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/php/extensions/uninstall [post] func (b *BaseApi) UnInstallPHPExtension(c *gin.Context) { var req request.PHPExtensionInstallReq @@ -296,6 +309,7 @@ func (b *BaseApi) UnInstallPHPExtension(c *gin.Context) { // @Param id path integer true "request" // @Success 200 {object} response.PHPConfig // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/php/config/:id [get] func (b *BaseApi) GetPHPConfig(c *gin.Context) { id, err := helper.GetParamID(c) @@ -317,6 +331,7 @@ func (b *BaseApi) GetPHPConfig(c *gin.Context) { // @Param request body request.PHPConfigUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/php/config [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"[domain] PHP 配置修改","formatEN":"[domain] PHP conf update"} func (b *BaseApi) UpdatePHPConfig(c *gin.Context) { @@ -328,7 +343,7 @@ func (b *BaseApi) UpdatePHPConfig(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Runtime @@ -337,6 +352,7 @@ func (b *BaseApi) UpdatePHPConfig(c *gin.Context) { // @Param request body request.PHPFileUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/php/update [post] // @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"php 配置修改 [domain]","formatEN":"Nginx conf update [domain]"} func (b *BaseApi) UpdatePHPFile(c *gin.Context) { @@ -348,15 +364,16 @@ func (b *BaseApi) UpdatePHPFile(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Runtime // @Summary Get php conf file // @Accept json // @Param request body request.PHPFileReq true "request" -// @Success 200 +// @Success 200 {object} response.FileInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/php/file [post] func (b *BaseApi) GetPHPConfigFile(c *gin.Context) { var req request.PHPFileReq @@ -377,6 +394,7 @@ func (b *BaseApi) GetPHPConfigFile(c *gin.Context) { // @Param request body request.FPMConfig true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/php/fpm/config [post] func (b *BaseApi) UpdateFPMConfig(c *gin.Context) { var req request.FPMConfig @@ -396,6 +414,7 @@ func (b *BaseApi) UpdateFPMConfig(c *gin.Context) { // @Param id path integer true "request" // @Success 200 {object} request.FPMConfig // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/php/fpm/config/:id [get] func (b *BaseApi) GetFPMConfig(c *gin.Context) { id, err := helper.GetParamID(c) @@ -415,8 +434,9 @@ func (b *BaseApi) GetFPMConfig(c *gin.Context) { // @Summary Get supervisor process // @Accept json // @Param id path integer true "request" -// @Success 200 {object} response.SupervisorProcessConfig +// @Success 200 {array} response.SupervisorProcessConfig // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/supervisor/process/:id [get] func (b *BaseApi) GetSupervisorProcess(c *gin.Context) { id, err := helper.GetParamID(c) @@ -438,6 +458,7 @@ func (b *BaseApi) GetSupervisorProcess(c *gin.Context) { // @Param request body request.PHPSupervisorProcessConfig true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/supervisor/process/operate [post] func (b *BaseApi) OperateSupervisorProcess(c *gin.Context) { var req request.PHPSupervisorProcessConfig @@ -456,8 +477,9 @@ func (b *BaseApi) OperateSupervisorProcess(c *gin.Context) { // @Summary Operate supervisor process file // @Accept json // @Param request body request.PHPSupervisorProcessFileReq true "request" -// @Success 200 +// @Success 200 {string} content // @Security ApiKeyAuth +// @Security Timestamp // @Router /runtimes/supervisor/process/file/operate [post] func (b *BaseApi) OperateSupervisorProcessFile(c *gin.Context) { var req request.PHPSupervisorProcessFileReq diff --git a/agent/app/api/v2/setting.go b/agent/app/api/v2/setting.go index 2623f0c9d..b2613661f 100644 --- a/agent/app/api/v2/setting.go +++ b/agent/app/api/v2/setting.go @@ -11,6 +11,7 @@ import ( // @Summary Load system setting info // @Success 200 {object} dto.SettingInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /settings/search [post] func (b *BaseApi) GetSettingInfo(c *gin.Context) { setting, err := settingService.GetSettingInfo() @@ -25,9 +26,10 @@ func (b *BaseApi) GetSettingInfo(c *gin.Context) { // @Summary Load system available status // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /settings/search/available [get] func (b *BaseApi) GetSystemAvailable(c *gin.Context) { - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -36,6 +38,7 @@ func (b *BaseApi) GetSystemAvailable(c *gin.Context) { // @Param request body dto.SettingUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /settings/update [post] // @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改系统配置 [key] => [value]","formatEN":"update system setting [key] => [value]"} func (b *BaseApi) UpdateSetting(c *gin.Context) { @@ -48,13 +51,14 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting // @Summary Load local backup dir // @Success 200 {string} path // @Security ApiKeyAuth +// @Security Timestamp // @Router /settings/basedir [get] func (b *BaseApi) LoadBaseDir(c *gin.Context) { helper.SuccessWithData(c, global.CONF.System.DataDir) diff --git a/agent/app/api/v2/snapshot.go b/agent/app/api/v2/snapshot.go index 1af151e93..4a3409b40 100644 --- a/agent/app/api/v2/snapshot.go +++ b/agent/app/api/v2/snapshot.go @@ -8,8 +8,9 @@ import ( // @Tags System Setting // @Summary Load system snapshot data -// @Success 200 +// @Success 200 {object} dto.SnapshotData // @Security ApiKeyAuth +// @Security Timestamp // @Router /settings/snapshot/load [get] func (b *BaseApi) LoadSnapshotData(c *gin.Context) { data, err := snapshotService.LoadSnapshotData() @@ -26,6 +27,7 @@ func (b *BaseApi) LoadSnapshotData(c *gin.Context) { // @Param request body dto.SnapshotCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /settings/snapshot [post] // @x-panel-log {"bodyKeys":["from", "description"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建系统快照 [description] 到 [from]","formatEN":"Create system backup [description] to [from]"} func (b *BaseApi) CreateSnapshot(c *gin.Context) { @@ -38,7 +40,7 @@ func (b *BaseApi) CreateSnapshot(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -47,6 +49,7 @@ func (b *BaseApi) CreateSnapshot(c *gin.Context) { // @Param request body dto.OperateByID true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /settings/snapshot/recrete [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"重试创建快照 [name]","formatEN":"recrete the snapshot [name]"} func (b *BaseApi) RecreateSnapshot(c *gin.Context) { @@ -59,7 +62,7 @@ func (b *BaseApi) RecreateSnapshot(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -68,6 +71,7 @@ func (b *BaseApi) RecreateSnapshot(c *gin.Context) { // @Param request body dto.SnapshotImport true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /settings/snapshot/import [post] // @x-panel-log {"bodyKeys":["from", "names"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"从 [from] 同步系统快照 [names]","formatEN":"Sync system snapshots [names] from [from]"} func (b *BaseApi) ImportSnapshot(c *gin.Context) { @@ -80,7 +84,7 @@ func (b *BaseApi) ImportSnapshot(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -89,6 +93,7 @@ func (b *BaseApi) ImportSnapshot(c *gin.Context) { // @Param request body dto.UpdateDescription true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /settings/snapshot/description/update [post] // @x-panel-log {"bodyKeys":["id","description"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"快照 [name] 描述信息修改 [description]","formatEN":"The description of the snapshot [name] is modified => [description]"} func (b *BaseApi) UpdateSnapDescription(c *gin.Context) { @@ -101,7 +106,7 @@ func (b *BaseApi) UpdateSnapDescription(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -110,6 +115,7 @@ func (b *BaseApi) UpdateSnapDescription(c *gin.Context) { // @Param request body dto.PageSnapshot true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /settings/snapshot/search [post] func (b *BaseApi) SearchSnapshot(c *gin.Context) { var req dto.PageSnapshot @@ -134,6 +140,7 @@ func (b *BaseApi) SearchSnapshot(c *gin.Context) { // @Param request body dto.SnapshotRecover true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /settings/snapshot/recover [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"从系统快照 [name] 恢复","formatEN":"Recover from system backup [name]"} func (b *BaseApi) RecoverSnapshot(c *gin.Context) { @@ -146,7 +153,7 @@ func (b *BaseApi) RecoverSnapshot(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -155,6 +162,7 @@ func (b *BaseApi) RecoverSnapshot(c *gin.Context) { // @Param request body dto.SnapshotRecover true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /settings/snapshot/rollback [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"从系统快照 [name] 回滚","formatEN":"Rollback from system backup [name]"} func (b *BaseApi) RollbackSnapshot(c *gin.Context) { @@ -167,7 +175,7 @@ func (b *BaseApi) RollbackSnapshot(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -176,6 +184,7 @@ func (b *BaseApi) RollbackSnapshot(c *gin.Context) { // @Param request body dto.SnapshotBatchDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /settings/snapshot/del [post] // @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"删除系统快照 [name]","formatEN":"Delete system backup [name]"} func (b *BaseApi) DeleteSnapshot(c *gin.Context) { @@ -188,5 +197,5 @@ func (b *BaseApi) DeleteSnapshot(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/ssh.go b/agent/app/api/v2/ssh.go index 675740525..f1675a0fb 100644 --- a/agent/app/api/v2/ssh.go +++ b/agent/app/api/v2/ssh.go @@ -10,6 +10,7 @@ import ( // @Summary Load host SSH setting info // @Success 200 {object} dto.SSHInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /host/ssh/search [post] func (b *BaseApi) GetSSHInfo(c *gin.Context) { info, err := sshService.GetSSHInfo() @@ -24,7 +25,9 @@ func (b *BaseApi) GetSSHInfo(c *gin.Context) { // @Summary Operate SSH // @Accept json // @Param request body dto.Operate true "request" +// @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /host/ssh/operate [post] // @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operation] SSH ","formatEN":"[operation] SSH"} func (b *BaseApi) OperateSSH(c *gin.Context) { @@ -37,7 +40,7 @@ func (b *BaseApi) OperateSSH(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags SSH @@ -46,6 +49,7 @@ func (b *BaseApi) OperateSSH(c *gin.Context) { // @Param request body dto.SSHUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /host/ssh/update [post] // @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置 [key] => [value]","formatEN":"update SSH setting [key] => [value]"} func (b *BaseApi) UpdateSSH(c *gin.Context) { @@ -58,7 +62,7 @@ func (b *BaseApi) UpdateSSH(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags SSH @@ -67,6 +71,7 @@ func (b *BaseApi) UpdateSSH(c *gin.Context) { // @Param request body dto.SSHConf true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /host/conffile/update [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置文件","formatEN":"update SSH conf"} func (b *BaseApi) UpdateSSHByfile(c *gin.Context) { @@ -79,7 +84,7 @@ func (b *BaseApi) UpdateSSHByfile(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags SSH @@ -88,6 +93,7 @@ func (b *BaseApi) UpdateSSHByfile(c *gin.Context) { // @Param request body dto.GenerateSSH true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /host/ssh/generate [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"生成 SSH 密钥 ","formatEN":"generate SSH secret"} func (b *BaseApi) GenerateSSH(c *gin.Context) { @@ -100,15 +106,16 @@ func (b *BaseApi) GenerateSSH(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags SSH // @Summary Load host SSH secret // @Accept json // @Param request body dto.GenerateLoad true "request" -// @Success 200 +// @Success 200 {string} secret // @Security ApiKeyAuth +// @Security Timestamp // @Router /host/ssh/secret [post] func (b *BaseApi) LoadSSHSecret(c *gin.Context) { var req dto.GenerateLoad @@ -130,6 +137,7 @@ func (b *BaseApi) LoadSSHSecret(c *gin.Context) { // @Param request body dto.SearchSSHLog true "request" // @Success 200 {object} dto.SSHLog // @Security ApiKeyAuth +// @Security Timestamp // @Router /host/ssh/log [post] func (b *BaseApi) LoadSSHLogs(c *gin.Context) { var req dto.SearchSSHLog @@ -147,8 +155,9 @@ func (b *BaseApi) LoadSSHLogs(c *gin.Context) { // @Tags SSH // @Summary Load host SSH conf -// @Success 200 +// @Success 200 {string} conf // @Security ApiKeyAuth +// @Security Timestamp // @Router /host/ssh/conf [get] func (b *BaseApi) LoadSSHConf(c *gin.Context) { data, err := sshService.LoadSSHConf() diff --git a/agent/app/api/v2/task.go b/agent/app/api/v2/task.go index fa0aa0494..6886ebf4c 100644 --- a/agent/app/api/v2/task.go +++ b/agent/app/api/v2/task.go @@ -12,6 +12,7 @@ import ( // @Param request body dto.SearchTaskLogReq true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /logs/tasks/search [post] func (b *BaseApi) PageTasks(c *gin.Context) { var req dto.SearchTaskLogReq @@ -33,6 +34,7 @@ func (b *BaseApi) PageTasks(c *gin.Context) { // @Summary Get the number of executing tasks // @Success 200 {object} int64 // @Security ApiKeyAuth +// @Security Timestamp // @Router /logs/tasks/executing/count [get] func (b *BaseApi) CountExecutingTasks(c *gin.Context) { count, err := taskService.CountExecutingTask() diff --git a/agent/app/api/v2/website.go b/agent/app/api/v2/website.go index 7810fbf52..284c97848 100644 --- a/agent/app/api/v2/website.go +++ b/agent/app/api/v2/website.go @@ -13,6 +13,7 @@ import ( // @Param request body request.WebsiteSearch true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/search [post] func (b *BaseApi) PageWebsite(c *gin.Context) { var req request.WebsiteSearch @@ -34,6 +35,7 @@ func (b *BaseApi) PageWebsite(c *gin.Context) { // @Summary List websites // @Success 200 {array} response.WebsiteDTO // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/list [get] func (b *BaseApi) GetWebsites(c *gin.Context) { websites, err := websiteService.GetWebsites() @@ -46,8 +48,9 @@ func (b *BaseApi) GetWebsites(c *gin.Context) { // @Tags Website // @Summary List website names -// @Success 200 {array} string +// @Success 200 {array} response.WebsiteOption // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/options [post] func (b *BaseApi) GetWebsiteOptions(c *gin.Context) { var req request.WebsiteOptionReq @@ -68,6 +71,7 @@ func (b *BaseApi) GetWebsiteOptions(c *gin.Context) { // @Param request body request.WebsiteCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites [post] // @x-panel-log {"bodyKeys":["primaryDomain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 [primaryDomain]","formatEN":"Create website [primaryDomain]"} func (b *BaseApi) CreateWebsite(c *gin.Context) { @@ -80,7 +84,7 @@ func (b *BaseApi) CreateWebsite(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Website @@ -89,6 +93,7 @@ func (b *BaseApi) CreateWebsite(c *gin.Context) { // @Param request body request.WebsiteOp true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/operate [post] // @x-panel-log {"bodyKeys":["id", "operate"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"[operate] 网站 [domain]","formatEN":"[operate] website [domain]"} func (b *BaseApi) OpWebsite(c *gin.Context) { @@ -101,7 +106,7 @@ func (b *BaseApi) OpWebsite(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Website @@ -110,6 +115,7 @@ func (b *BaseApi) OpWebsite(c *gin.Context) { // @Param request body request.WebsiteDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/del [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"删除网站 [domain]","formatEN":"Delete website [domain]"} func (b *BaseApi) DeleteWebsite(c *gin.Context) { @@ -122,7 +128,7 @@ func (b *BaseApi) DeleteWebsite(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Website @@ -131,6 +137,7 @@ func (b *BaseApi) DeleteWebsite(c *gin.Context) { // @Param request body request.WebsiteUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/update [post] // @x-panel-log {"bodyKeys":["primaryDomain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新网站 [primaryDomain]","formatEN":"Update website [primaryDomain]"} func (b *BaseApi) UpdateWebsite(c *gin.Context) { @@ -142,7 +149,7 @@ func (b *BaseApi) UpdateWebsite(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Website @@ -151,6 +158,7 @@ func (b *BaseApi) UpdateWebsite(c *gin.Context) { // @Param id path integer true "request" // @Success 200 {object} response.WebsiteDTO // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/:id [get] func (b *BaseApi) GetWebsite(c *gin.Context) { id, err := helper.GetParamID(c) @@ -172,6 +180,7 @@ func (b *BaseApi) GetWebsite(c *gin.Context) { // @Param id path integer true "request" // @Success 200 {object} response.FileInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/:id/config/:type [get] func (b *BaseApi) GetWebsiteNginx(c *gin.Context) { id, err := helper.GetParamID(c) @@ -195,6 +204,7 @@ func (b *BaseApi) GetWebsiteNginx(c *gin.Context) { // @Param request body request.NginxScopeReq true "request" // @Success 200 {object} response.WebsiteNginxConfig // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/config [post] func (b *BaseApi) GetNginxConfig(c *gin.Context) { var req request.NginxScopeReq @@ -215,6 +225,7 @@ func (b *BaseApi) GetNginxConfig(c *gin.Context) { // @Param request body request.NginxConfigUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/config/update [post] // @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"nginx 配置修改 [domain]","formatEN":"Nginx conf update [domain]"} func (b *BaseApi) UpdateNginxConfig(c *gin.Context) { @@ -226,7 +237,7 @@ func (b *BaseApi) UpdateNginxConfig(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Website HTTPS @@ -235,6 +246,7 @@ func (b *BaseApi) UpdateNginxConfig(c *gin.Context) { // @Param id path integer true "request" // @Success 200 {object} response.WebsiteHTTPS // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/:id/https [get] func (b *BaseApi) GetHTTPSConfig(c *gin.Context) { id, err := helper.GetParamID(c) @@ -256,6 +268,7 @@ func (b *BaseApi) GetHTTPSConfig(c *gin.Context) { // @Param request body request.WebsiteHTTPSOp true "request" // @Success 200 {object} response.WebsiteHTTPS // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/:id/https [post] // @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] https 配置","formatEN":"Update website https [domain] conf"} func (b *BaseApi) UpdateHTTPSConfig(c *gin.Context) { @@ -280,6 +293,7 @@ func (b *BaseApi) UpdateHTTPSConfig(c *gin.Context) { // @Param request body request.WebsiteInstallCheckReq true "request" // @Success 200 {array} response.WebsitePreInstallCheck // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/check [post] func (b *BaseApi) CreateWebsiteCheck(c *gin.Context) { var req request.WebsiteInstallCheckReq @@ -300,6 +314,7 @@ func (b *BaseApi) CreateWebsiteCheck(c *gin.Context) { // @Param request body request.WebsiteNginxUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/nginx/update [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"[domain] Nginx 配置修改","formatEN":"[domain] Nginx conf update"} func (b *BaseApi) UpdateWebsiteNginxConfig(c *gin.Context) { @@ -311,7 +326,7 @@ func (b *BaseApi) UpdateWebsiteNginxConfig(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Website @@ -320,6 +335,7 @@ func (b *BaseApi) UpdateWebsiteNginxConfig(c *gin.Context) { // @Param request body request.WebsiteLogReq true "request" // @Success 200 {object} response.WebsiteLog // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/log [post] // @x-panel-log {"bodyKeys":["id", "operate"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"[domain][operate] 日志","formatEN":"[domain][operate] logs"} func (b *BaseApi) OpWebsiteLog(c *gin.Context) { @@ -341,6 +357,7 @@ func (b *BaseApi) OpWebsiteLog(c *gin.Context) { // @Param request body request.WebsiteDefaultUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/default/server [post] // @x-panel-log {"bodyKeys":["id", "operate"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改默认 server => [domain]","formatEN":"Change default server => [domain]"} func (b *BaseApi) ChangeDefaultServer(c *gin.Context) { @@ -352,7 +369,7 @@ func (b *BaseApi) ChangeDefaultServer(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Website PHP @@ -361,6 +378,7 @@ func (b *BaseApi) ChangeDefaultServer(c *gin.Context) { // @Param request body request.WebsitePHPVersionReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/php/version [post] // @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"php 版本变更 [domain]","formatEN":"php version update [domain]"} func (b *BaseApi) ChangePHPVersion(c *gin.Context) { @@ -379,8 +397,9 @@ func (b *BaseApi) ChangePHPVersion(c *gin.Context) { // @Summary Get rewrite conf // @Accept json // @Param request body request.NginxRewriteReq true "request" -// @Success 200 +// @Success 200 {object} response.NginxRewriteRes // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/rewrite [post] func (b *BaseApi) GetRewriteConfig(c *gin.Context) { var req request.NginxRewriteReq @@ -401,6 +420,7 @@ func (b *BaseApi) GetRewriteConfig(c *gin.Context) { // @Param request body request.NginxRewriteUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/rewrite/update [post] // @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"伪静态配置修改 [domain]","formatEN":"Nginx conf rewrite update [domain]"} func (b *BaseApi) UpdateRewriteConfig(c *gin.Context) { @@ -412,7 +432,7 @@ func (b *BaseApi) UpdateRewriteConfig(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Website @@ -421,6 +441,7 @@ func (b *BaseApi) UpdateRewriteConfig(c *gin.Context) { // @Param request body request.WebsiteUpdateDir true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/dir/update [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] 目录","formatEN":"Update domain [domain] dir"} func (b *BaseApi) UpdateSiteDir(c *gin.Context) { @@ -441,6 +462,7 @@ func (b *BaseApi) UpdateSiteDir(c *gin.Context) { // @Param request body request.WebsiteUpdateDirPermission true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/dir/permission [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] 目录权限","formatEN":"Update domain [domain] dir permission"} func (b *BaseApi) UpdateSiteDirPermission(c *gin.Context) { @@ -459,8 +481,9 @@ func (b *BaseApi) UpdateSiteDirPermission(c *gin.Context) { // @Summary Get proxy conf // @Accept json // @Param request body request.WebsiteProxyReq true "request" -// @Success 200 +// @Success 200 {array} request.WebsiteProxyConfig // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/proxies [post] func (b *BaseApi) GetProxyConfig(c *gin.Context) { var req request.WebsiteProxyReq @@ -481,6 +504,7 @@ func (b *BaseApi) GetProxyConfig(c *gin.Context) { // @Param request body request.WebsiteProxyConfig true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/proxies/update [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改网站 [domain] 反向代理配置 ","formatEN":"Update domain [domain] proxy config"} func (b *BaseApi) UpdateProxyConfig(c *gin.Context) { @@ -502,6 +526,7 @@ func (b *BaseApi) UpdateProxyConfig(c *gin.Context) { // @Param request body request.NginxProxyUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/proxy/file [post] // @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新反向代理文件 [domain]","formatEN":"Nginx conf proxy file update [domain]"} func (b *BaseApi) UpdateProxyConfigFile(c *gin.Context) { @@ -520,8 +545,9 @@ func (b *BaseApi) UpdateProxyConfigFile(c *gin.Context) { // @Summary Get AuthBasic conf // @Accept json // @Param request body request.NginxAuthReq true "request" -// @Success 200 +// @Success 200 {object} response.NginxAuthRes // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/auths [post] func (b *BaseApi) GetAuthConfig(c *gin.Context) { var req request.NginxAuthReq @@ -542,6 +568,7 @@ func (b *BaseApi) GetAuthConfig(c *gin.Context) { // @Param request body request.NginxAuthUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/auths/update [post] func (b *BaseApi) UpdateAuthConfig(c *gin.Context) { var req request.NginxAuthUpdate @@ -559,8 +586,9 @@ func (b *BaseApi) UpdateAuthConfig(c *gin.Context) { // @Summary Get AuthBasic conf // @Accept json // @Param request body request.NginxAuthReq true "request" -// @Success 200 +// @Success 200 {object} response.NginxPathAuthRes // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/auths/path [post] func (b *BaseApi) GetPathAuthConfig(c *gin.Context) { var req request.NginxAuthReq @@ -581,6 +609,7 @@ func (b *BaseApi) GetPathAuthConfig(c *gin.Context) { // @Param request body request.NginxPathAuthUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/auths/path/update [post] func (b *BaseApi) UpdatePathAuthConfig(c *gin.Context) { var req request.NginxPathAuthUpdate @@ -598,8 +627,9 @@ func (b *BaseApi) UpdatePathAuthConfig(c *gin.Context) { // @Summary Get AntiLeech conf // @Accept json // @Param request body request.NginxCommonReq true "request" -// @Success 200 +// @Success 200 {object} response.NginxAntiLeechRes // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/leech [post] func (b *BaseApi) GetAntiLeech(c *gin.Context) { var req request.NginxCommonReq @@ -620,6 +650,7 @@ func (b *BaseApi) GetAntiLeech(c *gin.Context) { // @Param request body request.NginxAntiLeechUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/leech/update [post] func (b *BaseApi) UpdateAntiLeech(c *gin.Context) { var req request.NginxAntiLeechUpdate @@ -639,6 +670,7 @@ func (b *BaseApi) UpdateAntiLeech(c *gin.Context) { // @Param request body request.NginxRedirectReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/redirect/update [post] // @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改网站 [domain] 重定向理配置 ","formatEN":"Update domain [domain] redirect config"} func (b *BaseApi) UpdateRedirectConfig(c *gin.Context) { @@ -658,8 +690,9 @@ func (b *BaseApi) UpdateRedirectConfig(c *gin.Context) { // @Summary Get redirect conf // @Accept json // @Param request body request.WebsiteProxyReq true "request" -// @Success 200 +// @Success 200 {array} response.NginxRedirectConfig // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/redirect [post] func (b *BaseApi) GetRedirectConfig(c *gin.Context) { var req request.WebsiteRedirectReq @@ -680,6 +713,7 @@ func (b *BaseApi) GetRedirectConfig(c *gin.Context) { // @Param request body request.NginxRedirectUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/redirect/file [post] // @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新重定向文件 [domain]","formatEN":"Nginx conf redirect file update [domain]"} func (b *BaseApi) UpdateRedirectConfigFile(c *gin.Context) { @@ -698,8 +732,9 @@ func (b *BaseApi) UpdateRedirectConfigFile(c *gin.Context) { // @Summary Get website dir // @Accept json // @Param request body request.WebsiteCommonReq true "request" -// @Success 200 +// @Success 200 {object} response.WebsiteDirConfig // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/dir [post] func (b *BaseApi) GetDirConfig(c *gin.Context) { var req request.WebsiteCommonReq @@ -717,8 +752,9 @@ func (b *BaseApi) GetDirConfig(c *gin.Context) { // @Tags Website // @Summary Get default html // @Accept json -// @Success 200 {object} response.FileInfo +// @Success 200 {object} response.WebsiteHtmlRes // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/default/html/:type [get] func (b *BaseApi) GetDefaultHtml(c *gin.Context) { resourceType, err := helper.GetStrParamByKey(c, "type") @@ -740,6 +776,7 @@ func (b *BaseApi) GetDefaultHtml(c *gin.Context) { // @Param request body request.WebsiteHtmlUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/default/html/update [post] // @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新默认 html","formatEN":"Update default html"} func (b *BaseApi) UpdateDefaultHtml(c *gin.Context) { @@ -758,8 +795,9 @@ func (b *BaseApi) UpdateDefaultHtml(c *gin.Context) { // @Summary Get website upstreams // @Accept json // @Param request body request.WebsiteCommonReq true "request" -// @Success 200 +// @Success 200 {array} dto.NginxUpstream // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/lbs [get] func (b *BaseApi) GetLoadBalances(c *gin.Context) { id, err := helper.GetParamID(c) @@ -781,6 +819,7 @@ func (b *BaseApi) GetLoadBalances(c *gin.Context) { // @Param request body request.WebsiteLBCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/lbs/create [post] func (b *BaseApi) CreateLoadBalance(c *gin.Context) { var req request.WebsiteLBCreate @@ -800,6 +839,7 @@ func (b *BaseApi) CreateLoadBalance(c *gin.Context) { // @Param request body request.WebsiteLBDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/lbs/delete [post] func (b *BaseApi) DeleteLoadBalance(c *gin.Context) { var req request.WebsiteLBDelete @@ -819,6 +859,7 @@ func (b *BaseApi) DeleteLoadBalance(c *gin.Context) { // @Param request body request.WebsiteLBUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/lbs/update [post] func (b *BaseApi) UpdateLoadBalance(c *gin.Context) { var req request.WebsiteLBUpdate @@ -838,6 +879,7 @@ func (b *BaseApi) UpdateLoadBalance(c *gin.Context) { // @Param request body request.WebsiteLBUpdateFile true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/lbs/file [post] func (b *BaseApi) UpdateLoadBalanceFile(c *gin.Context) { var req request.WebsiteLBUpdateFile @@ -869,6 +911,7 @@ func (b *BaseApi) ChangeWebsiteGroup(c *gin.Context) { // @Param request body request.NginxProxyCacheUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/proxy/config [post] func (b *BaseApi) UpdateProxyCache(c *gin.Context) { var req request.NginxProxyCacheUpdate @@ -887,6 +930,7 @@ func (b *BaseApi) UpdateProxyCache(c *gin.Context) { // @Param id path int true "id" // @Success 200 {object} response.NginxProxyCache // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/proxy/config/{id} [get] func (b *BaseApi) GetProxyCache(c *gin.Context) { id, err := helper.GetParamID(c) @@ -908,6 +952,7 @@ func (b *BaseApi) GetProxyCache(c *gin.Context) { // @Param request body request.WebsiteRealIP true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/realip [post] // @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改 [domain] 网站真实IP配置 ","formatEN":"Modify the real IP configuration of [domain] website"} func (b *BaseApi) SetRealIPConfig(c *gin.Context) { @@ -928,6 +973,7 @@ func (b *BaseApi) SetRealIPConfig(c *gin.Context) { // @Param id path int true "id" // @Success 200 {object} response.WebsiteRealIP // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/realip/config/{id} [get] func (b *BaseApi) GetRealIPConfig(c *gin.Context) { id, err := helper.GetParamID(c) @@ -949,6 +995,7 @@ func (b *BaseApi) GetRealIPConfig(c *gin.Context) { // @Param id path int true "id" // @Success 200 {object} response.Resource // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/resource/{id} [get] func (b *BaseApi) GetWebsiteResource(c *gin.Context) { id, err := helper.GetParamID(c) @@ -969,6 +1016,7 @@ func (b *BaseApi) GetWebsiteResource(c *gin.Context) { // @Accept json // @Success 200 {object} response.Database // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/databases [get] func (b *BaseApi) GetWebsiteDatabase(c *gin.Context) { res, err := websiteService.ListDatabases() @@ -985,6 +1033,7 @@ func (b *BaseApi) GetWebsiteDatabase(c *gin.Context) { // @Param request body request.ChangeDatabase true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/databases [post] func (b *BaseApi) ChangeWebsiteDatabase(c *gin.Context) { var req request.ChangeDatabase @@ -1004,6 +1053,7 @@ func (b *BaseApi) ChangeWebsiteDatabase(c *gin.Context) { // @Param request body request.CustomRewriteOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/rewrite/custom [post] func (b *BaseApi) OperateCustomRewrite(c *gin.Context) { var req request.CustomRewriteOperate @@ -1020,8 +1070,9 @@ func (b *BaseApi) OperateCustomRewrite(c *gin.Context) { // @Tags Website // @Summary List custom rewrite // @Accept json -// @Success 200 {object} []string +// @Success 200 {array} string // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/rewrite/custom [get] func (b *BaseApi) ListCustomRewrite(c *gin.Context) { res, err := websiteService.ListCustomRewrite() @@ -1036,6 +1087,7 @@ func (b *BaseApi) ListCustomRewrite(c *gin.Context) { // @Summary Clear Website proxy cache // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/proxy/clear [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理 Openresty 代理缓存","formatEN":"Clear nginx proxy cache"} func (b *BaseApi) ClearProxyCache(c *gin.Context) { diff --git a/agent/app/api/v2/website_acme_account.go b/agent/app/api/v2/website_acme_account.go index 24a0eb05a..1a9fb116b 100644 --- a/agent/app/api/v2/website_acme_account.go +++ b/agent/app/api/v2/website_acme_account.go @@ -13,6 +13,7 @@ import ( // @Param request body dto.PageInfo true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/acme/search [post] func (b *BaseApi) PageWebsiteAcmeAccount(c *gin.Context) { var req dto.PageInfo @@ -36,6 +37,7 @@ func (b *BaseApi) PageWebsiteAcmeAccount(c *gin.Context) { // @Param request body request.WebsiteAcmeAccountCreate true "request" // @Success 200 {object} response.WebsiteAcmeAccountDTO // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/acme [post] // @x-panel-log {"bodyKeys":["email"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 acme [email]","formatEN":"Create website acme [email]"} func (b *BaseApi) CreateWebsiteAcmeAccount(c *gin.Context) { @@ -57,6 +59,7 @@ func (b *BaseApi) CreateWebsiteAcmeAccount(c *gin.Context) { // @Param request body request.WebsiteResourceReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/acme/del [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_acme_accounts","output_column":"email","output_value":"email"}],"formatZH":"删除网站 acme [email]","formatEN":"Delete website acme [email]"} func (b *BaseApi) DeleteWebsiteAcmeAccount(c *gin.Context) { @@ -68,5 +71,5 @@ func (b *BaseApi) DeleteWebsiteAcmeAccount(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/website_ca.go b/agent/app/api/v2/website_ca.go index befa00e78..f0efb6f0c 100644 --- a/agent/app/api/v2/website_ca.go +++ b/agent/app/api/v2/website_ca.go @@ -17,6 +17,7 @@ import ( // @Param request body request.WebsiteCASearch true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ca/search [post] func (b *BaseApi) PageWebsiteCA(c *gin.Context) { var req request.WebsiteCASearch @@ -40,6 +41,7 @@ func (b *BaseApi) PageWebsiteCA(c *gin.Context) { // @Param request body request.WebsiteCACreate true "request" // @Success 200 {object} request.WebsiteCACreate // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ca [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 ca [name]","formatEN":"Create website ca [name]"} func (b *BaseApi) CreateWebsiteCA(c *gin.Context) { @@ -61,6 +63,7 @@ func (b *BaseApi) CreateWebsiteCA(c *gin.Context) { // @Param id path int true "id" // @Success 200 {object} response.WebsiteCADTO // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ca/{id} [get] func (b *BaseApi) GetWebsiteCA(c *gin.Context) { id, err := helper.GetParamID(c) @@ -81,6 +84,7 @@ func (b *BaseApi) GetWebsiteCA(c *gin.Context) { // @Param request body request.WebsiteCommonReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ca/del [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_cas","output_column":"name","output_value":"name"}],"formatZH":"删除网站 ca [name]","formatEN":"Delete website ca [name]"} func (b *BaseApi) DeleteWebsiteCA(c *gin.Context) { @@ -101,6 +105,7 @@ func (b *BaseApi) DeleteWebsiteCA(c *gin.Context) { // @Param request body request.WebsiteCAObtain true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ca/obtain [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_cas","output_column":"name","output_value":"name"}],"formatZH":"自签 SSL 证书 [name]","formatEN":"Obtain SSL [name]"} func (b *BaseApi) ObtainWebsiteCA(c *gin.Context) { @@ -121,6 +126,7 @@ func (b *BaseApi) ObtainWebsiteCA(c *gin.Context) { // @Param request body request.WebsiteCAObtain true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ca/renew [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_cas","output_column":"name","output_value":"name"}],"formatZH":"自签 SSL 证书 [name]","formatEN":"Obtain SSL [name]"} func (b *BaseApi) RenewWebsiteCA(c *gin.Context) { @@ -146,6 +152,7 @@ func (b *BaseApi) RenewWebsiteCA(c *gin.Context) { // @Param request body request.WebsiteResourceReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ca/download [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_cas","output_column":"name","output_value":"name"}],"formatZH":"下载 CA 证书文件 [name]","formatEN":"download ca file [name]"} func (b *BaseApi) DownloadCAFile(c *gin.Context) { diff --git a/agent/app/api/v2/website_dns_account.go b/agent/app/api/v2/website_dns_account.go index 981f00670..deee15478 100644 --- a/agent/app/api/v2/website_dns_account.go +++ b/agent/app/api/v2/website_dns_account.go @@ -13,6 +13,7 @@ import ( // @Param request body dto.PageInfo true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/dns/search [post] func (b *BaseApi) PageWebsiteDnsAccount(c *gin.Context) { var req dto.PageInfo @@ -36,6 +37,7 @@ func (b *BaseApi) PageWebsiteDnsAccount(c *gin.Context) { // @Param request body request.WebsiteDnsAccountCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/dns [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 dns [name]","formatEN":"Create website dns [name]"} func (b *BaseApi) CreateWebsiteDnsAccount(c *gin.Context) { @@ -47,7 +49,7 @@ func (b *BaseApi) CreateWebsiteDnsAccount(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Website DNS @@ -56,6 +58,7 @@ func (b *BaseApi) CreateWebsiteDnsAccount(c *gin.Context) { // @Param request body request.WebsiteDnsAccountUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/dns/update [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新网站 dns [name]","formatEN":"Update website dns [name]"} func (b *BaseApi) UpdateWebsiteDnsAccount(c *gin.Context) { @@ -67,7 +70,7 @@ func (b *BaseApi) UpdateWebsiteDnsAccount(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Website DNS @@ -76,6 +79,7 @@ func (b *BaseApi) UpdateWebsiteDnsAccount(c *gin.Context) { // @Param request body request.WebsiteResourceReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/dns/del [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_dns_accounts","output_column":"name","output_value":"name"}],"formatZH":"删除网站 dns [name]","formatEN":"Delete website dns [name]"} func (b *BaseApi) DeleteWebsiteDnsAccount(c *gin.Context) { @@ -87,5 +91,5 @@ func (b *BaseApi) DeleteWebsiteDnsAccount(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/agent/app/api/v2/website_domain.go b/agent/app/api/v2/website_domain.go index 203ccbfa0..84bdc1345 100644 --- a/agent/app/api/v2/website_domain.go +++ b/agent/app/api/v2/website_domain.go @@ -12,6 +12,7 @@ import ( // @Param request body request.WebsiteDomainDelete true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/domains/del [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_domains","output_column":"domain","output_value":"domain"}],"formatZH":"删除域名 [domain]","formatEN":"Delete domain [domain]"} func (b *BaseApi) DeleteWebDomain(c *gin.Context) { @@ -23,7 +24,7 @@ func (b *BaseApi) DeleteWebDomain(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Website Domain @@ -32,6 +33,7 @@ func (b *BaseApi) DeleteWebDomain(c *gin.Context) { // @Param request body request.WebsiteDomainCreate true "request" // @Success 200 {object} model.WebsiteDomain // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/domains [post] // @x-panel-log {"bodyKeys":["domain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建域名 [domain]","formatEN":"Create domain [domain]"} func (b *BaseApi) CreateWebDomain(c *gin.Context) { @@ -53,6 +55,7 @@ func (b *BaseApi) CreateWebDomain(c *gin.Context) { // @Param websiteId path integer true "request" // @Success 200 {array} model.WebsiteDomain // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/domains/:websiteId [get] func (b *BaseApi) GetWebDomains(c *gin.Context) { websiteId, err := helper.GetIntParamByKey(c, "websiteId") @@ -68,13 +71,13 @@ func (b *BaseApi) GetWebDomains(c *gin.Context) { helper.SuccessWithData(c, list) } -// 写一个 update website domain 的接口 // @Tags Website Domain // @Summary Update website domain // @Accept json // @Param request body request.WebsiteDomainUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/domains/update [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_domains","output_column":"domain","output_value":"domain"}],"formatZH":"更新域名 [domain]","formatEN":"Update domain [domain]"} func (b *BaseApi) UpdateWebDomain(c *gin.Context) { diff --git a/agent/app/api/v2/website_ssl.go b/agent/app/api/v2/website_ssl.go index 82d7b9f40..02f1a911a 100644 --- a/agent/app/api/v2/website_ssl.go +++ b/agent/app/api/v2/website_ssl.go @@ -16,8 +16,9 @@ import ( // @Summary Page website ssl // @Accept json // @Param request body request.WebsiteSSLSearch true "request" -// @Success 200 +// @Success 200 {array} response.WebsiteSSLDTO // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ssl/search [post] func (b *BaseApi) PageWebsiteSSL(c *gin.Context) { var req request.WebsiteSSLSearch @@ -50,6 +51,7 @@ func (b *BaseApi) PageWebsiteSSL(c *gin.Context) { // @Param request body request.WebsiteSSLCreate true "request" // @Success 200 {object} request.WebsiteSSLCreate // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ssl [post] // @x-panel-log {"bodyKeys":["primaryDomain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 ssl [primaryDomain]","formatEN":"Create website ssl [primaryDomain]"} func (b *BaseApi) CreateWebsiteSSL(c *gin.Context) { @@ -71,6 +73,7 @@ func (b *BaseApi) CreateWebsiteSSL(c *gin.Context) { // @Param request body request.WebsiteSSLApply true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ssl/obtain [post] // @x-panel-log {"bodyKeys":["ID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ID","isList":false,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"申请证书 [domain]","formatEN":"apply ssl [domain]"} func (b *BaseApi) ApplyWebsiteSSL(c *gin.Context) { @@ -91,6 +94,7 @@ func (b *BaseApi) ApplyWebsiteSSL(c *gin.Context) { // @Param request body request.WebsiteDNSReq true "request" // @Success 200 {array} response.WebsiteDNSRes // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ssl/resolve [post] func (b *BaseApi) GetDNSResolve(c *gin.Context) { var req request.WebsiteDNSReq @@ -111,6 +115,7 @@ func (b *BaseApi) GetDNSResolve(c *gin.Context) { // @Param request body request.WebsiteBatchDelReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ssl/del [post] // @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"删除 ssl [domain]","formatEN":"Delete ssl [domain]"} func (b *BaseApi) DeleteWebsiteSSL(c *gin.Context) { @@ -122,15 +127,16 @@ func (b *BaseApi) DeleteWebsiteSSL(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Website SSL // @Summary Search website ssl by website id // @Accept json // @Param websiteId path integer true "request" -// @Success 200 +// @Success 200 {object} response.WebsiteSSLDTO // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ssl/website/:websiteId [get] func (b *BaseApi) GetWebsiteSSLByWebsiteId(c *gin.Context) { websiteId, err := helper.GetIntParamByKey(c, "websiteId") @@ -150,8 +156,9 @@ func (b *BaseApi) GetWebsiteSSLByWebsiteId(c *gin.Context) { // @Summary Search website ssl by id // @Accept json // @Param id path integer true "request" -// @Success 200 +// @Success 200 {object} response.WebsiteSSLDTO // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ssl/:id [get] func (b *BaseApi) GetWebsiteSSLById(c *gin.Context) { id, err := helper.GetParamID(c) @@ -173,6 +180,7 @@ func (b *BaseApi) GetWebsiteSSLById(c *gin.Context) { // @Param request body request.WebsiteSSLUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ssl/update [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新证书设置 [domain]","formatEN":"Update ssl config [domain]"} func (b *BaseApi) UpdateWebsiteSSL(c *gin.Context) { @@ -184,7 +192,7 @@ func (b *BaseApi) UpdateWebsiteSSL(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Website SSL @@ -193,6 +201,7 @@ func (b *BaseApi) UpdateWebsiteSSL(c *gin.Context) { // @Param request body request.WebsiteSSLUpload true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ssl/upload [post] // @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"上传 ssl [type]","formatEN":"Upload ssl [type]"} func (b *BaseApi) UploadWebsiteSSL(c *gin.Context) { @@ -204,7 +213,7 @@ func (b *BaseApi) UploadWebsiteSSL(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Website SSL @@ -213,6 +222,7 @@ func (b *BaseApi) UploadWebsiteSSL(c *gin.Context) { // @Param request body request.WebsiteResourceReq true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /websites/ssl/download [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"下载证书文件 [domain]","formatEN":"download ssl file [domain]"} func (b *BaseApi) DownloadWebsiteSSL(c *gin.Context) { diff --git a/agent/app/dto/alert.go b/agent/app/dto/alert.go new file mode 100644 index 000000000..6cf8d7829 --- /dev/null +++ b/agent/app/dto/alert.go @@ -0,0 +1,20 @@ +package dto + +type CreateOrUpdateAlert struct { + AlertTitle string `json:"alertTitle"` + AlertType string `json:"alertType"` + AlertCount uint `json:"alertCount"` + EntryID uint `json:"entryID"` +} + +type AlertBase struct { + AlertType string `json:"alertType"` + EntryID uint `json:"entryID"` +} + +type PushAlert struct { + TaskName string `json:"taskName"` + AlertType string `json:"alertType"` + EntryID uint `json:"entryID"` + Param string `json:"param"` +} diff --git a/agent/app/dto/clam.go b/agent/app/dto/clam.go index 317d84637..e34ac0d53 100644 --- a/agent/app/dto/clam.go +++ b/agent/app/dto/clam.go @@ -33,6 +33,7 @@ type ClamInfo struct { LastHandleDate string `json:"lastHandleDate"` Spec string `json:"spec"` Description string `json:"description"` + AlertCount uint `json:"alertCount"` } type ClamLogSearch struct { @@ -71,6 +72,8 @@ type ClamCreate struct { InfectedDir string `json:"infectedDir"` Spec string `json:"spec"` Description string `json:"description"` + AlertCount uint `json:"alertCount"` + AlertTitle string `json:"alertTitle"` } type ClamUpdate struct { @@ -82,6 +85,8 @@ type ClamUpdate struct { InfectedDir string `json:"infectedDir"` Spec string `json:"spec"` Description string `json:"description"` + AlertCount uint `json:"alertCount"` + AlertTitle string `json:"alertTitle"` } type ClamUpdateStatus struct { diff --git a/agent/app/dto/cronjob.go b/agent/app/dto/cronjob.go index 0265e5872..a760e916b 100644 --- a/agent/app/dto/cronjob.go +++ b/agent/app/dto/cronjob.go @@ -41,10 +41,14 @@ type CronjobCreate struct { DownloadAccountID uint `json:"downloadAccountID"` RetainCopies int `json:"retainCopies" validate:"number,min=1"` Secret string `json:"secret"` + + AlertCount uint `json:"alertCount"` + AlertTitle string `json:"alertTitle"` } type CronjobUpdate struct { ID uint `json:"id" validate:"required"` + Type string `json:"type" validate:"required"` Name string `json:"name" validate:"required"` SpecCustom bool `json:"specCustom"` Spec string `json:"spec" validate:"required"` @@ -69,6 +73,9 @@ type CronjobUpdate struct { DownloadAccountID uint `json:"downloadAccountID"` RetainCopies int `json:"retainCopies" validate:"number,min=1"` Secret string `json:"secret"` + + AlertCount uint `json:"alertCount"` + AlertTitle string `json:"alertTitle"` } type CronjobUpdateStatus struct { @@ -122,6 +129,8 @@ type CronjobInfo struct { LastRecordTime string `json:"lastRecordTime"` Status string `json:"status"` Secret string `json:"secret"` + + AlertCount uint `json:"alertCount"` } type SearchRecord struct { diff --git a/agent/app/service/clam.go b/agent/app/service/clam.go index 815124d5e..a87d9d887 100644 --- a/agent/app/service/clam.go +++ b/agent/app/service/clam.go @@ -3,15 +3,17 @@ package service import ( "bufio" "fmt" - "github.com/1Panel-dev/1Panel/agent/app/repo" "os" "os/exec" "path" "path/filepath" "sort" + "strconv" "strings" "time" + "github.com/1Panel-dev/1Panel/agent/app/repo" + "github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/buserr" @@ -155,6 +157,16 @@ func (c *ClamService) SearchWithPage(req dto.SearchClamWithPage) (int64, interfa } datas[i].LastHandleDate = t1.Format(constant.DateTimeLayout) } + alertBase := dto.AlertBase{ + AlertType: "clams", + EntryID: datas[i].ID, + } + alertCount := xpack.GetAlert(alertBase) + if alertCount != 0 { + datas[i].AlertCount = alertCount + } else { + datas[i].AlertCount = 0 + } } return total, datas, err } @@ -181,6 +193,18 @@ func (c *ClamService) Create(req dto.ClamCreate) error { if err := clamRepo.Create(&clam); err != nil { return err } + if req.AlertCount != 0 { + createAlert := dto.CreateOrUpdateAlert{ + AlertTitle: req.AlertTitle, + AlertCount: req.AlertCount, + AlertType: "clams", + EntryID: clam.ID, + } + err := xpack.CreateAlert(createAlert) + if err != nil { + return err + } + } return nil } @@ -226,6 +250,16 @@ func (c *ClamService) Update(req dto.ClamUpdate) error { if err := clamRepo.Update(req.ID, upMap); err != nil { return err } + updateAlert := dto.CreateOrUpdateAlert{ + AlertTitle: req.AlertTitle, + AlertType: "clams", + AlertCount: req.AlertCount, + EntryID: clam.ID, + } + err := xpack.UpdateAlert(updateAlert) + if err != nil { + return err + } return nil } @@ -266,6 +300,14 @@ func (c *ClamService) Delete(req dto.ClamDelete) error { if err := clamRepo.Delete(repo.WithByID(id)); err != nil { return err } + alertBase := dto.AlertBase{ + AlertType: "clams", + EntryID: clam.ID, + } + err := xpack.DeleteAlert(alertBase) + if err != nil { + return err + } } return nil } @@ -309,6 +351,7 @@ func (c *ClamService) HandleOnce(req dto.OperateByID) error { if err != nil { global.LOG.Errorf("clamdscan failed, stdout: %v, err: %v", stdout, err) } + handleAlert(stdout, clam.Name, clam.ID) }() return nil } @@ -586,3 +629,28 @@ func (c *ClamService) loadLogPath(name string) string { return "" } + +func handleAlert(stdout, clamName string, clamId uint) { + if strings.Contains(stdout, "- SCAN SUMMARY -") { + lines := strings.Split(stdout, "\n") + for _, line := range lines { + if strings.HasPrefix(line, "Infected files: ") { + var infectedFiles = 0 + infectedFiles, _ = strconv.Atoi(strings.TrimPrefix(line, "Infected files: ")) + if infectedFiles > 0 { + pushAlert := dto.PushAlert{ + TaskName: clamName, + AlertType: "clams", + EntryID: clamId, + Param: strconv.Itoa(infectedFiles), + } + err := xpack.PushAlert(pushAlert) + if err != nil { + global.LOG.Errorf("clamdscan push failed, err: %v", err) + } + break + } + } + } + } +} diff --git a/agent/app/service/container.go b/agent/app/service/container.go index 39f3642a0..e667bc798 100644 --- a/agent/app/service/container.go +++ b/agent/app/service/container.go @@ -812,8 +812,7 @@ func (u *ContainerService) StreamLogs(ctx *gin.Context, params dto.StreamLog) { } return true case err := <-errorChan: - errorMsg := fmt.Sprintf("event: error\ndata: %v\n\n", err.Error()) - _, err = fmt.Fprintf(w, errorMsg) + _, _ = fmt.Fprintf(w, "event: error\ndata: %v\n\n", err.Error()) return false case <-ctx.Request.Context().Done(): return false diff --git a/agent/app/service/cronjob.go b/agent/app/service/cronjob.go index 92967a5f5..8aee0698f 100644 --- a/agent/app/service/cronjob.go +++ b/agent/app/service/cronjob.go @@ -10,6 +10,7 @@ import ( "time" "github.com/1Panel-dev/1Panel/agent/app/repo" + "github.com/1Panel-dev/1Panel/agent/utils/xpack" "github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/model" @@ -58,6 +59,16 @@ func (u *CronjobService) SearchWithPage(search dto.PageCronjob) (int64, interfac item.LastRecordTime = "-" } item.SourceAccounts, item.DownloadAccount, _ = loadBackupNamesByID(cronjob.SourceAccountIDs, cronjob.DownloadAccountID) + alertBase := dto.AlertBase{ + AlertType: cronjob.Type, + EntryID: cronjob.ID, + } + alertCount := xpack.GetAlert(alertBase) + if alertCount != 0 { + item.AlertCount = alertCount + } else { + item.AlertCount = 0 + } dtoCronjobs = append(dtoCronjobs, item) } return total, dtoCronjobs, err @@ -208,6 +219,18 @@ func (u *CronjobService) Create(req dto.CronjobCreate) error { if err := cronjobRepo.Create(&cronjob); err != nil { return err } + if req.AlertCount != 0 { + createAlert := dto.CreateOrUpdateAlert{ + AlertTitle: req.AlertTitle, + AlertCount: req.AlertCount, + AlertType: cronjob.Type, + EntryID: cronjob.ID, + } + err := xpack.CreateAlert(createAlert) + if err != nil { + return err + } + } return nil } @@ -250,6 +273,14 @@ func (u *CronjobService) Delete(req dto.CronjobBatchDelete) error { if err := cronjobRepo.Delete(repo.WithByID(id)); err != nil { return err } + alertBase := dto.AlertBase{ + AlertType: cronjob.Type, + EntryID: cronjob.ID, + } + err := xpack.DeleteAlert(alertBase) + if err != nil { + return err + } } return nil @@ -303,7 +334,21 @@ func (u *CronjobService) Update(id uint, req dto.CronjobUpdate) error { upMap["download_account_id"] = req.DownloadAccountID upMap["retain_copies"] = req.RetainCopies upMap["secret"] = req.Secret - return cronjobRepo.Update(id, upMap) + err = cronjobRepo.Update(id, upMap) + if err != nil { + return err + } + updateAlert := dto.CreateOrUpdateAlert{ + AlertTitle: req.AlertTitle, + AlertType: cronModel.Type, + AlertCount: req.AlertCount, + EntryID: cronModel.ID, + } + err = xpack.UpdateAlert(updateAlert) + if err != nil { + return err + } + return nil } func (u *CronjobService) UpdateStatus(id uint, status string) error { @@ -315,6 +360,7 @@ func (u *CronjobService) UpdateStatus(id uint, status string) error { entryIDs string err error ) + if status == constant.StatusEnable { entryIDs, err = u.StartJob(&cronjob, false) if err != nil { diff --git a/agent/app/service/cronjob_helper.go b/agent/app/service/cronjob_helper.go index 0b8ff5049..1600a1125 100644 --- a/agent/app/service/cronjob_helper.go +++ b/agent/app/service/cronjob_helper.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/app/repo" "github.com/1Panel-dev/1Panel/agent/app/task" @@ -18,6 +19,7 @@ import ( "github.com/1Panel-dev/1Panel/agent/utils/cmd" "github.com/1Panel-dev/1Panel/agent/utils/files" "github.com/1Panel-dev/1Panel/agent/utils/ntp" + "github.com/1Panel-dev/1Panel/agent/utils/xpack" ) func (u *CronjobService) HandleJob(cronjob *model.Cronjob) { @@ -69,6 +71,7 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) { record.Records, _ = mkdirAndWriteFile(cronjob, record.StartTime, message) } cronjobRepo.EndRecords(record, constant.StatusFailed, err.Error(), record.Records) + handleCronJobAlert(cronjob) return } if len(message) != 0 { @@ -315,3 +318,17 @@ func (u *CronjobService) removeExpiredLog(cronjob model.Cronjob) { func hasBackup(cronjobType string) bool { return cronjobType == "app" || cronjobType == "database" || cronjobType == "website" || cronjobType == "directory" || cronjobType == "snapshot" || cronjobType == "log" } + +func handleCronJobAlert(cronjob *model.Cronjob) { + pushAlert := dto.PushAlert{ + TaskName: cronjob.Name, + AlertType: cronjob.Type, + EntryID: cronjob.ID, + Param: cronjob.Type, + } + err := xpack.PushAlert(pushAlert) + if err != nil { + global.LOG.Errorf("cronjob alert push failed, err: %v", err) + return + } +} diff --git a/agent/app/service/dashboard.go b/agent/app/service/dashboard.go index 75585d68c..9c2bf6fa2 100644 --- a/agent/app/service/dashboard.go +++ b/agent/app/service/dashboard.go @@ -3,7 +3,6 @@ package service import ( "encoding/json" "fmt" - "github.com/1Panel-dev/1Panel/agent/app/repo" network "net" "os" "sort" @@ -11,6 +10,8 @@ import ( "sync" "time" + "github.com/1Panel-dev/1Panel/agent/app/repo" + "github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/constant" @@ -122,7 +123,7 @@ func (u *DashboardService) LoadCurrentInfoForNode() *dto.NodeCurrent { var currentInfo dto.NodeCurrent currentInfo.CPUTotal, _ = cpu.Counts(true) - totalPercent, _ := cpu.Percent(0, false) + totalPercent, _ := cpu.Percent(100*time.Millisecond, false) if len(totalPercent) == 1 { currentInfo.CPUUsedPercent = totalPercent[0] currentInfo.CPUUsed = currentInfo.CPUUsedPercent * 0.01 * float64(currentInfo.CPUTotal) diff --git a/agent/app/service/docker.go b/agent/app/service/docker.go index d995f947b..a716a81cb 100644 --- a/agent/app/service/docker.go +++ b/agent/app/service/docker.go @@ -202,6 +202,23 @@ func (u *DockerService) UpdateConf(req dto.SettingUpdate) error { daemonMap["exec-opts"] = []string{"native.cgroupdriver=systemd"} } } + case "http-proxy", "https-proxy": + delete(daemonMap, "proxies") + if len(req.Value) > 0 { + proxies := map[string]interface{}{ + req.Key: req.Value, + } + daemonMap["proxies"] = proxies + } + case "socks5-proxy", "close-proxy": + delete(daemonMap, "proxies") + if len(req.Value) > 0 { + proxies := map[string]interface{}{ + "http-proxy": req.Value, + "https-proxy": req.Value, + } + daemonMap["proxies"] = proxies + } } if len(daemonMap) == 0 { _ = os.Remove(constant.DaemonJsonPath) diff --git a/agent/app/service/file.go b/agent/app/service/file.go index 3e45347c8..356fa8cda 100644 --- a/agent/app/service/file.go +++ b/agent/app/service/file.go @@ -65,9 +65,13 @@ func NewIFileService() IFileService { func (f *FileService) GetFileList(op request.FileOption) (response.FileInfo, error) { var fileInfo response.FileInfo - if _, err := os.Stat(op.Path); err != nil && os.IsNotExist(err) { + data, err := os.Stat(op.Path) + if err != nil && os.IsNotExist(err) { return fileInfo, nil } + if !data.IsDir() { + op.FileOption.Path = filepath.Dir(op.FileOption.Path) + } info, err := files.NewFileInfo(op.FileOption) if err != nil { return fileInfo, err @@ -210,6 +214,12 @@ func (f *FileService) Create(op request.FileCreate) error { } func (f *FileService) Delete(op request.FileDelete) error { + if op.IsDir { + excludeDir := global.CONF.System.DataDir + if filepath.Base(op.Path) == ".1panel_clash" || op.Path == excludeDir { + return buserr.New(constant.ErrPathNotDelete) + } + } fo := files.NewFileOp() recycleBinStatus, _ := settingRepo.Get(settingRepo.WithByKey("FileRecycleBin")) if recycleBinStatus.Value == "disable" { diff --git a/agent/app/service/monitor.go b/agent/app/service/monitor.go index 69fb2f407..03d19717d 100644 --- a/agent/app/service/monitor.go +++ b/agent/app/service/monitor.go @@ -4,10 +4,11 @@ import ( "context" "encoding/json" "fmt" - "github.com/1Panel-dev/1Panel/agent/app/repo" "strconv" "time" + "github.com/1Panel-dev/1Panel/agent/app/repo" + "github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/constant" @@ -298,16 +299,20 @@ func StartMonitor(removeBefore bool, interval string) error { service := NewIMonitorService() ctx, cancel := context.WithCancel(context.Background()) monitorCancel = cancel - monitorID, err := global.Cron.AddJob(fmt.Sprintf("@every %sm", interval), service) - if err != nil { - return err - } + now := time.Now() + nextMinute := now.Truncate(time.Minute).Add(time.Minute) + time.AfterFunc(time.Until(nextMinute), func() { + monitorID, err := global.Cron.AddJob(fmt.Sprintf("@every %sm", interval), service) + if err != nil { + return + } + global.MonitorCronID = monitorID + }) service.Run() go service.saveIODataToDB(ctx, float64(intervalItem)) go service.saveNetDataToDB(ctx, float64(intervalItem)) - global.MonitorCronID = monitorID return nil } diff --git a/agent/constant/alert.go b/agent/constant/alert.go new file mode 100644 index 000000000..c3efc44b0 --- /dev/null +++ b/agent/constant/alert.go @@ -0,0 +1,11 @@ +package constant + +const ( + AlertEnable = "Enable" + AlertDisable = "Disable" + AlertSuccess = "Success" + AlertError = "Error" + AlertSyncError = "SyncError" + AlertPushError = "PushError" + AlertPushSuccess = "PushSuccess" +) \ No newline at end of file diff --git a/agent/constant/errs.go b/agent/constant/errs.go index 3cde3ad93..edff902e8 100644 --- a/agent/constant/errs.go +++ b/agent/constant/errs.go @@ -85,6 +85,7 @@ var ( ErrFileDownloadDir = "ErrFileDownloadDir" ErrCmdNotFound = "ErrCmdNotFound" ErrFavoriteExist = "ErrFavoriteExist" + ErrPathNotDelete = "ErrPathNotDelete" ) // mysql @@ -143,3 +144,12 @@ var ( var ( ErrNotExistUser = "ErrNotExistUser" ) + +// alert +var ( + ErrAlert = "ErrAlert" + ErrAlertPush = "ErrAlertPush" + ErrAlertSave = "ErrAlertSave" + ErrAlertSync = "ErrAlertSync" + ErrAlertRemote = "ErrAlertRemote" +) diff --git a/agent/i18n/i18n.go b/agent/i18n/i18n.go index 3f718d0db..d7a73e468 100644 --- a/agent/i18n/i18n.go +++ b/agent/i18n/i18n.go @@ -125,5 +125,12 @@ func Init() { _, _ = bundle.LoadMessageFileFS(fs, "lang/zh.yaml") _, _ = bundle.LoadMessageFileFS(fs, "lang/en.yaml") _, _ = bundle.LoadMessageFileFS(fs, "lang/zh-Hant.yaml") + _, _ = bundle.LoadMessageFileFS(fs, "lang/fa.yaml") + _, _ = bundle.LoadMessageFileFS(fs, "lang/pt.yaml") + _, _ = bundle.LoadMessageFileFS(fs, "lang/pt-BR.yaml") + _, _ = bundle.LoadMessageFileFS(fs, "lang/ja.yaml") + _, _ = bundle.LoadMessageFileFS(fs, "lang/ru.yaml") + _, _ = bundle.LoadMessageFileFS(fs, "lang/ms.yaml") + _, _ = bundle.LoadMessageFileFS(fs, "lang/ko.yaml") global.I18n = i18n.NewLocalizer(bundle, "en") } diff --git a/agent/i18n/lang/en.yaml b/agent/i18n/lang/en.yaml index 7cf1e60cb..a0791e90a 100644 --- a/agent/i18n/lang/en.yaml +++ b/agent/i18n/lang/en.yaml @@ -96,6 +96,7 @@ ErrCmdNotFound: "{{ .name}} command does not exist, please install this command ErrSourcePathNotFound: "Source directory does not exist" ErrFavoriteExist: "This path has been collected" ErrInvalidChar: "Illegal characters are prohibited" +ErrPathNotDelete: "The selected directory cannot be deleted" #website ErrDomainIsExist: "Domain is already exist" @@ -364,3 +365,10 @@ websiteDir: "Website directory" RecoverFailedStartRollBack: "Recovery failed, starting rollback" AppBackupFileIncomplete: "Backup file is incomplete; missing app.json or app.tar.gz file" AppAttributesNotMatch: "Application type or name does not match" + +#alert +ErrAlert: "Alert information format error, please check and try again!" +ErrAlertPush: "Alert push error, please check and try again!" +ErrAlertSave: "Alert save error, please check and try again!" +ErrAlertSync: "Alert sync error, please check and try again!" +ErrAlertRemote: "Remote alert error, please check and try again!" \ No newline at end of file diff --git a/agent/i18n/lang/fa.yaml b/agent/i18n/lang/fa.yaml new file mode 100644 index 000000000..4073cec63 --- /dev/null +++ b/agent/i18n/lang/fa.yaml @@ -0,0 +1,63 @@ +#cmd +AppVersion: "Lotfan noskhe-ye barname ra vared konid" +AppCommands: "Dasturat-e marbut be barname" +AppInit: "Barname ra shoru' konid" +AppKeyVal: "Kelid-e barname (faghat az zabane englisi poshtibani mikonad)" +AppCreateFileErr: "Khalgh-e file {{ .name }} namovaffagh bud {{ .err }}" +AppCreateDirErr: "Khalgh-e folder {{ .name }} namovaffagh bud {{ .err }}" +AppMissKey: "Kelid-e barname mojood nist, az -k estefade konid" +AppMissVersion: "Noskhe-ye barname mojood nist, az -v estefade konid" +AppVersionExist: "Noskhe ghablan mojood ast!" +AppCreateSuccessful: "Khalgh ba movaffaghiat anjam shod!" +AppWriteErr: "Neveshtan file {{ .name }} namovaffagh bud {{ .err }}" +SudoHelper: "Lotfan in eskript ra be onvane karbare root ya ba mojavez sudo ejra konid" +ListenIPCommands: "IP goosh dadan ra taghir dahid" +ListenIPv4: "Goosh dadan bar IPv4" +ListenIPv6: "Goosh dadan bar IPv6" +ListenChangeSuccessful: "Taghir movaffagh! Hala bar {{ .value }} goosh midahad" +ResetCommands: "E'ade setadad etela'at-e system" +ResetMFA: "Fa'al-sazi do marhale'i 1Panel ra laghv konid" +ResetHttps: "Voroud HTTPS baraye 1Panel ra laghv konid" +ResetEntrance: "Voroud amin 1Panel ra laghv konid" +ResetIPs: "Mahdudiyat IP-haye mojaz 1Panel ra laghv konid" +ResetDomain: "Sazgari domain 1Panel ra laghv konid" +RestoreCommands: "Bargasht be khadamate 1Panel va data" +RestoreNoSuchFile: "Hich file mojood baraye bargasht nist" +RestoreStep1: "(1/5) Shoru' bargasht be khadamate 1Panel va data az directory {{ .name }} ..." +RestoreStep2: "(2/5) Bargasht be binary 1Panel ba movaffaghiat anjam shod" +RestoreStep3: "(3/5) Bargasht be script 1Panel ba movaffaghiat anjam shod" +RestoreStep4: "(4/5) Bargasht be khadamat 1Panel ba movaffaghiat anjam shod" +RestoreStep5: "(5/5) Bargasht be data 1Panel ba movaffaghiat anjam shod" +RestoreSuccessful: "Bargasht ba movaffaghiat anjam shod! Khadamat dar hale restart ast, lotfan montazer bashid..." +UpdateCommands: "Be'rooz resani etela'at-e panel" +UpdateUser: "Be'rooz resani karbare panel" +UpdatePassword: "Be'rooz resani ramz-e panel" +UpdatePort: "Be'rooz resani port-e panel" +UpdateUserNull: "Khatta: karbare panel khalist!" +UpdateUserBlank: "Khatta: karbare panel shamel faseleh ast!" +UpdateUserFormat: "Khatta: format-e karbare panel na dorost ast! Faghat az englisi, chine'i, adad va _, ba tool-e 3-30 poshtibani mikonad" +UpdateUserErr: "Khatta: be'rooz resani karbare panel namovaffagh bud, {{ .err }}" +UpdateSuccessful: "Be'rooz resani ba movaffaghiat anjam shod!" +UpdateUserResult: "Karbare panel: {{ .name }}" +UpdatePasswordRead: "Khatta: khatayi dar khandan etela'at-e ramz-e panel, {{ .err }}" +UpdatePasswordNull: "Khatta: ramz-e panel khalist!" +UpdateUPasswordBlank: "Khatta: ramz-e panel shamel faseleh ast!" +UpdatePasswordFormat: "Khatta: ramz-e panel faghat az harf, adad, karakter-haye vizhe !@#$%*_,.? ba tool-e 8-30 poshtibani mikonad!" +UpdatePasswordLen: "Khatta: lotfan ramzi bishtar az 6 karakter vared konid!" +UpdatePasswordRe: "Teyid-e ramz:" +UpdatePasswordErr: "Khatta: be'rooz resani ramz-e panel namovaffagh bud, {{ .err }}" +UpdatePasswordSame: "Khatta: do ramz ba ham yeksan nistand, lotfan barrasi konid va dobare talash konid!" +UpdatePasswordResult: "Ramz-e panel: {{ .name }}" +UpdatePortFormat: "Khatta: shomareye port bayad bein 1 ta 65535 bashad!" +UpdatePortUsed: "Khatta: shomareye port ghablan estefade shode ast, lotfan barrasi konid va dobare talash konid!" +UpdatePortErr: "Khatta: be'rooz resani port-e panel namovaffagh bud, {{ .err }}" +UpdatePortResult: "Port-e panel: {{ .name }}" +UpdatePortFirewallAdd: "Ezafe kardane ghanoun-e port firewall namovaffagh bud, {{ .err }}, lotfan port {{ .name }} ra be dast az qavaneen firewall ezafe konid." +UpdatePortFirewallDel: "Khatta: hazf-e port firewall namovaffagh bud, {{ .err }}" +UpdatePortFirewallReload: "Reload firewall namovaffagh bud, {{ .err }}, lotfan firewall ra be dast reload konid." +UserInfo: "Daryaft etela'at-e panel" +UserInfoAddr: "Address-e panel: " +UserInfoPassHelp: "Nokte: baraye taghiri ramz, mitavanid dastur zir ra anjam dahid: " +DBConnErr: "Khatta: etesal be database namovaffagh bud, {{ .err }}" +SystemVersion: "noskhe: " +SystemMode: "halat: " diff --git a/agent/i18n/lang/ja.yaml b/agent/i18n/lang/ja.yaml new file mode 100644 index 000000000..2d172bdb4 --- /dev/null +++ b/agent/i18n/lang/ja.yaml @@ -0,0 +1,283 @@ +ErrInvalidParams: "リクエストパラメーターエラー:{{.Detail}}" +ErrTokenParse: "トークン生成エラー:{{.Detail}}" +ErrInitialPassword: "初期パスワードエラー" +ErrInternalServer: "サービス内部エラー:{{.Detail}}" +ErrRecordExist: "レコードはすでに存在します" +ErrRecordNotFound: "記録が見つかりません" +ErrStructTransform: "タイプ変換障害:{{.Detail}}" +ErrNotLogin: "ユーザーはログインしません:{{.Detail}}" +ErrPasswordExpired: "現在のパスワードが期限切れになっています:{{.Detail}}" +ErrNotSupportType: "システムは現在のタイプをサポートしていません:{{.Detail}}" +ErrApiConfigStatusInvalid: "APIインターフェイスアクセス禁止:{{.Detail}}" +ErrApiConfigKeyInvalid: "APIインターフェイスキーエラー:{{.Detail}}" +ErrApiConfigIPInvalid: "APIインターフェイスIPはホワイトリストにありません:{{.Detail}}" +ErrApiConfigDisable: "このインターフェイスは、APIインターフェイスコールの使用を禁止しています:{{.Detail}}" + +#common +ErrNameIsExist: "名前はすでに存在しています" +ErrDemoEnvironment: "デモサーバー、この操作を禁止します!" +ErrCmdTimeout: "コマンド実行がタイムアウトしました!" +ErrCmdIllegal: "コマンドには違法な文字が含まれています。変更してもう一度やり直してください!" +ErrPortExist: '{{.port}}ポートはすでに{{.type}} [{{.name}}]によって占有されています。' +TYPE_APP: "応用" +TYPE_RUNTIME: "ランタイム環境" +TYPE_DOMAIN: "ドメイン名" +ErrTypePort: 'port {{.name}}フォーマットエラー' +ErrTypePortRange: 'ポートレンジは1-65535の間である必要があります' +Success: "成功" +Failed: "失敗した" +SystemRestart: "システムの再起動により、タスクが中断されます" + +#app +ErrPortInUsed: "{{.Detail}}ポートはすでに使用されています" +ErrAppLimit: "アプリはインストール制限を超えています" +ErrAppRequired: "{{.Detail}}アプリが必要です" +ErrNotInstall: "アプリがインストールされていません" +ErrPortInOtherApp: "{{.port}}ポートは既にapp {{.apps}}で使用されています" +ErrDbUserNotValid: "ストックデータベース、ユーザー名、パスワードが一致しません!" +ErrDockerComposeNotValid: "Docker-Composeファイル形式のエラー!" +ErrUpdateBuWebsite: 'アプリケーションは正常に更新されましたが、Webサイト構成ファイルの変更に失敗しました。構成を確認してください!' +Err1PanelNetworkFailed: 'デフォルトのコンテナネットワークの作成に失敗しました!{{ 。詳細 }}' +ErrFileParse: 'アプリケーションDocker-Composeファイルの解析は失敗しました!' +ErrInstallDirNotFound: 'インストールディレクトリは存在しません' +AppStoreIsUpToDate: '最新の' +LocalAppVersionNull: '{{.name}}アプリはバージョンに同期されません!アプリケーションリストに追加できませんでした' +LocalAppVersionErr: '{{.name}}}バージョン{{.version}}の同期に失敗しました!{{.err}}' +ErrFileNotFound: '{{.name}}ファイルは存在しません' +ErrFileParseApp: '{{.name}} file {{.err}}を解析できなかった' +ErrAppDirNull: 'バージョンフォルダーは存在しません' +LocalAppErr: "app {{.name}}同期が失敗しました!{{.err}}" +ErrContainerName: "cantablernameはすでに存在しています" +ErrAppSystemRestart: "1パネルの再起動により、タスクが終了します" +ErrCreateHttpClient: "http request {{.err}}の作成に失敗しました" +ErrHttpReqTimeOut: "リクエスト{{.err}}" +ErrHttpReqFailed: "リクエストが失敗しました{{.err}}" +ErrHttpReqNotFound: "ファイルは存在しません" +ErrNoSuchHost: "ネットワーク接続に失敗しました" +ErrImagePullTimeOut: '画像プルタイムアウト' +ErrContainerNotFound: '{{.name}}コンテナは存在しません' +ErrContainerMsg: '{{.name}}コンテナは異常です。詳細については、コンテナページのログを確認してください' +ErrAppBackup: '{{.name}}アプリケーションバックアップが失敗したerr {{.err}}' +ErrImagePull: '{{.name}}画像プルFailed err {{.err}}' +ErrVersionTooLow: '現在の1パネルバージョンが低すぎてApp Storeを更新できないので、バージョンをアップグレードしてください' +ErrAppNameExist: 'アプリ名はすでに存在しています' +AppStoreIsSyncing: 'App Storeが同期しています。後でもう一度やり直してください' +ErrGetCompose: "docker-compose.ymlファイルを取得できませんでした!{{ 。詳細 }}" +ErrAppWarn: "異常なステータス、ログを確認してください" +ErrAppParamKey: "parameter {{.name}}フィールド例外" +ErrAppUpgrade: "アプリケーションのアップグレードに失敗しました{{.name}} {{.err}}" +AppRecover: "app {{.name}}ロールバック" +PullImageStart: "画像の引っ張りを開始{{.name}}" +PullImageSuccess: "画像が正常に引っ張られました" +UpgradeAppStart: "アプリケーションのアップグレードを起動{{.name}}" +UpgradeAppSuccess: "App {{.Name}}アップグレードされました" + +#file +ErrFileCanNotRead: "ファイルは読み取れません" +ErrFileToLarge: "ファイルが大きすぎます" +ErrPathNotFound: "パスは見つかりません" +ErrMovePathFailed: "ターゲットパスには元のパスが含まれていません!" +ErrLinkPathNotFound: "ターゲットパスは存在しません!" +ErrFileIsExist: "ファイルまたはディレクトリはすでに存在します!" +ErrFileUpload: "file {{.name}} {{.detail}}}のアップロードに失敗しました" +ErrFileDownloadDir: "サポートされていないフォルダーをダウンロードします" +ErrCmdNotFound: "{{.name}}コマンドは存在しません。最初にホストにこのコマンドをインストールしてください" +ErrSourcePathNotFound: "ソースディレクトリは存在しません" +ErrFavoriteExist: "このパスが収集されました" +ErrInvalidChar: "違法なキャラクターは禁止されています" +ErrPathNotDelete: "選択したディレクトリを削除することはできません" + +#website +ErrDomainIsExist: "ドメインはすでに存在しています" +ErrAliasIsExist: "エイリアスはすでに存在しています" +ErrAppDelete: '他のウェブサイトはこのアプリを使用します' +ErrGroupIsUsed: "グループは使用されており、削除することはできません" +ErrBackupMatch: "バックアップファイルは、ウェブサイトの現在の部分的なデータと一致しません:{{.Detail}}" +ErrBackupExist: 'バックアップファイルは、存在しない元のデータの一部に対応しています。{{.Detail}}' +ErrPHPResource: 'ローカルランタイムはスイッチングをサポートしません!' +ErrPathPermission: 'インデックスディレクトリで1000:1000以外のアクセス許可を持つフォルダーが検出されたため、Webサイトにアクセスするとアクセスが拒否された場合があります。上の[保存]ボタンをクリックしてください' +ErrDomainIsUsed: "ドメインはすでにWebサイトで使用されています{{.Name}}" +ErrDomainFormat: "{{.name}}ドメイン形式エラー" +ErrDefaultAlias: "デフォルトは予約済みのコード名です。別のコード名を使用してください" +ErrImageNotExist: "実行中の環境{{.name}}画像は存在しません。実行中の環境を再編集してください" + +#ssl +ErrSSLCannotDelete: "証明書{{.Name}}はWebサイトで使用されており、削除できません" +ErrAccountCannotDelete: "アカウントに関連付けられた証明書を削除することはできません" +ErrSSLApply: "証明書は引き続き正常に署名されていますが、OpenRestyリロードが失敗します。構成を確認してください!" +ErrEmailIsExist: 'メールはすでに存在しています' +ErrSSLKeyNotFound: '秘密キーファイルは存在しません' +ErrSSLCertificateNotFound: '証明書ファイルは存在しません' +ErrSSLKeyFormat: '秘密キーファイル検証エラー' +ErrSSLCertificateFormat: '証明書ファイル形式エラー、PEM形式を使用してください' +ErrEabKidOrEabHmacKeyCannotBlank: 'eabkidまたはeabhmackeyは空にすることはできません' +ErrOpenrestyNotFound: 'HTTPモードでは、最初にOpenRestyをインストールする必要があります' +ApplySSLStart: '証明書、ドメイン名[{{.domain}}]アプリケーションメソッド[{{.type}}]の申請を開始します' +dnsAccount: "DNSオートマチック" +dnsManual: "DNSマニュアル" +http: "http" +ApplySSLFailed: '[{{.domain}}]証明書のアプリケーションが失敗しました、{{.detail}}' +ApplySSLSuccess: '[{{{.domain}}]証明書のアプリケーションが成功しました!!' +DNSAccountName: 'dnsアカウント[{{.name}}]メーカー[{{.type}}]' +PushDirLog: 'ディレクトリにプッシュされた証明書[{{.Path}}] {{.Status}}' +ErrDeleteCAWithSSL: "現在の組織の下に発行された証明書があり、削除できません" +ErrDeleteWithPanelSSL: "パネルSSL構成はこの証明書を使用しており、削除できません" +ErrDefaultCA: "デフォルトの証明書当局は削除できません" +ApplyWebSiteSSLLog: "{{.name}} Webサイト証明書の更新を開始します" +ErrUpdateWebsiteSSL: "{{.name}}ウェブサイトは証明書の更新に失敗しました:{{.err}}" +ApplyWebSiteSSLSuccess: "ウェブサイトの証明書を正常に更新します" +ErrExecShell: "スクリプトの実行に失敗した{{.err}}" +ExecShellStart: "スクリプトの実行を開始します" +ExecShellSuccess: "スクリプトは正常に実行されました" +StartUpdateSystemSSL: "システム証明書の更新を開始します" +UpdateSystemSSLSuccess: "システム証明書を正常に更新します" + +#mysql +ErrUserIsExist: "現在のユーザーはすでに存在しています。新しいユーザーを入力してください" +ErrDatabaseIsExist: "現在のデータベースはすでに存在しています。新しいデータベースを入力してください" +ErrExecTimeOut: "SQL実行のタイミングを出して、データベースを確認してください" +ErrRemoteExist: "リモートデータベースはすでにその名前に存在しています。それを変更して、再試行してください" +ErrLocalExist: "ローカルデータベースはすでにその名前に存在しています。それを変更して、もう一度試してください" + +#redis +ErrTypeOfRedis: "回復ファイルのタイプは、現在の永続性モードと一致しません。ファイルタイプを変更して、再試行してください" + +#container +ErrInUsed: "{{.Detail}}が使用されており、削除できません" +ErrObjectInUsed: "このオブジェクトは使用されており、削除することはできません" +ErrPortRules: "ポートの数が一致しません。再入力してください!" +ErrPgImagePull: "画像プルタイムアウト。画像の加速を構成するか、Postgres:16.0-Alpine画像を手動で引いて、再試行してください" + +#runtime +ErrDirNotFound: "ビルドフォルダーは存在しません!ファイルの整合性を確認してください!" +ErrFileNotExist: "{{.Detail}}ファイルは存在しません!ソースファイルの完全性を確認してください!" +ErrImageBuildErr: "画像ビルドが失敗しました" +ErrImageExist: "画像はすでに存在しています!" +ErrDelWithWebsite: "運用環境はウェブサイトに関連付けられており、削除することはできません" +ErrRuntimeStart: "開始に失敗しました" +ErrPackageJsonNotFound: "package.jsonファイルは存在しません" +ErrScriptsNotFound: "Package.jsonにスクリプト構成アイテムは見つかりませんでした" +ErrContainerNameNotFound: "コンテナ名を取得できない場合は、.envファイルを確認してください" +ErrNodeModulesNotFound: "node_modulesフォルダーは存在しません!実行中の環境を編集するか、実行中の環境が正常に開始するのを待ちます" + +#setting +ErrBackupInUsed: "バックアップアカウントは既にCronjobで使用されており、削除することはできません。" +ErrBackupCheck: "バックアップアカウントテスト接続に失敗した{{.err}}" +ErrOSSConn: "最新バージョンを取得できない場合は、サーバーが外部ネットワークに接続できるかどうかを確認してください。" +ErrEntrance: "セキュリティ入り口情報エラー。チェックしてもう一度やり直してください!" + +#tool +ErrConfigNotFound: "構成ファイルは存在しません" +ErrConfigParse: "構成ファイル形式エラー" +ErrConfigIsNull: "構成ファイルは空にすることは許可されていません" +ErrConfigDirNotFound: "実行中のディレクトリは存在しません" +ErrConfigAlreadyExist: "同じ名前の構成ファイルが既に存在しています" +ErrUserFindErr: "ユーザー{{.name}} {{.err}}を見つけられなかった" + +#ssh +ErrFirewallNone: "システムでFirewalldまたはUFWサービスは検出されませんでした。チェックしてもう一度やり直してください!" +ErrFirewallBoth: "FirewalldサービスとUFWサービスの両方がシステムで検出されます。競合を避けるために、1つをアンインストールして再試行してください!" + +#cronjob +ErrBashExecute: "スクリプト実行エラー、タスク出力テキスト領域の特定の情報を確認してください。" +ErrCutWebsiteLog: "{{.Name}} Webサイトログの切断が失敗した、エラー{{.err}}" +CutWebsiteLogSuccess: "{{.Name}} Webサイトログカットに正常にカット、バックアップパス{{.Path}}" + +#toolbox +ErrNotExistUser: "現在のユーザーは存在しません。変更して再試行してください!" +ErrBanAction: "失敗した設定では、現在の{{.name}}サービスが利用できません。チェックして再試行してください!" +ErrClamdscanNotFound: "Clamdscanコマンドは検出されませんでした。インストールするためにドキュメントを参照してください!" + +#waf +ErrScope: "この構成の変更はサポートされていません" +ErrStateChange: "状態の変更に失敗しました" +ErrRuleExist: "ルールが存在します" +ErrRuleNotExist: "ルールは存在しません" +ErrParseIP: "IP形式エラー" +ErrDefaultIP: "デフォルトは予約済みの名前です。別の名前に変更してください" +ErrGroupInUse: "IPグループはブラック/ホワイトリストで使用され、削除できません" +ErrGroupExist: "IPグループ名はすでに存在しています" +ErrIPRange: "間違ったIP範囲" +ErrIPExist: "IPは終了します" + +#license +ErrLicense: "ライセンス形式のエラー、チェックして再試行してください!" +ErrLicenseCheck: "ライセンスの確認が失敗しました。チェックしてもう一度やり直してください!" +ErrLicenseSave: "ライセンス情報の保存に失敗しました、{{.err}}、もう一度やり直してください!" +ErrLicenseSync: "ライセンス情報の同期に失敗し、データベースでライセンス情報は検出されませんでした!" +ErrXpackNotFound: "このセクションはプロフェッショナルエディション機能です。最初にパネルsettings-licenseインターフェイスにライセンスをインポートしてください" +ErrXpackNotActive: "このセクションはプロフェッショナルエディション機能です。最初にパネル設定リセンスインターフェイスでライセンスステータスを同期してください" +ErrXpackOutOfDate: "現在のライセンスの有効期限が切れています。パネル設定リセンスインターフェイスにライセンスを再輸入してください" +ErrXpackLost: "ライセンスは、再試行の最大数に達しました。[設定] [ライセンス]ページに移動し、[同期]ボタンを手動でクリックして、プロフェッショナルバージョンの機能が適切に機能していることを確認してください。" +ErrXpackTimeout: "リクエストタイムアウト、ネットワーク接続が不安定な場合があります。後でもう一度やり直してください!" + +#license +ErrAlert: "情報形式のエラーをアラートしてください。チェックして再試行してください!" +ErrAlertPush: "アラートプッシュエラー、チェックして再試行してください!" +ErrAlertSave: "エラーを保存してください、チェックして再試行してください!" +ErrAlertSync: "アラート同期エラー、チェックして再試行してください!" +ErrAlertRemote: "リモートアラートエラー、チェックして再試行してください!" + +#cmd +AppVersion: "アプリバージョン" +AppCommands: "アプリ関連のコマンド" +AppInit: "アプリを初期化します" +AppKeyVal: "アプリキー(英語のみをサポートする)" +AppCreateFileErr: "file {{.name}}作成に失敗した{{.err}}" +AppCreateDirErr: "Folder {{.name}}作成に失敗した{{.err}}" +AppMissKey: "アプリキーがありません、-kを使用して指定します" +AppMissVersion: "アプリバージョンがありません、-vを使用して指定します" +AppVersionExist: "バージョンはすでに存在します!" +AppCreateSuccessful: "創造は成功しました!" +AppWriteErr: "file {{.name}} write failed {{.err}}" +SudoHelper: "{{.cmd}}を使用するか、ルートユーザーに切り替えてください" +ListenIPCommands: "リスニングIPを切り替えます" +ListenIPv4: "IPv4で聞いてください" +ListenIPv6: "IPv6で聞く" +ListenChangeSuccessful: "切り替え成功!{{.Value}}で聞いています" +ResetCommands: "システム情報をリセットします" +ResetMFA: "1パネルの2要素認証をキャンセルします" +ResetHttps: "1Panel HTTPSログインをキャンセルします" +ResetEntrance: "1パネルの安全な入り口をキャンセルします" +ResetIPs: "1パネル認定IP制限をキャンセルします" +ResetDomain: "1パネルドメインバインディングをキャンセルします" +RestoreCommands: "ロールバック1パネルサービスとデータ" +RestoreNoSuchFile: "ロールバックに使用できるファイルはありません" +RestoreStep1: "(1/5){{.name}}ディレクトリからの1パネルサービスとデータの開始ロールバック..." +RestoreStep2: "(2/5)1パネルバイナリロールバックが成功しました" +RestoreStep3: "(3/5)1パネルスクリプトロールバック成功" +RestoreStep4: "(4/5)1パネルサービスロールバックが成功しました" +RestoreStep5: "(5/5)1パネルデータロールバックが成功しました" +RestoreSuccessful: "ロールバックが成功しました!サービスを再起動します、待ってください..." +UpdateCommands: "パネル情報を更新します" +UpdateUser: "パネルユーザーを更新します" +UpdatePassword: "パスワードを更新します" +UpdatePort: "パネルポートを更新します" +UpdateUserNull: "エラー:パネルユーザーは空です!" +UpdateUserBlank: "エラー:パネルユーザーにはスペースが含まれています!" +UpdateUserFormat: "エラー:無効なパネルユーザー形式!英語、中国語、数字、_、長さ3〜30のみをサポートしています" +UpdateUserErr: "エラー:パネルユーザーの更新に失敗しました{{.err}}" +UpdateSuccessful: "更新成功!" +UpdateUserResult: "パネルユーザー:{{.name}}" +UpdatePasswordRead: "エラー:パネルパスワード情報の読み取りに失敗しました、{{.err}}" +UpdatePasswordNull: "エラー:パネルパスワードは空です!" +UpdateUPasswordBlank: "エラー:パスワードにはスペースが含まれています!" +UpdatePasswordFormat: "エラー:パネルパスワードは、文字、数字、特殊文字のみをサポートします!@#$%*_、。、、長さ8-30!" +UpdatePasswordLen: "エラー:6文字より長くパスワードを入力してください!" +UpdatePasswordRe: "パスワードを認証する:" +UpdatePasswordErr: "エラー:{{.err}}のパスワードの更新に失敗しました" +UpdatePasswordSame: "エラー:2つのパスワードが一致しません。チェックして再試行してください!" +UpdatePasswordResult: "パネルパスワード:{{.name}}" +UpdatePortFormat: "エラー:入力ポート番号は1〜65535でなければなりません!" +UpdatePortUsed: "エラー:ポート番号はすでに使用されています。チェックして再試行してください!" +UpdatePortErr: "エラー:パネルポートの更新に失敗しました{{.err}}" +UpdatePortResult: "パネルポート:{{.name}}" +UpdatePortFirewallAdd: "ファイアウォールポートルールの追加に失敗した{{.err}}、ファイアウォールルールに{{.name}}ポートを手動で追加してください。" +UpdatePortFirewallDel: "エラー:ファイアウォールポートの削除に失敗しました、{{.err}}" +UpdatePortFirewallReload: "ファイアウォールのリロードに失敗しました{{.err}}、ファイアウォールを手動でリロードしてください。" +UserInfo: "パネル情報を取得します" +UserInfoAddr: "パネルアドレス:" +UserInfoPassHelp: "ヒント:パスワードを変更するには、コマンドを実行できます。" +DBConnErr: "エラー:データベース接続の初期化に失敗しました、{{.err}}" +SystemVersion: "バージョン:" +SystemMode: "モード:" diff --git a/agent/i18n/lang/ko.yaml b/agent/i18n/lang/ko.yaml new file mode 100644 index 000000000..2f1ecc59e --- /dev/null +++ b/agent/i18n/lang/ko.yaml @@ -0,0 +1,286 @@ +ErrInvalidParams: "요청 매개변수 오류: {{ .detail }}" +ErrTokenParse: "토큰 생성 오류: {{ .detail }}" +ErrInitialPassword: "초기 비밀번호 오류" +ErrInternalServer: "서버 내부 오류: {{ .detail }}" +ErrRecordExist: "기록이 이미 존재합니다" +ErrRecordNotFound: "기록을 찾을 수 없습니다" +ErrStructTransform: "형식 변환 실패: {{ .detail }}" +ErrNotLogin: "사용자가 로그인되지 않았습니다: {{ .detail }}" +ErrPasswordExpired: "현재 비밀번호가 만료되었습니다: {{ .detail }}" +ErrNotSupportType: "시스템에서 현재 유형을 지원하지 않습니다: {{ .detail }}" +ErrApiConfigStatusInvalid: "API 인터페이스 액세스 금지: {{ .detail }}" +ErrApiConfigKeyInvalid: "API 인터페이스 키 오류: {{ .detail }}" +ErrApiConfigIPInvalid: "API 인터페이스 IP가 화이트리스트에 없습니다: {{ .detail }}" +ErrApiConfigDisable: "이 인터페이스는 API 호출을 금지합니다: {{ .detail }}" +ErrApiConfigKeyTimeInvalid: "API 인터페이스 타임스탬프 오류: {{ .detail }}" + +# 공통 +ErrNameIsExist: "이름이 이미 존재합니다" +ErrDemoEnvironment: "데모 서버에서는 이 작업이 금지되어 있습니다!" +ErrCmdTimeout: "명령어 실행 시간이 초과되었습니다!" +ErrCmdIllegal: "명령어에 잘못된 문자가 포함되어 있습니다. 수정 후 다시 시도하세요!" +ErrPortExist: '{{ .port }} 포트가 {{ .type }} [{{ .name }}]에 의해 이미 사용 중입니다' +TYPE_APP: "애플리케이션" +TYPE_RUNTIME: "실행 환경" +TYPE_DOMAIN: "도메인 이름" +ErrTypePort: '포트 {{ .name }} 형식 오류' +ErrTypePortRange: '포트 범위는 1-65535 사이여야 합니다' +Success: "성공" +Failed: "실패" +SystemRestart: "시스템 재시작으로 인해 작업이 중단되었습니다" + +# 애플리케이션 +ErrPortInUsed: "{{ .detail }} 포트가 이미 사용 중입니다" +ErrAppLimit: "앱 설치 제한을 초과했습니다" +ErrAppRequired: "{{ .detail }} 앱이 필요합니다" +ErrNotInstall: "앱이 설치되지 않았습니다" +ErrPortInOtherApp: "{{ .port }} 포트가 {{ .apps }} 앱에 의해 이미 사용 중입니다" +ErrDbUserNotValid: "데이터베이스 사용자 이름과 비밀번호가 일치하지 않습니다!" +ErrDockerComposeNotValid: "docker-compose 파일 형식 오류!" +ErrUpdateBuWebsite: "애플리케이션이 성공적으로 업데이트되었지만, 웹사이트 구성 파일 수정에 실패했습니다. 구성을 확인하세요!" +Err1PanelNetworkFailed: "기본 컨테이너 네트워크 생성 실패! {{ .detail }}" +ErrFileParse: "애플리케이션 docker-compose 파일 분석 실패!" +ErrInstallDirNotFound: "설치 디렉터리가 존재하지 않습니다" +AppStoreIsUpToDate: "최신 상태입니다" +LocalAppVersionNull: "{{.name}} 앱 버전이 동기화되지 않았습니다! 애플리케이션 목록에 추가할 수 없습니다" +LocalAppVersionErr: "{{.name}} 버전 {{.version}} 동기화 실패! {{.err}}" +ErrFileNotFound: "{{.name}} 파일이 존재하지 않습니다" +ErrFileParseApp: "{{.name}} 파일 분석 실패 {{.err}}" +ErrAppDirNull: "버전 폴더가 존재하지 않습니다" +LocalAppErr: "앱 {{.name}} 동기화 실패! {{.err}}" +ErrContainerName: "컨테이너 이름이 이미 존재합니다" +ErrAppSystemRestart: "1Panel 재시작으로 인해 작업이 중단되었습니다" +ErrCreateHttpClient: "HTTP 요청 생성 실패 {{.err}}" +ErrHttpReqTimeOut: "요청 시간이 초과되었습니다 {{.err}}" +ErrHttpReqFailed: "요청 실패 {{.err}}" +ErrHttpReqNotFound: "파일이 존재하지 않습니다" +ErrNoSuchHost: "네트워크 연결 실패" +ErrImagePullTimeOut: "이미지 가져오기 시간 초과" +ErrContainerNotFound: "{{ .name }} 컨테이너가 존재하지 않습니다" +ErrContainerMsg: "{{ .name }} 컨테이너가 비정상적입니다. 자세한 내용은 컨테이너 페이지의 로그를 확인하세요" +ErrAppBackup: "{{ .name }} 애플리케이션 백업 실패 오류 {{.err}}" +ErrImagePull: "{{ .name }} 이미지 가져오기 실패 오류 {{.err}}" +ErrVersionTooLow: "현재 1Panel 버전이 낮아 앱 스토어를 업데이트할 수 없습니다. 버전을 업그레이드하세요" +ErrAppNameExist: "앱 이름이 이미 존재합니다" +AppStoreIsSyncing: "앱 스토어가 동기화 중입니다. 나중에 다시 시도하세요" +ErrGetCompose: "docker-compose.yml 파일 가져오기 실패! {{ .detail }}" +ErrAppWarn: "비정상 상태, 로그를 확인하세요" +ErrAppParamKey: "매개변수 {{ .name }} 필드 예외" +ErrAppUpgrade: "애플리케이션 {{ .name }} 업그레이드 실패 {{ .err }}" +AppRecover: "앱 {{ .name }} 롤백 완료" +PullImageStart: "이미지 {{ .name }} 가져오기 시작" +PullImageSuccess: "이미지 가져오기 성공" +UpgradeAppStart: "애플리케이션 {{ .name }} 업그레이드 시작" +UpgradeAppSuccess: "앱 {{ .name }} 업그레이드 성공" + +# 파일 +ErrFileCanNotRead: "파일을 읽을 수 없습니다" +ErrFileToLarge: "파일이 너무 큽니다" +ErrPathNotFound: "경로를 찾을 수 없습니다" +ErrMovePathFailed: "대상 경로가 원래 경로를 포함할 수 없습니다!" +ErrLinkPathNotFound: "대상 경로가 존재하지 않습니다!" +ErrFileIsExist: "파일 또는 디렉터리가 이미 존재합니다!" +ErrFileUpload: "파일 업로드 실패 {{.name}} {{.detail}}" +ErrFileDownloadDir: "다운로드 폴더는 지원되지 않습니다" +ErrCmdNotFound: "{{ .name }} 명령이 존재하지 않습니다. 호스트에 이 명령을 먼저 설치하세요" +ErrSourcePathNotFound: "소스 디렉터리가 존재하지 않습니다" +ErrFavoriteExist: "이 경로는 이미 즐겨찾기에 추가되었습니다" +ErrInvalidChar: "잘못된 문자는 금지됩니다" +ErrPathNotDelete: "선택한 디렉터리는 삭제할 수 없습니다" + +# 웹사이트 +ErrDomainIsExist: "도메인 이름이 이미 존재합니다" +ErrAliasIsExist: "별칭이 이미 존재합니다" +ErrAppDelete: "다른 웹사이트에서 이 애플리케이션을 사용 중입니다" +ErrGroupIsUsed: "그룹이 사용 중이므로 삭제할 수 없습니다" +ErrBackupMatch: "백업 파일이 현재 웹사이트 데이터와 일치하지 않습니다: {{ .detail }}" +ErrBackupExist: "백업 파일이 원본 데이터의 일부와 일치하지 않습니다: {{ .detail }}" +ErrPHPResource: "로컬 런타임에서 전환을 지원하지 않습니다!" +ErrPathPermission: "인덱스 디렉터리에 1000:1000 권한이 아닌 폴더가 감지되었습니다. 웹사이트 액세스 시 '접근 거부' 오류가 발생할 수 있습니다. 상단의 저장 버튼을 클릭하세요" +ErrDomainIsUsed: "도메인이 웹사이트 {{ .name }}에서 이미 사용 중입니다" +ErrDomainFormat: "{{ .name }} 도메인 형식 오류" +ErrDefaultAlias: "기본은 예약된 코드 이름입니다. 다른 이름을 사용하세요" +ErrImageNotExist: "실행 환경 {{.name}} 이미지가 존재하지 않습니다. 실행 환경을 다시 편집하세요" + +# SSL 관련 +ErrSSLCannotDelete: "인증서 {{ .name }}은(는) 웹사이트에서 사용 중이므로 삭제할 수 없습니다." +ErrAccountCannotDelete: "계정과 연결된 인증서는 삭제할 수 없습니다." +ErrSSLApply: "인증서가 성공적으로 서명되었지만 Openresty 다시 로드에 실패했습니다. 구성을 확인하세요!" +ErrEmailIsExist: "이메일이 이미 존재합니다." +ErrSSLKeyNotFound: "개인 키 파일이 존재하지 않습니다." +ErrSSLCertificateNotFound: "인증서 파일이 존재하지 않습니다." +ErrSSLKeyFormat: "개인 키 파일 검증 오류" +ErrSSLCertificateFormat: "인증서 파일 형식 오류입니다. pem 형식을 사용하세요." +ErrEabKidOrEabHmacKeyCannotBlank: "EabKid 또는 EabHmacKey 는 비워둘 수 없습니다." +ErrOpenrestyNotFound: "HTTP 모드는 먼저 Openresty 를 설치해야 합니다." +ApplySSLStart: "인증서를 신청하기 시작합니다. 도메인 이름 [{{ .domain }}], 신청 방법 [{{ .type }}]" +dnsAccount: "DNS 자동" +dnsManual: "DNS 수동" +http: "HTTP" +ApplySSLFailed: "도메인 [{{ .domain }}] 인증서 신청 실패, {{ .detail }}" +ApplySSLSuccess: "도메인 [{{ .domain }}] 인증서 신청 성공!" +DNSAccountName: "DNS 계정 [{{ .name }}] 제조사 [{{ .type }}]" +PushDirLog: "인증서를 디렉토리 [{{ .path }}]에 푸시했습니다. {{ .status }}" +ErrDeleteCAWithSSL: "현재 조직에 발급된 인증서가 있으므로 삭제할 수 없습니다." +ErrDeleteWithPanelSSL: "패널 SSL 구성이 이 인증서를 사용 중이므로 삭제할 수 없습니다." +ErrDefaultCA: "기본 인증 기관은 삭제할 수 없습니다." +ApplyWebSiteSSLLog: "{{ .name }} 웹사이트 인증서를 업데이트하기 시작합니다." +ErrUpdateWebsiteSSL: "{{ .name }} 웹사이트 인증서 업데이트 실패: {{ .err }}" +ApplyWebSiteSSLSuccess: "웹사이트 인증서 업데이트 성공" +ErrExecShell: "스크립트 실행 실패 {{ .err }}" +ExecShellStart: "스크립트 실행 시작" +ExecShellSuccess: "스크립트 실행 성공" +StartUpdateSystemSSL: "시스템 인증서 업데이트 시작" +UpdateSystemSSLSuccess: "시스템 인증서 업데이트 성공" + +# MySQL +ErrUserIsExist: "현재 사용자가 이미 존재합니다. 새로운 사용자를 입력하세요." +ErrDatabaseIsExist: "현재 데이터베이스가 이미 존재합니다. 새로운 데이터베이스를 입력하세요." +ErrExecTimeOut: "SQL 실행이 시간 초과되었습니다. 데이터베이스를 확인하세요." +ErrRemoteExist: "원격 데이터베이스에 동일한 이름이 이미 존재합니다. 이름을 수정한 후 다시 시도하세요." +ErrLocalExist: "로컬 데이터베이스에 동일한 이름이 이미 존재합니다. 이름을 수정한 후 다시 시도하세요." + +# Redis +ErrTypeOfRedis: "복구 파일 형식이 현재 지속성 모드와 일치하지 않습니다. 파일 형식을 수정한 후 다시 시도하세요." + +# Container +ErrInUsed: "{{ .detail }}이(가) 사용 중이므로 삭제할 수 없습니다." +ErrObjectInUsed: "이 객체는 사용 중이므로 삭제할 수 없습니다." +ErrObjectBeDependent: "이 이미지는 다른 이미지에 의해 의존되고 있어 삭제할 수 없습니다." +ErrPortRules: "포트 수가 일치하지 않습니다. 다시 입력하세요!" +ErrPgImagePull: "이미지 가져오기 시간이 초과되었습니다. 이미지 가속 구성을 설정하거나 postgres:16.0-alpine 이미지를 수동으로 가져온 후 다시 시도하세요." + +# Runtime +ErrDirNotFound: "빌드 폴더가 존재하지 않습니다! 파일의 무결성을 확인하세요!" +ErrFileNotExist: "{{ .detail }} 파일이 존재하지 않습니다! 소스 파일의 무결성을 확인하세요!" +ErrImageBuildErr: "이미지 빌드 실패" +ErrImageExist: "이미지가 이미 존재합니다!" +ErrDelWithWebsite: "운영 환경이 웹사이트와 연결되어 있어 삭제할 수 없습니다." +ErrRuntimeStart: "실행 시작 실패" +ErrPackageJsonNotFound: "package.json 파일이 존재하지 않습니다." +ErrScriptsNotFound: "package.json 에서 스크립트 구성 항목을 찾을 수 없습니다." +ErrContainerNameNotFound: "컨테이너 이름을 가져올 수 없습니다. .env 파일을 확인하세요." +ErrNodeModulesNotFound: "node_modules 폴더가 존재하지 않습니다! 실행 환경을 편집하거나 실행 환경이 성공적으로 시작되기를 기다리세요." + +# Setting +ErrBackupInUsed: "백업 계정이 크론 작업에 사용 중이므로 삭제할 수 없습니다." +ErrBackupCheck: "백업 계정 연결 테스트 실패 {{ .err }}" +ErrOSSConn: "최신 버전을 가져올 수 없습니다. 서버가 외부 네트워크에 연결할 수 있는지 확인하세요." +ErrEntrance: "보안 입구 정보 오류. 확인 후 다시 시도하세요!" + +# Tool +ErrConfigNotFound: "구성 파일이 존재하지 않습니다." +ErrConfigParse: "구성 파일 형식 오류" +ErrConfigIsNull: "구성 파일은 비워둘 수 없습니다." +ErrConfigDirNotFound: "실행 디렉토리가 존재하지 않습니다." +ErrConfigAlreadyExist: "동일한 이름의 구성 파일이 이미 존재합니다." +ErrUserFindErr: "사용자 {{ .name }} 찾기 실패 {{ .err }}" + +# SSH +ErrFirewallNone: "시스템에서 firewalld 또는 ufw 서비스를 감지하지 못했습니다. 확인 후 다시 시도하세요!" +ErrFirewallBoth: "시스템에서 firewalld 와 ufw 서비스가 모두 감지되었습니다. 충돌을 방지하려면 하나를 제거한 후 다시 시도하세요!" + +# Cronjob +ErrBashExecute: "스크립트 실행 오류. 작업 출력 텍스트 영역에서 구체적인 정보를 확인하세요." +ErrCutWebsiteLog: "{{ .name }} 웹사이트 로그 자르기 실패, 오류 {{ .err }}" +CutWebsiteLogSuccess: "{{ .name }} 웹사이트 로그 자르기 성공, 백업 경로 {{ .path }}" + +# Toolbox +ErrNotExistUser: "현재 사용자가 존재하지 않습니다. 수정 후 다시 시도하세요!" +ErrBanAction: "설정 실패, 현재 {{ .name }} 서비스가 사용할 수 없습니다. 확인 후 다시 시도하세요!" +ErrClamdscanNotFound: "clamdscan 명령을 감지하지 못했습니다. 설치 문서를 참조하세요!" + +# WAF +ErrScope: "이 구성의 수정은 지원되지 않습니다." +ErrStateChange: "상태 수정 실패" +ErrRuleExist: "규칙이 이미 존재합니다." +ErrRuleNotExist: "규칙이 존재하지 않습니다." +ErrParseIP: "IP 형식 오류" +ErrDefaultIP: "default 는 예약된 이름입니다. 다른 이름으로 변경하세요." +ErrGroupInUse: "IP 그룹이 블랙/화이트 리스트에서 사용 중이며 삭제할 수 없습니다." +ErrGroupExist: "IP 그룹 이름이 이미 존재합니다." +ErrIPRange: "잘못된 IP 범위" +ErrIPExist: "IP가 이미 존재합니다." + +# License +ErrLicense: "라이선스 형식 오류, 확인 후 다시 시도하세요!" +ErrLicenseCheck: "라이선스 검증 실패, 확인 후 다시 시도하세요!" +ErrXpackVersion: "라이선스 검증 실패, 이 라이선스는 버전 제한이 있어 성공적으로 가져올 수 없습니다. 확인 후 다시 시도하세요!" +ErrLicenseSave: "라이선스 정보 저장 실패, 오류 {{ .err }}. 다시 시도하세요!" +ErrLicenseSync: "라이선스 정보 동기화 실패, 데이터베이스에서 라이선스 정보를 감지하지 못했습니다!" +ErrXpackNotFound: "이 섹션은 전문가 버전 기능입니다. Panel 설정 - 라이선스 인터페이스에서 먼저 라이선스를 가져오세요." +ErrXpackNotActive: "이 섹션은 전문가 버전 기능입니다. Panel 설정 - 라이선스 인터페이스에서 먼저 라이선스 상태를 동기화하세요." +ErrXpackOutOfDate: "현재 라이선스가 만료되었습니다. Panel 설정 - 라이선스 인터페이스에서 라이선스를 다시 가져오세요." +ErrXpackLost: "라이선스가 최대 재시도 횟수에 도달했습니다. [설정] - [라이선스] 페이지로 이동하여 동기화 버튼을 수동으로 클릭해 전문가 버전 기능을 정상적으로 작동시키세요." +ErrXpackTimeout: "요청 시간이 초과되었습니다. 네트워크 연결이 불안정할 수 있으니 나중에 다시 시도하세요!" + +# Alert +ErrAlert: "알림 정보 형식 오류, 확인 후 다시 시도하세요!" +ErrAlertPush: "알림 전송 오류, 확인 후 다시 시도하세요!" +ErrAlertSave: "알림 저장 오류, 확인 후 다시 시도하세요!" +ErrAlertSync: "알림 동기화 오류, 확인 후 다시 시도하세요!" +ErrAlertRemote: "원격 알림 오류, 확인 후 다시 시도하세요!" + +# CMD +AppVersion: "앱 버전" +AppCommands: "앱 관련 명령어" +AppInit: "앱 초기화" +AppKeyVal: "앱 키 (영어만 지원)" +AppCreateFileErr: "파일 {{ .name }} 생성 실패 {{ .err }}" +AppCreateDirErr: "폴더 {{ .name }} 생성 실패 {{ .err }}" +AppMissKey: "앱 키가 없습니다. -k 옵션으로 지정하세요." +AppMissVersion: "앱 버전이 없습니다. -v 옵션으로 지정하세요." +AppVersionExist: "버전이 이미 존재합니다!" +AppCreateSuccessful: "생성 성공!" +AppWriteErr: "파일 {{ .name }} 쓰기 실패 {{ .err }}" +SudoHelper: "{{ .cmd }} 명령을 사용하거나 root 사용자로 전환하세요." +ListenIPCommands: "IP 변경" +ListenIPv4: "IPv4 에서 수신 대기" +ListenIPv6: "IPv6 에서 수신 대기" +ListenChangeSuccessful: "변경 성공! 현재 {{ .value }}에서 수신 대기 중입니다." +ResetCommands: "시스템 정보 초기화" +ResetMFA: "1Panel 이중 인증 취소" +ResetHttps: "1Panel HTTPS 로그인 취소" +ResetEntrance: "1Panel 보안 입구 취소" +ResetIPs: "1Panel 허용 IP 제한 취소" +ResetDomain: "1Panel 도메인 바인딩 취소" +RestoreCommands: "1Panel 서비스 및 데이터 복구" +RestoreNoSuchFile: "복구 가능한 파일이 없습니다." +RestoreStep1: "(1/5) {{ .name }} 디렉토리에서 1Panel 서비스 및 데이터 복구 시작..." +RestoreStep2: "(2/5) 1Panel 바이너리 복구 성공" +RestoreStep3: "(3/5) 1Panel 스크립트 복구 성공" +RestoreStep4: "(4/5) 1Panel 서비스 복구 성공" +RestoreStep5: "(5/5) 1Panel 데이터 복구 성공" +RestoreSuccessful: "복구 성공! 서비스를 다시 시작합니다. 잠시만 기다려주세요..." +UpdateCommands: "패널 정보 업데이트" +UpdateUser: "패널 사용자 업데이트" +UpdatePassword: "패널 비밀번호 업데이트" +UpdatePort: "패널 포트 업데이트" +UpdateUserNull: "오류: 패널 사용자가 비어 있습니다!" +UpdateUserBlank: "오류: 패널 사용자에 공백이 포함되어 있습니다!" +UpdateUserFormat: "오류: 잘못된 패널 사용자 형식! 영어, 중국어, 숫자, _만 지원하며 길이는 3~30자입니다." +UpdateUserErr: "오류: 패널 사용자 업데이트 실패 {{ .err }}" +UpdateSuccessful: "업데이트 성공!" +UpdateUserResult: "패널 사용자: {{ .name }}" +UpdatePasswordRead: "오류: 패널 비밀번호 정보 읽기 실패 {{ .err }}" +UpdatePasswordNull: "오류: 패널 비밀번호가 비어 있습니다!" +UpdateUPasswordBlank: "오류: 패널 비밀번호에 공백이 포함되어 있습니다!" +UpdatePasswordFormat: "오류: 패널 비밀번호는 문자, 숫자, 특수 문자 !@#$%*_,.?만 지원하며 길이는 8~30자입니다!" +UpdatePasswordLen: "오류: 6자 이상의 비밀번호를 입력하세요!" +UpdatePasswordRe: "비밀번호 확인:" +UpdatePasswordErr: "오류: 패널 비밀번호 업데이트 실패 {{ .err }}" +UpdatePasswordSame: "오류: 두 비밀번호가 일치하지 않습니다. 확인 후 다시 시도하세요!" +UpdatePasswordResult: "패널 비밀번호: {{ .name }}" +UpdatePortFormat: "오류: 입력한 포트 번호는 1~65535 사이여야 합니다!" +UpdatePortUsed: "오류: 포트 번호가 이미 사용 중입니다. 확인 후 다시 시도하세요!" +UpdatePortErr: "오류: 패널 포트 업데이트 실패 {{ .err }}" +UpdatePortResult: "패널 포트: {{ .name }}" +UpdatePortFirewallAdd: "방화벽 포트 규칙 추가 실패 {{ .err }}, 방화벽 규칙에 {{ .name }} 포트를 수동으로 추가하세요." +UpdatePortFirewallDel: "오류: 방화벽 포트 삭제 실패 {{ .err }}" +UpdatePortFirewallReload: "방화벽 다시 로드 실패 {{ .err }}, 방화벽을 수동으로 다시 로드하세요." +UserInfo: "패널 정보 가져오기" +UserInfoAddr: "패널 주소: " +UserInfoPassHelp: "팁: 비밀번호를 변경하려면 다음 명령어를 실행할 수 있습니다: " +DBConnErr: "오류: 데이터베이스 연결 초기화 실패 {{ .err }}" +SystemVersion: "버전: " +SystemMode: "모드: " diff --git a/agent/i18n/lang/ms.yml b/agent/i18n/lang/ms.yml new file mode 100644 index 000000000..02c5056cf --- /dev/null +++ b/agent/i18n/lang/ms.yml @@ -0,0 +1,285 @@ +ErrInvalidParams: "Ralat parameter permintaan: {{ .detail }}" +ErrTokenParse: "Ralat penjanaan token: {{ .detail }}" +ErrInitialPassword: "Ralat kata laluan awal" +ErrInternalServer: "Ralat dalaman perkhidmatan: {{ .detail }}" +ErrRecordExist: "Rekod sudah wujud" +ErrRecordNotFound: "Rekod tidak dijumpai" +ErrStructTransform: "Kegagalan penukaran jenis: {{ .detail }}" +ErrNotLogin: "Pengguna belum log masuk: {{ .detail }}" +ErrPasswordExpired: "Kata laluan semasa telah tamat tempoh: {{ .detail }}" +ErrNotSupportType: "Sistem tidak menyokong jenis semasa: {{ .detail }}" +ErrApiConfigStatusInvalid: "Akses antara muka API dilarang: {{ .detail }}" +ErrApiConfigKeyInvalid: "Ralat kunci antara muka API: {{ .detail }}" +ErrApiConfigIPInvalid: "IP antara muka API tidak berada dalam senarai putih: {{ .detail }}" +ErrApiConfigDisable: "Antara muka ini melarang penggunaan panggilan API: {{ .detail }}" +ErrApiConfigKeyTimeInvalid: "Ralat cap waktu antara muka API: {{ .detail }}" + +#common +ErrNameIsExist: "Nama sudah wujud" +ErrDemoEnvironment: "Pelayan demo, operasi ini dilarang!" +ErrCmdTimeout: "Pelaksanaan arahan telah tamat masa!" +ErrCmdIllegal: "Arahan mengandungi aksara tidak sah. Sila ubah dan cuba lagi!" +ErrPortExist: 'Port {{ .port }} sudah digunakan oleh {{ .type }} [{{ .name }}]' +TYPE_APP: "Aplikasi" +TYPE_RUNTIME: "Persekitaran runtime" +TYPE_DOMAIN: "Nama domain" +ErrTypePort: 'Format port {{ .name }} adalah salah' +ErrTypePortRange: 'Julat port perlu berada di antara 1-65535' +Success: "Berjaya" +Failed: "Gagal" +SystemRestart: "Mulakan semula sistem menyebabkan gangguan tugas" + +#app +ErrPortInUsed: "Port {{ .detail }} sudah digunakan" +ErrAppLimit: "Aplikasi melebihi had pemasangan" +ErrAppRequired: "Aplikasi {{ .detail }} diperlukan" +ErrNotInstall: "Aplikasi tidak dipasang" +ErrPortInOtherApp: "Port {{ .port }} sudah digunakan oleh aplikasi {{ .apps }}" +ErrDbUserNotValid: "Pangkalan data stok, nama pengguna dan kata laluan tidak sepadan!" +ErrDockerComposeNotValid: "Format fail docker-compose adalah salah!" +ErrUpdateBuWebsite: "Aplikasi berjaya dikemas kini, tetapi pengubahsuaian fail konfigurasi laman web gagal, sila semak konfigurasi!" +Err1PanelNetworkFailed: "Penciptaan rangkaian kontena lalai gagal! {{ .detail }}" +ErrFileParse: "Analisis fail docker-compose aplikasi gagal!" +ErrInstallDirNotFound: "Direktori pemasangan tidak wujud" +AppStoreIsUpToDate: "Terkini" +LocalAppVersionNull: "Aplikasi {{.name}} tidak diselaraskan ke versi! Tidak dapat menambah ke senarai aplikasi" +LocalAppVersionErr: "{{.name}} gagal diselaraskan ke versi {{.version}}! {{.err}}" +ErrFileNotFound: "Fail {{.name}} tidak wujud" +ErrFileParseApp: "Gagal menganalisis fail {{.name}} {{.err}}" +ErrAppDirNull: "Folder versi tidak wujud" +LocalAppErr: "Penyelarasan aplikasi {{.name}} gagal! {{.err}}" +ErrContainerName: "Nama Kontena sudah wujud" +ErrAppSystemRestart: "Pemulangan semula 1Panel menyebabkan tugas terhenti" +ErrCreateHttpClient: "Gagal mencipta permintaan HTTP {{.err}}" +ErrHttpReqTimeOut: "Permintaan tamat masa {{.err}}" +ErrHttpReqFailed: "Permintaan gagal {{.err}}" +ErrHttpReqNotFound: "Fail tidak wujud" +ErrNoSuchHost: "Sambungan rangkaian gagal" +ErrImagePullTimeOut: "Tarik imej tamat masa" +ErrContainerNotFound: "Kontena {{ .name }} tidak wujud" +ErrContainerMsg: "Kontena {{ .name }} bermasalah, sila semak log pada halaman kontena untuk maklumat lanjut" +ErrAppBackup: "Sandaran aplikasi {{ .name }} gagal err {{.err}}" +ErrImagePull: "Tarik imej {{ .name }} gagal err {{.err}}" +ErrVersionTooLow: "Versi 1Panel semasa terlalu rendah untuk mengemas kini gedung aplikasi, sila tingkatkan versi" +ErrAppNameExist: "Nama aplikasi sudah wujud" +AppStoreIsSyncing: "Gedung Aplikasi sedang menyelaraskan, sila cuba lagi nanti" +ErrGetCompose: "Gagal mendapatkan fail docker-compose.yml! {{ .detail }}" +ErrAppWarn: "Status tidak normal, sila semak log" +ErrAppParamKey: "Pengecualian medan parameter {{ .name }}" +ErrAppUpgrade: "Gagal menaik taraf aplikasi {{ .name }} {{ .err }}" +AppRecover: "Aplikasi {{ .name }} telah dikembalikan" +PullImageStart: "Memulakan penarikan imej {{ .name }}" +PullImageSuccess: "Imej berjaya ditarik" +UpgradeAppStart: "Memulakan peningkatan aplikasi {{ .name }}" +UpgradeAppSuccess: "Aplikasi {{ .name }} berjaya dinaik taraf" + +#file +ErrFileCanNotRead: "Fail tidak boleh dibaca" +ErrFileToLarge: "Fail terlalu besar" +ErrPathNotFound: "Laluan tidak dijumpai" +ErrMovePathFailed: "Laluan sasaran tidak boleh mengandungi laluan asal!" +ErrLinkPathNotFound: "Laluan sasaran tidak wujud!" +ErrFileIsExist: "Fail atau direktori sudah wujud!" +ErrFileUpload: "Gagal memuat naik fail {{.name}} {{.detail}}" +ErrFileDownloadDir: "Muat turun folder tidak disokong" +ErrCmdNotFound: "Arahan {{ .name }} tidak wujud, sila pasang arahan ini pada hos terlebih dahulu" +ErrSourcePathNotFound: "Direktori sumber tidak wujud" +ErrFavoriteExist: "Laluan ini telah dikumpulkan" +ErrInvalidChar: "Aksara tidak sah adalah dilarang" +ErrPathNotDelete: "Direktori yang dipilih tidak boleh dipadam" + +#website +ErrDomainIsExist: "Nama domain sudah wujud" +ErrAliasIsExist: "Alias sudah wujud" +ErrAppDelete: "Laman web lain menggunakan aplikasi ini" +ErrGroupIsUsed: "Kumpulan sedang digunakan dan tidak boleh dipadam" +ErrBackupMatch: "Fail sandaran tidak sepadan dengan data separa laman web semasa: {{ .detail }}" +ErrBackupExist: "Fail sandaran berkaitan dengan sebahagian data asal yang tidak wujud: {{ .detail }}" +ErrPHPResource: "Runtime tempatan tidak menyokong penukaran!" +ErrPathPermission: "Folder dengan kebenaran bukan 1000:1000 dikesan dalam direktori indeks, yang mungkin menyebabkan ralat 'Access denied' semasa mengakses laman web. Sila klik butang simpan di atas" +ErrDomainIsUsed: "Domain sudah digunakan oleh laman web {{ .name }}" +ErrDomainFormat: "Format domain {{ .name }} adalah salah" +ErrDefaultAlias: "default ialah nama kod terpelihara, sila gunakan nama kod lain" +ErrImageNotExist: "Imej persekitaran runtime {{.name}} tidak wujud, sila sunting semula persekitaran runtime" + +#ssl +ErrSSLCannotDelete: "Sijil {{ .name }} sedang digunakan oleh laman web dan tidak boleh dihapuskan" +ErrAccountCannotDelete: "Sijil yang dikaitkan dengan akaun tidak boleh dihapuskan" +ErrSSLApply: "Sijil berjaya terus ditandatangani, tetapi reload OpenResty gagal, sila semak konfigurasi!" +ErrEmailIsExist: "Emel sudah wujud" +ErrSSLKeyNotFound: "Fail kunci peribadi tidak wujud" +ErrSSLCertificateNotFound: "Fail sijil tidak wujud" +ErrSSLKeyFormat: "Ralat pengesahan fail kunci peribadi" +ErrSSLCertificateFormat: "Format fail sijil salah, sila gunakan format PEM" +ErrEabKidOrEabHmacKeyCannotBlank: "EabKid atau EabHmacKey tidak boleh kosong" +ErrOpenrestyNotFound: "Mod HTTP memerlukan OpenResty dipasang terlebih dahulu" +ApplySSLStart: "Memulakan permohonan sijil, nama domain [{{ .domain }}], kaedah permohonan [{{ .type }}]" +dnsAccount: "DNS Automatik" +dnsManual: "DNS Manual" +http: "HTTP" +ApplySSLFailed: "Permohonan sijil untuk [{{ .domain }}] gagal, {{.detail}}" +ApplySSLSuccess: "Permohonan sijil untuk [{{ .domain }}] berjaya!" +DNSAccountName: "Akaun DNS [{{ .name }}], pengeluar [{{ .type }}]" +PushDirLog: "Sijil dihantar ke direktori [{{ .path }}] {{ .status }}" +ErrDeleteCAWithSSL: "Terdapat sijil yang telah dikeluarkan di bawah organisasi semasa dan tidak boleh dihapuskan" +ErrDeleteWithPanelSSL: "Konfigurasi SSL panel menggunakan sijil ini dan tidak boleh dihapuskan" +ErrDefaultCA: "Pihak Berkuasa Sijil lalai tidak boleh dihapuskan" +ApplyWebSiteSSLLog: "Memulakan kemas kini sijil laman web {{ .name }}" +ErrUpdateWebsiteSSL: "Sijil laman web {{ .name }} gagal dikemas kini: {{ .err }}" +ApplyWebSiteSSLSuccess: "Sijil laman web berjaya dikemas kini" +ErrExecShell: "Pelaksanaan skrip gagal {{ .err }}" +ExecShellStart: "Memulakan pelaksanaan skrip" +ExecShellSuccess: "Skrip berjaya dilaksanakan" +StartUpdateSystemSSL: "Memulakan kemas kini sijil sistem" +UpdateSystemSSLSuccess: "Sijil sistem berjaya dikemas kini" + +#mysql +ErrUserIsExist: "Pengguna semasa sudah wujud. Sila masukkan pengguna baharu" +ErrDatabaseIsExist: "Pangkalan data semasa sudah wujud. Sila masukkan pangkalan data baharu" +ErrExecTimeOut: "Pelaksanaan SQL tamat masa, sila semak pangkalan data" +ErrRemoteExist: "Pangkalan data jauh dengan nama tersebut sudah wujud, sila ubah dan cuba lagi" +ErrLocalExist: "Pangkalan data tempatan dengan nama tersebut sudah wujud, sila ubah dan cuba lagi" + +#redis +ErrTypeOfRedis: "Jenis fail pemulihan tidak sepadan dengan mod ketekalan semasa. Sila ubah jenis fail dan cuba lagi." + +#container +ErrInUsed: "{{ .detail }} sedang digunakan dan tidak boleh dihapuskan" +ErrObjectInUsed: "Objek ini sedang digunakan dan tidak boleh dihapuskan" +ErrObjectBeDependent: "Imej ini bergantung kepada imej lain dan tidak boleh dihapuskan" +ErrPortRules: "Bilangan port tidak sepadan, sila masukkan semula!" +ErrPgImagePull: "Tarik imej tamat masa. Sila konfigurasikan pecutan imej atau tarik imej postgres:16.0-alpine secara manual dan cuba lagi" + +#runtime +ErrDirNotFound: "Folder binaan tidak wujud! Sila semak integriti fail!" +ErrFileNotExist: "Fail {{ .detail }} tidak wujud! Sila semak integriti fail sumber!" +ErrImageBuildErr: "Binaan imej gagal" +ErrImageExist: "Imej sudah wujud!" +ErrDelWithWebsite: "Persekitaran operasi telah dikaitkan dengan laman web dan tidak boleh dihapuskan" +ErrRuntimeStart: "Gagal memulakan" +ErrPackageJsonNotFound: "Fail package.json tidak wujud" +ErrScriptsNotFound: "Tiada item konfigurasi skrip dijumpai dalam package.json" +ErrContainerNameNotFound: "Tidak dapat mendapatkan nama kontena, sila semak fail .env" +ErrNodeModulesNotFound: "Folder node_modules tidak wujud! Sila sunting persekitaran operasi atau tunggu sehingga persekitaran operasi berjaya dimulakan" + +#setting +ErrBackupInUsed: "Akaun sandaran sedang digunakan dalam cronjob dan tidak boleh dihapuskan." +ErrBackupCheck: "Ujian sambungan akaun sandaran gagal {{ .err }}" +ErrOSSConn: "Tidak dapat mendapatkan versi terkini, sila semak sama ada pelayan boleh menyambung ke rangkaian luaran." +ErrEntrance: "Ralat maklumat pintu masuk keselamatan. Sila semak dan cuba lagi!" + +#tool +ErrConfigNotFound: "Fail konfigurasi tidak wujud" +ErrConfigParse: "Format fail konfigurasi salah" +ErrConfigIsNull: "Fail konfigurasi tidak boleh kosong" +ErrConfigDirNotFound: "Direktori operasi tidak wujud" +ErrConfigAlreadyExist: "Fail konfigurasi dengan nama yang sama sudah wujud" +ErrUserFindErr: "Gagal mencari pengguna {{ .name }} {{ .err }}" + +#ssh +ErrFirewallNone: "Tiada perkhidmatan firewalld atau ufw dikesan pada sistem. Sila semak dan cuba lagi!" +ErrFirewallBoth: "Kedua-dua perkhidmatan firewalld dan ufw dikesan pada sistem. Untuk mengelakkan konflik, sila nyahpasang salah satu dan cuba lagi!" + +#cronjob +ErrBashExecute: "Ralat pelaksanaan skrip, sila semak maklumat khusus dalam kawasan teks output tugas." +ErrCutWebsiteLog: "Pemotongan log laman web {{ .name }} gagal, ralat {{ .err }}" +CutWebsiteLogSuccess: "Log laman web {{ .name }} berjaya dipotong, laluan sandaran {{ .path }}" + +#toolbox +ErrNotExistUser: "Pengguna semasa tidak wujud. Sila ubah dan cuba lagi!" +ErrBanAction: "Tetapan gagal, perkhidmatan {{ .name }} semasa tidak tersedia, sila semak dan cuba lagi!" +ErrClamdscanNotFound: "Perintah clamdscan tidak dikesan, sila rujuk dokumentasi untuk memasangnya!" + +#waf +ErrScope: "Pengubahsuaian konfigurasi ini tidak disokong" +ErrStateChange: "Pengubahsuaian status gagal" +ErrRuleExist: "Peraturan sudah wujud" +ErrRuleNotExist: "Peraturan tidak wujud" +ErrParseIP: "Format IP salah" +ErrDefaultIP: "default adalah nama terpelihara, sila tukar kepada nama lain" +ErrGroupInUse: "Kumpulan IP sedang digunakan oleh senarai hitam/putih dan tidak boleh dihapuskan" +ErrGroupExist: "Nama kumpulan IP sudah wujud" +ErrIPRange: "Julat IP salah" +ErrIPExist: "IP sudah wujud" + +#license +ErrLicense: "Format lesen salah, sila semak dan cuba lagi!" +ErrLicenseCheck: "Pengesahan lesen gagal, sila semak dan cuba lagi!" +ErrLicenseSave: "Gagal menyimpan maklumat lesen, ralat {{ .err }}, sila cuba lagi!" +ErrLicenseSync: "Gagal menyelaraskan maklumat lesen, tiada maklumat lesen dikesan dalam pangkalan data!" +ErrXpackNotFound: "Bahagian ini adalah ciri edisi profesional, sila import lesen terlebih dahulu dalam Tetapan Panel - Antara Muka Lesen" +ErrXpackNotActive: "Bahagian ini adalah ciri edisi profesional, sila selaraskan status lesen terlebih dahulu dalam Tetapan Panel - Antara Muka Lesen" +ErrXpackOutOfDate: "Lesen semasa telah tamat tempoh, sila import semula lesen dalam Tetapan Panel - Antara Muka Lesen" +ErrXpackLost: "Lesen telah mencapai bilangan maksimum percubaan semula. Sila pergi ke halaman [Tetapan] [Lesen] dan klik butang selaraskan secara manual untuk memastikan ciri versi profesional berfungsi dengan baik." +ErrXpackTimeout: "Permintaan tamat masa, sambungan rangkaian mungkin tidak stabil, sila cuba lagi nanti!" + +#license +ErrAlert: "Format maklumat amaran salah, sila semak dan cuba lagi!" +ErrAlertPush: "Ralat penghantaran amaran, sila semak dan cuba lagi!" +ErrAlertSave: "Ralat penyimpanan amaran, sila semak dan cuba lagi!" +ErrAlertSync: "Ralat penyelarasan amaran, sila semak dan cuba lagi!" +ErrAlertRemote: "Ralat amaran jauh, sila semak dan cuba lagi!" + +#cmd +AppVersion: "Versi aplikasi" +AppCommands: "Arahan berkaitan aplikasi" +AppInit: "Inisialisasi aplikasi" +AppKeyVal: "Kunci aplikasi (hanya menyokong bahasa Inggeris)" +AppCreateFileErr: "Gagal mencipta fail {{ .name }} {{ .err }}" +AppCreateDirErr: "Gagal mencipta folder {{ .name }} {{ .err }}" +AppMissKey: "Kunci aplikasi hilang, gunakan -k untuk menetapkan" +AppMissVersion: "Versi aplikasi hilang, gunakan -v untuk menetapkan" +AppVersionExist: "Versi sudah wujud!" +AppCreateSuccessful: "Ciptaan berjaya!" +AppWriteErr: "Penulisan fail {{ .name }} gagal {{ .err }}" +SudoHelper: "Sila gunakan {{ .cmd }} atau tukar ke pengguna root" +ListenIPCommands: "Tukar IP mendengar" +ListenIPv4: "Mendengar pada IPv4" +ListenIPv6: "Mendengar pada IPv6" +ListenChangeSuccessful: "Tukar berjaya! Kini mendengar pada {{ .value }}" +ResetCommands: "Tetapkan semula maklumat sistem" +ResetMFA: "Batal pengesahan dua faktor 1Panel" +ResetHttps: "Batal log masuk HTTPS 1Panel" +ResetEntrance: "Batal pintu masuk keselamatan 1Panel" +ResetIPs: "Batal sekatan IP yang dibenarkan 1Panel" +ResetDomain: "Batal pengikatan domain 1Panel" +RestoreCommands: "Pulihkan perkhidmatan dan data 1Panel" +RestoreNoSuchFile: "Tiada fail tersedia untuk pemulihan" +RestoreStep1: "(1/5) Memulakan pemulihan perkhidmatan dan data 1Panel daripada direktori {{ .name }}..." +RestoreStep2: "(2/5) Pemulihan binari 1Panel berjaya" +RestoreStep3: "(3/5) Pemulihan skrip 1Panel berjaya" +RestoreStep4: "(4/5) Pemulihan perkhidmatan 1Panel berjaya" +RestoreStep5: "(5/5) Pemulihan data 1Panel berjaya" +RestoreSuccessful: "Pemulihan berjaya! Memulakan semula perkhidmatan, sila tunggu..." +UpdateCommands: "Kemas kini maklumat panel" +UpdateUser: "Kemas kini pengguna panel" +UpdatePassword: "Kemas kini kata laluan panel" +UpdatePort: "Kemas kini port panel" +UpdateUserNull: "Ralat: Pengguna panel kosong!" +UpdateUserBlank: "Ralat: Pengguna panel mengandungi ruang kosong!" +UpdateUserFormat: "Ralat: Format pengguna panel tidak sah! Hanya menyokong huruf Inggeris, Cina, nombor, dan , dengan panjang 3-30 aksara" +UpdateUserErr: "Ralat: Gagal mengemas kini pengguna panel, {{ .err }}" +UpdateSuccessful: "Kemas kini berjaya!" +UpdateUserResult: "Pengguna panel: {{ .name }}" +UpdatePasswordRead: "Ralat: Gagal membaca maklumat kata laluan panel, {{ .err }}" +UpdatePasswordNull: "Ralat: Kata laluan panel kosong!" +UpdateUPasswordBlank: "Ralat: Kata laluan panel mengandungi ruang kosong!" +UpdatePasswordFormat: "Ralat: Kata laluan panel hanya menyokong huruf, nombor, dan aksara khas !@#$%*,.?, dengan panjang 8-30 aksara!" +UpdatePasswordLen: "Ralat: Sila masukkan kata laluan lebih panjang daripada 6 aksara!" +UpdatePasswordRe: "Sahkan kata laluan:" +UpdatePasswordErr: "Ralat: Gagal mengemas kini kata laluan panel, {{ .err }}" +UpdatePasswordSame: "Ralat: Kedua-dua kata laluan tidak sepadan, sila semak dan cuba lagi!" +UpdatePasswordResult: "Kata laluan panel: {{ .name }}" +UpdatePortFormat: "Ralat: Nombor port yang dimasukkan mesti antara 1 hingga 65535!" +UpdatePortUsed: "Ralat: Nombor port sudah digunakan, sila semak dan cuba lagi!" +UpdatePortErr: "Ralat: Gagal mengemas kini port panel, {{ .err }}" +UpdatePortResult: "Port Panel: {{ .name }}" +UpdatePortFirewallAdd: "Gagal menambah peraturan port firewall, {{ .err }}, sila tambah port {{ .name }} secara manual ke dalam peraturan firewall." +UpdatePortFirewallDel: "Ralat: Gagal memadam port firewall, {{ .err }}" +UpdatePortFirewallReload: "Gagal memuat semula firewall, {{ .err }}, sila muat semula firewall secara manual." +UserInfo: "Dapatkan maklumat panel" +UserInfoAddr: "Alamat panel: " +UserInfoPassHelp: "Petua: Untuk menukar kata laluan, anda boleh menjalankan arahan: " +DBConnErr: "Ralat: Gagal memulakan sambungan pangkalan data, {{ .err }}" +SystemVersion: "Versi: " +SystemMode: "Mod: " diff --git a/agent/i18n/lang/pt-BR.yaml b/agent/i18n/lang/pt-BR.yaml new file mode 100644 index 000000000..9e9a5158e --- /dev/null +++ b/agent/i18n/lang/pt-BR.yaml @@ -0,0 +1,283 @@ +ErrInvalidParams: "Erro nos parâmetros da solicitação: {{ .detail }}" +ErrTokenParse: "Erro na geração do token: {{ .detail }}" +ErrInitialPassword: "Erro na senha inicial" +ErrInternalServer: "Erro interno do serviço: {{ .detail }}" +ErrRecordExist: "Registro já existente" +ErrRecordNotFound: "Registros não encontrados" +ErrStructTransform: "Falha na conversão de tipo: {{ .detail }}" +ErrNotLogin: "Usuário não está logado: {{ .detail }}" +ErrPasswordExpired: "A senha atual expirou: {{ .detail }}" +ErrNotSupportType: "O sistema não suporta o tipo atual: {{ .detail }}" +ErrApiConfigStatusInvalid: "Acesso à interface da API proibido: {{ .detail }}" +ErrApiConfigKeyInvalid: "Erro na chave da interface da API: {{ .detail }}" +ErrApiConfigIPInvalid: "O IP da interface da API não está na lista de permissões: {{ .detail }}" +ErrApiConfigDisable: "Esta interface proíbe o uso de chamadas de API: {{ .detail }}" + +#common +ErrNameIsExist: "O nome já existe" +ErrDemoEnvironment: "Servidor de demonstração, operação proibida!" +ErrCmdTimeout: "Tempo limite de execução do comando excedido!" +ErrCmdIllegal: "O comando contém caracteres ilegais. Por favor, modifique e tente novamente!" +ErrPortExist: 'A porta {{ .port }} já está ocupada por {{ .type }} [{{ .name }}]' +TYPE_APP: "Aplicação" +TYPE_RUNTIME: "Ambiente de execução" +TYPE_DOMAIN: "Nome de domínio" +ErrTypePort: 'Erro no formato da porta {{ .name }}' +ErrTypePortRange: 'O intervalo da porta deve estar entre 1-65535' +Success: "Sucesso" +Failed: "Falhou" +SystemRestart: "A reinicialização do sistema causa interrupção da tarefa" + +#app +ErrPortInUsed: "A porta {{ .detail }} já está em uso" +ErrAppLimit: "O limite de instalação de aplicativos foi excedido" +ErrAppRequired: "O aplicativo {{ .detail }} é necessário" +ErrNotInstall: "Aplicativo não instalado" +ErrPortInOtherApp: "A porta {{ .port }} já está em uso pelo aplicativo {{ .apps }}" +ErrDbUserNotValid: "Banco de dados padrão, nome de usuário e senha não correspondem!" +ErrDockerComposeNotValid: "Erro no formato do arquivo docker-compose!" +ErrUpdateBuWebsite: "O aplicativo foi atualizado com sucesso, mas a modificação do arquivo de configuração do site falhou. Verifique a configuração!" +Err1PanelNetworkFailed: "Falha ao criar a rede padrão do container! {{ .detail }}" +ErrFileParse: "Falha ao analisar o arquivo docker-compose do aplicativo!" +ErrInstallDirNotFound: "O diretório de instalação não existe" +AppStoreIsUpToDate: "Atualizado" +LocalAppVersionNull: "O aplicativo {{.name}} não está sincronizado com a versão! Não foi possível adicionar à lista de aplicativos" +LocalAppVersionErr: "Falha ao sincronizar a versão {{.version}} do {{.name}}! {{.err}}" +ErrFileNotFound: "O arquivo {{.name}} não existe" +ErrFileParseApp: "Falha ao analisar o arquivo {{.name}} {{.err}}" +ErrAppDirNull: "O diretório da versão não existe" +LocalAppErr: "Falha ao sincronizar o aplicativo {{.name}}! {{.err}}" +ErrContainerName: "O nome do container já existe" +ErrAppSystemRestart: "A reinicialização do 1Panel causa a interrupção da tarefa" +ErrCreateHttpClient: "Falha ao criar a solicitação HTTP {{.err}}" +ErrHttpReqTimeOut: "Tempo limite da solicitação excedido {{.err}}" +ErrHttpReqFailed: "Falha na solicitação {{.err}}" +ErrHttpReqNotFound: "O arquivo não existe" +ErrNoSuchHost: "Falha na conexão de rede" +ErrImagePullTimeOut: "Tempo limite ao puxar a imagem" +ErrContainerNotFound: "O container {{ .name }} não existe" +ErrContainerMsg: "O container {{ .name }} está anormal, verifique o log na página do container para mais detalhes" +ErrAppBackup: "Falha no backup do aplicativo {{ .name }} erro {{.err}}" +ErrImagePull: "Falha ao puxar a imagem {{ .name }} erro {{.err}}" +ErrVersionTooLow: "A versão atual do 1Panel é muito baixa para atualizar a loja de aplicativos, por favor atualize a versão" +ErrAppNameExist: "O nome do aplicativo já existe" +AppStoreIsSyncing: "A loja de aplicativos está sincronizando, tente novamente mais tarde" +ErrGetCompose: "Falha ao obter o arquivo docker-compose.yml! {{ .detail }}" +ErrAppWarn: "Status anormal, verifique o log" +ErrAppParamKey: "Exceção no campo do parâmetro {{ .name }}" +ErrAppUpgrade: "Falha ao atualizar o aplicativo {{ .name }} {{ .err }}" +AppRecover: "Aplicativo {{ .name }} revertido" +PullImageStart: "Iniciando o download da imagem {{ .name }}" +PullImageSuccess: "Imagem baixada com sucesso" +UpgradeAppStart: "Iniciando a atualização do aplicativo {{ .name }}" +UpgradeAppSuccess: "Aplicativo {{ .name }} atualizado com sucesso" + +#file +ErrFileCanNotRead: "Não foi possível ler o arquivo" +ErrFileToLarge: "O arquivo é muito grande" +ErrPathNotFound: "Caminho não encontrado" +ErrMovePathFailed: "O caminho de destino não pode conter o caminho original!" +ErrLinkPathNotFound: "O caminho de destino não existe!" +ErrFileIsExist: "O arquivo ou diretório já existe!" +ErrFileUpload: "Falha ao fazer upload do arquivo {{.name}} {{.detail}}" +ErrFileDownloadDir: "Pasta de download não é suportada" +ErrCmdNotFound: "O comando {{ .name }} não existe, por favor, instale este comando no host primeiro" +ErrSourcePathNotFound: "O diretório de origem não existe" +ErrFavoriteExist: "Este caminho já foi adicionado aos favoritos" +ErrInvalidChar: "Caracteres ilegais são proibidos" +ErrPathNotDelete: "O diretório selecionado não pode ser excluído" + +#website +ErrDomainIsExist: "O domínio já existe" +ErrAliasIsExist: "O alias já existe" +ErrAppDelete: "Outro site usa este aplicativo" +ErrGroupIsUsed: "O grupo está em uso e não pode ser excluído" +ErrBackupMatch: "O arquivo de backup não corresponde aos dados parciais atuais do site: {{ .detail }}" +ErrBackupExist: "O arquivo de backup corresponde a uma parte dos dados originais que não existe: {{ .detail }}" +ErrPHPResource: "O ambiente local não suporta a troca!" +ErrPathPermission: "Foi detectada uma pasta com permissões diferentes de 1000:1000 no diretório de índice, o que pode causar um erro de acesso negado ao acessar o site. Clique no botão salvar acima" +ErrDomainIsUsed: "O domínio já está sendo usado pelo site {{ .name }}" +ErrDomainFormat: "O formato do domínio {{ .name }} está incorreto" +ErrDefaultAlias: "default é um nome reservado, por favor, use outro nome" +ErrImageNotExist: "A imagem do ambiente de execução {{.name}} não existe, por favor, reconfigure o ambiente" + +#ssl +ErrSSLCannotDelete: "O certificado {{ .name }} está sendo usado pelo site e não pode ser removido" +ErrAccountCannotDelete: "O certificado associado à conta não pode ser excluído" +ErrSSLApply: "O certificado foi assinado com sucesso, mas o recarregamento do OpenResty falhou, por favor, verifique a configuração!" +ErrEmailIsExist: "O email já existe" +ErrSSLKeyNotFound: "O arquivo da chave privada não existe" +ErrSSLCertificateNotFound: "O arquivo do certificado não existe" +ErrSSLKeyFormat: "Erro na verificação do arquivo da chave privada" +ErrSSLCertificateFormat: "Erro no formato do arquivo do certificado, por favor, use o formato PEM" +ErrEabKidOrEabHmacKeyCannotBlank: "EabKid ou EabHmacKey não podem estar vazios" +ErrOpenrestyNotFound: "O modo HTTP requer a instalação prévia do OpenResty" +ApplySSLStart: "Iniciando aplicação do certificado, domínio [{{ .domain }}], método de aplicação [{{ .type }}]" +dnsAccount: "DNS Automático" +dnsManual: "DNS Manual" +http: "HTTP" +ApplySSLFailed: "A aplicação do certificado para [{{ .domain }}] falhou, {{.detail}}" +ApplySSLSuccess: "Certificado para [{{ .domain }}] aplicado com sucesso!" +DNSAccountName: "Conta DNS [{{ .name }}], provedor [{{.type}}]" +PushDirLog: "Certificado enviado para o diretório [{{ .path }}] {{ .status }}" +ErrDeleteCAWithSSL: "Há um certificado emitido sob a organização atual, não pode ser excluído" +ErrDeleteWithPanelSSL: "A configuração SSL do painel usa este certificado, não pode ser excluído" +ErrDefaultCA: "A autoridade certificadora padrão não pode ser excluída" +ApplyWebSiteSSLLog: "Iniciando atualização do certificado do site {{ .name }}" +ErrUpdateWebsiteSSL: "Falha ao atualizar o certificado do site {{ .name }}: {{ .err }}" +ApplyWebSiteSSLSuccess: "Certificado do site atualizado com sucesso" +ErrExecShell: "Falha na execução do script {{ .err }}" +ExecShellStart: "Iniciando execução do script" +ExecShellSuccess: "Script executado com sucesso" +StartUpdateSystemSSL: "Iniciando atualização do certificado do sistema" +UpdateSystemSSLSuccess: "Certificado do sistema atualizado com sucesso" + +#mysql +ErrUserIsExist: "O usuário atual já existe. Por favor, insira um novo usuário" +ErrDatabaseIsExist: "O banco de dados atual já existe. Por favor, insira um novo banco de dados" +ErrExecTimeOut: "Tempo de execução SQL expirado, por favor, verifique o banco de dados" +ErrRemoteExist: "O banco de dados remoto já existe com este nome, por favor, modifique e tente novamente" +ErrLocalExist: "O banco de dados local já existe com este nome, por favor, modifique e tente novamente" + +#redis +ErrTypeOfRedis: "O tipo do arquivo de recuperação não corresponde ao modo de persistência atual. Modifique o tipo do arquivo e tente novamente" + +#container +ErrInUsed: "{{ .detail }} está em uso e não pode ser excluído" +ErrObjectInUsed: "Este objeto está em uso e não pode ser excluído" +ErrPortRules: "O número de portas não corresponde. Por favor, insira novamente!" +ErrPgImagePull: "Tempo limite ao tentar puxar a imagem. Configure a aceleração de imagem ou puxe manualmente a imagem postgres:16.0-alpine e tente novamente" + +#runtime +ErrDirNotFound: "A pasta de build não existe! Por favor, verifique a integridade dos arquivos!" +ErrFileNotExist: "O arquivo {{ .detail }} não existe! Por favor, verifique a integridade do arquivo de origem!" +ErrImageBuildErr: "Falha ao construir a imagem" +ErrImageExist: "A imagem já existe!" +ErrDelWithWebsite: "O ambiente operacional está associado a um site e não pode ser excluído" +ErrRuntimeStart: "Falha ao iniciar" +ErrPackageJsonNotFound: "O arquivo package.json não existe" +ErrScriptsNotFound: "Nenhum item de configuração de scripts foi encontrado no package.json" +ErrContainerNameNotFound: "Não foi possível obter o nome do contêiner. Por favor, verifique o arquivo .env" +ErrNodeModulesNotFound: "A pasta node_modules não existe! Edite o ambiente de execução ou aguarde até que o ambiente seja iniciado com sucesso" + +#setting +ErrBackupInUsed: "A conta de backup já está sendo usada em um cronjob e não pode ser excluída" +ErrBackupCheck: "Falha ao testar a conexão com a conta de backup {{ .err }}" +ErrOSSConn: "Não foi possível recuperar a versão mais recente. Por favor, verifique se o servidor pode se conectar à rede externa." +ErrEntrance: "Erro nas informações da entrada de segurança. Por favor, verifique e tente novamente!" + +#tool +ErrConfigNotFound: "O arquivo de configuração não existe" +ErrConfigParse: "Erro no formato do arquivo de configuração" +ErrConfigIsNull: "O arquivo de configuração não pode estar vazio" +ErrConfigDirNotFound: "O diretório de execução não existe" +ErrConfigAlreadyExist: "Um arquivo de configuração com o mesmo nome já existe" +ErrUserFindErr: "Falha ao encontrar o usuário {{ .name }} {{ .err }}" + +#ssh +ErrFirewallNone: "Nenhum serviço firewalld ou ufw foi detectado no sistema. Por favor, verifique e tente novamente!" +ErrFirewallBoth: "Os serviços firewalld e ufw foram detectados no sistema. Para evitar conflitos, desinstale um deles e tente novamente!" + +#cronjob +ErrBashExecute: "Erro na execução do script. Por favor, verifique as informações específicas na área de saída da tarefa." +ErrCutWebsiteLog: "Falha ao cortar os logs do site {{ .name }}, erro {{ .err }}" +CutWebsiteLogSuccess: "Logs do site {{ .name }} cortados com sucesso, caminho do backup {{ .path }}" + +#toolbox +ErrNotExistUser: "O usuário atual não existe. Por favor, modifique e tente novamente!" +ErrBanAction: "Falha na configuração. O serviço {{ .name }} atual está indisponível, por favor, verifique e tente novamente!" +ErrClamdscanNotFound: "O comando clamdscan não foi detectado. Por favor, consulte a documentação para instalá-lo!" + +#waf +ErrScope: "A modificação dessa configuração não é suportada" +ErrStateChange: "Falha ao modificar o estado" +ErrRuleExist: "A regra já existe" +ErrRuleNotExist: "A regra não existe" +ErrParseIP: "Erro no formato do IP" +ErrDefaultIP: "default é um nome reservado, por favor, escolha outro nome" +ErrGroupInUse: "O grupo de IPs está sendo usado na lista de bloqueio/permitidos e não pode ser excluído" +ErrGroupExist: "O nome do grupo de IPs já existe" +ErrIPRange: "Intervalo de IP inválido" +ErrIPExist: "O IP já existe" + +#license +ErrLicense: "Erro no formato da licença, por favor, verifique e tente novamente!" +ErrLicenseCheck: "Falha na verificação da licença, por favor, verifique e tente novamente!" +ErrLicenseSave: "Falha ao salvar as informações da licença, erro {{ .err }}, por favor, tente novamente!" +ErrLicenseSync: "Falha ao sincronizar as informações da licença, nenhuma informação de licença detectada no banco de dados!" +ErrXpackNotFound: "Esta seção é um recurso da edição profissional. Por favor, importe a licença primeiro na interface Configurações do Painel - Licença." +ErrXpackNotActive: "Esta seção é um recurso da edição profissional. Por favor, sincronize o status da licença primeiro na interface Configurações do Painel - Licença." +ErrXpackOutOfDate: "A licença atual expirou, por favor, reimporte a licença na interface Configurações do Painel - Licença." +ErrXpackLost: "A licença atingiu o número máximo de tentativas de reexecução. Por favor, acesse as páginas [Configurações] [Licença] e clique manualmente no botão de sincronização para garantir que os recursos da versão profissional funcionem corretamente." +ErrXpackTimeout: "Tempo limite de solicitação, a conexão de rede pode estar instável, por favor, tente novamente mais tarde!" + +#license +ErrAlert: "Erro no formato das informações do alerta, por favor, verifique e tente novamente!" +ErrAlertPush: "Erro no envio do alerta, por favor, verifique e tente novamente!" +ErrAlertSave: "Erro ao salvar o alerta, por favor, verifique e tente novamente!" +ErrAlertSync: "Erro na sincronização do alerta, por favor, verifique e tente novamente!" +ErrAlertRemote: "Erro de alerta remoto, por favor, verifique e tente novamente!" + +#cmd +AppVersion: "Versão do aplicativo" +AppCommands: "Comandos relacionados ao aplicativo" +AppInit: "Inicializar aplicativo" +AppKeyVal: "Chave do aplicativo (somente suporta inglês)" +AppCreateFileErr: "Falha ao criar o arquivo {{ .name }} {{ .err }}" +AppCreateDirErr: "Falha ao criar a pasta {{ .name }} {{ .err }}" +AppMissKey: "Chave do aplicativo ausente, use -k para especificar" +AppMissVersion: "Versão do aplicativo ausente, use -v para especificar" +AppVersionExist: "A versão já existe!" +AppCreateSuccessful: "Criação bem-sucedida!" +AppWriteErr: "Falha ao escrever no arquivo {{ .name }} {{ .err }}" +SudoHelper: "Por favor, use {{ .cmd }} ou altere para o usuário root" +ListenIPCommands: "Trocar IP de escuta" +ListenIPv4: "Escutando em IPv4" +ListenIPv6: "Escutando em IPv6" +ListenChangeSuccessful: "Troca bem-sucedida! Agora escutando em {{ .value }}" +ResetCommands: "Redefinir informações do sistema" +ResetMFA: "Cancelar autenticação de dois fatores do 1Panel" +ResetHttps: "Cancelar login https do 1Panel" +ResetEntrance: "Cancelar entrada segura do 1Panel" +ResetIPs: "Cancelar restrições de IP autorizado do 1Panel" +ResetDomain: "Cancelar vinculação de domínio do 1Panel" +RestoreCommands: "Restaurar serviço e dados do 1Panel" +RestoreNoSuchFile: "Nenhum arquivo disponível para restauração" +RestoreStep1: "(1/5) Iniciando a restauração do serviço e dados do 1Panel a partir do diretório {{ .name }}..." +RestoreStep2: "(2/5) Restauração do binário do 1Panel bem-sucedida" +RestoreStep3: "(3/5) Restauração dos scripts do 1Panel bem-sucedida" +RestoreStep4: "(4/5) Restauração do serviço do 1Panel bem-sucedida" +RestoreStep5: "(5/5) Restauração dos dados do 1Panel bem-sucedida" +RestoreSuccessful: "Restauração bem-sucedida! Reiniciando o serviço, por favor, aguarde..." +UpdateCommands: "Atualizar informações do painel" +UpdateUser: "Atualizar usuário do painel" +UpdatePassword: "Atualizar senha do painel" +UpdatePort: "Atualizar porta do painel" +UpdateUserNull: "Erro: usuário do painel está vazio!" +UpdateUserBlank: "Erro: o usuário do painel contém espaços!" +UpdateUserFormat: "Erro: Formato de usuário do painel inválido! Apenas suporta inglês, chinês, números e _, comprimento de 3-30." +UpdateUserErr: "Erro: Falha ao atualizar o usuário do painel, {{ .err }}" +UpdateSuccessful: "Atualização bem-sucedida!" +UpdateUserResult: "Usuário do painel: {{ .name }}" +UpdatePasswordRead: "Erro: Falha ao ler as informações da senha do painel, {{ .err }}" +UpdatePasswordNull: "Erro: A senha do painel está vazia!" +UpdateUPasswordBlank: "Erro: A senha do painel contém espaços!" +UpdatePasswordFormat: "Erro: A senha do painel suporta apenas letras, números, caracteres especiais !@#$%*_,.?, comprimento de 8-30!" +UpdatePasswordLen: "Erro: Por favor, insira uma senha com mais de 6 caracteres!" +UpdatePasswordRe: "Confirmar senha:" +UpdatePasswordErr: "Erro: Falha ao atualizar a senha do painel, {{ .err }}" +UpdatePasswordSame: "Erro: As duas senhas não correspondem, por favor, verifique e tente novamente!" +UpdatePasswordResult: "Senha do painel: {{ .name }}" +UpdatePortFormat: "Erro: O número da porta deve estar entre 1 e 65535!" +UpdatePortUsed: "Erro: O número da porta já está em uso, por favor, verifique e tente novamente!" +UpdatePortErr: "Erro: Falha ao atualizar a porta do painel, {{ .err }}" +UpdatePortResult: "Porta do painel: {{ .name }}" +UpdatePortFirewallAdd: "Falha ao adicionar regra de porta ao firewall, {{ .err }}, por favor, adicione manualmente a porta {{ .name }} às regras do firewall." +UpdatePortFirewallDel: "Erro: Falha ao excluir a porta do firewall, {{ .err }}" +UpdatePortFirewallReload: "Falha ao recarregar o firewall, {{ .err }}, por favor, recarregue o firewall manualmente." +UserInfo: "Obter informações do painel" +UserInfoAddr: "Endereço do painel: " +UserInfoPassHelp: "Dica: Para alterar a senha, você pode executar o comando: " +DBConnErr: "Erro: Falha ao inicializar a conexão com o banco de dados, {{ .err }}" +SystemVersion: "versão: " +SystemMode: "modo: " \ No newline at end of file diff --git a/agent/i18n/lang/pt.yaml b/agent/i18n/lang/pt.yaml new file mode 100644 index 000000000..f42f9f515 --- /dev/null +++ b/agent/i18n/lang/pt.yaml @@ -0,0 +1,63 @@ +#cmd +AppVersion: "Versão do aplicativo" +AppCommands: "Comandos relacionados ao aplicativo" +AppInit: "Inicializar aplicativo" +AppKeyVal: "Chave do aplicativo (suporta apenas inglês)" +AppCreateFileErr: "Falha na criação do arquivo {{ .name }} {{ .err }}" +AppCreateDirErr: "Falha na criação da pasta {{ .name }} {{ .err }}" +AppMissKey: "Chave do aplicativo ausente, use -k para especificar" +AppMissVersion: "Versão do aplicativo ausente, use -v para especificar" +AppVersionExist: "Versão já existente!" +AppCreateSuccessful: "Criação bem-sucedida!" +AppWriteErr: "Falha na gravação do arquivo {{ .name }} {{ .err }}" +SudoHelper: "Por favor, use {{ .cmd }} ou troque para o usuário root" +ListenIPCommands: "Alterar IP de escuta" +ListenIPv4: "Escutar no IPv4" +ListenIPv6: "Escutar no IPv6" +ListenChangeSuccessful: "Alteração bem-sucedida! Agora escutando em {{ .value }}" +ResetCommands: "Redefinir informações do sistema" +ResetMFA: "Cancelar autenticação de dois fatores do 1Panel" +ResetHttps: "Cancelar login HTTPS do 1Panel" +ResetEntrance: "Cancelar entrada segura do 1Panel" +ResetIPs: "Cancelar restrições de IP autorizados do 1Panel" +ResetDomain: "Cancelar vinculação de domínio do 1Panel" +RestoreCommands: "Restaurar serviço e dados do 1Panel" +RestoreNoSuchFile: "Nenhum arquivo disponível para restauração" +RestoreStep1: "(1/5) Iniciando a restauração do serviço e dados do 1Panel a partir do diretório {{ .name }}..." +RestoreStep2: "(2/5) Restauração do binário do 1Panel bem-sucedida" +RestoreStep3: "(3/5) Restauração do script do 1Panel bem-sucedida" +RestoreStep4: "(4/5) Restauração do serviço do 1Panel bem-sucedida" +RestoreStep5: "(5/5) Restauração dos dados do 1Panel bem-sucedida" +RestoreSuccessful: "Restauração bem-sucedida! Reiniciando o serviço, aguarde..." +UpdateCommands: "Atualizar informações do painel" +UpdateUser: "Atualizar usuário do painel" +UpdatePassword: "Atualizar senha do painel" +UpdatePort: "Atualizar porta do painel" +UpdateUserNull: "Erro: usuário do painel está vazio!" +UpdateUserBlank: "Erro: usuário do painel contém espaços!" +UpdateUserFormat: "Erro: Formato de usuário inválido! Aceita apenas inglês, chinês, números e _, comprimento de 3-30" +UpdateUserErr: "Erro: Falha ao atualizar usuário do painel, {{ .err }}" +UpdateSuccessful: "Atualização bem-sucedida!" +UpdateUserResult: "Usuário do painel: {{ .name }}" +UpdatePasswordRead: "Erro: Falha ao ler informações da senha do painel, {{ .err }}" +UpdatePasswordNull: "Erro: Senha do painel está vazia!" +UpdateUPasswordBlank: "Erro: Senha do painel contém espaços!" +UpdatePasswordFormat: "Erro: A senha do painel aceita apenas letras, números, caracteres especiais !@#$%*_,.?, comprimento de 8-30!" +UpdatePasswordLen: "Erro: Por favor, insira uma senha com mais de 6 caracteres!" +UpdatePasswordRe: "Confirmar senha:" +UpdatePasswordErr: "Erro: Falha ao atualizar senha do painel, {{ .err }}" +UpdatePasswordSame: "Erro: As duas senhas não coincidem, por favor, verifique e tente novamente!" +UpdatePasswordResult: "Senha do painel: {{ .name }}" +UpdatePortFormat: "Erro: O número da porta deve estar entre 1 e 65535!" +UpdatePortUsed: "Erro: O número da porta já está em uso, por favor, verifique e tente novamente!" +UpdatePortErr: "Erro: Falha ao atualizar a porta do painel, {{ .err }}" +UpdatePortResult: "Porta do painel: {{ .name }}" +UpdatePortFirewallAdd: "Falha ao adicionar regra de porta no firewall, {{ .err }}, adicione manualmente a porta {{ .name }} às regras do firewall." +UpdatePortFirewallDel: "Erro: Falha ao excluir porta do firewall, {{ .err }}" +UpdatePortFirewallReload: "Falha ao recarregar o firewall, {{ .err }}, recarregue o firewall manualmente." +UserInfo: "Obter informações do painel" +UserInfoAddr: "Endereço do painel: " +UserInfoPassHelp: "Dica: Para alterar a senha, execute o comando: " +DBConnErr: "Erro: Falha ao inicializar conexão com o banco de dados, {{ .err }}" +SystemVersion: "versão: " +SystemMode: "modo: " \ No newline at end of file diff --git a/agent/i18n/lang/ru.yaml b/agent/i18n/lang/ru.yaml new file mode 100644 index 000000000..c813aa133 --- /dev/null +++ b/agent/i18n/lang/ru.yaml @@ -0,0 +1,286 @@ +ErrInvalidParams: "Ошибка параметра запроса: {{ .detail }}" +ErrTokenParse: "Ошибка генерации токена: {{ .detail }}" +ErrInitialPassword: "Ошибка исходного пароля" +ErrInternalServer: "Внутренняя ошибка сервиса: {{ .detail }}" +ErrRecordExist: "Запись уже существует" +ErrRecordNotFound: "Записи не найдены" +ErrStructTransform: "Ошибка преобразования типа: {{ .detail }}" +ErrNotLogin: "Пользователь не вошел в систему: {{ .detail }}" +ErrPasswordExpired: "Текущий пароль истек: {{ .detail }}" +ErrNotSupportType: "Система не поддерживает текущий тип: {{ .detail }}" +ErrApiConfigStatusInvalid: "Доступ к API интерфейсу запрещен: {{ .detail }}" +ErrApiConfigKeyInvalid: "Ошибка ключа API интерфейса: {{ .detail }}" +ErrApiConfigIPInvalid: "IP API интерфейса отсутствует в белом списке: {{ .detail }}" +ErrApiConfigDisable: "Этот интерфейс запрещает использование вызовов API интерфейса: {{ .detail }}" +ErrApiConfigKeyTimeInvalid: "Ошибка временной метки интерфейса API: {{ .detail }}" + +#common +ErrNameIsExist: "Имя уже существует" +ErrDemoEnvironment: "Демо-сервер, операция запрещена!" +ErrCmdTimeout: "Время выполнения команды истекло!" +ErrCmdIllegal: "Команда содержит недопустимые символы. Пожалуйста, измените и попробуйте снова!" +ErrPortExist: "{{ .port }} порт уже занят {{ .type }} [{{ .name }}]" +TYPE_APP: "Приложение" +TYPE_RUNTIME: "Среда выполнения" +TYPE_DOMAIN: "Доменное имя" +ErrTypePort: "Ошибка формата порта {{ .name }}" +ErrTypePortRange: "Диапазон портов должен быть между 1-65535" +Success: "Успех" +Failed: "Неудача" +SystemRestart: "Перезагрузка системы приводит к прерыванию задачи" + +#app +ErrPortInUsed: "Порт {{ .detail }} уже используется" +ErrAppLimit: "Превышен лимит установки приложения" +ErrAppRequired: "Требуется приложение {{ .detail }}" +ErrNotInstall: "Приложение не установлено" +ErrPortInOtherApp: "Порт {{ .port }} уже используется приложением {{ .apps }}" +ErrDbUserNotValid: "База данных акций, имя пользователя и пароль не совпадают!" +ErrDockerComposeNotValid: "Ошибка формата файла docker-compose!" +ErrUpdateBuWebsite: "Приложение успешно обновлено, но изменение конфигурационного файла веб-сайта не удалось, пожалуйста, проверьте конфигурацию!" +Err1PanelNetworkFailed: "Не удалось создать сеть контейнера по умолчанию! {{ .detail }}" +ErrFileParse: "Не удалось разобрать файл docker-compose приложения!" +ErrInstallDirNotFound: "Директория установки не существует" +AppStoreIsUpToDate: "Обновлено" +LocalAppVersionNull: "Приложение {{.name}} не синхронизировано с версией! Невозможно добавить в список приложений" +LocalAppVersionErr: "{{.name}} не удалось синхронизировать версию {{.version}}! {{.err}}" +ErrFileNotFound: "Файл {{.name}} не существует" +ErrFileParseApp: "Не удалось проанализировать файл {{.name}} {{.err}}" +ErrAppDirNull: "Папка версии не существует" +LocalAppErr: "Синхронизация приложения {{.name}} не удалась! {{.err}}" +ErrContainerName: "Имя контейнера уже существует" +ErrAppSystemRestart: "Перезапуск 1Panel приводит к завершению задачи" +ErrCreateHttpClient: "Не удалось создать HTTP-запрос {{.err}}" +ErrHttpReqTimeOut: "Превышено время ожидания запроса {{.err}}" +ErrHttpReqFailed: "Запрос не выполнен {{.err}}" +ErrHttpReqNotFound: "Файл не существует" +ErrNoSuchHost: "Сбой сетевого подключения" +ErrImagePullTimeOut: "Тайм-аут загрузки образа" +ErrContainerNotFound: "Контейнер {{ .name }} не существует" +ErrContainerMsg: "Контейнер {{ .name }} работает ненормально, пожалуйста, проверьте журнал на странице контейнера для подробностей" +ErrAppBackup: "Резервное копирование приложения {{ .name }} не удалось, ошибка {{.err}}" +ErrImagePull: "Не удалось загрузить образ {{ .name }}, ошибка {{.err}}" +ErrVersionTooLow: "Текущая версия 1Panel слишком стара для обновления магазина приложений, пожалуйста, обновите версию" +ErrAppNameExist: "Имя приложения уже существует" +AppStoreIsSyncing: "Магазин приложений синхронизируется, пожалуйста, попробуйте позже" +ErrGetCompose: "Не удалось получить файл docker-compose.yml! {{ .detail }}" +ErrAppWarn: "Аномальный статус, пожалуйста, проверьте журнал" +ErrAppParamKey: "Исключение в поле параметра {{ .name }}" +ErrAppUpgrade: "Не удалось обновить приложение {{ .name }} {{ .err }}" +AppRecover: "Приложение {{ .name }} откатилось " +PullImageStart: "Начало загрузки образа {{ .name }}" +PullImageSuccess: "Образ успешно загружен" +UpgradeAppStart: "Начало обновления приложения {{ .name }}" +UpgradeAppSuccess: "Приложение {{ .name }} успешно обновлено" + +#file +ErrFileCanNotRead: "Файл недоступен для чтения" +ErrFileToLarge: "Файл слишком большой" +ErrPathNotFound: "Путь не найден" +ErrMovePathFailed: "Целевой путь не может содержать исходный путь!" +ErrLinkPathNotFound: "Целевой путь не существует!" +ErrFileIsExist: "Файл или каталог уже существует!" +ErrFileUpload: "Не удалось загрузить файл {{.name}} {{.detail}}" +ErrFileDownloadDir: "Скачивание папки не поддерживается" +ErrCmdNotFound: "Команда {{ .name}} не существует, пожалуйста, сначала установите эту команду на хосте" +ErrSourcePathNotFound: "Исходный каталог не существует" +ErrFavoriteExist: "Этот путь уже в избранном" +ErrInvalidChar: "Недопустимые символы запрещены" +ErrPathNotDelete: "Выбранный каталог не может быть удален" + +#website +ErrDomainIsExist: "Доменное имя уже существует" +ErrAliasIsExist: "Псевдоним уже существует" +ErrAppDelete: "Другой веб-сайт использует это приложение" +ErrGroupIsUsed: "Группа используется и не может быть удалена" +ErrBackupMatch: "файл резервной копии не соответствует текущим данным части сайта: {{ .detail}}" +ErrBackupExist: "файл резервной копии соответствует части исходных данных, которая не существует: {{ .detail}}" +ErrPHPResource: "Локальная среда выполнения не поддерживает переключение!" +ErrPathPermission: "Обнаружена папка с правами доступа не 1000:1000 в каталоге индекса, что может вызвать ошибку отказа в доступе при доступе к веб-сайту. Пожалуйста, нажмите кнопку сохранения выше" +ErrDomainIsUsed: "Домен уже используется веб-сайтом {{ .name }}" +ErrDomainFormat: "Ошибка формата домена {{ .name }}" +ErrDefaultAlias: "default — зарезервированное кодовое имя, пожалуйста, используйте другое кодовое имя" +ErrImageNotExist: "Образ рабочей среды {{.name}} не существует, пожалуйста, перенастройте рабочую среду" + +#ssl +ErrSSLCannotDelete: "Сертификат {{ .name }} используется веб-сайтом и не может быть удален" +ErrAccountCannotDelete: "Сертификат, связанный с учетной записью, не может быть удален" +ErrSSLApply: "Сертификат продолжает успешно подписываться, но перезагрузка openresty не удалась, пожалуйста, проверьте конфигурацию!" +ErrEmailIsExist: "Электронная почта уже существует" +ErrSSLKeyNotFound: "Файл закрытого ключа не существует" +ErrSSLCertificateNotFound: "Файл сертификата не существует" +ErrSSLKeyFormat: "Ошибка проверки файла закрытого ключа" +ErrSSLCertificateFormat: "Ошибка формата файла сертификата, пожалуйста, используйте формат pem" +ErrEabKidOrEabHmacKeyCannotBlank: "EabKid или EabHmacKey не могут быть пустыми" +ErrOpenrestyNotFound: "Режим HTTP требует предварительной установки Openresty" +ApplySSLStart: "Начать подачу заявки на сертификат, доменное имя [{{ .domain }}] метод подачи заявки [{{ .type }}] " +dnsAccount: "Автоматический DNS" +dnsManual: "Ручной DNS" +http: "HTTP" +ApplySSLFailed: "Заявка на сертификат для [{{ .domain }}] не удалась, {{.detail}} " +ApplySSLSuccess: "Заявка на сертификат для [{{ .domain }}] успешна! " +DNSAccountName: "Учетная запись DNS [{{ .name }}] производитель [{{.type}}]" +PushDirLog: "Сертификат отправлен в каталог [{{ .path }}] {{ .status }}" +ErrDeleteCAWithSSL: "Существует выданный сертификат под текущей организацией, удаление невозможно" +ErrDeleteWithPanelSSL: "Конфигурация SSL панели использует этот сертификат и не может быть удален" +ErrDefaultCA: "Уполномоченный центр по умолчанию не может быть удален" +ApplyWebSiteSSLLog: "Начать обновление сертификата веб-сайта {{ .name }}" +ErrUpdateWebsiteSSL: "Не удалось обновить сертификат веб-сайта {{ .name }}: {{ .err }}" +ApplyWebSiteSSLSuccess: "Сертификат веб-сайта успешно обновлен" +ErrExecShell: "Не удалось выполнить скрипт {{ .err }}" +ExecShellStart: "Начать выполнение скрипта" +ExecShellSuccess: "Скрипт успешно выполнен" +StartUpdateSystemSSL: "Начать обновление системного сертификата" +UpdateSystemSSLSuccess: "Системный сертификат успешно обновлен" + +#mysql +ErrUserIsExist: "Текущий пользователь уже существует. Пожалуйста, введите нового пользователя" +ErrDatabaseIsExist: "Текущая база данных уже существует. Пожалуйста, введите новую базу данных" +ErrExecTimeOut: "Время выполнения SQL запроса истекло, пожалуйста, проверьте базу данных" +ErrRemoteExist: "Удаленная база данных с таким именем уже существует, пожалуйста, измените и попробуйте снова" +ErrLocalExist: "Локальная база данных с таким именем уже существует, пожалуйста, измените и попробуйте снова" + +#redis +ErrTypeOfRedis: "Тип восстановленного файла не соответствует текущему режиму сохранения. Измените тип файла и попробуйте снова" + +#container +ErrInUsed: "{{ .detail }} используется и не может быть удален" +ErrObjectInUsed: "Этот объект используется и не может быть удален" +ErrObjectBeDependent: "Этот образ зависит от других образов и не может быть удален" +ErrPortRules: "Количество портов не совпадает, пожалуйста, введите заново!" +ErrPgImagePull: "Тайм-аут загрузки образа. Пожалуйста, настройте ускорение загрузки образа или вручную загрузите образ postgres:16.0-alpine и попробуйте снова" + +#runtime +ErrDirNotFound: "Папка сборки не существует! Пожалуйста, проверьте целостность файла!" +ErrFileNotExist: "Файл {{ .detail }} не существует! Пожалуйста, проверьте целостность исходного файла!" +ErrImageBuildErr: "Не удалось создать образ" +ErrImageExist: "Образ уже существует!" +ErrDelWithWebsite: "Рабочая среда уже связана с веб-сайтом и не может быть удалена" +ErrRuntimeStart: "Не удалось запустить" +ErrPackageJsonNotFound: "Файл package.json не существует" +ErrScriptsNotFound: "Конфигурационный элемент scripts не найден в package.json" +ErrContainerNameNotFound: "Не удалось получить имя контейнера, пожалуйста, проверьте файл .env" +ErrNodeModulesNotFound: "Папка node_modules не существует! Пожалуйста, отредактируйте среду выполнения или дождитесь успешного запуска среды выполнения" + +#setting +ErrBackupInUsed: "Учетная запись резервного копирования уже используется в cronjob и не может быть удалена." +ErrBackupCheck: "Проверка подключения учетной записи резервного копирования не выполнена {{ .err}}" +ErrOSSConn: "Не удалось получить последнюю версию, пожалуйста, проверьте возможность подключения сервера к внешней сети." +ErrEntrance: "Информация о безопасном входе неверна. Пожалуйста, проверьте и попробуйте снова!" + +#tool +ErrConfigNotFound: "Конфигурационный файл не существует" +ErrConfigParse: "Ошибка формата конфигурационного файла" +ErrConfigIsNull: "Конфигурационный файл не может быть пустым" +ErrConfigDirNotFound: "Каталог выполнения не существует" +ErrConfigAlreadyExist: "Конфигурационный файл с таким именем уже существует" +ErrUserFindErr: "Не удалось найти пользователя {{ .name }} {{ .err }}" + +#ssh +ErrFirewallNone: "На системе не обнаружен сервис firewalld или ufw. Пожалуйста, проверьте и попробуйте снова!" +ErrFirewallBoth: "На системе обнаружены оба сервиса firewalld и ufw. Чтобы избежать конфликтов, удалите один и попробуйте снова!" + +#cronjob +ErrBashExecute: "Ошибка выполнения скрипта, пожалуйста, проверьте конкретную информацию в области вывода задачи." +ErrCutWebsiteLog: "Не удалось разрезать лог веб-сайта {{ .name }}, ошибка {{ .err }}" +CutWebsiteLogSuccess: "Лог веб-сайта {{ .name }} успешно разрезан, путь к резервной копии {{ .path }}" + +#toolbox +ErrNotExistUser: "Текущий пользователь не существует. Пожалуйста, измените и попробуйте снова!" +ErrBanAction: "Установка не выполнена, текущий сервис {{ .name }} недоступен, пожалуйста, проверьте и попробуйте снова!" +ErrClamdscanNotFound: "Команда clamdscan не обнаружена, пожалуйста, обратитесь к документации для установки!" + +#waf +ErrScope: "Изменение этой конфигурации не поддерживается" +ErrStateChange: "Не удалось изменить состояние" +ErrRuleExist: "Правило уже существует" +ErrRuleNotExist: "Правило не существует" +ErrParseIP: "Ошибка формата IP" +ErrDefaultIP: "default — зарезервированное имя, пожалуйста, измените на другое имя" +ErrGroupInUse: "IP-группа используется в черно/белом списке и не может быть удалена" +ErrGroupExist: "Имя IP-группы уже существует" +ErrIPRange: "Неверный диапазон IP" +ErrIPExist: "IP уже существует" + +#license +ErrLicense: "Ошибка формата лицензии, пожалуйста, проверьте и попробуйте снова!" +ErrLicenseCheck: "Проверка лицензии не выполнена, пожалуйста, проверьте и попробуйте снова!" +ErrXpackVersion: "Ошибка проверки лицензии, эта лицензия ограничена по версии и не может быть успешно импортирована. Пожалуйста, проверьте и попробуйте снова!" +ErrLicenseSave: "Не удалось сохранить информацию о лицензии, ошибка {{ .err }}, пожалуйста, попробуйте снова!" +ErrLicenseSync: "Не удалось синхронизировать информацию о лицензии, в базе данных не обнаружена информация о лицензии!" +ErrXpackNotFound: "Этот раздел является функцией профессионального издания, пожалуйста, сначала импортируйте лицензию в интерфейсе Настройки панели — Лицензия" +ErrXpackNotActive: "Этот раздел является функцией профессионального издания, пожалуйста, сначала синхронизируйте статус лицензии в интерфейсе Настройки панели — Лицензия" +ErrXpackOutOfDate: "Текущая лицензия истекла, пожалуйста, повторно импортируйте лицензию в интерфейсе Настройки панели — Лицензия" +ErrXpackLost: "Лицензия достигла максимального числа попыток повторной попытки. Пожалуйста, перейдите на страницу [Настройки] [Лицензия] и вручную нажмите кнопку синхронизации, чтобы обеспечить корректную работу функций профессиональной версии." +ErrXpackTimeout: "Превышено время ожидания запроса, возможно, нестабильное сетевое соединение, пожалуйста, повторите попытку позже!" + +#license +ErrAlert: "Ошибка формата информации об оповещении, пожалуйста, проверьте и попробуйте снова!" +ErrAlertPush: "Ошибка отправки оповещения, пожалуйста, проверьте и попробуйте снова!" +ErrAlertSave: "Ошибка сохранения оповещения, пожалуйста, проверьте и попробуйте снова!" +ErrAlertSync: "Ошибка синхронизации оповещения, пожалуйста, проверьте и попробуйте снова!" +ErrAlertRemote: "Ошибка удаленного оповещения, пожалуйста, проверьте и попробуйте снова!" + +#cmd +AppVersion: "Версия приложения" +AppCommands: "Команды, связанные с приложением" +AppInit: "Инициализировать приложение" +AppKeyVal: "Ключ приложения (поддерживает только английский)" +AppCreateFileErr: "Не удалось создать файл {{ .name }} {{ .err }}" +AppCreateDirErr: "Не удалось создать папку {{ .name }} {{ .err }}" +AppMissKey: "Отсутствует ключ приложения, используйте -k для указания" +AppMissVersion: "Отсутствует версия приложения, используйте -v для указания" +AppVersionExist: "Версия уже существует!" +AppCreateSuccessful: "Создание прошло успешно!" +AppWriteErr: "Ошибка записи файла {{ .name }} {{ .err }}" +SudoHelper: "Пожалуйста, используйте {{ .cmd }} или переключитесь на пользователя root" +ListenIPCommands: "Переключить IP прослушивания" +ListenIPv4: "Прослушивать IPv4" +ListenIPv6: "Прослушивать IPv6" +ListenChangeSuccessful: "Переключение успешно! Теперь прослушивается {{ .value }}" +ResetCommands: "Сбросить информацию системы" +ResetMFA: "Отменить двухфакторную аутентификацию 1Panel" +ResetHttps: "Отменить вход в 1Panel по https" +ResetEntrance: "Отменить безопасный вход в 1Panel" +ResetIPs: "Отменить авторизованные IP-ограничения 1Panel" +ResetDomain: "Отменить привязку домена 1Panel" +RestoreCommands: "Откатить сервис и данные 1Panel" +RestoreNoSuchFile: "Нет доступных файлов для отката" +RestoreStep1: "(1/5) Начало отката сервиса и данных 1Panel из каталога {{ .name }}..." +RestoreStep2: "(2/5) Откат бинарного файла 1Panel успешен" +RestoreStep3: "(3/5) Откат скрипта 1Panel успешен" +RestoreStep4: "(4/5) Откат сервиса 1Panel успешен" +RestoreStep5: "(5/5) Откат данных 1Panel успешен" +RestoreSuccessful: "Откат успешен! Перезапуск службы, пожалуйста, подождите..." +UpdateCommands: "Обновить информацию панели" +UpdateUser: "Обновить пользователя панели" +UpdatePassword: "Обновить пароль панели" +UpdatePort: "Обновить порт панели" +UpdateUserNull: "Ошибка: пользователь панели пуст!" +UpdateUserBlank: "Ошибка: пользователь панели содержит пробелы!" +UpdateUserFormat: "Ошибка: неверный формат пользователя панели! Поддерживаются только английский, китайский, цифры и , длина 3-30" +UpdateUserErr: "Ошибка: не удалось обновить пользователя панели, {{ .err }}" +UpdateSuccessful: "Обновление успешно!" +UpdateUserResult: "Пользователь панели: {{ .name }}" +UpdatePasswordRead: "Ошибка: не удалось прочитать информацию о пароле панели, {{ .err }}" +UpdatePasswordNull: "Ошибка: пароль панели пуст!" +UpdateUPasswordBlank: "Ошибка: пароль панели содержит пробелы!" +UpdatePasswordFormat: "Ошибка: пароль панели поддерживает только буквы, цифры, специальные символы !@#$%* ,., длина 8-30!" +UpdatePasswordLen: "Ошибка: Пожалуйста, введите пароль длиной более 6 символов!" +UpdatePasswordRe: "Подтвердите пароль:" +UpdatePasswordErr: "Ошибка: не удалось обновить пароль панели, {{ .err }}" +UpdatePasswordSame: "Ошибка: два пароля не совпадают, пожалуйста, проверьте и попробуйте снова!" +UpdatePasswordResult: "Пароль панели: {{ .name }}" +UpdatePortFormat: "Ошибка: введенный номер порта должен быть между 1 и 65535!" +UpdatePortUsed: "Ошибка: номер порта уже используется, пожалуйста, проверьте и попробуйте снова!" +UpdatePortErr: "Ошибка: не удалось обновить порт панели, {{ .err }}" +UpdatePortResult: "Порт панели: {{ .name }}" +UpdatePortFirewallAdd: "Не удалось добавить правило порта брандмауэра, {{ .err }}, пожалуйста, вручную добавьте порт {{ .name }} в правила брандмауэра." +UpdatePortFirewallDel: "Ошибка: не удалось удалить порт брандмауэра, {{ .err }}" +UpdatePortFirewallReload: "Не удалось перезагрузить брандмауэр, {{ .err }}, пожалуйста, вручную перезагрузите брандмауэр." +UserInfo: "Получить информацию панели" +UserInfoAddr: "Адрес панели: " +UserInfoPassHelp: "Подсказка: чтобы изменить пароль, вы можете выполнить команду: " +DBConnErr: "Ошибка: не удалось инициализировать подключение к базе данных, {{ .err }}" +SystemVersion: "версия: " +SystemMode: "режим: " diff --git a/agent/i18n/lang/zh-Hant.yaml b/agent/i18n/lang/zh-Hant.yaml index 1326be9bd..b998ecacf 100644 --- a/agent/i18n/lang/zh-Hant.yaml +++ b/agent/i18n/lang/zh-Hant.yaml @@ -4,6 +4,10 @@ ErrRecordExist: "記錄已存在" ErrRecordNotFound: "記錄未找到" ErrStructTransform: "類型轉換失敗: {{ .detail }}" ErrNotSupportType: "系統暫不支持當前類型: {{ .detail }}" +ErrApiConfigStatusInvalid: "API 接口禁止訪問: {{ .detail }}" +ErrApiConfigKeyInvalid: "API 接口密钥錯誤: {{ .detail }}" +ErrApiConfigIPInvalid: "调用 API 接口 IP 不在白名单: {{ .detail }}" +ErrApiConfigDisable: "此接口禁止使用 API 接口調用: {{ .detail }}" #common ErrNameIsExist: "名稱已存在" @@ -96,6 +100,7 @@ ErrFileDownloadDir: "不支持下載文件夾" ErrCmdNotFound: "{{ .name}} 命令不存在,請先在宿主機安裝此命令" ErrSourcePathNotFound: "源目錄不存在" ErrFavoriteExist: "已收藏此路徑" +ErrPathNotDelete: "所選目錄不可删除" #website ErrDomainIsExist: "域名已存在" @@ -365,3 +370,10 @@ websiteDir: "網站目錄" RecoverFailedStartRollBack: "恢復失敗,開始回滾" AppBackupFileIncomplete: "備份文件不完整,缺少 app.json 或 app.tar.gz 文件" AppAttributesNotMatch: "應用類型或名稱不一致" + +# alert +ErrAlert: "告警資訊格式錯誤,請檢查後重試!" +ErrAlertPush: "告警資訊推送錯誤,請檢查後重試!" +ErrAlertSave: "告警資訊保存錯誤,請檢查後重試!" +ErrAlertSync: "告警資訊同步錯誤,請檢查後重試!" +ErrAlertRemote: "告警資訊遠端錯誤,請檢查後重試!" \ No newline at end of file diff --git a/agent/i18n/lang/zh.yaml b/agent/i18n/lang/zh.yaml index 304105cc0..5cfbb23c3 100644 --- a/agent/i18n/lang/zh.yaml +++ b/agent/i18n/lang/zh.yaml @@ -1,20 +1,31 @@ ErrInvalidParams: "请求参数错误: {{ .detail }}" +ErrTokenParse: "Token 生成错误: {{ .detail }}" +ErrInitialPassword: "原密码错误" ErrInternalServer: "服务内部错误: {{ .detail }}" ErrRecordExist: "记录已存在" ErrRecordNotFound: "记录未能找到" ErrStructTransform: "类型转换失败: {{ .detail }}" +ErrNotLogin: "用户未登录: {{ .detail }}" +ErrPasswordExpired: "当前密码已过期: {{ .detail }}" ErrNotSupportType: "系统暂不支持当前类型: {{ .detail }}" +ErrProxy: "请求错误,请检查该节点状态: {{ .detail }}" +ErrApiConfigStatusInvalid: "API 接口禁止访问: {{ .detail }}" +ErrApiConfigKeyInvalid: "API 接口密钥错误: {{ .detail }}" +ErrApiConfigIPInvalid: "调用 API 接口 IP 不在白名单: {{ .detail }}" +ErrApiConfigDisable: "此接口禁止使用 API 接口调用: {{ .detail }}" +ErrApiConfigKeyTimeInvalid: "API 接口时间戳错误: {{ .detail }}" #common ErrNameIsExist: "名称已存在" ErrDemoEnvironment: "演示服务器,禁止此操作!" ErrCmdTimeout: "命令执行超时!" ErrCmdIllegal: "执行命令中存在不合法字符,请修改后重试!" -ErrPortExist: "{{ .port }} 端口已被 {{ .type }} [{{ .name }}] 占用" +ErrPortExist: '{{ .port }} 端口已被 {{ .type }} [{{ .name }}] 占用' TYPE_APP: "应用" TYPE_RUNTIME: "运行环境" TYPE_DOMAIN: "域名" -ErrTypePort: "端口 {{ .name }} 格式错误" +ErrTypePort: '端口 {{ .name }} 格式错误' +ErrTypePortRange: '端口范围需要在 1-65535 之间' Success: "成功" Failed: "失败" SystemRestart: "系统重启导致任务中断" @@ -33,16 +44,16 @@ ErrNotInstall: "应用未安装" ErrPortInOtherApp: "{{ .port }} 端口已被应用 {{ .apps }} 占用!" ErrDbUserNotValid: "存量数据库,用户名密码不匹配!" ErrDockerComposeNotValid: "docker-compose 文件格式错误" -ErrUpdateBuWebsite: "应用更新成功,但是网站配置文件修改失败,请检查配置!" -Err1PanelNetworkFailed: "默认容器网络创建失败!{{ .detail }}" -ErrFileParse: "应用 docker-compose 文件解析失败!" -ErrInstallDirNotFound: "安装目录不存在,如需卸载,请选择强制卸载" -AppStoreIsUpToDate: "应用商店已经是最新版本" -LocalAppVersionNull: "{{.name}} 应用未同步到版本!无法添加到应用列表" -LocalAppVersionErr: "{{.name}} 同步版本 {{.version}} 失败!{{.err}}" -ErrFileNotFound: "{{.name}} 文件不存在" -ErrFileParseApp: "{{.name}} 文件解析失败 {{.err}}" -ErrAppDirNull: "版本文件夹不存在" +ErrUpdateBuWebsite: '应用更新成功,但是网站配置文件修改失败,请检查配置!' +Err1PanelNetworkFailed: '默认容器网络创建失败!{{ .detail }}' +ErrFileParse: '应用 docker-compose 文件解析失败!' +ErrInstallDirNotFound: '安装目录不存在,如需卸载,请选择强制卸载' +AppStoreIsUpToDate: '应用商店已经是最新版本' +LocalAppVersionNull: '{{.name}} 应用未同步到版本!无法添加到应用列表' +LocalAppVersionErr: '{{.name}} 同步版本 {{.version}} 失败!{{.err}}' +ErrFileNotFound: '{{.name}} 文件不存在' +ErrFileParseApp: '{{.name}} 文件解析失败 {{.err}}' +ErrAppDirNull: '版本文件夹不存在' LocalAppErr: "应用 {{.name}} 同步失败!{{.err}}" ErrContainerName: "容器名称已存在" ErrAppSystemRestart: "1Panel 重启导致任务终止" @@ -51,14 +62,14 @@ ErrHttpReqTimeOut: "请求超时 {{.err}}" ErrHttpReqFailed: "请求失败 {{.err}}" ErrHttpReqNotFound: "文件不存在" ErrNoSuchHost: "网络连接失败" -ErrImagePullTimeOut: "镜像拉取超时" -ErrContainerNotFound: "{{ .name }} 容器不存在" -ErrContainerMsg: "{{ .name }} 容器异常,具体请在容器页面查看日志" -ErrAppBackup: "{{ .name }} 应用备份失败 err {{.err}}" -ErrImagePull: "镜像拉取失败 {{.err}}" -ErrVersionTooLow: "当前 1Panel 版本过低,无法更新应用商店,请升级版本之后操作" -ErrAppNameExist: "应用名称已存在" -AppStoreIsSyncing: "应用商店正在同步中,请稍后再试" +ErrImagePullTimeOut: '镜像拉取超时' +ErrContainerNotFound: '{{ .name }} 容器不存在' +ErrContainerMsg: '{{ .name }} 容器异常,具体请在容器页面查看日志' +ErrAppBackup: '{{ .name }} 应用备份失败 err {{.err}}' +ErrImagePull: '镜像拉取失败 {{.err}}' +ErrVersionTooLow: '当前 1Panel 版本过低,无法更新应用商店,请升级版本之后操作' +ErrAppNameExist: '应用名称已存在' +AppStoreIsSyncing: '应用商店正在同步中,请稍后再试' ErrGetCompose: "docker-compose.yml 文件获取失败!{{ .detail }}" ErrAppWarn: "状态异常,请查看日志" ErrAppParamKey: "参数 {{ .name }} 字段异常" @@ -84,7 +95,7 @@ PullImageTimeout: "拉取镜像超时,请尝试增加镜像加速或者更换其 #file ErrFileCanNotRead: "此文件不支持预览" -ErrFileToLarge: "文件超过10M,无法打开" +ErrFileToLarge: "文件超过10M,无法打开" ErrPathNotFound: "目录不存在" ErrMovePathFailed: "目标路径不能包含原路径!" ErrLinkPathNotFound: "目标路径不存在!" @@ -95,16 +106,17 @@ ErrCmdNotFound: "{{ .name}} 命令不存在,请先在宿主机安装此命令" ErrSourcePathNotFound: "源目录不存在" ErrFavoriteExist: "已收藏此路径" ErrInvalidChar: "禁止使用非法字符" +ErrPathNotDelete: "所选目录不可删除" #website ErrDomainIsExist: "域名已存在" ErrAliasIsExist: "代号已存在" -ErrAppDelete: "其他网站使用此应用,无法删除" -ErrGroupIsUsed: "分组正在使用中,无法删除" -ErrBackupMatch: "该备份文件与当前网站部分数据不匹配 {{ .detail}}" -ErrBackupExist: "该备份文件对应部分源数据不存在 {{ .detail}}" -ErrPHPResource: "本地运行环境不支持切换!" -ErrPathPermission: "index 目录下检测到非 1000:1000 权限文件夹,可能导致网站访问 Access denied 错误,请点击上方保存按钮" +ErrAppDelete: '其他网站使用此应用,无法删除' +ErrGroupIsUsed: '分组正在使用中,无法删除' +ErrBackupMatch: '该备份文件与当前网站部分数据不匹配 {{ .detail}}' +ErrBackupExist: '该备份文件对应部分源数据不存在 {{ .detail}}' +ErrPHPResource: '本地运行环境不支持切换!' +ErrPathPermission: 'index 目录下检测到非 1000:1000 权限文件夹,可能导致网站访问 Access denied 错误,请点击上方保存按钮' ErrDomainIsUsed: "域名已被网站【{{ .name }}】使用" ErrDomainFormat: "{{ .name }} 域名格式不正确" ErrDefaultAlias: "default 为保留代号,请使用其他代号" @@ -116,32 +128,32 @@ ErrImageNotExist: "运行环境 {{.name}} 镜像不存在,请重新编辑运 ErrSSLCannotDelete: "{{ .name }} 证书正在被网站使用,无法删除" ErrAccountCannotDelete: "账号关联证书,无法删除" ErrSSLApply: "证书续签成功,openresty reload失败,请检查配置!" -ErrEmailIsExist: "邮箱已存在" -ErrSSLKeyNotFound: "私钥文件不存在" -ErrSSLCertificateNotFound: "证书文件不存在" -ErrSSLKeyFormat: "私钥文件校验失败" -ErrSSLCertificateFormat: "证书文件格式错误,请使用 pem 格式" -ErrEabKidOrEabHmacKeyCannotBlank: "EabKid 或 EabHmacKey 不能为空" -ErrOpenrestyNotFound: "Http 模式需要首先安装 Openresty" -ApplySSLStart: "开始申请证书,域名 [{{ .domain }}] 申请方式 [{{ .type }}] " +ErrEmailIsExist: '邮箱已存在' +ErrSSLKeyNotFound: '私钥文件不存在' +ErrSSLCertificateNotFound: '证书文件不存在' +ErrSSLKeyFormat: '私钥文件校验失败' +ErrSSLCertificateFormat: '证书文件格式错误,请使用 pem 格式' +ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 或 EabHmacKey 不能为空' +ErrOpenrestyNotFound: 'Http 模式需要首先安装 Openresty' +ApplySSLStart: '开始申请证书,域名 [{{ .domain }}] 申请方式 [{{ .type }}] ' dnsAccount: "DNS 自动" dnsManual: "DNS 手动" http: "HTTP" -ApplySSLFailed: "申请 [{{ .domain }}] 证书失败, {{.detail}} " -ApplySSLSuccess: "申请 [{{ .domain }}] 证书成功!!" -DNSAccountName: "DNS 账号 [{{ .name }}] 厂商 [{{.type}}]" -PushDirLog: "证书推送到目录 [{{ .path }}] {{ .status }}" +ApplySSLFailed: '申请 [{{ .domain }}] 证书失败, {{.detail}} ' +ApplySSLSuccess: '申请 [{{ .domain }}] 证书成功!!' +DNSAccountName: 'DNS 账号 [{{ .name }}] 厂商 [{{.type}}]' +PushDirLog: '证书推送到目录 [{{ .path }}] {{ .status }}' ErrDeleteCAWithSSL: "当前机构下存在已签发证书,无法删除" ErrDeleteWithPanelSSL: "面板 SSL 配置使用此证书,无法删除" ErrDefaultCA: "默认机构不能删除" ApplyWebSiteSSLLog: "开始更新 {{ .name }} 网站证书" ErrUpdateWebsiteSSL: "{{ .name }} 网站更新证书失败: {{ .err }}" ApplyWebSiteSSLSuccess: "更新网站证书成功" -StartUpdateSystemSSL: "开始更新系统证书" -UpdateSystemSSLSuccess: "更新系统证书成功" ErrExecShell: "执行脚本失败 {{ .err }}" ExecShellStart: "开始执行脚本" ExecShellSuccess: "脚本执行成功" +StartUpdateSystemSSL: "开始更新系统证书" +UpdateSystemSSLSuccess: "更新系统证书成功" #mysql ErrUserIsExist: "当前用户已存在,请重新输入" @@ -173,12 +185,6 @@ ErrContainerNameNotFound: "无法获取容器名称,请检查 .env 文件" ErrNodeModulesNotFound: "node_modules 文件夹不存在!请编辑运行环境或者等待运行环境启动成功" ErrContainerNameIsNull: "容器名称不存在" -#setting -ErrBackupInUsed: "该备份账号已在计划任务中使用,无法删除" -ErrBackupCheck: "备份账号测试连接失败 {{ .err}}" -ErrOSSConn: "无法获取最新版本,请确认服务器是否能够连接外部网络。" -ErrEntrance: "安全入口信息错误,请检查后重试!" - #tool ErrConfigNotFound: "配置文件不存在" ErrConfigParse: "配置文件格式有误" @@ -389,4 +395,11 @@ Rollback: "回滚" websiteDir: "网站目录" RecoverFailedStartRollBack: "恢复失败,开始回滚" AppBackupFileIncomplete: "备份文件不完整 缺少 app.json 或者 app.tar.gz 文件" -AppAttributesNotMatch: "应用类型或者名称不一致" \ No newline at end of file +AppAttributesNotMatch: "应用类型或者名称不一致" + +#alert +ErrAlert: "告警信息格式错误,请检查后重试!" +ErrAlertPush: "告警信息推送错误,请检查后重试!" +ErrAlertSave: "告警信息保存错误,请检查后重试!" +ErrAlertSync: "告警信息同步错误,请检查后重试!" +ErrAlertRemote: "告警信息远端错误,请检查后重试!" \ No newline at end of file diff --git a/agent/init/hook/hook.go b/agent/init/hook/hook.go index eb64f738d..5605b2bac 100644 --- a/agent/init/hook/hook.go +++ b/agent/init/hook/hook.go @@ -3,12 +3,14 @@ package hook import ( "path" + "github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/app/repo" "github.com/1Panel-dev/1Panel/agent/app/service" "github.com/1Panel-dev/1Panel/agent/constant" "github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/utils/common" + "github.com/1Panel-dev/1Panel/agent/utils/xpack" ) func Init() { @@ -58,11 +60,24 @@ func handleSnapStatus() { } func handleCronjobStatus() { - _ = global.DB.Model(&model.JobRecords{}).Where("status = ?", constant.StatusWaiting). - Updates(map[string]interface{}{ - "status": constant.StatusFailed, - "message": "the task was interrupted due to the restart of the 1panel service", - }).Error + var jobRecords []model.JobRecords + _ = global.DB.Where("status = ?", constant.StatusWaiting).Find(&jobRecords).Error + for _, record := range jobRecords { + err := global.DB.Model(&model.JobRecords{}).Where("status = ?", constant.StatusWaiting). + Updates(map[string]interface{}{ + "status": constant.StatusFailed, + "message": "the task was interrupted due to the restart of the 1panel service", + }).Error + + if err != nil { + global.LOG.Errorf("Failed to update job ID: %v, Error:%v", record.ID, err) + continue + } + + var cronjob *model.Cronjob + _ = global.DB.Where("id = ?", record.CronjobID).First(&cronjob).Error + handleCronJobAlert(cronjob) + } } func loadLocalDir() { @@ -73,3 +88,17 @@ func loadLocalDir() { } global.CONF.System.Backup = account.BackupPath } + +func handleCronJobAlert(cronjob *model.Cronjob) { + pushAlert := dto.PushAlert{ + TaskName: cronjob.Name, + AlertType: cronjob.Type, + EntryID: cronjob.ID, + Param: cronjob.Type, + } + err := xpack.PushAlert(pushAlert) + if err != nil { + global.LOG.Errorf("cronjob alert push failed, err: %v", err) + return + } +} diff --git a/agent/utils/common/common.go b/agent/utils/common/common.go index 2b4d3006f..278d4db28 100644 --- a/agent/utils/common/common.go +++ b/agent/utils/common/common.go @@ -3,7 +3,6 @@ package common import ( "crypto/rand" "fmt" - "github.com/gin-gonic/gin" "io" mathRand "math/rand" "net" @@ -15,6 +14,8 @@ import ( "time" "unicode" + "github.com/gin-gonic/gin" + "github.com/1Panel-dev/1Panel/agent/utils/cmd" "golang.org/x/net/idna" ) @@ -325,6 +326,30 @@ func IsValidIP(ip string) bool { return net.ParseIP(ip) != nil } +const ( + b = uint64(1) + kb = 1024 * b + mb = 1024 * kb + gb = 1024 * mb +) + +func FormatBytes(bytes uint64) string { + switch { + case bytes < kb: + return fmt.Sprintf("%dB", bytes) + case bytes < mb: + return fmt.Sprintf("%.2fKB", float64(bytes)/float64(kb)) + case bytes < gb: + return fmt.Sprintf("%.2fMB", float64(bytes)/float64(mb)) + default: + return fmt.Sprintf("%.2fGB", float64(bytes)/float64(gb)) + } +} + +func FormatPercent(percent float64) string { + return fmt.Sprintf("%.2f%%", percent) +} + func GetLang(context *gin.Context) string { lang := context.GetHeader("Accept-Language") if strings.Contains(lang, "zh") { diff --git a/agent/utils/files/file_op.go b/agent/utils/files/file_op.go index 7959ff95c..2e7f1275c 100644 --- a/agent/utils/files/file_op.go +++ b/agent/utils/files/file_op.go @@ -677,6 +677,9 @@ func (f FileOp) decompressWithSDK(srcFile string, dst string, cType CompressType func (f FileOp) Decompress(srcFile string, dst string, cType CompressType, secret string) error { if cType == Tar || cType == Zip || cType == TarGz { shellArchiver, err := NewShellArchiver(cType) + if !f.Stat(dst) { + _ = f.CreateDir(dst, 0755) + } if err == nil { if err = shellArchiver.Extract(srcFile, dst, secret); err == nil { return nil diff --git a/agent/utils/files/fileinfo.go b/agent/utils/files/fileinfo.go index c2e318976..60a0a5ded 100644 --- a/agent/utils/files/fileinfo.go +++ b/agent/utils/files/fileinfo.go @@ -73,6 +73,9 @@ func NewFileInfo(op FileOption) (*FileInfo, error) { info, err := appFs.Stat(op.Path) if err != nil { + if os.IsNotExist(err) { + return nil, buserr.New(constant.ErrLinkPathNotFound) + } return nil, err } @@ -102,7 +105,26 @@ func NewFileInfo(op FileOption) (*FileInfo, error) { } if file.IsSymlink { - file.LinkPath = GetSymlink(op.Path) + linkPath := GetSymlink(op.Path) + if !filepath.IsAbs(linkPath) { + dir := filepath.Dir(op.Path) + var err error + linkPath, err = filepath.Abs(filepath.Join(dir, linkPath)) + if err != nil { + return nil, err + } + } + file.LinkPath = linkPath + targetInfo, err := appFs.Stat(linkPath) + if err != nil { + file.IsDir = false + file.Mode = "-" + file.User = "-" + file.Group = "-" + } else { + file.IsDir = targetInfo.IsDir() + } + file.Extension = filepath.Ext(file.LinkPath) } if op.Expand { if err := handleExpansion(file, op); err != nil { @@ -309,7 +331,26 @@ func (f *FileInfo) processFiles(files []FileSearchInfo, option FileOption) ([]*F file.FavoriteID = favorite.ID } if isSymlink { - file.LinkPath = GetSymlink(fPath) + linkPath := GetSymlink(fPath) + if !filepath.IsAbs(linkPath) { + dir := filepath.Dir(fPath) + var err error + linkPath, err = filepath.Abs(filepath.Join(dir, linkPath)) + if err != nil { + return nil, err + } + } + file.LinkPath = linkPath + targetInfo, err := file.Fs.Stat(linkPath) + if err != nil { + file.IsDir = false + file.Mode = "-" + file.User = "-" + file.Group = "-" + } else { + file.IsDir = targetInfo.IsDir() + } + file.Extension = filepath.Ext(file.LinkPath) } if df.Size() > 0 { file.MimeType = GetMimeType(fPath) diff --git a/agent/utils/files/tar.go b/agent/utils/files/tar.go index 521c989b7..a4b013c55 100644 --- a/agent/utils/files/tar.go +++ b/agent/utils/files/tar.go @@ -19,7 +19,7 @@ func NewTarArchiver(compressType CompressType) ShellArchiver { } func (t TarArchiver) Extract(FilePath string, dstDir string, secret string) error { - return cmd.ExecCmd(fmt.Sprintf("%s %s %s -C %s", t.Cmd, t.getOptionStr("extract"), FilePath, dstDir)) + return cmd.ExecCmd(fmt.Sprintf("%s %s \"%s\" -C \"%s\"", t.Cmd, t.getOptionStr("extract"), FilePath, dstDir)) } func (t TarArchiver) Compress(sourcePaths []string, dstFile string, secret string) error { diff --git a/agent/utils/files/tar_gz.go b/agent/utils/files/tar_gz.go index c0cf1d8f2..e8e95e41a 100644 --- a/agent/utils/files/tar_gz.go +++ b/agent/utils/files/tar_gz.go @@ -20,11 +20,11 @@ func (t TarGzArchiver) Extract(filePath, dstDir string, secret string) error { var err error commands := "" if len(secret) != 0 { - extraCmd := "openssl enc -d -aes-256-cbc -k '" + secret + "' -in " + filePath + " | " - commands = fmt.Sprintf("%s tar -zxvf - -C %s", extraCmd, dstDir+" > /dev/null 2>&1") + extraCmd := fmt.Sprintf("openssl enc -d -aes-256-cbc -k '%s' -in '%s' | ", secret, filePath) + commands = fmt.Sprintf("%s tar -zxvf - -C '%s' > /dev/null 2>&1", extraCmd, dstDir) global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" %s ", secret), "******")) } else { - commands = fmt.Sprintf("tar -zxvf %s %s", filePath+" -C ", dstDir+" > /dev/null 2>&1") + commands = fmt.Sprintf("tar -zxvf '%s' -C '%s' > /dev/null 2>&1", filePath, dstDir) global.LOG.Debug(commands) } if err = cmd.ExecCmd(commands); err != nil { diff --git a/agent/utils/websocket/process_data.go b/agent/utils/websocket/process_data.go index b07c741b3..6e470e8c3 100644 --- a/agent/utils/websocket/process_data.go +++ b/agent/utils/websocket/process_data.go @@ -9,6 +9,7 @@ import ( "time" "github.com/1Panel-dev/1Panel/agent/global" + "github.com/1Panel-dev/1Panel/agent/utils/common" "github.com/1Panel-dev/1Panel/agent/utils/files" "github.com/shirou/gopsutil/v3/host" "github.com/shirou/gopsutil/v3/net" @@ -146,26 +147,6 @@ func getDownloadProcess(progress DownloadProgress) (res []byte, err error) { return } -const ( - b = uint64(1) - kb = 1024 * b - mb = 1024 * kb - gb = 1024 * mb -) - -func formatBytes(bytes uint64) string { - switch { - case bytes < kb: - return fmt.Sprintf("%dB", bytes) - case bytes < mb: - return fmt.Sprintf("%.2fKB", float64(bytes)/float64(kb)) - case bytes < gb: - return fmt.Sprintf("%.2fMB", float64(bytes)/float64(mb)) - default: - return fmt.Sprintf("%.2fGB", float64(bytes)/float64(gb)) - } -} - func getProcessData(processConfig PsProcessConfig) (res []byte, err error) { var processes []*process.Process processes, err = process.Processes() @@ -229,14 +210,14 @@ func getProcessData(processConfig PsProcessConfig) (res []byte, err error) { procData.CpuPercent = fmt.Sprintf("%.2f", procData.CpuValue) + "%" menInfo, procErr := proc.MemoryInfo() if procErr == nil { - procData.Rss = formatBytes(menInfo.RSS) + procData.Rss = common.FormatBytes(menInfo.RSS) procData.RssValue = menInfo.RSS - procData.Data = formatBytes(menInfo.Data) - procData.VMS = formatBytes(menInfo.VMS) - procData.HWM = formatBytes(menInfo.HWM) - procData.Stack = formatBytes(menInfo.Stack) - procData.Locked = formatBytes(menInfo.Locked) - procData.Swap = formatBytes(menInfo.Swap) + procData.Data = common.FormatBytes(menInfo.Data) + procData.VMS = common.FormatBytes(menInfo.VMS) + procData.HWM = common.FormatBytes(menInfo.HWM) + procData.Stack = common.FormatBytes(menInfo.Stack) + procData.Locked = common.FormatBytes(menInfo.Locked) + procData.Swap = common.FormatBytes(menInfo.Swap) } else { procData.Rss = "--" procData.Data = "--" @@ -250,8 +231,8 @@ func getProcessData(processConfig PsProcessConfig) (res []byte, err error) { } ioStat, procErr := proc.IOCounters() if procErr == nil { - procData.DiskWrite = formatBytes(ioStat.WriteBytes) - procData.DiskRead = formatBytes(ioStat.ReadBytes) + procData.DiskWrite = common.FormatBytes(ioStat.WriteBytes) + procData.DiskRead = common.FormatBytes(ioStat.ReadBytes) } else { procData.DiskWrite = "--" procData.DiskRead = "--" diff --git a/agent/utils/xpack/xpack.go b/agent/utils/xpack/xpack.go index bd3cbbb29..2dfeedae1 100644 --- a/agent/utils/xpack/xpack.go +++ b/agent/utils/xpack/xpack.go @@ -10,6 +10,7 @@ import ( "strings" "time" + "github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/buserr" "github.com/1Panel-dev/1Panel/agent/constant" @@ -70,3 +71,20 @@ func GetImagePrefix() string { func IsUseCustomApp() bool { return false } + +// alert +func CreateAlert(createAlert dto.CreateOrUpdateAlert) error { + return nil +} +func UpdateAlert(updateAlert dto.CreateOrUpdateAlert) error { + return nil +} +func DeleteAlert(alertBase dto.AlertBase) error { + return nil +} +func GetAlert(alertBase dto.AlertBase) uint { + return 0 +} +func PushAlert(pushAlert dto.PushAlert) error { + return nil +} diff --git a/core/app/api/v2/app_launcher.go b/core/app/api/v2/app_launcher.go index b63984003..8b5e8cd72 100644 --- a/core/app/api/v2/app_launcher.go +++ b/core/app/api/v2/app_launcher.go @@ -22,6 +22,7 @@ func (b *BaseApi) SearchAppLauncher(c *gin.Context) { // @Param request body dto.ChangeShow true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/app/launcher/show [post] // @x-panel-log {"bodyKeys":["key", "value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"首页应用 [key] => 显示:[value]","formatEN":"app launcher [key] => show: [value]"} func (b *BaseApi) UpdateAppLauncher(c *gin.Context) { @@ -34,5 +35,5 @@ func (b *BaseApi) UpdateAppLauncher(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/core/app/api/v2/auth.go b/core/app/api/v2/auth.go index fa2c49b4a..71bc991ff 100644 --- a/core/app/api/v2/auth.go +++ b/core/app/api/v2/auth.go @@ -2,6 +2,7 @@ package v2 import ( "encoding/base64" + "github.com/1Panel-dev/1Panel/core/app/api/v2/helper" "github.com/1Panel-dev/1Panel/core/app/dto" "github.com/1Panel-dev/1Panel/core/app/model" @@ -78,13 +79,14 @@ func (b *BaseApi) MFALogin(c *gin.Context) { // @Summary User logout // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/auth/logout [post] func (b *BaseApi) LogOut(c *gin.Context) { if err := authService.LogOut(c); err != nil { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Auth @@ -111,7 +113,7 @@ func (b *BaseApi) GetResponsePage(c *gin.Context) { // @Tags Auth // @Summary Check System isDemo -// @Success 200 +// @Success 200 {boolean} demo // @Router /core/auth/demo [get] func (b *BaseApi) CheckIsDemo(c *gin.Context) { helper.SuccessWithData(c, global.CONF.System.IsDemo) @@ -119,7 +121,7 @@ func (b *BaseApi) CheckIsDemo(c *gin.Context) { // @Tags Auth // @Summary Load System Language -// @Success 200 +// @Success 200 {string} language // @Router /core/auth/language [get] func (b *BaseApi) GetLanguage(c *gin.Context) { settingInfo, err := settingService.GetSettingInfo() @@ -151,3 +153,11 @@ func saveLoginLogs(c *gin.Context, err error) { //logs.Address = address _ = logService.CreateLoginLog(logs) } + +// @Tags Auth +// @Summary Check System IsIntl +// @Success 200 {string} intl +// @Router /auth/intl [get] +func (b *BaseApi) CheckIsIntl(c *gin.Context) { + helper.SuccessWithData(c, global.CONF.System.IsIntl) +} diff --git a/core/app/api/v2/backup.go b/core/app/api/v2/backup.go index c5924527c..d24c5b7db 100644 --- a/core/app/api/v2/backup.go +++ b/core/app/api/v2/backup.go @@ -14,6 +14,7 @@ import ( // @Param request body dto.BackupOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/backups [post] // @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建备份账号 [type]","formatEN":"create backup account [type]"} func (b *BaseApi) CreateBackup(c *gin.Context) { @@ -35,6 +36,7 @@ func (b *BaseApi) CreateBackup(c *gin.Context) { // @Param request body dto.BackupOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/backups/refresh/token [post] func (b *BaseApi) RefreshToken(c *gin.Context) { var req dto.OperateByID @@ -54,6 +56,7 @@ func (b *BaseApi) RefreshToken(c *gin.Context) { // @Param request body dto.ForBuckets true "request" // @Success 200 {array} string // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/backups/buckets [post] func (b *BaseApi) ListBuckets(c *gin.Context) { var req dto.ForBuckets @@ -74,6 +77,7 @@ func (b *BaseApi) ListBuckets(c *gin.Context) { // @Accept json // @Success 200 {object} dto.OneDriveInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/backups/client/:clientType [get] func (b *BaseApi) LoadBackupClientInfo(c *gin.Context) { clientType, ok := c.Params.Get("clientType") @@ -95,6 +99,7 @@ func (b *BaseApi) LoadBackupClientInfo(c *gin.Context) { // @Param request body dto.OperateByID true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/backups/del [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"backup_accounts","output_column":"type","output_value":"types"}],"formatZH":"删除备份账号 [types]","formatEN":"delete backup account [types]"} func (b *BaseApi) DeleteBackup(c *gin.Context) { @@ -107,7 +112,7 @@ func (b *BaseApi) DeleteBackup(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Backup Account @@ -116,6 +121,7 @@ func (b *BaseApi) DeleteBackup(c *gin.Context) { // @Param request body dto.BackupOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/backups/update [post] // @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新备份账号 [types]","formatEN":"update backup account [types]"} func (b *BaseApi) UpdateBackup(c *gin.Context) { @@ -128,5 +134,5 @@ func (b *BaseApi) UpdateBackup(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) -} \ No newline at end of file + helper.SuccessWithOutData(c) +} diff --git a/core/app/api/v2/command.go b/core/app/api/v2/command.go index b1e558e5d..27d07d722 100644 --- a/core/app/api/v2/command.go +++ b/core/app/api/v2/command.go @@ -13,6 +13,7 @@ import ( // @Param request body dto.CommandOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/commands [post] // @x-panel-log {"bodyKeys":["name","command"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建快捷命令 [name][command]","formatEN":"create quick command [name][command]"} func (b *BaseApi) CreateCommand(c *gin.Context) { @@ -25,7 +26,7 @@ func (b *BaseApi) CreateCommand(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Command @@ -34,6 +35,7 @@ func (b *BaseApi) CreateCommand(c *gin.Context) { // @Param request body dto.SearchWithPage true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/commands/search [post] func (b *BaseApi) SearchCommand(c *gin.Context) { var req dto.SearchCommandWithPage @@ -59,6 +61,7 @@ func (b *BaseApi) SearchCommand(c *gin.Context) { // @Param request body dto.OperateByType true "request" // @Success 200 {Array} dto.CommandTree // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/commands/tree [get] func (b *BaseApi) SearchCommandTree(c *gin.Context) { var req dto.OperateByType @@ -81,6 +84,7 @@ func (b *BaseApi) SearchCommandTree(c *gin.Context) { // @Param request body dto.OperateByType true "request" // @Success 200 {object} dto.CommandInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/commands/command [get] func (b *BaseApi) ListCommand(c *gin.Context) { var req dto.OperateByType @@ -103,6 +107,7 @@ func (b *BaseApi) ListCommand(c *gin.Context) { // @Param request body dto.OperateByIDs true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/commands/del [post] // @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"commands","output_column":"name","output_value":"names"}],"formatZH":"删除快捷命令 [names]","formatEN":"delete quick command [names]"} func (b *BaseApi) DeleteCommand(c *gin.Context) { @@ -115,7 +120,7 @@ func (b *BaseApi) DeleteCommand(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Command @@ -124,6 +129,7 @@ func (b *BaseApi) DeleteCommand(c *gin.Context) { // @Param request body dto.CommandOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/commands/update [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新快捷命令 [name]","formatEN":"update quick command [name]"} func (b *BaseApi) UpdateCommand(c *gin.Context) { @@ -140,5 +146,5 @@ func (b *BaseApi) UpdateCommand(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/core/app/api/v2/group.go b/core/app/api/v2/group.go index 8621e20b6..10dfbd9f5 100644 --- a/core/app/api/v2/group.go +++ b/core/app/api/v2/group.go @@ -13,6 +13,7 @@ import ( // @Param request body dto.GroupCreate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/groups [post] // @x-panel-log {"bodyKeys":["name","type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建组 [name][type]","formatEN":"create group [name][type]"} func (b *BaseApi) CreateGroup(c *gin.Context) { @@ -25,7 +26,7 @@ func (b *BaseApi) CreateGroup(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Group @@ -34,6 +35,7 @@ func (b *BaseApi) CreateGroup(c *gin.Context) { // @Param request body dto.OperateByID true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/groups/del [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"groups","output_column":"name","output_value":"name"},{"input_column":"id","input_value":"id","isList":false,"db":"groups","output_column":"type","output_value":"type"}],"formatZH":"删除组 [type][name]","formatEN":"delete group [type][name]"} func (b *BaseApi) DeleteGroup(c *gin.Context) { @@ -46,7 +48,7 @@ func (b *BaseApi) DeleteGroup(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Group @@ -55,6 +57,7 @@ func (b *BaseApi) DeleteGroup(c *gin.Context) { // @Param request body dto.GroupUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/groups/update [post] // @x-panel-log {"bodyKeys":["name","type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新组 [name][type]","formatEN":"update group [name][type]"} func (b *BaseApi) UpdateGroup(c *gin.Context) { @@ -67,7 +70,7 @@ func (b *BaseApi) UpdateGroup(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Group @@ -76,6 +79,7 @@ func (b *BaseApi) UpdateGroup(c *gin.Context) { // @Param request body dto.GroupSearch true "request" // @Success 200 {array} dto.OperateByType // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/groups/search [post] func (b *BaseApi) ListGroup(c *gin.Context) { var req dto.OperateByType diff --git a/core/app/api/v2/host.go b/core/app/api/v2/host.go index 4c2597cf6..bf5e31b90 100644 --- a/core/app/api/v2/host.go +++ b/core/app/api/v2/host.go @@ -24,8 +24,9 @@ import ( // @Summary Create host // @Accept json // @Param request body dto.HostOperate true "request" -// @Success 200 +// @Success 200 {object} dto.HostInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/hosts [post] // @x-panel-log {"bodyKeys":["name","addr"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建主机 [name][addr]","formatEN":"create host [name][addr]"} func (b *BaseApi) CreateHost(c *gin.Context) { @@ -46,8 +47,9 @@ func (b *BaseApi) CreateHost(c *gin.Context) { // @Summary Test host conn by info // @Accept json // @Param request body dto.HostConnTest true "request" -// @Success 200 +// @Success 200 {boolean} status // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/hosts/test/byinfo [post] func (b *BaseApi) TestByInfo(c *gin.Context) { var req dto.HostConnTest @@ -65,6 +67,7 @@ func (b *BaseApi) TestByInfo(c *gin.Context) { // @Param id path integer true "request" // @Success 200 {boolean} connStatus // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/hosts/test/byid/:id [post] func (b *BaseApi) TestByID(c *gin.Context) { idParam, ok := c.Params.Get("id") @@ -88,6 +91,7 @@ func (b *BaseApi) TestByID(c *gin.Context) { // @Param request body dto.SearchForTree true "request" // @Success 200 {array} dto.HostTree // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/hosts/tree [post] func (b *BaseApi) HostTree(c *gin.Context) { var req dto.SearchForTree @@ -108,8 +112,9 @@ func (b *BaseApi) HostTree(c *gin.Context) { // @Summary Page host // @Accept json // @Param request body dto.SearchHostWithPage true "request" -// @Success 200 {array} dto.HostTree +// @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/hosts/search [post] func (b *BaseApi) SearchHost(c *gin.Context) { var req dto.SearchHostWithPage @@ -135,6 +140,7 @@ func (b *BaseApi) SearchHost(c *gin.Context) { // @Param request body dto.OperateByIDs true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/hosts/del [post] // @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"hosts","output_column":"addr","output_value":"addrs"}],"formatZH":"删除主机 [addrs]","formatEN":"delete host [addrs]"} func (b *BaseApi) DeleteHost(c *gin.Context) { @@ -147,7 +153,7 @@ func (b *BaseApi) DeleteHost(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Host @@ -156,6 +162,7 @@ func (b *BaseApi) DeleteHost(c *gin.Context) { // @Param request body dto.HostOperate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/hosts/update [post] // @x-panel-log {"bodyKeys":["name","addr"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新主机信息 [name][addr]","formatEN":"update host [name][addr]"} func (b *BaseApi) UpdateHost(c *gin.Context) { @@ -212,7 +219,7 @@ func (b *BaseApi) UpdateHost(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags Host @@ -221,6 +228,7 @@ func (b *BaseApi) UpdateHost(c *gin.Context) { // @Param request body dto.ChangeHostGroup true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/hosts/update/group [post] // @x-panel-log {"bodyKeys":["id","group"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"hosts","output_column":"addr","output_value":"addr"}],"formatZH":"切换主机[addr]分组 => [group]","formatEN":"change host [addr] group => [group]"} func (b *BaseApi) UpdateHostGroup(c *gin.Context) { @@ -235,7 +243,7 @@ func (b *BaseApi) UpdateHostGroup(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } func (b *BaseApi) WsSsh(c *gin.Context) { diff --git a/core/app/api/v2/logs.go b/core/app/api/v2/logs.go index ea9154cc4..f6f2bbe03 100644 --- a/core/app/api/v2/logs.go +++ b/core/app/api/v2/logs.go @@ -13,6 +13,7 @@ import ( // @Param request body dto.SearchLgLogWithPage true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/logs/login [post] func (b *BaseApi) GetLoginLogs(c *gin.Context) { var req dto.SearchLgLogWithPage @@ -38,6 +39,7 @@ func (b *BaseApi) GetLoginLogs(c *gin.Context) { // @Param request body dto.SearchOpLogWithPage true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/logs/operation [post] func (b *BaseApi) GetOperationLogs(c *gin.Context) { var req dto.SearchOpLogWithPage @@ -63,6 +65,7 @@ func (b *BaseApi) GetOperationLogs(c *gin.Context) { // @Param request body dto.CleanLog true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/logs/clean [post] // @x-panel-log {"bodyKeys":["logType"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清空 [logType] 日志信息","formatEN":"Clean the [logType] log information"} func (b *BaseApi) CleanLogs(c *gin.Context) { @@ -76,5 +79,5 @@ func (b *BaseApi) CleanLogs(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/core/app/api/v2/setting.go b/core/app/api/v2/setting.go index 1ad1d51f8..09710b4fc 100644 --- a/core/app/api/v2/setting.go +++ b/core/app/api/v2/setting.go @@ -18,6 +18,7 @@ import ( // @Summary Load system setting info // @Success 200 {object} dto.SettingInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/search [post] func (b *BaseApi) GetSettingInfo(c *gin.Context) { setting, err := settingService.GetSettingInfo() @@ -32,6 +33,7 @@ func (b *BaseApi) GetSettingInfo(c *gin.Context) { // @Summary Load system terminal setting info // @Success 200 {object} dto.TerminalInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/terminal/search [post] func (b *BaseApi) GetTerminalSettingInfo(c *gin.Context) { setting, err := settingService.GetTerminalInfo() @@ -46,9 +48,10 @@ func (b *BaseApi) GetTerminalSettingInfo(c *gin.Context) { // @Summary Load system available status // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/search/available [get] func (b *BaseApi) GetSystemAvailable(c *gin.Context) { - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -57,6 +60,7 @@ func (b *BaseApi) GetSystemAvailable(c *gin.Context) { // @Param request body dto.SettingUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/update [post] // @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改系统配置 [key] => [value]","formatEN":"update system setting [key] => [value]"} func (b *BaseApi) UpdateSetting(c *gin.Context) { @@ -69,7 +73,7 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -78,6 +82,7 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) { // @Param request body dto.TerminalInfo true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/terminal/update [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改系统终端配置","formatEN":"update system terminal setting"} func (b *BaseApi) UpdateTerminalSetting(c *gin.Context) { @@ -90,7 +95,7 @@ func (b *BaseApi) UpdateTerminalSetting(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -99,6 +104,7 @@ func (b *BaseApi) UpdateTerminalSetting(c *gin.Context) { // @Param request body dto.ProxyUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/proxy/update [post] // @x-panel-log {"bodyKeys":["proxyUrl","proxyPort"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"服务器代理配置 [proxyPort]:[proxyPort]","formatEN":"set proxy [proxyPort]:[proxyPort]."} func (b *BaseApi) UpdateProxy(c *gin.Context) { @@ -120,7 +126,7 @@ func (b *BaseApi) UpdateProxy(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -129,6 +135,7 @@ func (b *BaseApi) UpdateProxy(c *gin.Context) { // @Param request body dto.SettingUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/menu/update [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"隐藏高级功能菜单","formatEN":"Hide advanced feature menu."} func (b *BaseApi) UpdateMenu(c *gin.Context) { @@ -141,7 +148,7 @@ func (b *BaseApi) UpdateMenu(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -150,6 +157,7 @@ func (b *BaseApi) UpdateMenu(c *gin.Context) { // @Param request body dto.PasswordUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/password/update [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改系统密码","formatEN":"update system password"} func (b *BaseApi) UpdatePassword(c *gin.Context) { @@ -162,7 +170,7 @@ func (b *BaseApi) UpdatePassword(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -171,6 +179,7 @@ func (b *BaseApi) UpdatePassword(c *gin.Context) { // @Param request body dto.SSLUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/ssl/update [post] // @x-panel-log {"bodyKeys":["ssl"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改系统 ssl => [ssl]","formatEN":"update system ssl => [ssl]"} func (b *BaseApi) UpdateSSL(c *gin.Context) { @@ -183,13 +192,14 @@ func (b *BaseApi) UpdateSSL(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting // @Summary Load system cert info -// @Success 200 {object} dto.SettingInfo +// @Success 200 {object} dto.SSLInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/ssl/info [get] func (b *BaseApi) LoadFromCert(c *gin.Context) { info, err := settingService.LoadFromCert() @@ -204,6 +214,7 @@ func (b *BaseApi) LoadFromCert(c *gin.Context) { // @Summary Download system cert // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/ssl/download [post] func (b *BaseApi) DownloadSSL(c *gin.Context) { pathItem := path.Join(global.CONF.System.BaseDir, "1panel/secret/server.crt") @@ -218,8 +229,9 @@ func (b *BaseApi) DownloadSSL(c *gin.Context) { // @Tags System Setting // @Summary Load system address // @Accept json -// @Success 200 +// @Success 200 {array} string // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/interface [get] func (b *BaseApi) LoadInterfaceAddr(c *gin.Context) { data, err := settingService.LoadInterfaceAddr() @@ -236,6 +248,7 @@ func (b *BaseApi) LoadInterfaceAddr(c *gin.Context) { // @Param request body dto.BindInfo true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/bind/update [post] // @x-panel-log {"bodyKeys":["ipv6", "bindAddress"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改系统监听信息 => ipv6: [ipv6], 监听 IP: [bindAddress]","formatEN":"update system bind info => ipv6: [ipv6], 监听 IP: [bindAddress]"} func (b *BaseApi) UpdateBindInfo(c *gin.Context) { @@ -248,7 +261,7 @@ func (b *BaseApi) UpdateBindInfo(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -257,6 +270,7 @@ func (b *BaseApi) UpdateBindInfo(c *gin.Context) { // @Param request body dto.PortUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/port/update [post] // @x-panel-log {"bodyKeys":["serverPort"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改系统端口 => [serverPort]","formatEN":"update system port => [serverPort]"} func (b *BaseApi) UpdatePort(c *gin.Context) { @@ -269,7 +283,7 @@ func (b *BaseApi) UpdatePort(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -278,6 +292,7 @@ func (b *BaseApi) UpdatePort(c *gin.Context) { // @Param request body dto.PasswordUpdate true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/expired/handle [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"重置过期密码","formatEN":"reset an expired Password"} func (b *BaseApi) HandlePasswordExpired(c *gin.Context) { @@ -290,7 +305,7 @@ func (b *BaseApi) HandlePasswordExpired(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -299,6 +314,7 @@ func (b *BaseApi) HandlePasswordExpired(c *gin.Context) { // @Param request body dto.MfaCredential true "request" // @Success 200 {object} mfa.Otp // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/mfa [post] func (b *BaseApi) LoadMFA(c *gin.Context) { var req dto.MfaRequest @@ -321,6 +337,7 @@ func (b *BaseApi) LoadMFA(c *gin.Context) { // @Param request body dto.MfaCredential true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/mfa/bind [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"mfa 绑定","formatEN":"bind mfa"} func (b *BaseApi) MFABind(c *gin.Context) { @@ -350,7 +367,7 @@ func (b *BaseApi) MFABind(c *gin.Context) { return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } func (b *BaseApi) ReloadSSL(c *gin.Context) { @@ -365,3 +382,52 @@ func (b *BaseApi) ReloadSSL(c *gin.Context) { } helper.SuccessWithOutData(c) } + +// @Tags System Setting +// @Summary generate api key +// @Accept json +// @Success 200 {string} key +// @Security ApiKeyAuth +// @Security Timestamp +// @Router /settings/api/config/generate/key [post] +// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"生成 API 接口密钥","formatEN":"generate api key"} +func (b *BaseApi) GenerateApiKey(c *gin.Context) { + panelToken := c.GetHeader("1Panel-Token") + if panelToken != "" { + helper.ErrorWithDetail(c, constant.CodeErrUnauthorized, constant.ErrApiConfigDisable, nil) + return + } + apiKey, err := settingService.GenerateApiKey() + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, apiKey) +} + +// @Tags System Setting +// @Summary Update api config +// @Accept json +// @Param request body dto.ApiInterfaceConfig true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Security Timestamp +// @Router /settings/api/config/update [post] +// @x-panel-log {"bodyKeys":["ipWhiteList"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 API 接口配置 => IP 白名单: [ipWhiteList]","formatEN":"update api config => IP White List: [ipWhiteList]"} +func (b *BaseApi) UpdateApiConfig(c *gin.Context) { + panelToken := c.GetHeader("1Panel-Token") + if panelToken != "" { + helper.ErrorWithDetail(c, constant.CodeErrUnauthorized, constant.ErrApiConfigDisable, nil) + return + } + var req dto.ApiInterfaceConfig + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + + if err := settingService.UpdateApiConfig(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithOutData(c) +} diff --git a/core/app/api/v2/upgrade.go b/core/app/api/v2/upgrade.go index c0f68a06e..5ce9f1f5b 100644 --- a/core/app/api/v2/upgrade.go +++ b/core/app/api/v2/upgrade.go @@ -11,6 +11,7 @@ import ( // @Summary Load upgrade info // @Success 200 {object} dto.UpgradeInfo // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/upgrade [get] func (b *BaseApi) GetUpgradeInfo(c *gin.Context) { info, err := upgradeService.SearchUpgrade() @@ -25,8 +26,9 @@ func (b *BaseApi) GetUpgradeInfo(c *gin.Context) { // @Summary Load release notes by version // @Accept json // @Param request body dto.Upgrade true "request" -// @Success 200 +// @Success 200 {string} notes // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/upgrade [get] func (b *BaseApi) GetNotesByVersion(c *gin.Context) { var req dto.Upgrade @@ -48,6 +50,7 @@ func (b *BaseApi) GetNotesByVersion(c *gin.Context) { // @Param request body dto.Upgrade true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/upgrade [post] // @x-panel-log {"bodyKeys":["version"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新系统 => [version]","formatEN":"upgrade system => [version]"} func (b *BaseApi) Upgrade(c *gin.Context) { @@ -60,7 +63,7 @@ func (b *BaseApi) Upgrade(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } // @Tags System Setting @@ -69,6 +72,7 @@ func (b *BaseApi) Upgrade(c *gin.Context) { // @Param request body dto.OperateByID true "request" // @Success 200 // @Security ApiKeyAuth +// @Security Timestamp // @Router /core/settings/rollback [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"upgrade_logs","output_column":"old_version","output_value":"version"}],"formatZH":"回滚系统 => [version]","formatEN":"rollback system => [version]"} func (b *BaseApi) Rollback(c *gin.Context) { @@ -81,5 +85,5 @@ func (b *BaseApi) Rollback(c *gin.Context) { helper.InternalServer(c, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithOutData(c) } diff --git a/core/app/dto/auth.go b/core/app/dto/auth.go index ccaa2ec12..b39948499 100644 --- a/core/app/dto/auth.go +++ b/core/app/dto/auth.go @@ -29,7 +29,7 @@ type Login struct { Captcha string `json:"captcha"` CaptchaID string `json:"captchaID"` AuthMethod string `json:"authMethod" validate:"required,oneof=jwt session"` - Language string `json:"language" validate:"required,oneof=zh en tw"` + Language string `json:"language" validate:"required,oneof=zh en tw ja ru ms 'pt-BR'"` } type MFALogin struct { diff --git a/core/app/dto/setting.go b/core/app/dto/setting.go index 975a953ac..8bcd19489 100644 --- a/core/app/dto/setting.go +++ b/core/app/dto/setting.go @@ -42,6 +42,11 @@ type SettingInfo struct { ProxyUser string `json:"proxyUser"` ProxyPasswd string `json:"proxyPasswd"` ProxyPasswdKeep string `json:"proxyPasswdKeep"` + + ApiInterfaceStatus string `json:"apiInterfaceStatus"` + ApiKey string `json:"apiKey"` + IpWhiteList string `json:"ipWhiteList"` + ApiKeyValidityTime string `json:"apiKeyValidityTime"` } type SettingUpdate struct { @@ -196,6 +201,13 @@ type XpackHideMenu struct { Children []XpackHideMenu `json:"children,omitempty"` } +type ApiInterfaceConfig struct { + ApiInterfaceStatus string `json:"apiInterfaceStatus"` + ApiKey string `json:"apiKey"` + IpWhiteList string `json:"ipWhiteList"` + ApiKeyValidityTime string `json:"apiKeyValidityTime"` +} + type TerminalInfo struct { LineHeight string `json:"lineHeight"` LetterSpacing string `json:"letterSpacing"` diff --git a/core/app/service/setting.go b/core/app/service/setting.go index 2a0fcba3e..26f05a1e3 100644 --- a/core/app/service/setting.go +++ b/core/app/service/setting.go @@ -38,6 +38,8 @@ type ISettingService interface { UpdateSSL(c *gin.Context, req dto.SSLUpdate) error LoadFromCert() (*dto.SSLInfo, error) HandlePasswordExpired(c *gin.Context, old, new string) error + GenerateApiKey() (string, error) + UpdateApiConfig(req dto.ApiInterfaceConfig) error GetTerminalInfo() (*dto.TerminalInfo, error) UpdateTerminal(req dto.TerminalInfo) error @@ -410,6 +412,35 @@ func (u *SettingService) UpdateSystemSSL() error { return nil } +func (u *SettingService) GenerateApiKey() (string, error) { + apiKey := common.RandStr(32) + if err := settingRepo.Update("ApiKey", apiKey); err != nil { + return global.CONF.System.ApiKey, err + } + global.CONF.System.ApiKey = apiKey + return apiKey, nil +} + +func (u *SettingService) UpdateApiConfig(req dto.ApiInterfaceConfig) error { + if err := settingRepo.Update("ApiInterfaceStatus", req.ApiInterfaceStatus); err != nil { + return err + } + global.CONF.System.ApiInterfaceStatus = req.ApiInterfaceStatus + if err := settingRepo.Update("ApiKey", req.ApiKey); err != nil { + return err + } + global.CONF.System.ApiKey = req.ApiKey + if err := settingRepo.Update("IpWhiteList", req.IpWhiteList); err != nil { + return err + } + global.CONF.System.IpWhiteList = req.IpWhiteList + if err := settingRepo.Update("ApiKeyValidityTime", req.ApiKeyValidityTime); err != nil { + return err + } + global.CONF.System.ApiKeyValidityTime = req.ApiKeyValidityTime + return nil +} + func loadInfoFromCert() (dto.SSLInfo, error) { var info dto.SSLInfo certFile := path.Join(global.CONF.System.BaseDir, "1panel/secret/server.crt") diff --git a/core/cmd/server/cmd/listen-ip.go b/core/cmd/server/cmd/listen-ip.go index 9935b9ce5..0fe5a64ff 100644 --- a/core/cmd/server/cmd/listen-ip.go +++ b/core/cmd/server/cmd/listen-ip.go @@ -3,50 +3,59 @@ package cmd import ( "fmt" - "github.com/1Panel-dev/1Panel/core/constant" + "github.com/1Panel-dev/1Panel/core/i18n" "github.com/spf13/cobra" ) func init() { + listenCmd.SetHelpFunc(func(c *cobra.Command, s []string) { + i18n.UseI18nForCmd(language) + loadListenIPHelper() + }) + RootCmd.AddCommand(listenCmd) listenCmd.AddCommand(listenIpv4Cmd) listenCmd.AddCommand(listenIpv6Cmd) } var listenCmd = &cobra.Command{ - Use: "listen-ip", - Short: "切换监听 IP", + Use: "listen-ip", + RunE: func(cmd *cobra.Command, args []string) error { + i18n.UseI18nForCmd(language) + loadListenIPHelper() + return nil + }, } var listenIpv4Cmd = &cobra.Command{ - Use: "ipv4", - Short: "监听 IPv4", + Use: "ipv4", RunE: func(cmd *cobra.Command, args []string) error { + i18n.UseI18nForCmd(language) return updateBindInfo("ipv4") }, } var listenIpv6Cmd = &cobra.Command{ - Use: "ipv6", - Short: "监听 IPv6", + Use: "ipv6", RunE: func(cmd *cobra.Command, args []string) error { + i18n.UseI18nForCmd(language) return updateBindInfo("ipv6") }, } func updateBindInfo(protocol string) error { if !isRoot() { - fmt.Println("请使用 sudo 1pctl listen-ip ipv6 或者切换到 root 用户") + fmt.Println(i18n.GetMsgWithMapForCmd("SudoHelper", map[string]interface{}{"cmd": "sudo 1pctl listen-ip ipv6"})) return nil } db, err := loadDBConn() if err != nil { return err } - ipv6 := constant.StatusDisable + ipv6 := "disable" tcp := "tcp4" address := "0.0.0.0" if protocol == "ipv6" { - ipv6 = constant.StatusEnable + ipv6 = "enable" tcp = "tcp6" address = "::" } @@ -56,6 +65,15 @@ func updateBindInfo(protocol string) error { if err := setSettingByKey(db, "BindAddress", address); err != nil { return err } - fmt.Printf("切换成功!已切换至监听 %s [%s]", tcp, address) + fmt.Println(i18n.GetMsgWithMapForCmd("ListenChangeSuccessful", map[string]interface{}{"value": fmt.Sprintf(" %s [%s]", tcp, address)})) return nil } + +func loadListenIPHelper() { + fmt.Println(i18n.GetMsgByKeyForCmd("UpdateCommands")) + fmt.Println("\nUsage:\n 1panel listen-ip [command]\n\nAvailable Commands:") + fmt.Println("\n ipv4 " + i18n.GetMsgByKeyForCmd("ListenIPv4")) + fmt.Println(" ipv6 " + i18n.GetMsgByKeyForCmd("ListenIPv6")) + fmt.Println("\nFlags:\n -h, --help help for listen-ip") + fmt.Println("\nUse \"1panel listen-ip [command] --help\" for more information about a command.") +} diff --git a/core/cmd/server/cmd/reset.go b/core/cmd/server/cmd/reset.go index 95eb2e3c2..1521577de 100644 --- a/core/cmd/server/cmd/reset.go +++ b/core/cmd/server/cmd/reset.go @@ -3,11 +3,16 @@ package cmd import ( "fmt" - "github.com/1Panel-dev/1Panel/core/constant" + "github.com/1Panel-dev/1Panel/core/i18n" "github.com/spf13/cobra" ) func init() { + resetCmd.SetHelpFunc(func(c *cobra.Command, s []string) { + i18n.UseI18nForCmd(language) + loadResetHelper() + }) + RootCmd.AddCommand(resetCmd) resetCmd.AddCommand(resetMFACmd) resetCmd.AddCommand(resetSSLCmd) @@ -17,16 +22,20 @@ func init() { } var resetCmd = &cobra.Command{ - Use: "reset", - Short: "重置系统信息", + Use: "reset", + RunE: func(cmd *cobra.Command, args []string) error { + i18n.UseI18nForCmd(language) + loadResetHelper() + return nil + }, } var resetMFACmd = &cobra.Command{ - Use: "mfa", - Short: "取消 1Panel 两步验证", + Use: "mfa", RunE: func(cmd *cobra.Command, args []string) error { + i18n.UseI18nForCmd(language) if !isRoot() { - fmt.Println("请使用 sudo 1pctl reset mfa 或者切换到 root 用户") + fmt.Println(i18n.GetMsgWithMapForCmd("SudoHelper", map[string]interface{}{"cmd": "sudo 1pctl reset mfa"})) return nil } db, err := loadDBConn() @@ -34,15 +43,15 @@ var resetMFACmd = &cobra.Command{ return err } - return setSettingByKey(db, "MFAStatus", constant.StatusDisable) + return setSettingByKey(db, "MFAStatus", "disable") }, } var resetSSLCmd = &cobra.Command{ - Use: "https", - Short: "取消 1Panel https 方式登录", + Use: "https", RunE: func(cmd *cobra.Command, args []string) error { + i18n.UseI18nForCmd(language) if !isRoot() { - fmt.Println("请使用 sudo 1pctl reset https 或者切换到 root 用户") + fmt.Println(i18n.GetMsgWithMapForCmd("SudoHelper", map[string]interface{}{"cmd": "sudo 1pctl reset https"})) return nil } db, err := loadDBConn() @@ -50,15 +59,15 @@ var resetSSLCmd = &cobra.Command{ return err } - return setSettingByKey(db, "SSL", constant.StatusDisable) + return setSettingByKey(db, "SSL", "disable") }, } var resetEntranceCmd = &cobra.Command{ - Use: "entrance", - Short: "取消 1Panel 安全入口", + Use: "entrance", RunE: func(cmd *cobra.Command, args []string) error { + i18n.UseI18nForCmd(language) if !isRoot() { - fmt.Println("请使用 sudo 1pctl reset entrance 或者切换到 root 用户") + fmt.Println(i18n.GetMsgWithMapForCmd("SudoHelper", map[string]interface{}{"cmd": "sudo 1pctl reset entrance"})) return nil } db, err := loadDBConn() @@ -70,11 +79,11 @@ var resetEntranceCmd = &cobra.Command{ }, } var resetBindIpsCmd = &cobra.Command{ - Use: "ips", - Short: "取消 1Panel 授权 IP 限制", + Use: "ips", RunE: func(cmd *cobra.Command, args []string) error { + i18n.UseI18nForCmd(language) if !isRoot() { - fmt.Println("请使用 sudo 1pctl reset ips 或者切换到 root 用户") + fmt.Println(i18n.GetMsgWithMapForCmd("SudoHelper", map[string]interface{}{"cmd": "sudo 1pctl reset ips"})) return nil } db, err := loadDBConn() @@ -86,11 +95,11 @@ var resetBindIpsCmd = &cobra.Command{ }, } var resetDomainCmd = &cobra.Command{ - Use: "domain", - Short: "取消 1Panel 访问域名绑定", + Use: "domain", RunE: func(cmd *cobra.Command, args []string) error { + i18n.UseI18nForCmd(language) if !isRoot() { - fmt.Println("请使用 sudo 1pctl reset domain 或者切换到 root 用户") + fmt.Println(i18n.GetMsgWithMapForCmd("SudoHelper", map[string]interface{}{"cmd": "sudo 1pctl reset domain"})) return nil } db, err := loadDBConn() @@ -101,3 +110,15 @@ var resetDomainCmd = &cobra.Command{ return setSettingByKey(db, "BindDomain", "") }, } + +func loadResetHelper() { + fmt.Println(i18n.GetMsgByKeyForCmd("ResetCommands")) + fmt.Println("\nUsage:\n 1panel reset [command]\n\nAvailable Commands:") + fmt.Println("\n domain " + i18n.GetMsgByKeyForCmd("ResetDomain")) + fmt.Println(" entrance " + i18n.GetMsgByKeyForCmd("ResetEntrance")) + fmt.Println(" https " + i18n.GetMsgByKeyForCmd("ResetHttps")) + fmt.Println(" ips " + i18n.GetMsgByKeyForCmd("ResetIPs")) + fmt.Println(" mfa " + i18n.GetMsgByKeyForCmd("ResetMFA")) + fmt.Println("\nFlags:\n -h, --help help for reset") + fmt.Println("\nUse \"1panel reset [command] --help\" for more information about a command.") +} diff --git a/core/cmd/server/cmd/restore.go b/core/cmd/server/cmd/restore.go index f4dbf5b8f..4d5a7f260 100644 --- a/core/cmd/server/cmd/restore.go +++ b/core/cmd/server/cmd/restore.go @@ -6,9 +6,13 @@ import ( "path" "sort" "strings" + "time" + "github.com/1Panel-dev/1Panel/core/global" + "github.com/1Panel-dev/1Panel/core/i18n" cmdUtils "github.com/1Panel-dev/1Panel/core/utils/cmd" "github.com/1Panel-dev/1Panel/core/utils/files" + "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -18,11 +22,11 @@ func init() { } var restoreCmd = &cobra.Command{ - Use: "restore", - Short: "回滚 1Panel 服务及数据", + Use: "restore", RunE: func(cmd *cobra.Command, args []string) error { + i18n.UseI18nForCmd(language) if !isRoot() { - fmt.Println("请使用 sudo 1pctl restore 或者切换到 root 用户") + fmt.Println(i18n.GetMsgWithMapForCmd("SudoHelper", map[string]interface{}{"cmd": "sudo 1pctl restore"})) return nil } stdout, err := cmdUtils.Exec("grep '^BASE_DIR=' /usr/local/bin/1pctl | cut -d'=' -f2") @@ -36,40 +40,56 @@ var restoreCmd = &cobra.Command{ if err != nil { return err } - if tmpPath == "暂无可回滚文件" { - fmt.Println("暂无可回滚文件") + if tmpPath == "no such file" { + fmt.Println(i18n.GetMsgByKeyForCmd("RestoreNoSuchFile")) return nil } tmpPath = path.Join(upgradeDir, tmpPath, "original") - fmt.Printf("(0/4) 开始从 %s 目录回滚 1Panel 服务及数据... \n", tmpPath) + fmt.Println(i18n.GetMsgWithMapForCmd("RestoreStep1", map[string]interface{}{"name": tmpPath})) - if err := files.CopyItem(false, true, path.Join(tmpPath, "1panel*"), "/usr/local/bin"); err != nil { + if err := files.CopyFile(path.Join(tmpPath, "1panel"), "/usr/local/bin", true); err != nil { return err } - fmt.Println("(1/4) 1panel 二进制回滚成功") - if err := files.CopyItem(false, true, path.Join(tmpPath, "1pctl"), "/usr/local/bin"); err != nil { + fmt.Println(i18n.GetMsgByKeyForCmd("RestoreStep2")) + if err := files.CopyFile(path.Join(tmpPath, "1pctl"), "/usr/local/bin", true); err != nil { return err } - fmt.Println("(2/4) 1panel 脚本回滚成功") - if err := files.CopyItem(false, true, path.Join(tmpPath, "1panel*.service"), "/etc/systemd/system"); err != nil { + _, _ = cmdUtils.Execf("cp -r %s /usr/local/bin", path.Join(tmpPath, "lang")) + geoPath := path.Join(global.CONF.System.BaseDir, "1panel/geo") + _, _ = cmdUtils.Execf("mkdir %s && cp %s %s/", geoPath, path.Join(tmpPath, "GeoIP.mmdb"), geoPath) + fmt.Println(i18n.GetMsgByKeyForCmd("RestoreStep3")) + if err := files.CopyFile(path.Join(tmpPath, "1panel.service"), "/etc/systemd/system", true); err != nil { return err } - fmt.Println("(3/4) 1panel 服务回滚成功") - if _, err := os.Stat(path.Join(tmpPath, "core.db")); err == nil { - if err := files.CopyItem(true, true, path.Join(tmpPath, "db"), path.Join(baseDir, "1panel")); err != nil { + fmt.Println(i18n.GetMsgByKeyForCmd("RestoreStep4")) + checkPointOfWal() + if _, err := os.Stat(path.Join(tmpPath, "1Panel.db")); err == nil { + if err := files.CopyFile(path.Join(tmpPath, "1Panel.db"), path.Join(baseDir, "1panel/db"), true); err != nil { return err } } - fmt.Printf("(4/4) 1panel 数据回滚成功 \n\n") - - fmt.Println("回滚成功!正在重启服务,请稍候...") + if _, err := os.Stat(path.Join(tmpPath, "db.tar.gz")); err == nil { + if err := handleUnTar(path.Join(tmpPath, "db.tar.gz"), path.Join(baseDir, "1panel")); err != nil { + return err + } + } + fmt.Println(i18n.GetMsgByKeyForCmd("RestoreStep5")) + fmt.Println(i18n.GetMsgByKeyForCmd("RestoreSuccessful")) return nil }, } +func checkPointOfWal() { + db, err := loadDBConn() + if err != nil { + return + } + _ = db.Exec("PRAGMA wal_checkpoint(TRUNCATE);").Error +} + func loadRestorePath(upgradeDir string) (string, error) { if _, err := os.Stat(upgradeDir); err != nil && os.IsNotExist(err) { - return "暂无可回滚文件", nil + return "no such file", nil } files, err := os.ReadDir(upgradeDir) if err != nil { @@ -82,10 +102,25 @@ func loadRestorePath(upgradeDir string) (string, error) { } } if len(folders) == 0 { - return "暂无可回滚文件", nil + return "no such file", nil } sort.Slice(folders, func(i, j int) bool { return folders[i] > folders[j] }) return folders[0], nil } + +func handleUnTar(sourceFile, targetDir string) error { + if _, err := os.Stat(targetDir); err != nil && os.IsNotExist(err) { + if err = os.MkdirAll(targetDir, os.ModePerm); err != nil { + return err + } + } + + commands := fmt.Sprintf("tar zxvfC %s %s", sourceFile, targetDir) + stdout, err := cmdUtils.ExecWithTimeOut(commands, 20*time.Second) + if err != nil { + return errors.New(stdout) + } + return nil +} diff --git a/core/cmd/server/cmd/root.go b/core/cmd/server/cmd/root.go index 749fd1851..40ecd298c 100644 --- a/core/cmd/server/cmd/root.go +++ b/core/cmd/server/cmd/root.go @@ -3,7 +3,6 @@ package cmd import ( "fmt" "os/user" - "path" "strings" "time" @@ -14,11 +13,14 @@ import ( "gorm.io/gorm" ) -func init() {} +var language string + +func init() { + RootCmd.PersistentFlags().StringVarP(&language, "language", "l", "en", "Set the language") +} var RootCmd = &cobra.Command{ - Use: "1panel", - Short: "1Panel ,一款现代化的 Linux 面板", + Use: "1panel", RunE: func(cmd *cobra.Command, args []string) error { server.Start() return nil @@ -29,9 +31,9 @@ type setting struct { ID uint `gorm:"primarykey;AUTO_INCREMENT" json:"id"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` - Key string `json:"key" gorm:"not null;"` - Value string `json:"value"` - About string `json:"about"` + Key string `json:"key" gorm:"type:varchar(256);not null;"` + Value string `json:"value" gorm:"type:varchar(256)"` + About string `json:"about" gorm:"type:longText"` } func loadDBConn() (*gorm.DB, error) { @@ -43,7 +45,11 @@ func loadDBConn() (*gorm.DB, error) { if len(baseDir) == 0 { return nil, fmt.Errorf("error `BASE_DIR` find in /usr/local/bin/1pctl \n") } - db, err := gorm.Open(sqlite.Open(path.Join(baseDir, "/1panel/db/core.db")), &gorm.Config{}) + if strings.HasSuffix(baseDir, "/") { + baseDir = baseDir[:strings.LastIndex(baseDir, "/")] + } + + db, err := gorm.Open(sqlite.Open(baseDir+"/1panel/db/1Panel.db"), &gorm.Config{}) if err != nil { return nil, fmt.Errorf("init my db conn failed, err: %v \n", err) } diff --git a/core/cmd/server/cmd/update.go b/core/cmd/server/cmd/update.go index 67f0a14fb..148a33867 100644 --- a/core/cmd/server/cmd/update.go +++ b/core/cmd/server/cmd/update.go @@ -9,8 +9,8 @@ import ( "strings" "unicode" - "github.com/1Panel-dev/1Panel/core/constant" "github.com/1Panel-dev/1Panel/core/global" + "github.com/1Panel-dev/1Panel/core/i18n" "github.com/1Panel-dev/1Panel/core/utils/cmd" "github.com/1Panel-dev/1Panel/core/utils/common" "github.com/1Panel-dev/1Panel/core/utils/encrypt" @@ -19,6 +19,11 @@ import ( ) func init() { + updateCmd.SetHelpFunc(func(c *cobra.Command, s []string) { + i18n.UseI18nForCmd(language) + loadUpdateHelper() + }) + RootCmd.AddCommand(updateCmd) updateCmd.AddCommand(updateUserName) updateCmd.AddCommand(updatePassword) @@ -26,16 +31,21 @@ func init() { } var updateCmd = &cobra.Command{ - Use: "update", - Short: "修改面板信息", + Use: "update", + RunE: func(cmd *cobra.Command, args []string) error { + i18n.UseI18nForCmd(language) + loadUpdateHelper() + return nil + }, } var updateUserName = &cobra.Command{ Use: "username", - Short: "修改面板用户", + Short: i18n.GetMsgByKeyForCmd("UpdateUser"), RunE: func(cmd *cobra.Command, args []string) error { + i18n.UseI18nForCmd(language) if !isRoot() { - fmt.Println("请使用 sudo 1pctl update username 或者切换到 root 用户") + fmt.Println(i18n.GetMsgWithMapForCmd("SudoHelper", map[string]interface{}{"cmd": "sudo 1pctl update username"})) return nil } username() @@ -44,10 +54,11 @@ var updateUserName = &cobra.Command{ } var updatePassword = &cobra.Command{ Use: "password", - Short: "修改面板密码", + Short: i18n.GetMsgByKeyForCmd("UpdatePassword"), RunE: func(cmd *cobra.Command, args []string) error { + i18n.UseI18nForCmd(language) if !isRoot() { - fmt.Println("请使用 sudo 1pctl update password 或者切换到 root 用户") + fmt.Println(i18n.GetMsgWithMapForCmd("SudoHelper", map[string]interface{}{"cmd": "sudo 1pctl update password"})) return nil } password() @@ -56,10 +67,11 @@ var updatePassword = &cobra.Command{ } var updatePort = &cobra.Command{ Use: "port", - Short: "修改面板端口", + Short: i18n.GetMsgByKeyForCmd("UpdatePort"), RunE: func(cmd *cobra.Command, args []string) error { + i18n.UseI18nForCmd(language) if !isRoot() { - fmt.Println("请使用 sudo 1pctl update port 或者切换到 root 用户") + fmt.Println(i18n.GetMsgWithMapForCmd("SudoHelper", map[string]interface{}{"cmd": "sudo 1pctl update port"})) return nil } port() @@ -69,83 +81,83 @@ var updatePort = &cobra.Command{ func username() { reader := bufio.NewReader(os.Stdin) - fmt.Print("修改面板用户: ") + fmt.Print(i18n.GetMsgByKeyForCmd("UpdateUser") + ": ") newUsername, _ := reader.ReadString('\n') newUsername = strings.Trim(newUsername, "\n") if len(newUsername) == 0 { - fmt.Println("错误:输入面板用户为空!") + fmt.Println(i18n.GetMsgByKeyForCmd("UpdateUserNull")) return } if strings.Contains(newUsername, " ") { - fmt.Println("错误:输入面板用户中包含空格字符!") + fmt.Println(i18n.GetMsgByKeyForCmd("UpdateUserBlank")) return } result, err := regexp.MatchString("^[a-zA-Z0-9_\u4e00-\u9fa5]{3,30}$", newUsername) if !result || err != nil { - fmt.Println("错误:输入面板用户错误!仅支持英文、中文、数字和_,长度3-30") + fmt.Println(i18n.GetMsgByKeyForCmd("UpdateUserFormat")) return } db, err := loadDBConn() if err != nil { - fmt.Printf("错误:初始化数据库连接失败,%v\n", err) + fmt.Println(i18n.GetMsgWithMapForCmd("DBConnErr", map[string]interface{}{"err": err.Error()})) return } if err := setSettingByKey(db, "UserName", newUsername); err != nil { - fmt.Printf("错误:面板用户修改失败,%v\n", err) + fmt.Println(i18n.GetMsgWithMapForCmd("UpdateUserErr", map[string]interface{}{"err": err.Error()})) return } - fmt.Printf("修改成功!\n\n") - fmt.Printf("面板用户:%s\n", newUsername) + fmt.Println("\n" + i18n.GetMsgByKeyForCmd("UpdateSuccessful")) + fmt.Println(i18n.GetMsgWithMapForCmd("UpdateUserResult", map[string]interface{}{"name": newUsername})) } func password() { - fmt.Print("修改面板密码:") + fmt.Print(i18n.GetMsgByKeyForCmd("UpdatePassword") + ": ") bytePassword, err := term.ReadPassword(int(os.Stdin.Fd())) if err != nil { - fmt.Printf("\n错误:面板密码信息读取错误,%v\n", err) + fmt.Println("\n" + i18n.GetMsgWithMapForCmd("UpdatePasswordRead", map[string]interface{}{"err": err.Error()})) return } newPassword := string(bytePassword) newPassword = strings.Trim(newPassword, "\n") if len(newPassword) == 0 { - fmt.Println("\n错误:输入面板密码为空!") + fmt.Println("\n", i18n.GetMsgByKeyForCmd("UpdatePasswordNull")) return } if strings.Contains(newPassword, " ") { - fmt.Println("\n错误:输入面板密码中包含空格字符!") + fmt.Println("\n" + i18n.GetMsgByKeyForCmd("UpdateUPasswordBlank")) return } db, err := loadDBConn() if err != nil { - fmt.Printf("\n错误:初始化数据库连接失败,%v\n", err) + fmt.Println("\n" + i18n.GetMsgWithMapForCmd("DBConnErr", map[string]interface{}{"err": err.Error()})) return } complexSetting := getSettingByKey(db, "ComplexityVerification") - if complexSetting == constant.StatusEnable { + if complexSetting == "enable" { if isValidPassword("newPassword") { - fmt.Println("\n错误:面板密码仅支持字母、数字、特殊字符(!@#$%*_,.?),长度 8-30 位!") + fmt.Println("\n" + i18n.GetMsgByKeyForCmd("UpdatePasswordFormat")) return } } if len(newPassword) < 6 { - fmt.Println("错误:请输入 6 位以上密码!") + fmt.Println(i18n.GetMsgByKeyForCmd("UpdatePasswordLen")) return } - fmt.Print("\n确认密码:") + fmt.Print("\n" + i18n.GetMsgByKeyForCmd("UpdatePasswordRe")) byteConfirmPassword, err := term.ReadPassword(int(os.Stdin.Fd())) if err != nil { - fmt.Printf("\n错误:面板密码信息读取错误,%v\n", err) + fmt.Println("\n" + i18n.GetMsgWithMapForCmd("UpdatePasswordRead", map[string]interface{}{"err": err.Error()})) return } confirmPassword := string(byteConfirmPassword) confirmPassword = strings.Trim(confirmPassword, "\n") if newPassword != confirmPassword { - fmt.Printf("\n错误:两次密码不匹配,请检查后重试!,%v\n", err) + fmt.Println("\n", i18n.GetMsgByKeyForCmd("UpdatePasswordSame")) return } @@ -158,43 +170,43 @@ func password() { p = newPassword } if err := setSettingByKey(db, "Password", p); err != nil { - fmt.Printf("\n错误:面板密码修改失败,%v\n", err) + fmt.Println("\n", i18n.GetMsgWithMapForCmd("UpdatePortErr", map[string]interface{}{"err": err.Error()})) return } username := getSettingByKey(db, "UserName") - fmt.Printf("\n修改成功!\n\n") - fmt.Printf("面板用户:%s\n", username) - fmt.Printf("面板密码:%s\n", string(newPassword)) + fmt.Println("\n" + i18n.GetMsgByKeyForCmd("UpdateSuccessful")) + fmt.Println(i18n.GetMsgWithMapForCmd("UpdateUserResult", map[string]interface{}{"name": username})) + fmt.Println(i18n.GetMsgWithMapForCmd("UpdatePasswordResult", map[string]interface{}{"name": string(newPassword)})) } func port() { reader := bufio.NewReader(os.Stdin) - fmt.Print("修改面板端口:") + fmt.Print(i18n.GetMsgByKeyForCmd("UpdatePort") + ": ") newPortStr, _ := reader.ReadString('\n') newPortStr = strings.Trim(newPortStr, "\n") newPort, err := strconv.Atoi(strings.TrimSpace(newPortStr)) if err != nil || newPort < 1 || newPort > 65535 { - fmt.Println("错误:输入的端口号必须在 1 到 65535 之间!") + fmt.Println(i18n.GetMsgByKeyForCmd("UpdatePortFormat")) return } if common.ScanPort(newPort) { - fmt.Println("错误:该端口号正被占用,请检查后重试!") + fmt.Println(i18n.GetMsgByKeyForCmd("UpdatePortUsed")) return } db, err := loadDBConn() if err != nil { - fmt.Printf("错误:初始化数据库连接失败,%v\n", err) + fmt.Println(i18n.GetMsgWithMapForCmd("DBConnErr", map[string]interface{}{"err": err.Error()})) return } if err := setSettingByKey(db, "ServerPort", newPortStr); err != nil { - fmt.Printf("错误:面板端口修改失败,%v\n", err) + fmt.Println(i18n.GetMsgWithMapForCmd("UpdatePortErr", map[string]interface{}{"err": err.Error()})) return } - fmt.Printf("修改成功!\n\n") - fmt.Printf("面板端口:%s\n", newPortStr) + fmt.Println("\n" + i18n.GetMsgByKeyForCmd("UpdateSuccessful")) + fmt.Println(i18n.GetMsgWithMapForCmd("UpdatePortResult", map[string]interface{}{"name": newPortStr})) std, err := cmd.Exec("1pctl restart") if err != nil { @@ -239,3 +251,13 @@ func contains(specialChars string, char rune) bool { } return false } + +func loadUpdateHelper() { + fmt.Println(i18n.GetMsgByKeyForCmd("UpdateCommands")) + fmt.Println("\nUsage:\n 1panel update [command]\n\nAvailable Commands:") + fmt.Println("\n password " + i18n.GetMsgByKeyForCmd("UpdatePassword")) + fmt.Println(" port " + i18n.GetMsgByKeyForCmd("UpdatePort")) + fmt.Println(" username " + i18n.GetMsgByKeyForCmd("UpdateUser")) + fmt.Println("\nFlags:\n -h, --help help for update") + fmt.Println("\nUse \"1panel update [command] --help\" for more information about a command.") +} diff --git a/core/cmd/server/cmd/user-info.go b/core/cmd/server/cmd/user-info.go index 991a18749..dfd40e577 100644 --- a/core/cmd/server/cmd/user-info.go +++ b/core/cmd/server/cmd/user-info.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/1Panel-dev/1Panel/core/global" + "github.com/1Panel-dev/1Panel/core/i18n" "github.com/1Panel-dev/1Panel/core/utils/encrypt" "github.com/spf13/cobra" ) @@ -13,11 +14,11 @@ func init() { } var userinfoCmd = &cobra.Command{ - Use: "user-info", - Short: "获取面板信息", + Use: "user-info", RunE: func(cmd *cobra.Command, args []string) error { + i18n.UseI18nForCmd(language) if !isRoot() { - fmt.Println("请使用 sudo 1pctl user-info 或者切换到 root 用户") + fmt.Println(i18n.GetMsgWithMapForCmd("SudoHelper", map[string]interface{}{"cmd": "sudo 1pctl user-info"})) return nil } db, err := loadDBConn() @@ -47,10 +48,10 @@ var userinfoCmd = &cobra.Command{ address = "$LOCAL_IP" } - fmt.Printf("面板地址: %s://%s:%s/%s \n", protocol, address, port, entrance) - fmt.Println("面板用户: ", user) - fmt.Println("面板密码: ", pass) - fmt.Println("提示:修改密码可执行命令:1pctl update password") + fmt.Println(i18n.GetMsgByKeyForCmd("UserInfoAddr") + fmt.Sprintf("%s://%s:%s/%s ", protocol, address, port, entrance)) + fmt.Println(i18n.GetMsgWithMapForCmd("UpdateUserResult", map[string]interface{}{"name": user})) + fmt.Println(i18n.GetMsgWithMapForCmd("UpdatePasswordResult", map[string]interface{}{"name": pass})) + fmt.Println(i18n.GetMsgByKeyForCmd("UserInfoPassHelp") + "1pctl update password") return nil }, } diff --git a/core/cmd/server/cmd/version.go b/core/cmd/server/cmd/version.go index 326773c2a..150bd94f8 100644 --- a/core/cmd/server/cmd/version.go +++ b/core/cmd/server/cmd/version.go @@ -5,8 +5,10 @@ import ( "github.com/1Panel-dev/1Panel/core/cmd/server/conf" "github.com/1Panel-dev/1Panel/core/configs" - "github.com/spf13/cobra" + "github.com/1Panel-dev/1Panel/core/i18n" "gopkg.in/yaml.v3" + + "github.com/spf13/cobra" ) func init() { @@ -14,11 +16,11 @@ func init() { } var versionCmd = &cobra.Command{ - Use: "version", - Short: "获取系统版本信息", + Use: "version", RunE: func(cmd *cobra.Command, args []string) error { + i18n.UseI18nForCmd(language) if !isRoot() { - fmt.Println("请使用 sudo 1pctl version 或者切换到 root 用户") + fmt.Println(i18n.GetMsgWithMapForCmd("SudoHelper", map[string]interface{}{"cmd": "sudo 1pctl version"})) return nil } db, err := loadDBConn() @@ -27,12 +29,12 @@ var versionCmd = &cobra.Command{ } version := getSettingByKey(db, "SystemVersion") - fmt.Printf("1panel version: %s\n", version) + fmt.Println(i18n.GetMsgByKeyForCmd("SystemVersion") + version) config := configs.ServerConfig{} if err := yaml.Unmarshal(conf.AppYaml, &config); err != nil { - return fmt.Errorf("unmarshal conf.App.Yaml failed, errL %v", err) + return fmt.Errorf("unmarshal conf.App.Yaml failed, err: %v", err) } else { - fmt.Printf("mode: %s\n", config.System.Mode) + fmt.Println(i18n.GetMsgByKeyForCmd("SystemMode") + config.System.Mode) } return nil }, diff --git a/core/cmd/server/conf/app.yaml b/core/cmd/server/conf/app.yaml index 3765fcae9..cd5dbc0c4 100644 --- a/core/cmd/server/conf/app.yaml +++ b/core/cmd/server/conf/app.yaml @@ -5,6 +5,7 @@ system: repo_url: https://resource.fit2cloud.com/1panel/package app_repo: https://apps-assets.fit2cloud.com is_demo: false + is_intl: true port: 9999 username: admin password: admin123 diff --git a/core/cmd/server/main.go b/core/cmd/server/main.go index 836ed3e9c..cd296a717 100644 --- a/core/cmd/server/main.go +++ b/core/cmd/server/main.go @@ -11,13 +11,31 @@ import ( ) // @title 1Panel -// @version 2.0 -// @description 开源Linux面板 +// @version 1.0 +// @description Open Source Linux Panel // @termsOfService http://swagger.io/terms/ // @license.name Apache 2.0 // @license.url http://www.apache.org/licenses/LICENSE-2.0.html -// @host localhost -// @BasePath /api/v2 +// @BasePath /api/v1 +// @schemes http https + +// @securityDefinitions.apikey ApiKeyAuth +// @description Custom Token Format, Format: md5('1panel' + API-Key + UnixTimestamp). +// @description ``` +// @description eg: +// @description curl -X GET "http://localhost:4004/api/v1/resource" \ +// @description -H "1Panel-Token: <1panel_token>" \ +// @description -H "1Panel-Timestamp: " +// @description ``` +// @description - `1Panel-Token` is the key for the panel API Key. +// @type apiKey +// @in Header +// @name 1Panel-Token +// @securityDefinitions.apikey Timestamp +// @type apiKey +// @in header +// @name 1Panel-Timestamp +// @description - `1Panel-Timestamp` is the Unix timestamp of the current time in seconds. func main() { if err := cmd.RootCmd.Execute(); err != nil { diff --git a/core/configs/system.go b/core/configs/system.go index ffcc155f8..502a60c7d 100644 --- a/core/configs/system.go +++ b/core/configs/system.go @@ -16,6 +16,13 @@ type System struct { Username string `mapstructure:"username"` Password string `mapstructure:"password"` Entrance string `mapstructure:"entrance"` + Language string `mapstructure:"language"` IsDemo bool `mapstructure:"is_demo"` + IsIntl bool `mapstructure:"is_intl"` ChangeUserInfo string `mapstructure:"change_user_info"` + + ApiInterfaceStatus string `mapstructure:"api_interface_status"` + ApiKey string `mapstructure:"api_key"` + IpWhiteList string `mapstructure:"ip_white_list"` + ApiKeyValidityTime string `mapstructure:"api_key_validity_time"` } diff --git a/core/constant/errs.go b/core/constant/errs.go index d8133192c..67da38fd4 100644 --- a/core/constant/errs.go +++ b/core/constant/errs.go @@ -23,14 +23,19 @@ const ( // internal var ( - ErrCaptchaCode = errors.New("ErrCaptchaCode") - ErrAuth = errors.New("ErrAuth") - ErrRecordExist = errors.New("ErrRecordExist") - ErrRecordNotFound = errors.New("ErrRecordNotFound") - ErrTransform = errors.New("ErrTransform") - ErrInitialPassword = errors.New("ErrInitialPassword") - ErrInvalidParams = errors.New("ErrInvalidParams") - ErrNotSupportType = errors.New("ErrNotSupportType") + ErrCaptchaCode = errors.New("ErrCaptchaCode") + ErrAuth = errors.New("ErrAuth") + ErrRecordExist = errors.New("ErrRecordExist") + ErrRecordNotFound = errors.New("ErrRecordNotFound") + ErrTransform = errors.New("ErrTransform") + ErrInitialPassword = errors.New("ErrInitialPassword") + ErrInvalidParams = errors.New("ErrInvalidParams") + ErrNotSupportType = errors.New("ErrNotSupportType") + ErrApiConfigStatusInvalid = "ErrApiConfigStatusInvalid" + ErrApiConfigKeyInvalid = "ErrApiConfigKeyInvalid" + ErrApiConfigIPInvalid = "ErrApiConfigIPInvalid" + ErrApiConfigDisable = "ErrApiConfigDisable" + ErrApiConfigKeyTimeInvalid = "ErrApiConfigKeyTimeInvalid" ErrTokenParse = errors.New("ErrTokenParse") ErrStructTransform = errors.New("ErrStructTransform") @@ -77,4 +82,6 @@ var ( ErrNodeBound = "ErrNodeBound" ErrNodeBind = "ErrNodeBind" ConnInfoNotMatch = "ConnInfoNotMatch" + + ErrAlertSync = "ErrAlertSync" ) diff --git a/core/global/global.go b/core/global/global.go index abb4f75b7..1defcf957 100644 --- a/core/global/global.go +++ b/core/global/global.go @@ -20,7 +20,8 @@ var ( SESSION *psession.PSession Viper *viper.Viper - I18n *i18n.Localizer + I18n *i18n.Localizer + I18nForCmd *i18n.Localizer Cron *cron.Cron ) diff --git a/core/i18n/i18n.go b/core/i18n/i18n.go index dfd7d20bb..2bfa9c292 100644 --- a/core/i18n/i18n.go +++ b/core/i18n/i18n.go @@ -125,4 +125,53 @@ func Init() { _, _ = bundle.LoadMessageFileFS(fs, "lang/zh.yaml") _, _ = bundle.LoadMessageFileFS(fs, "lang/en.yaml") _, _ = bundle.LoadMessageFileFS(fs, "lang/zh-Hant.yaml") + _, _ = bundle.LoadMessageFileFS(fs, "lang/fa.yaml") + _, _ = bundle.LoadMessageFileFS(fs, "lang/pt.yaml") + _, _ = bundle.LoadMessageFileFS(fs, "lang/pt-BR.yaml") + _, _ = bundle.LoadMessageFileFS(fs, "lang/ja.yaml") + _, _ = bundle.LoadMessageFileFS(fs, "lang/ru.yaml") + _, _ = bundle.LoadMessageFileFS(fs, "lang/ms.yaml") + _, _ = bundle.LoadMessageFileFS(fs, "lang/ko.yaml") +} + +func UseI18nForCmd(lang string) { + if lang == "" { + lang = "en" + } + + if bundle == nil { + Init() + } + global.I18nForCmd = i18n.NewLocalizer(bundle, lang) +} +func GetMsgByKeyForCmd(key string) string { + if global.I18nForCmd == nil { + UseI18nForCmd("") + } + content, _ := global.I18nForCmd.Localize(&i18n.LocalizeConfig{ + MessageID: key, + }) + return content +} +func GetMsgWithMapForCmd(key string, maps map[string]interface{}) string { + if global.I18nForCmd == nil { + UseI18nForCmd("") + } + var content string + if maps == nil { + content, _ = global.I18nForCmd.Localize(&i18n.LocalizeConfig{ + MessageID: key, + }) + } else { + content, _ = global.I18nForCmd.Localize(&i18n.LocalizeConfig{ + MessageID: key, + TemplateData: maps, + }) + } + content = strings.ReplaceAll(content, ": ", "") + if content == "" { + return key + } else { + return content + } } diff --git a/core/i18n/lang/en.yaml b/core/i18n/lang/en.yaml index c0b6d0bd1..8a096550c 100644 --- a/core/i18n/lang/en.yaml +++ b/core/i18n/lang/en.yaml @@ -1,62 +1,62 @@ ErrInvalidParams: "Request parameter error: {{ .detail }}" ErrTokenParse: "Token generation error: {{ .detail }}" -ErrInitialPassword: "Initial password error" -ErrInternalServer: "Service internal error: {{ .detail }}" +ErrInitialPassword: "Original password is incorrect" +ErrInternalServer: "Internal server error: {{ .detail }}" ErrRecordExist: "Record already exists" -ErrRecordNotFound: "Records not found" -ErrTransform: "Type conversion failure: {{ .detail }}" -ErrNotLogin: "User is not Login: {{ .detail }}" -ErrPasswordExpired: "The current password has expired: {{ .detail }}" -ErrNotSupportType: "The system does not support the current type: {{ .detail }}" -ErrProxy: "Request error, please check the node status: {{ .detail }}" +ErrRecordNotFound: "Record not found" +ErrStructTransform: "Type conversion failed: {{ .detail }}" +ErrNotLogin: "User not logged in: {{ .detail }}" +ErrPasswordExpired: "Current password has expired: {{ .detail }}" +ErrNotSupportType: "System does not support current type: {{ .detail }}" +ErrProxy: "Request error, please check node status: {{ .detail }}" +ErrApiConfigStatusInvalid: "API access forbidden: {{ .detail }}" +ErrApiConfigKeyInvalid: "API key error: {{ .detail }}" +ErrApiConfigIPInvalid: "API IP not in whitelist: {{ .detail }}" +ErrApiConfigDisable: "API call is disabled for this endpoint: {{ .detail }}" +ErrApiConfigKeyTimeInvalid: "API timestamp error: {{ .detail }}" #common -ErrNameIsExist: "Name is already exist" -ErrDemoEnvironment: "Demo server, prohibit this operation!" -ErrEntrance: "Security entrance information error. Please check and try again!" -ErrGroupIsUsed: "The group is in use and cannot be deleted" -ErrLocalDelete: "Unable to delete local node!" - -#app -ErrPortInUsed: "{{ .detail }} port already in use" -ErrCreateHttpClient: "Failed to create HTTP request {{.err}}" -ErrHttpReqTimeOut: "Request timed out {{.err}}" -ErrHttpReqFailed: "Request failed {{.err}}" -ErrHttpReqNotFound: "The file does not exist" -ErrNoSuchHost: "Network connection failed" +ErrDemoEnvironment: "Demo server, operation forbidden!" +ErrCmdTimeout: "Command execution timeout!" +ErrEntrance: "Security entrance error, please check and retry!" +ErrGroupIsDefault: 'Default group, cannot be deleted' +ErrLocalDelete: "Cannot delete local node!" #backup -ErrBackupInUsed: "The backup account is currently in use in a scheduled task and cannot be deleted." -ErrBackupCheck: "Backup account test connection failed {{.err}}" -ErrBackupLocal: "The local server backup account does not support this operation at the moment!" -ErrBackupPublic: "Detected that the backup account is non-public, please check and try again!" +ErrBackupInUsed: "Backup account is in use by a scheduled task, cannot delete" +ErrBackupCheck: "Backup account connection test failed {{ .err}}" +ErrBackupLocal: "Local backup account does not support this operation!" +ErrBackupPublic: "Non-public backup account detected, please check and retry!" +ErrOSSConn: "Cannot retrieve latest version, please check if the server can connect to external network." +ErrEntrance: "Security entrance error, please check and retry!" #license -ErrLicense: "License format error, please check and try again!" -ErrLicenseCheck: "License verification failed, please check and try again!" -ErrLicenseSave: "Failed to save license information, error {{ .err }}, please try again!" -ErrLicenseSync: "Failed to sync license information, no license information detected in the database!" -ErrXpackNotFound: "This section is a professional edition feature, please import the license first in Panel Settings-License interface" -ErrXpackExceptional: "This section is a professional edition feature, please synchronize the license status first in Panel Settings-License interface" -ErrXpackOutOfDate: "The current license has expired, please re-import the license in Panel Settings-License interface" -ErrXpackLost: "The license has reached the maximum number of retry attempts. Please go to the [Settings] [License] page and manually click the sync button to ensure that the professional version features are functioning properly." -ErrXpackTimeout: "Request timed out, the network connection may be unstable, please try again later!" -ErrUnbindMaster: "Detected that there are nodes in the node management, unable to unbind the current license. Please remove them first and try again!" -ErrFreeNodeLimit: "The number of nodes for the community edition has reached the free limit. Please visit www.lxware.cn/1panel to purchase and try again!" -ErrNodeBound: "This license is already bound to another node. Please check and try again!" -ErrNoSuchNode: "Failed to find the node information. Please check and try again!" -ErrNodeUnbind: "Detected that this node is no longer within the license binding range. Please check and try again!" -ErrNodeBind: "The node is already bound to a license. Please check and try again!" +ErrLicense: "License format error, please check and retry!" +ErrLicenseCheck: "License validation failed, please check and retry!" +ErrXpackVersion: "License validation failed, this license is version-limited, cannot import, please check and retry!" +ErrLicenseSave: "Failed to save license information, error {{ .err }}, please retry!" +ErrLicenseSync: "License synchronization failed, no license info detected in database!" +ErrXpackNotFound: "This section is for professional edition, please import the license in Panel Settings - License" +ErrXpackExceptional: "This section is for professional edition, please sync license status in Panel Settings - License" +ErrXpackOutOfDate: "Current license has expired, please import the license again in Panel Settings - License" +ErrXpackLost: "License has reached the maximum retry count, please go to the [Panel Settings] [License] page and click the sync button manually to ensure the professional features work correctly" +ErrXpackTimeout: "Request timeout, network connection might be unstable, please try again later!" +ErrUnbindMaster: "Detected nodes in node management, unable to unbind the current license, please remove nodes first and retry!" +ErrFreeNodeLimit: "Community version node limit reached, please go to www.lxware.cn/1panel to purchase and retry!" +ErrNodeBound: "This license is bound to another node, please check and retry!" +ErrNoSuchNode: "Node information not found, please check and retry!" +ErrNodeUnbind: "This node is not within the license binding range, please check and retry!" +ErrNodeBind: "This node is already bound to a license, please check and retry!" #task -TaskStart: "{{.name}} Task Start [START]" -TaskEnd: "{{.name}} Task End [COMPLETED]" -TaskFailed: "{{.name}} Task Failed" -TaskTimeout: "{{.name}} Timeout" -TaskSuccess: "{{.name}} Task Successful" -TaskRetry: "Starting the {{.name}} retry" -SubTaskSuccess: "{{ .name }} Successful" -SubTaskFailed: "{{ .name }} Failed: {{ .err }}" +TaskStart: "{{.name}} task started [START]" +TaskEnd: "{{.name}} task completed [COMPLETED]" +TaskFailed: "{{.name}} task failed" +TaskTimeout: "{{.name}} timeout" +TaskSuccess: "{{.name}} task successful" +TaskRetry: "Starting retry {{.name}}" +SubTaskSuccess: "{{ .name }} successful" +SubTaskFailed: "{{ .name }} failed: {{ .err }}" TaskInstall: "Install" TaskUninstall: "Uninstall" TaskCreate: "Create" @@ -65,26 +65,90 @@ TaskUpgrade: "Upgrade" TaskUpdate: "Update" TaskRestart: "Restart" TaskRollback: "Rollback" -SuccessStatus: "{{ .name }} Successful" -FailedStatus: "{{ .name }} Failed {{.err}}" -PullImage: "Pull Image" +SuccessStatus: "{{ .name }} successful" +FailedStatus: "{{ .name }} failed {{.err}}" +PullImage: "Pull image" Start: "Start" -Run: "Launch" +Run: "Run" Stop: "Stop" SubTask: "Subtask" #upgrade node -NodeUpgrade: "Upgrade Node {name}" -NewSSHClient: "Initialize SSH Connection" -BackupBeforeUpgrade: "Backup Data Before Upgrade" -UploadUpgradeFile: "Distribute Upgrade Required Files" -RestartAfterUpgrade: "Start Service After Upgrade" +NodeUpgrade: "Upgrade node {name}" +NewSSHClient: "Initialize SSH connection" +BackupBeforeUpgrade: "Backup data before upgrade" +UploadUpgradeFile: "Distribute upgrade files" +RestartAfterUpgrade: "Start services after upgrade" #add node -TaskAddNode: "Add Node" -SyncAgentBaseInfo: "Sync Node Base Data" -GenerateSSLInfo: "Generate Node SSL Information" -ConnInfoNotMatch: "Connection information does not match"; -MakeAgentPackage: "Generate Node Installation Package" -SendAgent: "Distribute Node Installation Package" -StartService: "Start Service" \ No newline at end of file +TaskAddNode: "Add node" +SyncAgentBaseInfo: "Sync basic node info" +GenerateSSLInfo: "Generate node SSL info" +ConnInfoNotMatch: "Connection info mismatch" +MakeAgentPackage: "Generate node installation package" +SendAgent: "Distribute node installation package" +StartService: "Start service" + +#cmd +AppVersion: "App version" +AppCommands: "App related commands" +AppInit: "Initialize app" +AppKeyVal: "App key (only supports English)" +AppCreateFileErr: "File {{ .name }} creation failed {{ .err }}" +AppCreateDirErr: "Folder {{ .name }} creation failed {{ .err }}" +AppMissKey: "App key missing, use -k to specify" +AppMissVersion: "App version missing, use -v to specify" +AppVersionExist: "Version already exists!" +AppCreateSuccessful: "Creation successful!" +AppWriteErr: "File {{ .name }} write failed {{ .err }}" +SudoHelper: "Please use {{ .cmd }} or switch to root user" +ListenIPCommands: "Switch listening ip" +ListenIPv4: "Listen on IPv4" +ListenIPv6: "Listen on IPv6" +ListenChangeSuccessful: "Switch successful! Now listening on {{ .value }}" +ResetCommands: "Reset system info" +ResetMFA: "Cancel 1Panel two-factor authentication" +ResetHttps: "Cancel 1Panel https login" +ResetEntrance: "Cancel 1Panel secure entrance" +ResetIPs: "Cancel 1Panel authorized ip restrictions" +ResetDomain: "Cancel 1Panel domain binding" +RestoreCommands: "Rollback 1Panel service and data" +RestoreNoSuchFile: "No files available for rollback" +RestoreStep1: "(1/5) Starting rollback of 1Panel service and data from {{ .name }} directory..." +RestoreStep2: "(2/5) 1Panel binary rollback successful" +RestoreStep3: "(3/5) 1Panel script rollback successful" +RestoreStep4: "(4/5) 1Panel service rollback successful" +RestoreStep5: "(5/5) 1Panel data rollback successful" +RestoreSuccessful: "Rollback successful! Restarting service, please wait..." +UpdateCommands: "Update panel info" +UpdateUser: "Update panel user" +UpdatePassword: "Update panel password" +UpdatePort: "Update panel port" +UpdateUserNull: "Error: panel user is empty!" +UpdateUserBlank: "Error: panel user contains spaces!" +UpdateUserFormat: "Error: Invalid panel user format! Only supports English, Chinese, numbers, and _, length 3-30" +UpdateUserErr: "Error: Failed to update panel user, {{ .err }}" +UpdateSuccessful: "Update successful!" +UpdateUserResult: "Panel user: {{ .name }}" +UpdatePasswordRead: "Error: Failed to read panel password information, {{ .err }}" +UpdatePasswordNull: "Error: Panel password is empty!" +UpdateUPasswordBlank: "Error: Panel password contains spaces!" +UpdatePasswordFormat: "Error: Panel password only supports letters, numbers, special characters !@#$%*_,.?, length 8-30!" +UpdatePasswordLen: "Error: Please enter a password longer than 6 characters!" +UpdatePasswordRe: "Confirm password:" +UpdatePasswordErr: "Error: Failed to update panel password, {{ .err }}" +UpdatePasswordSame: "Error: The two passwords do not match, please check and try again!" +UpdatePasswordResult: "Panel password: {{ .name }}" +UpdatePortFormat: "Error: The input port number must be between 1 and 65535!" +UpdatePortUsed: "Error: The port number is already in use, please check and try again!" +UpdatePortErr: "Error: Failed to update panel port, {{ .err }}" +UpdatePortResult: "Panel Port: {{ .name }}" +UpdatePortFirewallAdd: "Failed to add firewall port rule, {{ .err }}, please manually add the {{ .name }} port to the firewall rules." +UpdatePortFirewallDel: "Error: Failed to delete firewall port, {{ .err }}" +UpdatePortFirewallReload: "Failed to reload the firewall, {{ .err }}, please manually reload the firewall." +UserInfo: "Get panel information" +UserInfoAddr: "Panel address: " +UserInfoPassHelp: "Tip: To change the password, you can execute the command: " +DBConnErr: "Error: Failed to initialize database connection, {{ .err }}" +SystemVersion: "version: " +SystemMode: "mode: " diff --git a/core/i18n/lang/fa.yaml b/core/i18n/lang/fa.yaml new file mode 100644 index 000000000..4073cec63 --- /dev/null +++ b/core/i18n/lang/fa.yaml @@ -0,0 +1,63 @@ +#cmd +AppVersion: "Lotfan noskhe-ye barname ra vared konid" +AppCommands: "Dasturat-e marbut be barname" +AppInit: "Barname ra shoru' konid" +AppKeyVal: "Kelid-e barname (faghat az zabane englisi poshtibani mikonad)" +AppCreateFileErr: "Khalgh-e file {{ .name }} namovaffagh bud {{ .err }}" +AppCreateDirErr: "Khalgh-e folder {{ .name }} namovaffagh bud {{ .err }}" +AppMissKey: "Kelid-e barname mojood nist, az -k estefade konid" +AppMissVersion: "Noskhe-ye barname mojood nist, az -v estefade konid" +AppVersionExist: "Noskhe ghablan mojood ast!" +AppCreateSuccessful: "Khalgh ba movaffaghiat anjam shod!" +AppWriteErr: "Neveshtan file {{ .name }} namovaffagh bud {{ .err }}" +SudoHelper: "Lotfan in eskript ra be onvane karbare root ya ba mojavez sudo ejra konid" +ListenIPCommands: "IP goosh dadan ra taghir dahid" +ListenIPv4: "Goosh dadan bar IPv4" +ListenIPv6: "Goosh dadan bar IPv6" +ListenChangeSuccessful: "Taghir movaffagh! Hala bar {{ .value }} goosh midahad" +ResetCommands: "E'ade setadad etela'at-e system" +ResetMFA: "Fa'al-sazi do marhale'i 1Panel ra laghv konid" +ResetHttps: "Voroud HTTPS baraye 1Panel ra laghv konid" +ResetEntrance: "Voroud amin 1Panel ra laghv konid" +ResetIPs: "Mahdudiyat IP-haye mojaz 1Panel ra laghv konid" +ResetDomain: "Sazgari domain 1Panel ra laghv konid" +RestoreCommands: "Bargasht be khadamate 1Panel va data" +RestoreNoSuchFile: "Hich file mojood baraye bargasht nist" +RestoreStep1: "(1/5) Shoru' bargasht be khadamate 1Panel va data az directory {{ .name }} ..." +RestoreStep2: "(2/5) Bargasht be binary 1Panel ba movaffaghiat anjam shod" +RestoreStep3: "(3/5) Bargasht be script 1Panel ba movaffaghiat anjam shod" +RestoreStep4: "(4/5) Bargasht be khadamat 1Panel ba movaffaghiat anjam shod" +RestoreStep5: "(5/5) Bargasht be data 1Panel ba movaffaghiat anjam shod" +RestoreSuccessful: "Bargasht ba movaffaghiat anjam shod! Khadamat dar hale restart ast, lotfan montazer bashid..." +UpdateCommands: "Be'rooz resani etela'at-e panel" +UpdateUser: "Be'rooz resani karbare panel" +UpdatePassword: "Be'rooz resani ramz-e panel" +UpdatePort: "Be'rooz resani port-e panel" +UpdateUserNull: "Khatta: karbare panel khalist!" +UpdateUserBlank: "Khatta: karbare panel shamel faseleh ast!" +UpdateUserFormat: "Khatta: format-e karbare panel na dorost ast! Faghat az englisi, chine'i, adad va _, ba tool-e 3-30 poshtibani mikonad" +UpdateUserErr: "Khatta: be'rooz resani karbare panel namovaffagh bud, {{ .err }}" +UpdateSuccessful: "Be'rooz resani ba movaffaghiat anjam shod!" +UpdateUserResult: "Karbare panel: {{ .name }}" +UpdatePasswordRead: "Khatta: khatayi dar khandan etela'at-e ramz-e panel, {{ .err }}" +UpdatePasswordNull: "Khatta: ramz-e panel khalist!" +UpdateUPasswordBlank: "Khatta: ramz-e panel shamel faseleh ast!" +UpdatePasswordFormat: "Khatta: ramz-e panel faghat az harf, adad, karakter-haye vizhe !@#$%*_,.? ba tool-e 8-30 poshtibani mikonad!" +UpdatePasswordLen: "Khatta: lotfan ramzi bishtar az 6 karakter vared konid!" +UpdatePasswordRe: "Teyid-e ramz:" +UpdatePasswordErr: "Khatta: be'rooz resani ramz-e panel namovaffagh bud, {{ .err }}" +UpdatePasswordSame: "Khatta: do ramz ba ham yeksan nistand, lotfan barrasi konid va dobare talash konid!" +UpdatePasswordResult: "Ramz-e panel: {{ .name }}" +UpdatePortFormat: "Khatta: shomareye port bayad bein 1 ta 65535 bashad!" +UpdatePortUsed: "Khatta: shomareye port ghablan estefade shode ast, lotfan barrasi konid va dobare talash konid!" +UpdatePortErr: "Khatta: be'rooz resani port-e panel namovaffagh bud, {{ .err }}" +UpdatePortResult: "Port-e panel: {{ .name }}" +UpdatePortFirewallAdd: "Ezafe kardane ghanoun-e port firewall namovaffagh bud, {{ .err }}, lotfan port {{ .name }} ra be dast az qavaneen firewall ezafe konid." +UpdatePortFirewallDel: "Khatta: hazf-e port firewall namovaffagh bud, {{ .err }}" +UpdatePortFirewallReload: "Reload firewall namovaffagh bud, {{ .err }}, lotfan firewall ra be dast reload konid." +UserInfo: "Daryaft etela'at-e panel" +UserInfoAddr: "Address-e panel: " +UserInfoPassHelp: "Nokte: baraye taghiri ramz, mitavanid dastur zir ra anjam dahid: " +DBConnErr: "Khatta: etesal be database namovaffagh bud, {{ .err }}" +SystemVersion: "noskhe: " +SystemMode: "halat: " diff --git a/core/i18n/lang/ja.yaml b/core/i18n/lang/ja.yaml new file mode 100644 index 000000000..116231463 --- /dev/null +++ b/core/i18n/lang/ja.yaml @@ -0,0 +1,157 @@ +ErrInvalidParams: "リクエストパラメーターエラー: {{ .detail }}" +ErrTokenParse: "トークン生成エラー: {{ .detail }}" +ErrInitialPassword: "元のパスワードが間違っています" +ErrInternalServer: "サーバ内部エラー: {{ .detail }}" +ErrRecordExist: "レコードはすでに存在します" +ErrRecordNotFound: "レコードが見つかりません" +ErrStructTransform: "型変換エラー: {{ .detail }}" +ErrNotLogin: "ユーザーはログインしていません: {{ .detail }}" +ErrPasswordExpired: "現在のパスワードは期限切れです: {{ .detail }}" +ErrNotSupportType: "システムは現在のタイプをサポートしていません: {{ .detail }}" +ErrProxy: "リクエストエラー、ノードの状態を確認してください: {{ .detail }}" +ErrApiConfigStatusInvalid: "APIインターフェースへのアクセスが禁止されています: {{ .detail }}" +ErrApiConfigKeyInvalid: "APIインターフェースのキーエラー: {{ .detail }}" +ErrApiConfigIPInvalid: "APIインターフェースのIPがホワイトリストにありません: {{ .detail }}" +ErrApiConfigDisable: "このインターフェースはAPI呼び出しが無効です: {{ .detail }}" +ErrApiConfigKeyTimeInvalid: "APIインターフェースのタイムスタンプエラー: {{ .detail }}" + +#common +ErrDemoEnvironment: "デモサーバーで、この操作は許可されていません!" +ErrCmdTimeout: "コマンド実行のタイムアウト!" +ErrEntrance: "セキュアエントランス情報エラー、確認して再試行してください!" +ErrGroupIsDefault: 'デフォルトグループは削除できません' +ErrLocalDelete: "ローカルノードは削除できません!" + +#backup +ErrBackupInUsed: "バックアップアカウントは計画タスクで使用中のため削除できません" +ErrBackupCheck: "バックアップアカウントの接続テストに失敗しました {{ .err}}" +ErrBackupLocal: "ローカルサーバーのバックアップアカウントはこの操作をサポートしていません!" +ErrBackupPublic: "バックアップアカウントが公開ではないことが検出されました、確認して再試行してください!" +ErrOSSConn: "最新バージョンを取得できませんでした、サーバーが外部ネットワークに接続できるか確認してください。" +ErrEntrance: "セキュアエントランス情報エラー、確認して再試行してください!" + +#license +ErrLicense: "ライセンスフォーマットエラー、確認して再試行してください!" +ErrLicenseCheck: "ライセンスの確認に失敗しました、確認して再試行してください!" +ErrXpackVersion: "ライセンスの確認に失敗しました、このライセンスはバージョン制限があり、正常にインポートできません、確認して再試行してください!" +ErrLicenseSave: "ライセンス情報の保存に失敗しました、エラー {{ .err }}、再試行してください!" +ErrLicenseSync: "ライセンス情報の同期に失敗しました、データベースにライセンス情報が検出されませんでした!" +ErrXpackNotFound: "この部分はプロフェッショナル版機能です、まず「パネル設定-ライセンス」画面でライセンスをインポートしてください" +ErrXpackExceptional: "この部分はプロフェッショナル版機能です、まず「パネル設定-ライセンス」画面でライセンス状態を同期してください" +ErrXpackOutOfDate: "現在のライセンスは期限切れです、再度「パネル設定-ライセンス」画面でライセンスをインポートしてください" +ErrXpackLost: "ライセンスの最大試行回数に達しました、「パネル設定」「ライセンス」ページに移動し、手動で同期ボタンをクリックして、プロフェッショナル版機能が正常に使用できることを確認してください" +ErrXpackTimeout: "リクエストタイムアウト、ネットワーク接続が不安定な可能性があります。後で再試行してください!" +ErrUnbindMaster: "ノード管理にノードが存在するため、現在のライセンスを解除できません。ノードを削除してから再試行してください!" +ErrFreeNodeLimit: "コミュニティ版のノード数が無料上限に達しました、www.lxware.cn/1panel で購入して再試行してください!" +ErrNodeBound: "このライセンスは他のノードにバインドされています、確認して再試行してください!" +ErrNoSuchNode: "そのノード情報が見つかりませんでした、確認して再試行してください!" +ErrNodeUnbind: "そのノードはライセンスのバインド範囲内ではありません、確認して再試行してください!" +ErrNodeBind: "そのノードはライセンスにバインドされています、確認して再試行してください!" + +# alert +ErrAlertSync: "アラート情報の同期エラー、確認して再試行してください!" + +#task +TaskStart: "{{.name}} タスク開始 [START]" +TaskEnd: "{{.name}} タスク終了 [COMPLETED]" +TaskFailed: "{{.name}} タスク失敗" +TaskTimeout: "{{.name}} タイムアウト" +TaskSuccess: "{{.name}} タスク成功" +TaskRetry: "{{.name}} 番目の再試行を開始" +SubTaskSuccess: "{{ .name }} 成功" +SubTaskFailed: "{{ .name }} 失敗: {{ .err }}" +TaskInstall: "インストール" +TaskUninstall: "アンインストール" +TaskCreate: "作成" +TaskDelete: "削除" +TaskUpgrade: "アップグレード" +TaskUpdate: "更新" +TaskRestart: "再起動" +TaskRollback: "ロールバック" +SuccessStatus: "{{ .name }} 成功" +FailedStatus: "{{ .name }} 失敗 {{.err}}" +PullImage: "イメージを取得" +Start: "開始" +Run: "実行" +Stop: "停止" +SubTask: "サブタスク" + +#upgrade node +NodeUpgrade: "ノードのアップグレード {name}" +NewSSHClient: "SSH接続を初期化" +BackupBeforeUpgrade: "アップグレード前のデータバックアップ" +UploadUpgradeFile: "アップグレードに必要なファイルを送信" +RestartAfterUpgrade: "アップグレード後にサービスを再起動" + +#add node +TaskAddNode: "ノードを追加" +SyncAgentBaseInfo: "ノードの基本情報を同期" +GenerateSSLInfo: "ノードのSSL情報を生成" +ConnInfoNotMatch: "接続情報が一致しません" +MakeAgentPackage: "ノードインストールパッケージを生成" +SendAgent: "ノードインストールパッケージを送信" +StartService: "サービスを開始" + +#cmd +AppVersion: "アプリバージョン" +AppCommands: "アプリ関連のコマンド" +AppInit: "アプリを初期化します" +AppKeyVal: "アプリキー(英語のみをサポートする)" +AppCreateFileErr: "file {{.name}}作成に失敗した{{.err}}" +AppCreateDirErr: "Folder {{.name}}作成に失敗した{{.err}}" +AppMissKey: "アプリキーがありません、-kを使用して指定します" +AppMissVersion: "アプリバージョンがありません、-vを使用して指定します" +AppVersionExist: "バージョンはすでに存在します!" +AppCreateSuccessful: "創造は成功しました!" +AppWriteErr: "file {{.name}} write failed {{.err}}" +SudoHelper: "{{.cmd}}を使用するか、ルートユーザーに切り替えてください" +ListenIPCommands: "リスニングIPを切り替えます" +ListenIPv4: "IPv4で聞いてください" +ListenIPv6: "IPv6で聞く" +ListenChangeSuccessful: "切り替え成功!{{.Value}}で聞いています" +ResetCommands: "システム情報をリセットします" +ResetMFA: "1パネルの2要素認証をキャンセルします" +ResetHttps: "1Panel HTTPSログインをキャンセルします" +ResetEntrance: "1パネルの安全な入り口をキャンセルします" +ResetIPs: "1パネル認定IP制限をキャンセルします" +ResetDomain: "1パネルドメインバインディングをキャンセルします" +RestoreCommands: "ロールバック1パネルサービスとデータ" +RestoreNoSuchFile: "ロールバックに使用できるファイルはありません" +RestoreStep1: "(1/5){{.name}}ディレクトリからの1パネルサービスとデータの開始ロールバック..." +RestoreStep2: "(2/5)1パネルバイナリロールバックが成功しました" +RestoreStep3: "(3/5)1パネルスクリプトロールバック成功" +RestoreStep4: "(4/5)1パネルサービスロールバックが成功しました" +RestoreStep5: "(5/5)1パネルデータロールバックが成功しました" +RestoreSuccessful: "ロールバックが成功しました!サービスを再起動します、待ってください..." +UpdateCommands: "パネル情報を更新します" +UpdateUser: "パネルユーザーを更新します" +UpdatePassword: "パスワードを更新します" +UpdatePort: "パネルポートを更新します" +UpdateUserNull: "エラー:パネルユーザーは空です!" +UpdateUserBlank: "エラー:パネルユーザーにはスペースが含まれています!" +UpdateUserFormat: "エラー:無効なパネルユーザー形式!英語、中国語、数字、_、長さ3〜30のみをサポートしています" +UpdateUserErr: "エラー:パネルユーザーの更新に失敗しました{{.err}}" +UpdateSuccessful: "更新成功!" +UpdateUserResult: "パネルユーザー:{{.name}}" +UpdatePasswordRead: "エラー:パネルパスワード情報の読み取りに失敗しました、{{.err}}" +UpdatePasswordNull: "エラー:パネルパスワードは空です!" +UpdateUPasswordBlank: "エラー:パスワードにはスペースが含まれています!" +UpdatePasswordFormat: "エラー:パネルパスワードは、文字、数字、特殊文字のみをサポートします!@#$%*_、。、、長さ8-30!" +UpdatePasswordLen: "エラー:6文字より長くパスワードを入力してください!" +UpdatePasswordRe: "パスワードを認証する:" +UpdatePasswordErr: "エラー:{{.err}}のパスワードの更新に失敗しました" +UpdatePasswordSame: "エラー:2つのパスワードが一致しません。チェックして再試行してください!" +UpdatePasswordResult: "パネルパスワード:{{.name}}" +UpdatePortFormat: "エラー:入力ポート番号は1〜65535でなければなりません!" +UpdatePortUsed: "エラー:ポート番号はすでに使用されています。チェックして再試行してください!" +UpdatePortErr: "エラー:パネルポートの更新に失敗しました{{.err}}" +UpdatePortResult: "パネルポート:{{.name}}" +UpdatePortFirewallAdd: "ファイアウォールポートルールの追加に失敗した{{.err}}、ファイアウォールルールに{{.name}}ポートを手動で追加してください。" +UpdatePortFirewallDel: "エラー:ファイアウォールポートの削除に失敗しました、{{.err}}" +UpdatePortFirewallReload: "ファイアウォールのリロードに失敗しました{{.err}}、ファイアウォールを手動でリロードしてください。" +UserInfo: "パネル情報を取得します" +UserInfoAddr: "パネルアドレス:" +UserInfoPassHelp: "ヒント:パスワードを変更するには、コマンドを実行できます。" +DBConnErr: "エラー:データベース接続の初期化に失敗しました、{{.err}}" +SystemVersion: "バージョン:" +SystemMode: "モード:" diff --git a/core/i18n/lang/ko.yaml b/core/i18n/lang/ko.yaml new file mode 100644 index 000000000..d96ea103d --- /dev/null +++ b/core/i18n/lang/ko.yaml @@ -0,0 +1,157 @@ +ErrInvalidParams: "요청 매개변수가 잘못되었습니다: {{ .detail }}" +ErrTokenParse: "토큰 생성 오류: {{ .detail }}" +ErrInitialPassword: "기존 비밀번호가 틀렸습니다" +ErrInternalServer: "서비스 내부 오류: {{ .detail }}" +ErrRecordExist: "레코드가 이미 존재합니다" +ErrRecordNotFound: "레코드를 찾을 수 없습니다" +ErrStructTransform: "타입 변환 실패: {{ .detail }}" +ErrNotLogin: "사용자가 로그인하지 않았습니다: {{ .detail }}" +ErrPasswordExpired: "현재 비밀번호가 만료되었습니다: {{ .detail }}" +ErrNotSupportType: "시스템이 현재 유형을 지원하지 않습니다: {{ .detail }}" +ErrProxy: "요청 오류, 노드 상태를 확인하세요: {{ .detail }}" +ErrApiConfigStatusInvalid: "API 인터페이스 접근 금지: {{ .detail }}" +ErrApiConfigKeyInvalid: "API 인터페이스 키 오류: {{ .detail }}" +ErrApiConfigIPInvalid: "API 인터페이스 호출 IP가 화이트리스트에 없습니다: {{ .detail }}" +ErrApiConfigDisable: "이 인터페이스는 API 인터페이스 호출을 사용할 수 없습니다: {{ .detail }}" +ErrApiConfigKeyTimeInvalid: "API 인터페이스 타임스탬프 오류: {{ .detail }} + +#common +ErrDemoEnvironment: "데모 서버에서는 이 작업을 수행할 수 없습니다!" +ErrCmdTimeout: "명령 실행 시간 초과!" +ErrEntrance: "보안 입구 정보가 잘못되었습니다. 다시 확인하고 시도해 주세요!" +ErrGroupIsDefault: '기본 그룹은 삭제할 수 없습니다' +ErrLocalDelete: "로컬 노드를 삭제할 수 없습니다!" + +#backup +ErrBackupInUsed: "이 백업 계정은 이미 예약 작업에서 사용 중입니다. 삭제할 수 없습니다." +ErrBackupCheck: "백업 계정 연결 테스트 실패 {{ .err}}" +ErrBackupLocal: "로컬 서버 백업 계정은 현재 작업을 지원하지 않습니다!" +ErrBackupPublic: "이 백업 계정이 공용이 아님을 감지했습니다. 다시 확인하고 시도해 주세요!" +ErrOSSConn: "최신 버전을 가져올 수 없습니다. 서버가 외부 네트워크에 연결되어 있는지 확인하세요." +ErrEntrance: "보안 입구 정보가 잘못되었습니다. 다시 확인하고 시도해 주세요!" + +#license +ErrLicense: "라이선스 형식이 잘못되었습니다. 다시 확인하고 시도해 주세요!" +ErrLicenseCheck: "라이선스 검증 실패. 다시 확인하고 시도해 주세요!" +ErrXpackVersion: "라이선스 검증 실패, 이 라이선스는 버전 제한이 있습니다. 성공적으로 가져올 수 없습니다. 다시 확인하고 시도해 주세요!" +ErrLicenseSave: "라이선스 정보 저장 실패, 오류 {{ .err }}, 다시 시도해 주세요!" +ErrLicenseSync: "라이선스 정보 동기화 실패, 데이터베이스에서 라이선스 정보를 찾을 수 없습니다!" +ErrXpackNotFound: "이 섹션은 프로페셔널 에디션 기능입니다. 먼저 [패널 설정]-[라이선스] 인터페이스에서 라이선스를 가져오세요." +ErrXpackExceptional: "이 섹션은 프로페셔널 에디션 기능입니다. 먼저 [패널 설정]-[라이선스] 인터페이스에서 라이선스 상태를 동기화하세요." +ErrXpackOutOfDate: "현재 라이선스가 만료되었습니다. 다시 [패널 설정]-[라이선스] 인터페이스에서 라이선스를 가져오세요." +ErrXpackLost: "라이선스가 최대 재시도 횟수에 도달했습니다. [패널 설정][라이선스] 페이지로 이동하여 수동으로 동기화 버튼을 클릭하여 프로페셔널 기능을 정상적으로 사용할 수 있도록 하세요." +ErrXpackTimeout: "요청 시간 초과, 네트워크 연결이 불안정할 수 있습니다. 나중에 다시 시도해 주세요!" +ErrUnbindMaster: "노드 관리 내에 노드가 존재함을 감지하였습니다. 현재 라이선스를 해제할 수 없습니다. 먼저 제거 후 다시 시도해 주세요!" +ErrFreeNodeLimit: "커뮤니티 에디션 노드 수가 무료 한도에 도달하였습니다. www.lxware.cn/1panel 에서 구매 후 다시 시도해 주세요!" +ErrNodeBound: "이 라이선스는 다른 노드에 바인딩되어 있습니다. 다시 확인하고 시도해 주세요!" +ErrNoSuchNode: "노드 정보를 찾을 수 없습니다. 다시 확인하고 시도해 주세요!" +ErrNodeUnbind: "이 노드가 라이선스 바인딩 범위에 있지 않음을 감지하였습니다. 다시 확인하고 시도해 주세요!" +ErrNodeBind: "이 노드가 이미 라이선스에 바인딩되어 있음을 감지하였습니다. 다시 확인하고 시도해 주세요!" + +# alert +ErrAlertSync: "경고 정보 동기화 오류, 다시 확인하고 시도해 주세요!" + +#task +TaskStart: "{{.name}} 작업 시작 [START]" +TaskEnd: "{{.name}} 작업 완료 [COMPLETED]" +TaskFailed: "{{.name}} 작업 실패" +TaskTimeout: "{{.name}} 시간 초과" +TaskSuccess: "{{.name}} 작업 성공" +TaskRetry: "{{.name}} 번째 재시도 시작" +SubTaskSuccess: "{{ .name }} 성공" +SubTaskFailed: "{{ .name }} 실패: {{ .err }}" +TaskInstall: "설치" +TaskUninstall: "제거" +TaskCreate: "생성" +TaskDelete: "삭제" +TaskUpgrade: "업그레이드" +TaskUpdate: "업데이트" +TaskRestart: "재시작" +TaskRollback: "롤백" +SuccessStatus: "{{ .name }} 성공" +FailedStatus: "{{ .name }} 실패 {{.err}}" +PullImage: "이미지 가져오기" +Start: "시작" +Run: "실행" +Stop: "중지" +SubTask: "하위 작업" + +#upgrade node +NodeUpgrade: "노드 {name} 업그레이드" +NewSSHClient: "SSH 연결 초기화" +BackupBeforeUpgrade: "업그레이드 전 데이터 백업" +UploadUpgradeFile: "업그레이드 파일 배포" +RestartAfterUpgrade: "업그레이드 후 서비스 재시작" + +#add node +TaskAddNode: "노드 추가" +SyncAgentBaseInfo: "노드 기본 데이터 동기화" +GenerateSSLInfo: "노드 SSL 정보 생성" +ConnInfoNotMatch: "연결 정보가 일치하지 않음" +MakeAgentPackage: "노드 설치 패키지 생성" +SendAgent: "노드 설치 패키지 배포" +StartService: "서비스 시작" + +# CMD +AppVersion: "앱 버전" +AppCommands: "앱 관련 명령어" +AppInit: "앱 초기화" +AppKeyVal: "앱 키 (영어만 지원)" +AppCreateFileErr: "파일 {{ .name }} 생성 실패 {{ .err }}" +AppCreateDirErr: "폴더 {{ .name }} 생성 실패 {{ .err }}" +AppMissKey: "앱 키가 없습니다. -k 옵션으로 지정하세요." +AppMissVersion: "앱 버전이 없습니다. -v 옵션으로 지정하세요." +AppVersionExist: "버전이 이미 존재합니다!" +AppCreateSuccessful: "생성 성공!" +AppWriteErr: "파일 {{ .name }} 쓰기 실패 {{ .err }}" +SudoHelper: "{{ .cmd }} 명령을 사용하거나 root 사용자로 전환하세요." +ListenIPCommands: "IP 변경" +ListenIPv4: "IPv4 에서 수신 대기" +ListenIPv6: "IPv6 에서 수신 대기" +ListenChangeSuccessful: "변경 성공! 현재 {{ .value }}에서 수신 대기 중입니다." +ResetCommands: "시스템 정보 초기화" +ResetMFA: "1Panel 이중 인증 취소" +ResetHttps: "1Panel HTTPS 로그인 취소" +ResetEntrance: "1Panel 보안 입구 취소" +ResetIPs: "1Panel 허용 IP 제한 취소" +ResetDomain: "1Panel 도메인 바인딩 취소" +RestoreCommands: "1Panel 서비스 및 데이터 복구" +RestoreNoSuchFile: "복구 가능한 파일이 없습니다." +RestoreStep1: "(1/5) {{ .name }} 디렉토리에서 1Panel 서비스 및 데이터 복구 시작..." +RestoreStep2: "(2/5) 1Panel 바이너리 복구 성공" +RestoreStep3: "(3/5) 1Panel 스크립트 복구 성공" +RestoreStep4: "(4/5) 1Panel 서비스 복구 성공" +RestoreStep5: "(5/5) 1Panel 데이터 복구 성공" +RestoreSuccessful: "복구 성공! 서비스를 다시 시작합니다. 잠시만 기다려주세요..." +UpdateCommands: "패널 정보 업데이트" +UpdateUser: "패널 사용자 업데이트" +UpdatePassword: "패널 비밀번호 업데이트" +UpdatePort: "패널 포트 업데이트" +UpdateUserNull: "오류: 패널 사용자가 비어 있습니다!" +UpdateUserBlank: "오류: 패널 사용자에 공백이 포함되어 있습니다!" +UpdateUserFormat: "오류: 잘못된 패널 사용자 형식! 영어, 중국어, 숫자, _만 지원하며 길이는 3~30자입니다." +UpdateUserErr: "오류: 패널 사용자 업데이트 실패 {{ .err }}" +UpdateSuccessful: "업데이트 성공!" +UpdateUserResult: "패널 사용자: {{ .name }}" +UpdatePasswordRead: "오류: 패널 비밀번호 정보 읽기 실패 {{ .err }}" +UpdatePasswordNull: "오류: 패널 비밀번호가 비어 있습니다!" +UpdateUPasswordBlank: "오류: 패널 비밀번호에 공백이 포함되어 있습니다!" +UpdatePasswordFormat: "오류: 패널 비밀번호는 문자, 숫자, 특수 문자 !@#$%*_,.?만 지원하며 길이는 8~30자입니다!" +UpdatePasswordLen: "오류: 6자 이상의 비밀번호를 입력하세요!" +UpdatePasswordRe: "비밀번호 확인:" +UpdatePasswordErr: "오류: 패널 비밀번호 업데이트 실패 {{ .err }}" +UpdatePasswordSame: "오류: 두 비밀번호가 일치하지 않습니다. 확인 후 다시 시도하세요!" +UpdatePasswordResult: "패널 비밀번호: {{ .name }}" +UpdatePortFormat: "오류: 입력한 포트 번호는 1~65535 사이여야 합니다!" +UpdatePortUsed: "오류: 포트 번호가 이미 사용 중입니다. 확인 후 다시 시도하세요!" +UpdatePortErr: "오류: 패널 포트 업데이트 실패 {{ .err }}" +UpdatePortResult: "패널 포트: {{ .name }}" +UpdatePortFirewallAdd: "방화벽 포트 규칙 추가 실패 {{ .err }}, 방화벽 규칙에 {{ .name }} 포트를 수동으로 추가하세요." +UpdatePortFirewallDel: "오류: 방화벽 포트 삭제 실패 {{ .err }}" +UpdatePortFirewallReload: "방화벽 다시 로드 실패 {{ .err }}, 방화벽을 수동으로 다시 로드하세요." +UserInfo: "패널 정보 가져오기" +UserInfoAddr: "패널 주소: " +UserInfoPassHelp: "팁: 비밀번호를 변경하려면 다음 명령어를 실행할 수 있습니다: " +DBConnErr: "오류: 데이터베이스 연결 초기화 실패 {{ .err }}" +SystemVersion: "버전: " +SystemMode: "모드: " diff --git a/core/i18n/lang/ms.yml b/core/i18n/lang/ms.yml new file mode 100644 index 000000000..b58145f6f --- /dev/null +++ b/core/i18n/lang/ms.yml @@ -0,0 +1,157 @@ +ErrInvalidParams: "Parameter permintaan salah: {{ .detail }}" +ErrTokenParse: "Ralat penjanaan token: {{ .detail }}" +ErrInitialPassword: "Kata laluan asal salah" +ErrInternalServer: "Ralat dalaman perkhidmatan: {{ .detail }}" +ErrRecordExist: "Rekod sudah wujud" +ErrRecordNotFound: "Rekod tidak dijumpai" +ErrStructTransform: "Penukaran jenis gagal: {{ .detail }}" +ErrNotLogin: "Pengguna tidak log masuk: {{ .detail }}" +ErrPasswordExpired: "Kata laluan semasa telah tamat tempoh: {{ .detail }}" +ErrNotSupportType: "Sistem tidak menyokong jenis semasa: {{ .detail }}" +ErrProxy: "Ralat permintaan, sila semak status nod ini: {{ .detail }}" +ErrApiConfigStatusInvalid: "API sambungan dilarang: {{ .detail }}" +ErrApiConfigKeyInvalid: "Kunci API tidak sah: {{ .detail }}" +ErrApiConfigIPInvalid: "IP memanggil API tidak dalam senarai putih: {{ .detail }}" +ErrApiConfigDisable: "Sambungan ini dilarang menggunakan panggilan API: {{ .detail }}" +ErrApiConfigKeyTimeInvalid: "Timestamp API tidak sah: {{ .detail }} + +#common +ErrDemoEnvironment: "Pelayan demo, larangan operasi ini!" +ErrCmdTimeout: "Masa tamat untuk melaksanakan arahan!" +ErrEntrance: "Maklumat pintu masuk selamat salah, sila semak dan cuba lagi!" +ErrGroupIsDefault: 'Kumpulan default, tidak boleh dipadam' +ErrLocalDelete: "Tidak dapat memadam nod tempatan!" + +#backup +ErrBackupInUsed: "Akaun sandaran ini sedang digunakan dalam tugas terjadual, tidak boleh dipadam" +ErrBackupCheck: "Cubaan sambungan akaun sandaran gagal {{ .err}}" +ErrBackupLocal: "Akaun sandaran pelayan tempatan tidak menyokong operasi ini!" +ErrBackupPublic: "Akaun sandaran ini didapati bukan awam, sila semak dan cuba lagi!" +ErrOSSConn: "Tidak dapat mendapatkan versi terkini, sila pastikan pelayan boleh disambung ke rangkaian luar." +ErrEntrance: "Maklumat pintu masuk selamat salah, sila semak dan cuba lagi!" + +#license +ErrLicense: "Format lesen salah, sila semak dan cuba lagi!" +ErrLicenseCheck: "Pengecaman lesen gagal, sila semak dan cuba lagi!" +ErrXpackVersion: "Pengecaman lesen gagal, lesen ini dibatasi oleh versi dan tidak dapat diimport dengan berjaya, sila semak dan cuba lagi!" +ErrLicenseSave: "Simpanan maklumat lesen gagal, ralat {{ .err }}, sila cuba lagi!" +ErrLicenseSync: "Penyingkronan maklumat lesen gagal, tiada maklumat lesen dijumpai dalam pangkalan data!" +ErrXpackNotFound: "Bahagian ini adalah ciri profesional, sila import lesen melalui paparan Tetapan Panel-Lesen dahulu" +ErrXpackExceptional: "Bahagian ini adalah ciri profesional, sila singkronkan status lesen melalui paparan Tetapan Panel-Lesen dahulu" +ErrXpackOutOfDate: "Lesen semasa telah tamat tempoh, sila import semula lesen melalui paparan Tetapan Panel-Lesen" +ErrXpackLost: "Lesen telah mencapai jumlah cubaan maksimum, sila klik butang penyinkronan secara manual pada halaman [Tetapan Panel] [Lesen] untuk memastikan fungsi profesional dapat digunakan dengan normal" +ErrXpackTimeout: "Masa tamat permintaan, sambungan internet mungkin tidak stabil, sila cuba lagi kemudian!" +ErrUnbindMaster: "Nod dijumpai dalam pengurusan nod, tidak dapat menanggalkan lesen semasa, sila singkirkan dahulu dan cuba lagi!" +ErrFreeNodeLimit: "Bilangan nod edisi komuniti telah mencapai had percuma, sila beli di www.lxware.cn/1panel dahulu dan cuba lagi!" +ErrNodeBound: "Lesen ini telah diikat kepada nod lain, sila semak dan cuba lagi!" +ErrNoSuchNode: "Maklumat nod tidak dijumpai, sila semak dan cuba lagi!" +ErrNodeUnbind: "Nod ini didapati tidak dalam lingkungan ikatan lesen, sila semak dan cuba lagi!" +ErrNodeBind: "Nod ini didapati telah diikat dengan lesen, sila semak dan cuba lagi!" + +# alert +ErrAlertSync: "Ralat penyinkronan maklumat amaran, sila semak dan cuba lagi!" + +#task +TaskStart: "{{.name}} tugas bermula [START]" +TaskEnd: "{{.name}} tugas selesai [COMPLETED]" +TaskFailed: "{{.name}} tugas gagal" +TaskTimeout: "{{.name}} masa tamat" +TaskSuccess: "{{.name}} tugas berjaya" +TaskRetry: "Mula cubaan ke-{{.name}}" +SubTaskSuccess: "{{ .name }} berjaya" +SubTaskFailed: "{{ .name }} gagal: {{ .err }}" +TaskInstall: "Pasang" +TaskUninstall: "Buang Pasangan" +TaskCreate: "Cipta" +TaskDelete: "Padam" +TaskUpgrade: "Naik Taraf" +TaskUpdate: "Kemas Kini" +TaskRestart: "Mulakan Semula" +TaskRollback: "Rollback" +SuccessStatus: "{{ .name }} berjaya" +FailedStatus: "{{ .name }} gagal {{.err}}" +PullImage: "Tarik Imej" +Start: "Mula" +Run: "Jalankan" +Stop: "Hentikan" +SubTask: "Sub-tugas" + +#upgrade node +NodeUpgrade: "Naik taraf nod {name}" +NewSSHClient: "Permulaan sambungan SSH" +BackupBeforeUpgrade: "Sandar data sebelum naik taraf" +UploadUpgradeFile: "Muat naik fail yang diperlukan untuk naik taraf" +RestartAfterUpgrade: "Mulakan semula perkhidmatan selepas naik taraf" + +#add node +TaskAddNode: "Tambah nod" +SyncAgentBaseInfo: "Sinkronkan maklumat asas nod" +GenerateSSLInfo: "Cipta maklumat SSL nod" +ConnInfoNotMatch: "Maklumat sambungan tidak sepadan" +MakeAgentPackage: "Cipta pakej pemasangan nod" +SendAgent: "Muat naik pakej pemasangan nod" +StartService: "Mulakan perkhidmatan" + +#cmd +AppVersion: "Versi aplikasi" +AppCommands: "Arahan berkaitan aplikasi" +AppInit: "Inisialisasi aplikasi" +AppKeyVal: "Kunci aplikasi (hanya menyokong bahasa Inggeris)" +AppCreateFileErr: "Gagal mencipta fail {{ .name }} {{ .err }}" +AppCreateDirErr: "Gagal mencipta folder {{ .name }} {{ .err }}" +AppMissKey: "Kunci aplikasi hilang, gunakan -k untuk menetapkan" +AppMissVersion: "Versi aplikasi hilang, gunakan -v untuk menetapkan" +AppVersionExist: "Versi sudah wujud!" +AppCreateSuccessful: "Ciptaan berjaya!" +AppWriteErr: "Penulisan fail {{ .name }} gagal {{ .err }}" +SudoHelper: "Sila gunakan {{ .cmd }} atau tukar ke pengguna root" +ListenIPCommands: "Tukar IP mendengar" +ListenIPv4: "Mendengar pada IPv4" +ListenIPv6: "Mendengar pada IPv6" +ListenChangeSuccessful: "Tukar berjaya! Kini mendengar pada {{ .value }}" +ResetCommands: "Tetapkan semula maklumat sistem" +ResetMFA: "Batal pengesahan dua faktor 1Panel" +ResetHttps: "Batal log masuk HTTPS 1Panel" +ResetEntrance: "Batal pintu masuk keselamatan 1Panel" +ResetIPs: "Batal sekatan IP yang dibenarkan 1Panel" +ResetDomain: "Batal pengikatan domain 1Panel" +RestoreCommands: "Pulihkan perkhidmatan dan data 1Panel" +RestoreNoSuchFile: "Tiada fail tersedia untuk pemulihan" +RestoreStep1: "(1/5) Memulakan pemulihan perkhidmatan dan data 1Panel daripada direktori {{ .name }}..." +RestoreStep2: "(2/5) Pemulihan binari 1Panel berjaya" +RestoreStep3: "(3/5) Pemulihan skrip 1Panel berjaya" +RestoreStep4: "(4/5) Pemulihan perkhidmatan 1Panel berjaya" +RestoreStep5: "(5/5) Pemulihan data 1Panel berjaya" +RestoreSuccessful: "Pemulihan berjaya! Memulakan semula perkhidmatan, sila tunggu..." +UpdateCommands: "Kemas kini maklumat panel" +UpdateUser: "Kemas kini pengguna panel" +UpdatePassword: "Kemas kini kata laluan panel" +UpdatePort: "Kemas kini port panel" +UpdateUserNull: "Ralat: Pengguna panel kosong!" +UpdateUserBlank: "Ralat: Pengguna panel mengandungi ruang kosong!" +UpdateUserFormat: "Ralat: Format pengguna panel tidak sah! Hanya menyokong huruf Inggeris, Cina, nombor, dan , dengan panjang 3-30 aksara" +UpdateUserErr: "Ralat: Gagal mengemas kini pengguna panel, {{ .err }}" +UpdateSuccessful: "Kemas kini berjaya!" +UpdateUserResult: "Pengguna panel: {{ .name }}" +UpdatePasswordRead: "Ralat: Gagal membaca maklumat kata laluan panel, {{ .err }}" +UpdatePasswordNull: "Ralat: Kata laluan panel kosong!" +UpdateUPasswordBlank: "Ralat: Kata laluan panel mengandungi ruang kosong!" +UpdatePasswordFormat: "Ralat: Kata laluan panel hanya menyokong huruf, nombor, dan aksara khas !@#$%*,.?, dengan panjang 8-30 aksara!" +UpdatePasswordLen: "Ralat: Sila masukkan kata laluan lebih panjang daripada 6 aksara!" +UpdatePasswordRe: "Sahkan kata laluan:" +UpdatePasswordErr: "Ralat: Gagal mengemas kini kata laluan panel, {{ .err }}" +UpdatePasswordSame: "Ralat: Kedua-dua kata laluan tidak sepadan, sila semak dan cuba lagi!" +UpdatePasswordResult: "Kata laluan panel: {{ .name }}" +UpdatePortFormat: "Ralat: Nombor port yang dimasukkan mesti antara 1 hingga 65535!" +UpdatePortUsed: "Ralat: Nombor port sudah digunakan, sila semak dan cuba lagi!" +UpdatePortErr: "Ralat: Gagal mengemas kini port panel, {{ .err }}" +UpdatePortResult: "Port Panel: {{ .name }}" +UpdatePortFirewallAdd: "Gagal menambah peraturan port firewall, {{ .err }}, sila tambah port {{ .name }} secara manual ke dalam peraturan firewall." +UpdatePortFirewallDel: "Ralat: Gagal memadam port firewall, {{ .err }}" +UpdatePortFirewallReload: "Gagal memuat semula firewall, {{ .err }}, sila muat semula firewall secara manual." +UserInfo: "Dapatkan maklumat panel" +UserInfoAddr: "Alamat panel: " +UserInfoPassHelp: "Petua: Untuk menukar kata laluan, anda boleh menjalankan arahan: " +DBConnErr: "Ralat: Gagal memulakan sambungan pangkalan data, {{ .err }}" +SystemVersion: "Versi: " +SystemMode: "Mod: " diff --git a/core/i18n/lang/pt-BR.yaml b/core/i18n/lang/pt-BR.yaml new file mode 100644 index 000000000..cbdeef6c0 --- /dev/null +++ b/core/i18n/lang/pt-BR.yaml @@ -0,0 +1,157 @@ +ErrInvalidParams: "Erro nos parâmetros da solicitação: {{ .detail }}" +ErrTokenParse: "Erro na geração do token: {{ .detail }}" +ErrInitialPassword: "Senha original incorreta" +ErrInternalServer: "Erro interno no servidor: {{ .detail }}" +ErrRecordExist: "O registro já existe" +ErrRecordNotFound: "Registro não encontrado" +ErrStructTransform: "Falha na conversão de tipo: {{ .detail }}" +ErrNotLogin: "Usuário não está logado: {{ .detail }}" +ErrPasswordExpired: "A senha atual expirou: {{ .detail }}" +ErrNotSupportType: "O sistema não suporta o tipo atual: {{ .detail }}" +ErrProxy: "Erro na solicitação, verifique o estado do nó: {{ .detail }}" +ErrApiConfigStatusInvalid: "Acesso à API bloqueado: {{ .detail }}" +ErrApiConfigKeyInvalid: "Chave da API inválida: {{ .detail }}" +ErrApiConfigIPInvalid: "O IP da API não está na lista branca: {{ .detail }}" +ErrApiConfigDisable: "Esta API não pode ser chamada: {{ .detail }}" +ErrApiConfigKeyTimeInvalid: "Erro no timestamp da API: {{ .detail }}" + +#common +ErrDemoEnvironment: "Servidor de demonstração, esta operação é proibida!" +ErrCmdTimeout: "Tempo limite de execução do comando!" +ErrEntrance: "Erro nas informações de entrada de segurança, verifique e tente novamente!" +ErrGroupIsDefault: 'Grupo padrão, não é possível excluir' +ErrLocalDelete: "Não é possível excluir o nó local!" + +#backup +ErrBackupInUsed: "A conta de backup já está em uso em uma tarefa agendada, não é possível excluir" +ErrBackupCheck: "Falha na conexão de teste da conta de backup {{ .err}}" +ErrBackupLocal: "A conta de backup do servidor local não suporta essa operação!" +ErrBackupPublic: "Detectamos que a conta de backup não é pública, verifique e tente novamente!" +ErrOSSConn: "Não foi possível obter a versão mais recente, verifique se o servidor pode se conectar à rede externa." +ErrEntrance: "Erro nas informações de entrada de segurança, verifique e tente novamente!" + +#license +ErrLicense: "Erro no formato da licença, verifique e tente novamente!" +ErrLicenseCheck: "Falha na verificação da licença, verifique e tente novamente!" +ErrXpackVersion: "Falha na verificação da licença, a licença está restrita por versão e não pode ser importada com sucesso, verifique e tente novamente!" +ErrLicenseSave: "Falha ao salvar as informações da licença, erro {{ .err }}, tente novamente!" +ErrLicenseSync: "Falha na sincronização das informações da licença, não foram detectadas informações de licença no banco de dados!" +ErrXpackNotFound: "Esta parte é um recurso da versão profissional, primeiro importe a licença na tela de Configuração do Painel - Licença" +ErrXpackExceptional: "Esta parte é um recurso da versão profissional, primeiro sincronize o status da licença na tela de Configuração do Painel - Licença" +ErrXpackOutOfDate: "A licença atual expirou, reimporte a licença na tela de Configuração do Painel - Licença" +ErrXpackLost: "A licença atingiu o número máximo de tentativas, vá para a página [Configuração do Painel][Licença] e clique manualmente no botão de sincronização para garantir o uso normal dos recursos da versão profissional" +ErrXpackTimeout: "Tempo de solicitação esgotado, a conexão de rede pode estar instável, tente novamente mais tarde!" +ErrUnbindMaster: "Foi detectado um nó no gerenciamento de nós, não é possível desvincular a licença atual, remova o nó primeiro e tente novamente!" +ErrFreeNodeLimit: "O número de nós da versão comunitária atingiu o limite gratuito, acesse www.lxware.cn/1panel para comprar e tente novamente!" +ErrNodeBound: "A licença já está vinculada a outro nó, verifique e tente novamente!" +ErrNoSuchNode: "Não foi possível encontrar as informações do nó, verifique e tente novamente!" +ErrNodeUnbind: "O nó não está dentro do escopo de vinculação da licença, verifique e tente novamente!" +ErrNodeBind: "O nó já está vinculado a uma licença, verifique e tente novamente!" + +# alert +ErrAlertSync: "Erro na sincronização das informações de alerta, verifique e tente novamente!" + +#task +TaskStart: "{{.name}} tarefa iniciada [INICIADA]" +TaskEnd: "{{.name}} tarefa concluída [CONCLUÍDA]" +TaskFailed: "{{.name}} tarefa falhou" +TaskTimeout: "{{.name}} tempo esgotado" +TaskSuccess: "{{.name}} tarefa bem-sucedida" +TaskRetry: "Iniciando a {{.name}}ª tentativa" +SubTaskSuccess: "{{ .name }} sucesso" +SubTaskFailed: "{{ .name }} falhou: {{ .err }}" +TaskInstall: "Instalar" +TaskUninstall: "Desinstalar" +TaskCreate: "Criar" +TaskDelete: "Excluir" +TaskUpgrade: "Atualizar" +TaskUpdate: "Atualizar" +TaskRestart: "Reiniciar" +TaskRollback: "Reverter" +SuccessStatus: "{{ .name }} sucesso" +FailedStatus: "{{ .name }} falhou {{.err}}" +PullImage: "Baixar imagem" +Start: "Iniciar" +Run: "Executar" +Stop: "Parar" +SubTask: "Subtarefa" + +#upgrade node +NodeUpgrade: "Atualizar nó {name}" +NewSSHClient: "Inicializando conexão SSH" +BackupBeforeUpgrade: "Fazendo backup antes da atualização" +UploadUpgradeFile: "Enviando arquivos necessários para a atualização" +RestartAfterUpgrade: "Reiniciando o serviço após a atualização" + +#add node +TaskAddNode: "Adicionar nó" +SyncAgentBaseInfo: "Sincronizando dados básicos do nó" +GenerateSSLInfo: "Gerando informações SSL do nó" +ConnInfoNotMatch: "As informações de conexão não coincidem" +MakeAgentPackage: "Gerando pacote de instalação do nó" +SendAgent: "Enviando pacote de instalação do nó" +StartService: "Iniciando serviço" + +#cmd +AppVersion: "Versão do aplicativo" +AppCommands: "Comandos relacionados ao aplicativo" +AppInit: "Inicializar aplicativo" +AppKeyVal: "Chave do aplicativo (somente suporta inglês)" +AppCreateFileErr: "Falha ao criar o arquivo {{ .name }} {{ .err }}" +AppCreateDirErr: "Falha ao criar a pasta {{ .name }} {{ .err }}" +AppMissKey: "Chave do aplicativo ausente, use -k para especificar" +AppMissVersion: "Versão do aplicativo ausente, use -v para especificar" +AppVersionExist: "A versão já existe!" +AppCreateSuccessful: "Criação bem-sucedida!" +AppWriteErr: "Falha ao escrever no arquivo {{ .name }} {{ .err }}" +SudoHelper: "Por favor, use {{ .cmd }} ou altere para o usuário root" +ListenIPCommands: "Trocar IP de escuta" +ListenIPv4: "Escutando em IPv4" +ListenIPv6: "Escutando em IPv6" +ListenChangeSuccessful: "Troca bem-sucedida! Agora escutando em {{ .value }}" +ResetCommands: "Redefinir informações do sistema" +ResetMFA: "Cancelar autenticação de dois fatores do 1Panel" +ResetHttps: "Cancelar login https do 1Panel" +ResetEntrance: "Cancelar entrada segura do 1Panel" +ResetIPs: "Cancelar restrições de IP autorizado do 1Panel" +ResetDomain: "Cancelar vinculação de domínio do 1Panel" +RestoreCommands: "Restaurar serviço e dados do 1Panel" +RestoreNoSuchFile: "Nenhum arquivo disponível para restauração" +RestoreStep1: "(1/5) Iniciando a restauração do serviço e dados do 1Panel a partir do diretório {{ .name }}..." +RestoreStep2: "(2/5) Restauração do binário do 1Panel bem-sucedida" +RestoreStep3: "(3/5) Restauração dos scripts do 1Panel bem-sucedida" +RestoreStep4: "(4/5) Restauração do serviço do 1Panel bem-sucedida" +RestoreStep5: "(5/5) Restauração dos dados do 1Panel bem-sucedida" +RestoreSuccessful: "Restauração bem-sucedida! Reiniciando o serviço, por favor, aguarde..." +UpdateCommands: "Atualizar informações do painel" +UpdateUser: "Atualizar usuário do painel" +UpdatePassword: "Atualizar senha do painel" +UpdatePort: "Atualizar porta do painel" +UpdateUserNull: "Erro: usuário do painel está vazio!" +UpdateUserBlank: "Erro: o usuário do painel contém espaços!" +UpdateUserFormat: "Erro: Formato de usuário do painel inválido! Apenas suporta inglês, chinês, números e _, comprimento de 3-30." +UpdateUserErr: "Erro: Falha ao atualizar o usuário do painel, {{ .err }}" +UpdateSuccessful: "Atualização bem-sucedida!" +UpdateUserResult: "Usuário do painel: {{ .name }}" +UpdatePasswordRead: "Erro: Falha ao ler as informações da senha do painel, {{ .err }}" +UpdatePasswordNull: "Erro: A senha do painel está vazia!" +UpdateUPasswordBlank: "Erro: A senha do painel contém espaços!" +UpdatePasswordFormat: "Erro: A senha do painel suporta apenas letras, números, caracteres especiais !@#$%*_,.?, comprimento de 8-30!" +UpdatePasswordLen: "Erro: Por favor, insira uma senha com mais de 6 caracteres!" +UpdatePasswordRe: "Confirmar senha:" +UpdatePasswordErr: "Erro: Falha ao atualizar a senha do painel, {{ .err }}" +UpdatePasswordSame: "Erro: As duas senhas não correspondem, por favor, verifique e tente novamente!" +UpdatePasswordResult: "Senha do painel: {{ .name }}" +UpdatePortFormat: "Erro: O número da porta deve estar entre 1 e 65535!" +UpdatePortUsed: "Erro: O número da porta já está em uso, por favor, verifique e tente novamente!" +UpdatePortErr: "Erro: Falha ao atualizar a porta do painel, {{ .err }}" +UpdatePortResult: "Porta do painel: {{ .name }}" +UpdatePortFirewallAdd: "Falha ao adicionar regra de porta ao firewall, {{ .err }}, por favor, adicione manualmente a porta {{ .name }} às regras do firewall." +UpdatePortFirewallDel: "Erro: Falha ao excluir a porta do firewall, {{ .err }}" +UpdatePortFirewallReload: "Falha ao recarregar o firewall, {{ .err }}, por favor, recarregue o firewall manualmente." +UserInfo: "Obter informações do painel" +UserInfoAddr: "Endereço do painel: " +UserInfoPassHelp: "Dica: Para alterar a senha, você pode executar o comando: " +DBConnErr: "Erro: Falha ao inicializar a conexão com o banco de dados, {{ .err }}" +SystemVersion: "versão: " +SystemMode: "modo: " \ No newline at end of file diff --git a/core/i18n/lang/pt.yaml b/core/i18n/lang/pt.yaml new file mode 100644 index 000000000..4527246a3 --- /dev/null +++ b/core/i18n/lang/pt.yaml @@ -0,0 +1,157 @@ +ErrInvalidParams: "Erro nos parâmetros da solicitação: {{ .detail }}" +ErrTokenParse: "Erro na geração do token: {{ .detail }}" +ErrInitialPassword: "Senha original incorreta" +ErrInternalServer: "Erro interno no servidor: {{ .detail }}" +ErrRecordExist: "O registro já existe" +ErrRecordNotFound: "Registro não encontrado" +ErrStructTransform: "Falha na conversão de tipo: {{ .detail }}" +ErrNotLogin: "Usuário não está logado: {{ .detail }}" +ErrPasswordExpired: "A senha atual expirou: {{ .detail }}" +ErrNotSupportType: "O sistema não suporta o tipo atual: {{ .detail }}" +ErrProxy: "Erro na solicitação, verifique o estado do nó: {{ .detail }}" +ErrApiConfigStatusInvalid: "Acesso à API bloqueado: {{ .detail }}" +ErrApiConfigKeyInvalid: "Chave da API inválida: {{ .detail }}" +ErrApiConfigIPInvalid: "O IP da API não está na lista branca: {{ .detail }}" +ErrApiConfigDisable: "Esta API não pode ser chamada: {{ .detail }}" +ErrApiConfigKeyTimeInvalid: "Erro no timestamp da API: {{ .detail }}" + +#common +ErrDemoEnvironment: "Servidor de demonstração, esta operação é proibida!" +ErrCmdTimeout: "Tempo limite de execução do comando!" +ErrEntrance: "Erro nas informações de entrada de segurança, verifique e tente novamente!" +ErrGroupIsDefault: 'Grupo padrão, não é possível excluir' +ErrLocalDelete: "Não é possível excluir o nó local!" + +#backup +ErrBackupInUsed: "A conta de backup já está em uso em uma tarefa agendada, não é possível excluir" +ErrBackupCheck: "Falha na conexão de teste da conta de backup {{ .err}}" +ErrBackupLocal: "A conta de backup do servidor local não suporta essa operação!" +ErrBackupPublic: "Detectamos que a conta de backup não é pública, verifique e tente novamente!" +ErrOSSConn: "Não foi possível obter a versão mais recente, verifique se o servidor pode se conectar à rede externa." +ErrEntrance: "Erro nas informações de entrada de segurança, verifique e tente novamente!" + +#license +ErrLicense: "Erro no formato da licença, verifique e tente novamente!" +ErrLicenseCheck: "Falha na verificação da licença, verifique e tente novamente!" +ErrXpackVersion: "Falha na verificação da licença, a licença está restrita por versão e não pode ser importada com sucesso, verifique e tente novamente!" +ErrLicenseSave: "Falha ao salvar as informações da licença, erro {{ .err }}, tente novamente!" +ErrLicenseSync: "Falha na sincronização das informações da licença, não foram detectadas informações de licença no banco de dados!" +ErrXpackNotFound: "Esta parte é um recurso da versão profissional, primeiro importe a licença na tela de Configuração do Painel - Licença" +ErrXpackExceptional: "Esta parte é um recurso da versão profissional, primeiro sincronize o status da licença na tela de Configuração do Painel - Licença" +ErrXpackOutOfDate: "A licença atual expirou, reimporte a licença na tela de Configuração do Painel - Licença" +ErrXpackLost: "A licença atingiu o número máximo de tentativas, vá para a página [Configuração do Painel][Licença] e clique manualmente no botão de sincronização para garantir o uso normal dos recursos da versão profissional" +ErrXpackTimeout: "Tempo de solicitação esgotado, a conexão de rede pode estar instável, tente novamente mais tarde!" +ErrUnbindMaster: "Foi detectado um nó no gerenciamento de nós, não é possível desvincular a licença atual, remova o nó primeiro e tente novamente!" +ErrFreeNodeLimit: "O número de nós da versão comunitária atingiu o limite gratuito, acesse www.lxware.cn/1panel para comprar e tente novamente!" +ErrNodeBound: "A licença já está vinculada a outro nó, verifique e tente novamente!" +ErrNoSuchNode: "Não foi possível encontrar as informações do nó, verifique e tente novamente!" +ErrNodeUnbind: "O nó não está dentro do escopo de vinculação da licença, verifique e tente novamente!" +ErrNodeBind: "O nó já está vinculado a uma licença, verifique e tente novamente!" + +# alert +ErrAlertSync: "Erro na sincronização das informações de alerta, verifique e tente novamente!" + +#task +TaskStart: "{{.name}} tarefa iniciada [INICIADA]" +TaskEnd: "{{.name}} tarefa concluída [CONCLUÍDA]" +TaskFailed: "{{.name}} tarefa falhou" +TaskTimeout: "{{.name}} tempo esgotado" +TaskSuccess: "{{.name}} tarefa bem-sucedida" +TaskRetry: "Iniciando a {{.name}}ª tentativa" +SubTaskSuccess: "{{ .name }} sucesso" +SubTaskFailed: "{{ .name }} falhou: {{ .err }}" +TaskInstall: "Instalar" +TaskUninstall: "Desinstalar" +TaskCreate: "Criar" +TaskDelete: "Excluir" +TaskUpgrade: "Atualizar" +TaskUpdate: "Atualizar" +TaskRestart: "Reiniciar" +TaskRollback: "Reverter" +SuccessStatus: "{{ .name }} sucesso" +FailedStatus: "{{ .name }} falhou {{.err}}" +PullImage: "Baixar imagem" +Start: "Iniciar" +Run: "Executar" +Stop: "Parar" +SubTask: "Subtarefa" + +#upgrade node +NodeUpgrade: "Atualizar nó {name}" +NewSSHClient: "Inicializando conexão SSH" +BackupBeforeUpgrade: "Fazendo backup antes da atualização" +UploadUpgradeFile: "Enviando arquivos necessários para a atualização" +RestartAfterUpgrade: "Reiniciando o serviço após a atualização" + +#add node +TaskAddNode: "Adicionar nó" +SyncAgentBaseInfo: "Sincronizando dados básicos do nó" +GenerateSSLInfo: "Gerando informações SSL do nó" +ConnInfoNotMatch: "As informações de conexão não coincidem" +MakeAgentPackage: "Gerando pacote de instalação do nó" +SendAgent: "Enviando pacote de instalação do nó" +StartService: "Iniciando serviço" + +#cmd +AppVersion: "Versão do aplicativo" +AppCommands: "Comandos relacionados ao aplicativo" +AppInit: "Inicializar aplicativo" +AppKeyVal: "Chave do aplicativo (suporta apenas inglês)" +AppCreateFileErr: "Falha na criação do arquivo {{ .name }} {{ .err }}" +AppCreateDirErr: "Falha na criação da pasta {{ .name }} {{ .err }}" +AppMissKey: "Chave do aplicativo ausente, use -k para especificar" +AppMissVersion: "Versão do aplicativo ausente, use -v para especificar" +AppVersionExist: "Versão já existente!" +AppCreateSuccessful: "Criação bem-sucedida!" +AppWriteErr: "Falha na gravação do arquivo {{ .name }} {{ .err }}" +SudoHelper: "Por favor, use {{ .cmd }} ou troque para o usuário root" +ListenIPCommands: "Alterar IP de escuta" +ListenIPv4: "Escutar no IPv4" +ListenIPv6: "Escutar no IPv6" +ListenChangeSuccessful: "Alteração bem-sucedida! Agora escutando em {{ .value }}" +ResetCommands: "Redefinir informações do sistema" +ResetMFA: "Cancelar autenticação de dois fatores do 1Panel" +ResetHttps: "Cancelar login HTTPS do 1Panel" +ResetEntrance: "Cancelar entrada segura do 1Panel" +ResetIPs: "Cancelar restrições de IP autorizados do 1Panel" +ResetDomain: "Cancelar vinculação de domínio do 1Panel" +RestoreCommands: "Restaurar serviço e dados do 1Panel" +RestoreNoSuchFile: "Nenhum arquivo disponível para restauração" +RestoreStep1: "(1/5) Iniciando a restauração do serviço e dados do 1Panel a partir do diretório {{ .name }}..." +RestoreStep2: "(2/5) Restauração do binário do 1Panel bem-sucedida" +RestoreStep3: "(3/5) Restauração do script do 1Panel bem-sucedida" +RestoreStep4: "(4/5) Restauração do serviço do 1Panel bem-sucedida" +RestoreStep5: "(5/5) Restauração dos dados do 1Panel bem-sucedida" +RestoreSuccessful: "Restauração bem-sucedida! Reiniciando o serviço, aguarde..." +UpdateCommands: "Atualizar informações do painel" +UpdateUser: "Atualizar usuário do painel" +UpdatePassword: "Atualizar senha do painel" +UpdatePort: "Atualizar porta do painel" +UpdateUserNull: "Erro: usuário do painel está vazio!" +UpdateUserBlank: "Erro: usuário do painel contém espaços!" +UpdateUserFormat: "Erro: Formato de usuário inválido! Aceita apenas inglês, chinês, números e _, comprimento de 3-30" +UpdateUserErr: "Erro: Falha ao atualizar usuário do painel, {{ .err }}" +UpdateSuccessful: "Atualização bem-sucedida!" +UpdateUserResult: "Usuário do painel: {{ .name }}" +UpdatePasswordRead: "Erro: Falha ao ler informações da senha do painel, {{ .err }}" +UpdatePasswordNull: "Erro: Senha do painel está vazia!" +UpdateUPasswordBlank: "Erro: Senha do painel contém espaços!" +UpdatePasswordFormat: "Erro: A senha do painel aceita apenas letras, números, caracteres especiais !@#$%*_,.?, comprimento de 8-30!" +UpdatePasswordLen: "Erro: Por favor, insira uma senha com mais de 6 caracteres!" +UpdatePasswordRe: "Confirmar senha:" +UpdatePasswordErr: "Erro: Falha ao atualizar senha do painel, {{ .err }}" +UpdatePasswordSame: "Erro: As duas senhas não coincidem, por favor, verifique e tente novamente!" +UpdatePasswordResult: "Senha do painel: {{ .name }}" +UpdatePortFormat: "Erro: O número da porta deve estar entre 1 e 65535!" +UpdatePortUsed: "Erro: O número da porta já está em uso, por favor, verifique e tente novamente!" +UpdatePortErr: "Erro: Falha ao atualizar a porta do painel, {{ .err }}" +UpdatePortResult: "Porta do painel: {{ .name }}" +UpdatePortFirewallAdd: "Falha ao adicionar regra de porta no firewall, {{ .err }}, adicione manualmente a porta {{ .name }} às regras do firewall." +UpdatePortFirewallDel: "Erro: Falha ao excluir porta do firewall, {{ .err }}" +UpdatePortFirewallReload: "Falha ao recarregar o firewall, {{ .err }}, recarregue o firewall manualmente." +UserInfo: "Obter informações do painel" +UserInfoAddr: "Endereço do painel: " +UserInfoPassHelp: "Dica: Para alterar a senha, execute o comando: " +DBConnErr: "Erro: Falha ao inicializar conexão com o banco de dados, {{ .err }}" +SystemVersion: "versão: " +SystemMode: "modo: " \ No newline at end of file diff --git a/core/i18n/lang/ru.yaml b/core/i18n/lang/ru.yaml new file mode 100644 index 000000000..f3d0c639e --- /dev/null +++ b/core/i18n/lang/ru.yaml @@ -0,0 +1,286 @@ +ErrInvalidParams: "Ошибка параметра запроса: {{ .detail }}" +ErrTokenParse: "Ошибка генерации токена: {{ .detail }}" +ErrInitialPassword: "Ошибка исходного пароля" +ErrInternalServer: "Внутренняя ошибка сервиса: {{ .detail }}" +ErrRecordExist: "Запись уже существует" +ErrRecordNotFound: "Записи не найдены" +ErrStructTransform: "Ошибка преобразования типа: {{ .detail }}" +ErrNotLogin: "Пользователь не вошел в систему: {{ .detail }}" +ErrPasswordExpired: "Текущий пароль истек: {{ .detail }}" +ErrNotSupportType: "Система не поддерживает текущий тип: {{ .detail }}" +ErrApiConfigStatusInvalid: "Доступ к API интерфейсу запрещен: {{ .detail }}" +ErrApiConfigKeyInvalid: "Ошибка ключа API интерфейса: {{ .detail }}" +ErrApiConfigIPInvalid: "IP API интерфейса отсутствует в белом списке: {{ .detail }}" +ErrApiConfigDisable: "Этот интерфейс запрещает использование вызовов API интерфейса: {{ .detail }}" +ErrApiConfigKeyTimeInvalid: "Ошибка временной метки интерфейса API: {{ .detail }}" + +#common +ErrNameIsExist: "Имя уже существует" +ErrDemoEnvironment: "Демо-сервер, операция запрещена!" +ErrCmdTimeout: "Время выполнения команды истекло!" +ErrCmdIllegal: "Команда содержит недопустимые символы. Пожалуйста, измените и попробуйте снова!" +ErrPortExist: "{{ .port }} порт уже занят {{ .type }} [{{ .name }}]" +TYPE_APP: "Приложение" +TYPE_RUNTIME: "Среда выполнения" +TYPE_DOMAIN: "Доменное имя" +ErrTypePort: "Ошибка формата порта {{ .name }}" +ErrTypePortRange: "Диапазон портов должен быть между 1-65535" +Success: "Успех" +Failed: "Неудача" +SystemRestart: "Перезагрузка системы приводит к прерыванию задачи" + +#app +ErrPortInUsed: "Порт {{ .detail }} уже используется" +ErrAppLimit: "Превышен лимит установки приложения" +ErrAppRequired: "Требуется приложение {{ .detail }}" +ErrNotInstall: "Приложение не установлено" +ErrPortInOtherApp: "Порт {{ .port }} уже используется приложением {{ .apps }}" +ErrDbUserNotValid: "База данных акций, имя пользователя и пароль не совпадают!" +ErrDockerComposeNotValid: "Ошибка формата файла docker-compose!" +ErrUpdateBuWebsite: "Приложение успешно обновлено, но изменение конфигурационного файла веб-сайта не удалось, пожалуйста, проверьте конфигурацию!" +Err1PanelNetworkFailed: "Не удалось создать сеть контейнера по умолчанию! {{ .detail }}" +ErrFileParse: "Не удалось разобрать файл docker-compose приложения!" +ErrInstallDirNotFound: "Директория установки не существует" +AppStoreIsUpToDate: "Обновлено" +LocalAppVersionNull: "Приложение {{.name}} не синхронизировано с версией! Невозможно добавить в список приложений" +LocalAppVersionErr: "{{.name}} не удалось синхронизировать версию {{.version}}! {{.err}}" +ErrFileNotFound: "Файл {{.name}} не существует" +ErrFileParseApp: "Не удалось проанализировать файл {{.name}} {{.err}}" +ErrAppDirNull: "Папка версии не существует" +LocalAppErr: "Синхронизация приложения {{.name}} не удалась! {{.err}}" +ErrContainerName: "Имя контейнера уже существует" +ErrAppSystemRestart: "Перезапуск 1Panel приводит к завершению задачи" +ErrCreateHttpClient: "Не удалось создать HTTP-запрос {{.err}}" +ErrHttpReqTimeOut: "Превышено время ожидания запроса {{.err}}" +ErrHttpReqFailed: "Запрос не выполнен {{.err}}" +ErrHttpReqNotFound: "Файл не существует" +ErrNoSuchHost: "Сбой сетевого подключения" +ErrImagePullTimeOut: "Тайм-аут загрузки образа" +ErrContainerNotFound: "Контейнер {{ .name }} не существует" +ErrContainerMsg: "Контейнер {{ .name }} работает ненормально, пожалуйста, проверьте журнал на странице контейнера для подробностей" +ErrAppBackup: "Резервное копирование приложения {{ .name }} не удалось, ошибка {{.err}}" +ErrImagePull: "Не удалось загрузить образ {{ .name }}, ошибка {{.err}}" +ErrVersionTooLow: "Текущая версия 1Panel слишком стара для обновления магазина приложений, пожалуйста, обновите версию" +ErrAppNameExist: "Имя приложения уже существует" +AppStoreIsSyncing: "Магазин приложений синхронизируется, пожалуйста, попробуйте позже" +ErrGetCompose: "Не удалось получить файл docker-compose.yml! {{ .detail }}" +ErrAppWarn: "Аномальный статус, пbожалуйста, проверьте журнал" +ErrAppParamKey: "Исключение в поле параметра {{ .name }}" +ErrAppUpgrade: "Не удалось обновить приложение {{ .name }} {{ .err }}" +AppRecover: "Приложение {{ .name }} откатилось " +PullImageStart: "Начало загрузки образа {{ .name }}" +PullImageSuccess: "Образ успешно загружен" +UpgradeAppStart: "Начало обновления приложения {{ .name }}" +UpgradeAppSuccess: "Приложение {{ .name }} успешно обновлено" + +#file +ErrFileCanNotRead: "Файл недоступен для чтения" +ErrFileToLarge: "Файл слишком большой" +ErrPathNotFound: "Путь не найден" +ErrMovePathFailed: "Целевой путь не может содержать исходный путь!" +ErrLinkPathNotFound: "Целевой путь не существует!" +ErrFileIsExist: "Файл или каталог уже существует!" +ErrFileUpload: "Не удалось загрузить файл {{.name}} {{.detail}}" +ErrFileDownloadDir: "Скачивание папки не поддерживается" +ErrCmdNotFound: "Команда {{ .name}} не существует, пожалуйста, сначала установите эту команду на хосте" +ErrSourcePathNotFound: "Исходный каталог не существует" +ErrFavoriteExist: "Этот путь уже в избранном" +ErrInvalidChar: "Недопустимые символы запрещены" +ErrPathNotDelete: "Выбранный каталог не может быть удален" + +#website +ErrDomainIsExist: "Доменное имя уже существует" +ErrAliasIsExist: "Псевдоним уже существует" +ErrAppDelete: "Другой веб-сайт использует это приложение" +ErrGroupIsUsed: "Группа используется и не может быть удалена" +ErrBackupMatch: "файл резервной копии не соответствует текущим данным части сайта: {{ .detail}}" +ErrBackupExist: "файл резервной копии соответствует части исходных данных, которая не существует: {{ .detail}}" +ErrPHPResource: "Локальная среда выполнения не поддерживает переключение!" +ErrPathPermission: "Обнаружена папка с правами доступа не 1000:1000 в каталоге индекса, что может вызвать ошибку отказа в доступе при доступе к веб-сайту. Пожалуйста, нажмите кнопку сохранения выше" +ErrDomainIsUsed: "Домен уже используется веб-сайтом {{ .name }}" +ErrDomainFormat: "Ошибка формата домена {{ .name }}" +ErrDefaultAlias: "default — зарезервированное кодовое имя, пожалуйста, используйте другое кодовое имя" +ErrImageNotExist: "Образ рабочей среды {{.name}} не существует, пожалуйста, перенастройте рабочую среду" + +#ssl +ErrSSLCannotDelete: "Сертификат {{ .name }} используется веб-сайтом и не может быть удален" +ErrAccountCannotDelete: "Сертификат, связанный с учетной записью, не может быть удален" +ErrSSLApply: "Сертификат продолжает успешно подписываться, но перезагрузка openresty не удалась, пожалуйста, проверьте конфигурацию!" +ErrEmailIsExist: "Электронная почта уже существует" +ErrSSLKeyNotFound: "Файл закрытого ключа не существует" +ErrSSLCertificateNotFound: "Файл сертификата не существует" +ErrSSLKeyFormat: "Ошибка проверки файла закрытого ключа" +ErrSSLCertificateFormat: "Ошибка формата файла сертификата, пожалуйста, используйте формат pem" +ErrEabKidOrEabHmacKeyCannotBlank: "EabKid или EabHmacKey не могут быть пустыми" +ErrOpenrestyNotFound: "Режим HTTP требует предварительной установки Openresty" +ApplySSLStart: "Начать подачу заявки на сертификат, доменное имя [{{ .domain }}] метод подачи заявки [{{ .type }}] " +dnsAccount: "Автоматический DNS" +dnsManual: "Ручной DNS" +http: "HTTP" +ApplySSLFailed: "Заявка на сертификат для [{{ .domain }}] не удалась, {{.detail}} " +ApplySSLSuccess: "Заявка на сертификат для [{{ .domain }}] успешна! " +DNSAccountName: "Учетная запись DNS [{{ .name }}] производитель [{{.type}}]" +PushDirLog: "Сертификат отправлен в каталог [{{ .path }}] {{ .status }}" +ErrDeleteCAWithSSL: "Существует выданный сертификат под текущей организацией, удаление невозможно" +ErrDeleteWithPanelSSL: "Конфигурация SSL панели использует этот сертификат и не может быть удален" +ErrDefaultCA: "Уполномоченный центр по умолчанию не может быть удален" +ApplyWebSiteSSLLog: "Начать обновление сертификата веб-сайта {{ .name }}" +ErrUpdateWebsiteSSL: "Не удалось обновить сертификат веб-сайта {{ .name }}: {{ .err }}" +ApplyWebSiteSSLSuccess: "Сертификат веб-сайта успешно обновлен" +ErrExecShell: "Не удалось выполнить скрипт {{ .err }}" +ExecShellStart: "Начать выполнение скрипта" +ExecShellSuccess: "Скрипт успешно выполнен" +StartUpdateSystemSSL: "Начать обновление системного сертификата" +UpdateSystemSSLSuccess: "Системный сертификат успешно обновлен" + +#mysql +ErrUserIsExist: "Текущий пользователь уже существует. Пожалуйста, введите нового пользователя" +ErrDatabaseIsExist: "Текущая база данных уже существует. Пожалуйста, введите новую базу данных" +ErrExecTimeOut: "Время выполнения SQL запроса истекло, пожалуйста, проверьте базу данных" +ErrRemoteExist: "Удаленная база данных с таким именем уже существует, пожалуйста, измените и попробуйте снова" +ErrLocalExist: "Локальная база данных с таким именем уже существует, пожалуйста, измените и попробуйте снова" + +#redis +ErrTypeOfRedis: "Тип восстановленного файла не соответствует текущему режиму сохранения. Измените тип файла и попробуйте снова" + +#container +ErrInUsed: "{{ .detail }} используется и не может быть удален" +ErrObjectInUsed: "Этот объект используется и не может быть удален" +ErrObjectBeDependent: "Этот образ зависит от других образов и не может быть удален" +ErrPortRules: "Количество портов не совпадает, пожалуйста, введите заново!" +ErrPgImagePull: "Тайм-аут загрузки образа. Пожалуйста, настройте ускорение загрузки образа или вручную загрузите образ postgres:16.0-alpine и попробуйте снова" + +#runtime +ErrDirNotFound: "Папка сборки не существует! Пожалуйста, проверьте целостность файла!" +ErrFileNotExist: "Файл {{ .detail }} не существует! Пожалуйста, проверьте целостность исходного файла!" +ErrImageBuildErr: "Не удалось создать образ" +ErrImageExist: "Образ уже существует!" +ErrDelWithWebsite: "Рабочая среда уже связана с веб-сайтом и не может быть удалена" +ErrRuntimeStart: "Не удалось запустить" +ErrPackageJsonNotFound: "Файл package.json не существует" +ErrScriptsNotFound: "Конфигурационный элемент scripts не найден в package.json" +ErrContainerNameNotFound: "Не удалось получить имя контейнера, пожалуйста, проверьте файл .env" +ErrNodeModulesNotFound: "Папка node_modules не существует! Пожалуйста, отредактируйте среду выполнения или дождитесь успешного запуска среды выполнения" + +#setting +ErrBackupInUsed: "Учетная запись резервного копирования уже используется в cronjob и не может быть удалена." +ErrBackupCheck: "Проверка подключения учетной записи резервного копирования не выполнена {{ .err}}" +ErrOSSConn: "Не удалось получить последнюю версию, пожалуйста, проверьте возможность подключения сервера к внешней сети." +ErrEntrance: "Информация о безопасном входе неверна. Пожалуйста, проверьте и попробуйте снова!" + +#tool +ErrConfigNotFound: "Конфигурационный файл не существует" +ErrConfigParse: "Ошибка формата конфигурационного файла" +ErrConfigIsNull: "Конфигурационный файл не может быть пустым" +ErrConfigDirNotFound: "Каталог выполнения не существует" +ErrConfigAlreadyExist: "Конфигурационный файл с таким именем уже существует" +ErrUserFindErr: "Не удалось найти пользователя {{ .name }} {{ .err }}" + +#ssh +ErrFirewallNone: "На системе не обнаружен сервис firewalld или ufw. Пожалуйста, проверьте и попробуйте снова!" +ErrFirewallBoth: "На системе обнаружены оба сервиса firewalld и ufw. Чтобы избежать конфликтов, удалите один и попробуйте снова!" + +#cronjob +ErrBashExecute: "Ошибка выполнения скрипта, пожалуйста, проверьте конкретную информацию в области вывода задачи." +ErrCutWebsiteLog: "Не удалось разрезать лог веб-сайта {{ .name }}, ошибка {{ .err }}" +CutWebsiteLogSuccess: "Лог веб-сайта {{ .name }} успешно разрезан, путь к резервной копии {{ .path }}" + +#toolbox +ErrNotExistUser: "Текущий пользователь не существует. Пожалуйста, измените и попробуйте снова!" +ErrBanAction: "Установка не выполнена, текущий сервис {{ .name }} недоступен, пожалуйста, проверьте и попробуйте снова!" +ErrClamdscanNotFound: "Команда clamdscan не обнаружена, пожалуйста, обратитесь к документации для установки!" + +#waf +ErrScope: "Изменение этой конфигурации не поддерживается" +ErrStateChange: "Не удалось изменить состояние" +ErrRuleExist: "Правило уже существует" +ErrRuleNotExist: "Правило не существует" +ErrParseIP: "Ошибка формата IP" +ErrDefaultIP: "default — зарезервированное имя, пожалуйста, измените на другое имя" +ErrGroupInUse: "IP-группа используется в черно/белом списке и не может быть удалена" +ErrGroupExist: "Имя IP-группы уже существует" +ErrIPRange: "Неверный диапазон IP" +ErrIPExist: "IP уже существует" + +#license +ErrLicense: "Ошибка формата лицензии, пожалуйста, проверьте и попробуйте снова!" +ErrLicenseCheck: "Проверка лицензии не выполнена, пожалуйста, проверьте и попробуйте снова!" +ErrXpackVersion: "Ошибка проверки лицензии, эта лицензия ограничена по версии и не может быть успешно импортирована. Пожалуйста, проверьте и попробуйте снова!" +ErrLicenseSave: "Не удалось сохранить информацию о лицензии, ошибка {{ .err }}, пожалуйста, попробуйте снова!" +ErrLicenseSync: "Не удалось синхронизировать информацию о лицензии, в базе данных не обнаружена информация о лицензии!" +ErrXpackNotFound: "Этот раздел является функцией профессионального издания, пожалуйста, сначала импортируйте лицензию в интерфейсе Настройки панели — Лицензия" +ErrXpackNotActive: "Этот раздел является функцией профессионального издания, пожалуйста, сначала синхронизируйте статус лицензии в интерфейсе Настройки панели — Лицензия" +ErrXpackOutOfDate: "Текущая лицензия истекла, пожалуйста, повторно импортируйте лицензию в интерфейсе Настройки панели — Лицензия" +ErrXpackLost: "Лицензия достигла максимального числа попыток повторной попытки. Пожалуйста, перейдите на страницу [Настройки] [Лицензия] и вручную нажмите кнопку синхронизации, чтобы обеспечить корректную работу функций профессиональной версии." +ErrXpackTimeout: "Превышено время ожидания запроса, возможно, нестабильное сетевое соединение, пожалуйста, повторите попытку позже!" + +#license +ErrAlert: "Ошибка формата информации об оповещении, пожалуйста, проверьте и попробуйте снова!" +ErrAlertPush: "Ошибка отправки оповещения, пожалуйста, проверьте и попробуйте снова!" +ErrAlertSave: "Ошибка сохранения оповещения, пожалуйста, проверьте и попробуйте снова!" +ErrAlertSync: "Ошибка синхронизации оповещения, пожалуйста, проверьте и попробуйте снова!" +ErrAlertRemote: "Ошибка удаленного оповещения, пожалуйста, проверьте и попробуйте снова!" + +#cmd +AppVersion: "Версия приложения" +AppCommands: "Команды, связанные с приложением" +AppInit: "Инициализировать приложение" +AppKeyVal: "Ключ приложения (поддерживает только английский)" +AppCreateFileErr: "Не удалось создать файл {{ .name }} {{ .err }}" +AppCreateDirErr: "Не удалось создать папку {{ .name }} {{ .err }}" +AppMissKey: "Отсутствует ключ приложения, используйте -k для указания" +AppMissVersion: "Отсутствует версия приложения, используйте -v для указания" +AppVersionExist: "Версия уже существует!" +AppCreateSuccessful: "Создание прошло успешно!" +AppWriteErr: "Ошибка записи файла {{ .name }} {{ .err }}" +SudoHelper: "Пожалуйста, используйте {{ .cmd }} или переключитесь на пользователя root" +ListenIPCommands: "Переключить IP прослушивания" +ListenIPv4: "Прослушивать IPv4" +ListenIPv6: "Прослушивать IPv6" +ListenChangeSuccessful: "Переключение успешно! Теперь прослушивается {{ .value }}" +ResetCommands: "Сбросить информацию системы" +ResetMFA: "Отменить двухфакторную аутентификацию 1Panel" +ResetHttps: "Отменить вход в 1Panel по https" +ResetEntrance: "Отменить безопасный вход в 1Panel" +ResetIPs: "Отменить авторизованные IP-ограничения 1Panel" +ResetDomain: "Отменить привязку домена 1Panel" +RestoreCommands: "Откатить сервис и данные 1Panel" +RestoreNoSuchFile: "Нет доступных файлов для отката" +RestoreStep1: "(1/5) Начало отката сервиса и данных 1Panel из каталога {{ .name }}..." +RestoreStep2: "(2/5) Откат бинарного файла 1Panel успешен" +RestoreStep3: "(3/5) Откат скрипта 1Panel успешен" +RestoreStep4: "(4/5) Откат сервиса 1Panel успешен" +RestoreStep5: "(5/5) Откат данных 1Panel успешен" +RestoreSuccessful: "Откат успешен! Перезапуск службы, пожалуйста, подождите..." +UpdateCommands: "Обновить информацию панели" +UpdateUser: "Обновить пользователя панели" +UpdatePassword: "Обновить пароль панели" +UpdatePort: "Обновить порт панели" +UpdateUserNull: "Ошибка: пользователь панели пуст!" +UpdateUserBlank: "Ошибка: пользователь панели содержит пробелы!" +UpdateUserFormat: "Ошибка: неверный формат пользователя панели! Поддерживаются только английский, китайский, цифры и , длина 3-30" +UpdateUserErr: "Ошибка: не удалось обновить пользователя панели, {{ .err }}" +UpdateSuccessful: "Обновление успешно!" +UpdateUserResult: "Пользователь панели: {{ .name }}" +UpdatePasswordRead: "Ошибка: не удалось прочитать информацию о пароле панели, {{ .err }}" +UpdatePasswordNull: "Ошибка: пароль панели пуст!" +UpdateUPasswordBlank: "Ошибка: пароль панели содержит пробелы!" +UpdatePasswordFormat: "Ошибка: пароль панели поддерживает только буквы, цифры, специальные символы !@#$%* ,., длина 8-30!" +UpdatePasswordLen: "Ошибка: Пожалуйста, введите пароль длиной более 6 символов!" +UpdatePasswordRe: "Подтвердите пароль:" +UpdatePasswordErr: "Ошибка: не удалось обновить пароль панели, {{ .err }}" +UpdatePasswordSame: "Ошибка: два пароля не совпадают, пожалуйста, проверьте и попробуйте снова!" +UpdatePasswordResult: "Пароль панели: {{ .name }}" +UpdatePortFormat: "Ошибка: введенный номер порта должен быть между 1 и 65535!" +UpdatePortUsed: "Ошибка: номер порта уже используется, пожалуйста, проверьте и попробуйте снова!" +UpdatePortErr: "Ошибка: не удалось обновить порт панели, {{ .err }}" +UpdatePortResult: "Порт панели: {{ .name }}" +UpdatePortFirewallAdd: "Не удалось добавить правило порта брандмауэра, {{ .err }}, пожалуйста, вручную добавьте порт {{ .name }} в правила брандмауэра." +UpdatePortFirewallDel: "Ошибка: не удалось удалить порт брандмауэра, {{ .err }}" +UpdatePortFirewallReload: "Не удалось перезагрузить брандмауэр, {{ .err }}, пожалуйста, вручную перезагрузите брандмауэр." +UserInfo: "Получить информацию панели" +UserInfoAddr: "Адрес панели: " +UserInfoPassHelp: "Подсказка: чтобы изменить пароль, вы можете выполнить команду: " +DBConnErr: "Ошибка: не удалось инициализировать подключение к базе данных, {{ .err }}" +SystemVersion: "версия: " +SystemMode: "режим: " diff --git a/core/i18n/lang/zh-Hant.yaml b/core/i18n/lang/zh-Hant.yaml index 521bd1aa7..78ebd58bb 100644 --- a/core/i18n/lang/zh-Hant.yaml +++ b/core/i18n/lang/zh-Hant.yaml @@ -1,48 +1,48 @@ ErrInvalidParams: "請求參數錯誤: {{ .detail }}" -ErrTokenParse: "Token 產生錯誤: {{ .detail }}" +ErrTokenParse: "Token 生成錯誤: {{ .detail }}" ErrInitialPassword: "原密碼錯誤" -ErrInternalServer: "伺服器內部錯誤: {{ .detail }}" +ErrInternalServer: "服務內部錯誤: {{ .detail }}" ErrRecordExist: "記錄已存在" -ErrRecordNotFound: "記錄未找到" -ErrTransform: "類型轉換失敗: {{ .detail }}" -ErrNotLogin: "用戶未登入: {{ .detail }}" +ErrRecordNotFound: "記錄未能找到" +ErrStructTransform: "類型轉換失敗: {{ .detail }}" +ErrNotLogin: "用戶未登錄: {{ .detail }}" ErrPasswordExpired: "當前密碼已過期: {{ .detail }}" ErrNotSupportType: "系統暫不支持當前類型: {{ .detail }}" ErrProxy: "請求錯誤,請檢查該節點狀態: {{ .detail }}" +ErrApiConfigStatusInvalid: "API 介面禁止訪問: {{ .detail }}" +ErrApiConfigKeyInvalid: "API 介面密鑰錯誤: {{ .detail }}" +ErrApiConfigIPInvalid: "調用 API 介面 IP 不在白名單: {{ .detail }}" +ErrApiConfigDisable: "此介面禁止使用 API 介面調用: {{ .detail }}" +ErrApiConfigKeyTimeInvalid: "API 介面時間戳錯誤: {{ .detail }}" #common -ErrNameIsExist: "名稱已存在" ErrDemoEnvironment: "演示伺服器,禁止此操作!" +ErrCmdTimeout: "命令執行超時!" ErrEntrance: "安全入口信息錯誤,請檢查後重試!" -ErrGroupIsUsed: "分組正在使用中,無法刪除" +ErrGroupIsDefault: '默認分組,無法刪除' ErrLocalDelete: "無法刪除本地節點!" -#app -ErrPortInUsed: "{{ .detail }} 端口已被佔用!" -ErrCreateHttpClient: "創建HTTP請求失敗 {{.err}}" -ErrHttpReqTimeOut: "請求超時 {{.err}}" -ErrHttpReqFailed: "請求失敗 {{.err}}" -ErrHttpReqNotFound: "文件不存在" -ErrNoSuchHost: "網路連接失敗" - #backup ErrBackupInUsed: "該備份帳號已在計劃任務中使用,無法刪除" -ErrBackupCheck: "備份帳號測試連接失敗 {{.err}}" +ErrBackupCheck: "備份帳號測試連接失敗 {{ .err}}" ErrBackupLocal: "本地伺服器備份帳號暫不支持該操作!" ErrBackupPublic: "檢測到該備份帳號為非公用,請檢查後重試!" +ErrOSSConn: "無法獲取最新版本,請確認伺服器是否能夠連接外部網絡。" +ErrEntrance: "安全入口信息錯誤,請檢查後重試!" #license ErrLicense: "許可證格式錯誤,請檢查後重試!" ErrLicenseCheck: "許可證校驗失敗,請檢查後重試!" -ErrLicenseSave: "許可證信息保存失敗,錯誤 {{ .err }}, 請重試!" -ErrLicenseSync: "許可證信息同步失敗,資料庫中未檢測到許可證信息!" +ErrXpackVersion: "許可證校驗失敗,該許可證受版本限制,無法成功導入,請檢查後重試!" +ErrLicenseSave: "許可證信息保存失敗,錯誤 {{ .err }},請重試!" +ErrLicenseSync: "許可證信息同步失敗,數據庫中未檢測到許可證信息!" ErrXpackNotFound: "該部分為專業版功能,請先在 面板設置-許可證 界面導入許可證" ErrXpackExceptional: "該部分為專業版功能,請先在 面板設置-許可證 界面同步許可證狀態" ErrXpackOutOfDate: "當前許可證已過期,請重新在 面板設置-許可證 界面導入許可證" -ErrXpackLost: "許可證已達到最大重試次數,請進入【面板設定】【許可證】頁面手動點擊同步按鈕,以確保專業版功能正常使用" +ErrXpackLost: "許可證已達到最大重試次數,請進入【面板設置】【許可證】頁面手動點擊同步按鈕,以確保專業版功能正常使用" ErrXpackTimeout: "請求超時,網絡連接可能不穩定,請稍後再試!" ErrUnbindMaster: "檢測到節點管理內存在節點,無法解綁當前許可證,請先移除後重試!" -ErrFreeNodeLimit: "社區版節點數量已達到免費上限,請前往 www.lxware.cn/1panel 購買後重試!" +ErrFreeNodeLimit: "社區版節點數量已達免費上限,請前往 www.lxware.cn/1panel 購買後重試!" ErrNodeBound: "該許可證已綁定到其他節點,請檢查後重試!" ErrNoSuchNode: "未能找到該節點信息,請檢查後重試!" ErrNodeUnbind: "檢測到該節點未在許可證綁定範圍內,請檢查後重試!" @@ -65,7 +65,7 @@ TaskUpgrade: "升級" TaskUpdate: "更新" TaskRestart: "重啟" TaskRollback: "回滾" -SuccessStatus: "{{ .name }} 成功" +SuccessStatus: "{{ .name }} 成功" FailedStatus: "{{ .name }} 失敗 {{.err}}" PullImage: "拉取鏡像" Start: "開始" @@ -73,18 +73,82 @@ Run: "啟動" Stop: "停止" SubTask: "子任務" -#node upgrade +#upgrade node NodeUpgrade: "升級節點 {name}" NewSSHClient: "初始化 SSH 連接" BackupBeforeUpgrade: "升級前備份數據" UploadUpgradeFile: "下發升級所需文件" RestartAfterUpgrade: "升級後啟動服務" -#node create +#add node TaskAddNode: "添加節點" SyncAgentBaseInfo: "同步節點基礎數據" GenerateSSLInfo: "生成節點 SSL 信息" -ConnInfoNotMatch: "連接信息不匹配"; +ConnInfoNotMatch: "連接信息不匹配" MakeAgentPackage: "生成節點安裝包" SendAgent: "下發節點安裝包" -StartService: "啟動服務" \ No newline at end of file +StartService: "啟動服務" + +#cmd +AppVersion: "應用版本" +AppCommands: "應用相關命令" +AppInit: "初始化應用" +AppKeyVal: "應用的 key(僅支援英文)" +AppCreateFileErr: "文件 {{ .name }} 建立失敗 {{ .err }}" +AppCreateDirErr: "資料夾 {{ .name }} 建立失敗 {{ .err }}" +AppMissKey: "應用的 key 缺失,使用 -k 指定" +AppMissVersion: "應用版本缺失,使用 -v 指定" +AppVersionExist: "版本已存在!" +AppCreateSuccessful: "建立成功!" +AppWriteErr: "文件 {{ .name }} 寫入失敗 {{ .err }}" +SudoHelper: "請使用 {{ .cmd }} 或者切換到 root 用戶" +ListenIPCommands: "切換監聽 IP" +ListenIPv4: "監聽 IPv4" +ListenIPv6: "監聽 IPv6" +ListenChangeSuccessful: "切換成功!已切換至監聽 {{ .value }}" +ResetCommands: "重置系統資訊" +ResetMFA: "取消 1Panel 兩步驗證" +ResetHttps: "取消 1Panel https 方式登錄" +ResetEntrance: "取消 1Panel 安全入口" +ResetIPs: "取消 1Panel 授權 IP 限制" +ResetDomain: "取消 1Panel 訪問域名綁定" +RestoreCommands: "回滾 1Panel 服務及數據" +RestoreNoSuchFile: "暫無可回滾文件" +RestoreStep1: "(1/5)開始從 {{ .name }} 目錄回滾 1Panel 服務及數據... " +RestoreStep2: "(2/5)1Panel 二進制回滾成功" +RestoreStep3: "(3/5)1Panel 腳本回滾成功" +RestoreStep4: "(4/5)1Panel 服務回滾成功" +RestoreStep5: "(5/5)1Panel 數據回滾成功" +RestoreSuccessful: "回滾成功!正在重啟服務,請稍候..." +UpdateCommands: "修改面板資訊" +UpdateUser: "修改面板用戶" +UpdatePassword: "修改面板密碼" +UpdatePort: "修改面板埠" +UpdateUserNull: "錯誤:輸入面板用戶為空!" +UpdateUserBlank: "錯誤:輸入面板用戶中包含空格字符!" +UpdateUserFormat: "錯誤:輸入面板用戶錯誤!僅支援英文、中文、數字和_,長度3-30" +UpdateUserErr: "錯誤:面板用戶修改失敗,{{ .err }}" +UpdateSuccessful: "修改成功!" +UpdateUserResult: "面板用戶:{{ .name }}" +UpdatePasswordRead: "錯誤:面板密碼資訊讀取錯誤,{{ .err }}" +UpdatePasswordNull: "錯誤:輸入面板密碼為空!" +UpdateUPasswordBlank: "錯誤:輸入面板密碼中包含空格字符!" +UpdatePasswordFormat: "錯誤:面板密碼僅支援字母、數字、特殊字符(!@#$%*_,.?),長度 8-30 位!" +UpdatePasswordLen: "錯誤:請輸入 6 位以上密碼!" +UpdatePasswordRe: "確認密碼:" +UpdatePasswordErr: "錯誤:面板密碼修改失敗,{{ .err }}" +UpdatePasswordSame: "錯誤:兩次密碼不匹配,請檢查後重試!" +UpdatePasswordResult: "面板密碼:{{ .name }}" +UpdatePortFormat: "錯誤:輸入的埠號必須在 1 到 65535 之間!" +UpdatePortUsed: "錯誤:該埠號正被佔用,請檢查後重試!" +UpdatePortErr: "錯誤:面板埠修改失敗,{{ .err }}" +UpdatePortResult: "面板埠:{{ .name }}" +UpdatePortFirewallAdd: "添加防火牆埠規則失敗,{{ .err }},請您手動將 {{ .name }} 埠添加至防火牆規則中。" +UpdatePortFirewallDel: "錯誤:防火牆埠刪除失敗,{{ .err }}" +UpdatePortFirewallReload: "防火牆重載失敗,{{ .err }},請您手動重載防火牆。" +UserInfo: "取得面板資訊" +UserInfoAddr: "面板地址:" +UserInfoPassHelp: "提示:修改密碼可執行命令:" +DBConnErr: "錯誤:初始化資料庫連接失敗,{{ .err }}" +SystemVersion: "版本:" +SystemMode: "模式:" diff --git a/core/i18n/lang/zh.yaml b/core/i18n/lang/zh.yaml index 70061ecb3..a57912a91 100644 --- a/core/i18n/lang/zh.yaml +++ b/core/i18n/lang/zh.yaml @@ -4,37 +4,36 @@ ErrInitialPassword: "原密码错误" ErrInternalServer: "服务内部错误: {{ .detail }}" ErrRecordExist: "记录已存在" ErrRecordNotFound: "记录未能找到" -ErrTransform: "类型转换失败: {{ .detail }}" +ErrStructTransform: "类型转换失败: {{ .detail }}" ErrNotLogin: "用户未登录: {{ .detail }}" ErrPasswordExpired: "当前密码已过期: {{ .detail }}" ErrNotSupportType: "系统暂不支持当前类型: {{ .detail }}" ErrProxy: "请求错误,请检查该节点状态: {{ .detail }}" +ErrApiConfigStatusInvalid: "API 接口禁止访问: {{ .detail }}" +ErrApiConfigKeyInvalid: "API 接口密钥错误: {{ .detail }}" +ErrApiConfigIPInvalid: "调用 API 接口 IP 不在白名单: {{ .detail }}" +ErrApiConfigDisable: "此接口禁止使用 API 接口调用: {{ .detail }}" +ErrApiConfigKeyTimeInvalid: "API 接口时间戳错误: {{ .detail }}" #common ErrDemoEnvironment: "演示服务器,禁止此操作!" ErrCmdTimeout: "命令执行超时!" ErrEntrance: "安全入口信息错误,请检查后重试!" ErrGroupIsDefault: '默认分组,无法删除' -ErrGroupIsUsed: "分组正在使用中,无法删除" ErrLocalDelete: "无法删除本地节点!" -#app -ErrPortInUsed: "{{ .detail }} 端口已被占用!" -ErrCreateHttpClient: "创建HTTP请求失败 {{.err}}" -ErrHttpReqTimeOut: "请求超时 {{.err}}" -ErrHttpReqFailed: "请求失败 {{.err}}" -ErrHttpReqNotFound: "文件不存在" -ErrNoSuchHost: "网络连接失败" - #backup ErrBackupInUsed: "该备份账号已在计划任务中使用,无法删除" ErrBackupCheck: "备份账号测试连接失败 {{ .err}}" ErrBackupLocal: "本地服务器备份账号暂不支持该操作!" ErrBackupPublic: "检测到该备份账号为非公用,请检查后重试!" +ErrOSSConn: "无法获取最新版本,请确认服务器是否能够连接外部网络。" +ErrEntrance: "安全入口信息错误,请检查后重试!" #license ErrLicense: "许可证格式错误,请检查后重试!" ErrLicenseCheck: "许可证校验失败,请检查后重试!" +ErrXpackVersion: "许可证校验失败,该许可证受版本限制,无法成功导入,请检查后重试!" ErrLicenseSave: "许可证信息保存失败,错误 {{ .err }},请重试!" ErrLicenseSync: "许可证信息同步失败,数据库中未检测到许可证信息!" ErrXpackNotFound: "该部分为专业版功能,请先在 面板设置-许可证 界面导入许可证" @@ -49,6 +48,9 @@ ErrNoSuchNode: "未能找到该节点信息,请检查后重试!" ErrNodeUnbind: "检测到该节点未在许可证绑定范围内,请检查后重试!" ErrNodeBind: "检测到该节点已绑定许可证,请检查后重试!" +# alert +ErrAlertSync: "告警信息同步错误,请检查后重试!" + #task TaskStart: "{{.name}} 任务开始 [START]" TaskEnd: "{{.name}} 任务结束 [COMPLETED]" @@ -88,4 +90,68 @@ GenerateSSLInfo: "生成节点 SSL 信息" ConnInfoNotMatch: "连接信息不匹配" MakeAgentPackage: "生成节点安装包" SendAgent: "下发节点安装包" -StartService: "启动服务" \ No newline at end of file +StartService: "启动服务" + +#cmd +AppVersion: "应用版本" +AppCommands: "应用相关命令" +AppInit: "初始化应用" +AppKeyVal: "应用的 key(仅支持英文)" +AppCreateFileErr: "文件 {{ .name }} 创建失败 {{ .err }}" +AppCreateDirErr: "文件夹 {{ .name }} 创建失败 {{ .err }}" +AppMissKey: "应用的 key 缺失,使用 -k 指定" +AppMissVersion: "应用版本缺失,使用 -v 指定" +AppVersionExist: "版本已存在!" +AppCreateSuccessful: "创建成功!" +AppWriteErr: "文件 {{ .name }} 写入失败 {{ .err }}" +SudoHelper: "请使用 {{ .cmd }} 或者切换到 root 用户" +ListenIPCommands: "切换监听 IP" +ListenIPv4: "监听 IPv4" +ListenIPv6: "监听 IPv6" +ListenChangeSuccessful: "切换成功!已切换至监听 {{ .value }}" +ResetCommands: "重置系统信息" +ResetMFA: "取消 1Panel 两步验证" +ResetHttps: "取消 1Panel https 方式登录" +ResetEntrance: "取消 1Panel 安全入口" +ResetIPs: "取消 1Panel 授权 IP 限制" +ResetDomain: "取消 1Panel 访问域名绑定" +RestoreCommands: "回滚 1Panel 服务及数据" +RestoreNoSuchFile: "暂无可回滚文件" +RestoreStep1: "(1/5)开始从 {{ .name }} 目录回滚 1Panel 服务及数据... " +RestoreStep2: "(2/5)1Panel 二进制回滚成功" +RestoreStep3: "(3/5)1Panel 脚本回滚成功" +RestoreStep4: "(4/5)1Panel 服务回滚成功" +RestoreStep5: "(5/5)1Panel 数据回滚成功" +RestoreSuccessful: "回滚成功!正在重启服务,请稍候..." +UpdateCommands: "修改面板信息" +UpdateUser: "修改面板用户" +UpdatePassword: "修改面板密码" +UpdatePort: "修改面板端口" +UpdateUserNull: "错误:输入面板用户为空!" +UpdateUserBlank: "错误:输入面板用户中包含空格字符!" +UpdateUserFormat: "错误:输入面板用户错误!仅支持英文、中文、数字和_,长度3-30" +UpdateUserErr: "错误:面板用户修改失败,{{ .err }}" +UpdateSuccessful: "修改成功!" +UpdateUserResult: "面板用户:{{ .name }}" +UpdatePasswordRead: "错误:面板密码信息读取错误,{{ .err }}" +UpdatePasswordNull: "错误:输入面板密码为空!" +UpdateUPasswordBlank: "错误:输入面板密码中包含空格字符!" +UpdatePasswordFormat: "错误:面板密码仅支持字母、数字、特殊字符(!@#$%*_,.?),长度 8-30 位!" +UpdatePasswordLen: "错误:请输入 6 位以上密码!" +UpdatePasswordRe: "确认密码:" +UpdatePasswordErr: "错误:面板密码修改失败,{{ .err }}" +UpdatePasswordSame: "错误:两次密码不匹配,请检查后重试!" +UpdatePasswordResult: "面板密码:{{ .name }}" +UpdatePortFormat: "错误:输入的端口号必须在 1 到 65535 之间!" +UpdatePortUsed: "错误:该端口号正被占用,请检查后重试!" +UpdatePortErr: "错误:面板端口修改失败,{{ .err }}" +UpdatePortResult: "面板端口:{{ .name }}" +UpdatePortFirewallAdd: "添加防火墙端口规则失败,{{ .err }},请您手动将 {{ .name }} 端口添加至防火墙规则中。" +UpdatePortFirewallDel: "错误:防火墙端口删除失败,{{ .err }}" +UpdatePortFirewallReload: "防火墙重载失败,{{ .err }},请您手动重载防火墙。" +UserInfo: "获取面板信息" +UserInfoAddr: "面板地址:" +UserInfoPassHelp: "提示:修改密码可执行命令:" +DBConnErr: "错误:初始化数据库连接失败,{{ .err }}" +SystemVersion: "版本:" +SystemMode: "模式:" \ No newline at end of file diff --git a/core/init/hook/hook.go b/core/init/hook/hook.go index 7c31fc5c5..d4ab6f4fc 100644 --- a/core/init/hook/hook.go +++ b/core/init/hook/hook.go @@ -4,6 +4,7 @@ import ( "strings" "github.com/1Panel-dev/1Panel/core/app/repo" + "github.com/1Panel-dev/1Panel/core/constant" "github.com/1Panel-dev/1Panel/core/global" "github.com/1Panel-dev/1Panel/core/utils/cmd" "github.com/1Panel-dev/1Panel/core/utils/common" @@ -22,6 +23,28 @@ func Init() { global.LOG.Errorf("load ipv6 status from setting failed, err: %v", err) } global.CONF.System.Ipv6 = ipv6Setting.Value + apiInterfaceStatusSetting, err := settingRepo.Get(repo.WithByKey("ApiInterfaceStatus")) + if err != nil { + global.LOG.Errorf("load service api interface from setting failed, err: %v", err) + } + global.CONF.System.ApiInterfaceStatus = apiInterfaceStatusSetting.Value + if apiInterfaceStatusSetting.Value == constant.StatusEnable { + apiKeySetting, err := settingRepo.Get(repo.WithByKey("ApiKey")) + if err != nil { + global.LOG.Errorf("load service api key from setting failed, err: %v", err) + } + global.CONF.System.ApiKey = apiKeySetting.Value + ipWhiteListSetting, err := settingRepo.Get(repo.WithByKey("IpWhiteList")) + if err != nil { + global.LOG.Errorf("load service ip white list from setting failed, err: %v", err) + } + global.CONF.System.IpWhiteList = ipWhiteListSetting.Value + apiKeyValidityTimeSetting, err := settingRepo.Get(repo.WithByKey("ApiKeyValidityTime")) + if err != nil { + global.LOG.Errorf("load service api key validity time from setting failed, err: %v", err) + } + global.CONF.System.ApiKeyValidityTime = apiKeyValidityTimeSetting.Value + } bindAddressSetting, err := settingRepo.Get(repo.WithByKey("BindAddress")) if err != nil { global.LOG.Errorf("load bind address from setting failed, err: %v", err) diff --git a/core/init/lang/lang.go b/core/init/lang/lang.go new file mode 100644 index 000000000..6e64ef49d --- /dev/null +++ b/core/init/lang/lang.go @@ -0,0 +1,134 @@ +package lang + +import ( + "fmt" + "os" + "path" + "sort" + "strings" + + "github.com/1Panel-dev/1Panel/core/global" + "github.com/1Panel-dev/1Panel/core/utils/cmd" + fileUtils "github.com/1Panel-dev/1Panel/core/utils/files" +) + +func Init() { + go initLang() +} + +func initLang() { + geoPath := path.Join(global.CONF.System.BaseDir, "1panel/geo/GeoIP.mmdb") + isLangExist := fileUtils.Stat("/usr/local/bin/lang/zh.sh") + isGeoExist := fileUtils.Stat(geoPath) + if isLangExist && isGeoExist { + return + } + upgradePath := path.Join(global.CONF.System.BaseDir, "1panel/tmp/upgrade") + tmpPath, err := loadRestorePath(upgradePath) + upgradeDir := path.Join(upgradePath, tmpPath, "downloads") + if err != nil || len(tmpPath) == 0 || !fileUtils.Stat(upgradeDir) { + if !isLangExist { + downloadLangFromRemote() + } + if !isGeoExist { + downloadGeoFromRemote(geoPath) + } + return + } + + files, _ := os.ReadDir(upgradeDir) + if len(files) == 0 { + tmpPath = "no such file" + } else { + for _, item := range files { + if item.IsDir() && strings.HasPrefix(item.Name(), "1panel-") { + tmpPath = path.Join(upgradePath, tmpPath, "downloads", item.Name()) + break + } + } + } + if tmpPath == "no such file" || !fileUtils.Stat(tmpPath) { + if !isLangExist { + downloadLangFromRemote() + } + if !isGeoExist { + downloadGeoFromRemote(geoPath) + } + return + } + if !isLangExist { + if !fileUtils.Stat(path.Join(tmpPath, "lang")) { + downloadLangFromRemote() + return + } + std, err := cmd.Execf("cp -r %s %s", path.Join(tmpPath, "lang"), "/usr/local/bin/") + if err != nil { + global.LOG.Errorf("load lang from package failed, std: %s, err: %v", std, err) + return + } + global.LOG.Info("init lang successful") + } + if !isGeoExist { + if !fileUtils.Stat(path.Join(tmpPath, "GeoIP.mmdb")) { + downloadGeoFromRemote(geoPath) + return + } + std, err := cmd.Execf("mkdir %s && cp %s %s/", path.Dir(geoPath), path.Join(tmpPath, "GeoIP.mmdb"), path.Dir(geoPath)) + if err != nil { + global.LOG.Errorf("load geo ip from package failed, std: %s, err: %v", std, err) + return + } + global.LOG.Info("init geo ip successful") + } +} + +func loadRestorePath(upgradeDir string) (string, error) { + if _, err := os.Stat(upgradeDir); err != nil && os.IsNotExist(err) { + return "no such file", nil + } + files, err := os.ReadDir(upgradeDir) + if err != nil { + return "", err + } + var folders []string + for _, file := range files { + if file.IsDir() { + folders = append(folders, file.Name()) + } + } + if len(folders) == 0 { + return "no such file", nil + } + sort.Slice(folders, func(i, j int) bool { + return folders[i] > folders[j] + }) + return folders[0], nil +} + +func downloadLangFromRemote() { + path := fmt.Sprintf("%s/language/lang.tar.gz", global.CONF.System.RepoUrl) + if err := fileUtils.DownloadFile(path, "/usr/local/bin/lang.tar.gz"); err != nil { + global.LOG.Errorf("download lang.tar.gz failed, err: %v", err) + return + } + if !fileUtils.Stat("/usr/local/bin/lang.tar.gz") { + global.LOG.Error("download lang.tar.gz failed, no such file") + return + } + std, err := cmd.Execf("tar zxvfC %s %s", "/usr/local/bin/lang.tar.gz", "/usr/local/bin/") + if err != nil { + fmt.Printf("decompress lang.tar.gz failed, std: %s, err: %v", std, err) + return + } + _ = os.Remove("/usr/local/bin/lang.tar.gz") + global.LOG.Info("download lang successful") +} +func downloadGeoFromRemote(targetPath string) { + _ = os.MkdirAll(path.Dir(targetPath), os.ModePerm) + pathItem := fmt.Sprintf("%s/geo/GeoIP.mmdb", global.CONF.System.RepoUrl) + if err := fileUtils.DownloadFile(pathItem, targetPath); err != nil { + global.LOG.Errorf("download geo ip failed, err: %v", err) + return + } + global.LOG.Info("download geo ip successful") +} diff --git a/core/init/migration/migrations/init.go b/core/init/migration/migrations/init.go index 7e7d0ce7e..5067e9448 100644 --- a/core/init/migration/migrations/init.go +++ b/core/init/migration/migrations/init.go @@ -39,6 +39,10 @@ var InitSetting = &gormigrate.Migration{ } global.CONF.System.EncryptKey = encryptKey pass, _ := encrypt.StringEncrypt(global.CONF.System.Password) + language := "en" + if global.CONF.System.Language == "zh" { + language = "zh" + } if err := tx.Create(&model.Setting{Key: "Password", Value: pass}).Error; err != nil { return err } @@ -51,7 +55,7 @@ var InitSetting = &gormigrate.Migration{ if err := tx.Create(&model.Setting{Key: "PanelName", Value: "1Panel"}).Error; err != nil { return err } - if err := tx.Create(&model.Setting{Key: "Language", Value: "zh"}).Error; err != nil { + if err := tx.Create(&model.Setting{Key: "Language", Value: language}).Error; err != nil { return err } if err := tx.Create(&model.Setting{Key: "SessionTimeout", Value: "86400"}).Error; err != nil { @@ -89,7 +93,8 @@ var InitSetting = &gormigrate.Migration{ if err := tx.Create(&model.Setting{Key: "PrsoxyPasswdKeep", Value: ""}).Error; err != nil { return err } - if err := tx.Create(&model.Setting{Key: "XpackHideMenu", Value: "{\"id\":\"1\",\"label\":\"/xpack\",\"isCheck\":true,\"title\":\"xpack.menu\",\"children\":[{\"id\":\"2\",\"title\":\"xpack.waf.name\",\"path\":\"/xpack/waf/dashboard\",\"label\":\"Dashboard\",\"isCheck\":true},{\"id\":\"3\",\"title\":\"xpack.tamper.tamper\",\"path\":\"/xpack/tamper\",\"label\":\"Tamper\",\"isCheck\":true},{\"id\":\"4\",\"title\":\"xpack.gpu.gpu\",\"path\":\"/xpack/gpu\",\"label\":\"GPU\",\"isCheck\":true},{\"id\":\"5\",\"title\":\"xpack.setting.setting\",\"path\":\"/xpack/setting\",\"label\":\"XSetting\",\"isCheck\":true},{\"id\":\"6\",\"title\":\"xpack.monitor.name\",\"path\":\"/xpack/monitor/dashboard\",\"label\":\"MonitorDashboard\",\"isCheck\":true},{\"id\":\"7\",\"title\":\"xpack.node.nodeManagement\",\"path\":\"/xpack/node\",\"label\":\"Node\",\"isCheck\":true}]}"}).Error; err != nil { + val := `{"id":"1","label":"/xpack","isCheck":true,"title":"xpack.menu","children":[{"id":"2","label":"Dashboard","isCheck":true,"title":"xpack.waf.name","path":"/xpack/waf/dashboard"},{"id":"3","label":"Tamper","isCheck":true,"title":"xpack.tamper.tamper","path":"/xpack/tamper"},{"id":"4","label":"GPU","isCheck":true,"title":"xpack.gpu.gpu","path":"/xpack/gpu"},{"id":"5","label":"XSetting","isCheck":true,"title":"xpack.setting.setting","path":"/xpack/setting"},{"id":"6","label":"MonitorDashboard","isCheck":true,"title":"xpack.monitor.name","path":"/xpack/monitor/dashboard"},{"id":"7","label":"XAlertDashboard","isCheck":true,"title":"xpack.alert.alert","path":"/xpack/alert/dashboard"},{"id":"8","label":"Node","isCheck":true,"title":"xpack.node.nodeManagement","path":"/xpack/node"}]}` + if err := tx.Create(&model.Setting{Key: "XpackHideMenu", Value: val}).Error; err != nil { return err } @@ -144,6 +149,18 @@ var InitSetting = &gormigrate.Migration{ if err := tx.Create(&model.Setting{Key: "NoAuthSetting", Value: "200"}).Error; err != nil { return err } + if err := tx.Create(&model.Setting{Key: "ApiInterfaceStatus", Value: "disable"}).Error; err != nil { + return err + } + if err := tx.Create(&model.Setting{Key: "ApiKey", Value: ""}).Error; err != nil { + return err + } + if err := tx.Create(&model.Setting{Key: "IpWhiteList", Value: ""}).Error; err != nil { + return err + } + if err := tx.Create(&model.Setting{Key: "ApiKeyValidityTime", Value: "120"}).Error; err != nil { + return err + } return nil }, } diff --git a/core/init/viper/viper.go b/core/init/viper/viper.go index ef33ec977..058b80d62 100644 --- a/core/init/viper/viper.go +++ b/core/init/viper/viper.go @@ -21,7 +21,7 @@ func Init() { port := "9999" mode := "" version := "v2.0.0" - username, password, entrance := "", "", "" + username, password, entrance, language := "", "", "", "zh" v := viper.NewWithOptions() v.SetConfigType("yaml") @@ -46,6 +46,7 @@ func Init() { username = loadParams("ORIGINAL_USERNAME") password = loadParams("ORIGINAL_PASSWORD") entrance = loadParams("ORIGINAL_ENTRANCE") + language = loadParams("LANGUAGE") reader := bytes.NewReader(conf.AppYaml) if err := v.ReadConfig(reader); err != nil { @@ -81,16 +82,21 @@ func Init() { if serverConfig.System.Entrance != "" { entrance = serverConfig.System.Entrance } + if serverConfig.System.IsIntl { + language = "en" + } } global.CONF = serverConfig global.CONF.System.BaseDir = baseDir global.CONF.System.IsDemo = v.GetBool("system.is_demo") + global.CONF.System.IsIntl = v.GetBool("system.is_intl") global.CONF.System.Port = port global.CONF.System.Version = version global.CONF.System.Username = username global.CONF.System.Password = password global.CONF.System.Entrance = entrance + global.CONF.System.Language = language global.CONF.System.ChangeUserInfo = loadChangeInfo() global.Viper = v } diff --git a/core/middleware/session.go b/core/middleware/session.go index f301d21e1..d2a72bd0c 100644 --- a/core/middleware/session.go +++ b/core/middleware/session.go @@ -1,8 +1,12 @@ package middleware import ( + "crypto/md5" + "encoding/hex" + "net" "strconv" "strings" + "time" "github.com/1Panel-dev/1Panel/core/app/api/v2/helper" "github.com/1Panel-dev/1Panel/core/app/repo" @@ -21,6 +25,33 @@ func SessionAuth() gin.HandlerFunc { c.Next() return } + + panelToken := c.GetHeader("1Panel-Token") + panelTimestamp := c.GetHeader("1Panel-Timestamp") + if panelToken != "" || panelTimestamp != "" { + if global.CONF.System.ApiInterfaceStatus == constant.StatusEnable { + clientIP := c.ClientIP() + if !isValid1PanelTimestamp(panelTimestamp) { + helper.ErrorWithDetail(c, constant.CodeErrUnauthorized, constant.ErrApiConfigKeyTimeInvalid, nil) + return + } + if !isValid1PanelToken(panelToken, panelTimestamp) { + helper.ErrorWithDetail(c, constant.CodeErrUnauthorized, constant.ErrApiConfigKeyInvalid, nil) + return + } + + if !isIPInWhiteList(clientIP) { + helper.ErrorWithDetail(c, constant.CodeErrUnauthorized, constant.ErrApiConfigIPInvalid, nil) + return + } + c.Next() + return + } else { + helper.ErrorWithDetail(c, constant.CodeErrUnauthorized, constant.ErrApiConfigStatusInvalid, nil) + return + } + } + psession, err := global.SESSION.Get(c) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrUnauthorized, constant.ErrTypeNotLogin, err) @@ -42,3 +73,52 @@ func SessionAuth() gin.HandlerFunc { c.Next() } } + +func isValid1PanelTimestamp(panelTimestamp string) bool { + apiKeyValidityTime := global.CONF.System.ApiKeyValidityTime + apiTime, err := strconv.Atoi(apiKeyValidityTime) + if err != nil { + return false + } + panelTime, err := strconv.ParseInt(panelTimestamp, 10, 64) + if err != nil { + return false + } + nowTime := time.Now().Unix() + if panelTime > nowTime { + return false + } + return apiTime == 0 || nowTime-panelTime <= int64(apiTime*60) +} + +func isValid1PanelToken(panelToken string, panelTimestamp string) bool { + system1PanelToken := global.CONF.System.ApiKey + return panelToken == GenerateMD5("1panel"+system1PanelToken+panelTimestamp) +} + +func isIPInWhiteList(clientIP string) bool { + ipWhiteString := global.CONF.System.IpWhiteList + ipWhiteList := strings.Split(ipWhiteString, "\n") + for _, cidr := range ipWhiteList { + if cidr == "0.0.0.0" { + return true + } + _, ipNet, err := net.ParseCIDR(cidr) + if err != nil { + if cidr == clientIP { + return true + } + continue + } + if ipNet.Contains(net.ParseIP(clientIP)) { + return true + } + } + return false +} + +func GenerateMD5(input string) string { + hash := md5.New() + hash.Write([]byte(input)) + return hex.EncodeToString(hash.Sum(nil)) +} diff --git a/core/router/ro_base.go b/core/router/ro_base.go index 1de636851..f106a3f4a 100644 --- a/core/router/ro_base.go +++ b/core/router/ro_base.go @@ -17,5 +17,6 @@ func (s *BaseRouter) InitRouter(Router *gin.RouterGroup) { baseRouter.POST("/logout", baseApi.LogOut) baseRouter.GET("/demo", baseApi.CheckIsDemo) baseRouter.GET("/language", baseApi.GetLanguage) + baseRouter.GET("/intl", baseApi.CheckIsIntl) } } diff --git a/core/router/ro_setting.go b/core/router/ro_setting.go index d3225d599..479f240e1 100644 --- a/core/router/ro_setting.go +++ b/core/router/ro_setting.go @@ -41,6 +41,8 @@ func (s *SettingRouter) InitRouter(Router *gin.RouterGroup) { settingRouter.POST("/upgrade", baseApi.Upgrade) settingRouter.POST("/upgrade/notes", baseApi.GetNotesByVersion) settingRouter.GET("/upgrade", baseApi.GetUpgradeInfo) + settingRouter.POST("/api/config/generate/key", baseApi.GenerateApiKey) + settingRouter.POST("/api/config/update", baseApi.UpdateApiConfig) noAuthRouter.POST("/ssl/reload", baseApi.ReloadSSL) } diff --git a/core/server/server.go b/core/server/server.go index d5db15f92..96be44198 100644 --- a/core/server/server.go +++ b/core/server/server.go @@ -15,6 +15,7 @@ import ( "github.com/1Panel-dev/1Panel/core/init/cron" "github.com/1Panel-dev/1Panel/core/init/db" "github.com/1Panel-dev/1Panel/core/init/hook" + "github.com/1Panel-dev/1Panel/core/init/lang" "github.com/1Panel-dev/1Panel/core/init/log" "github.com/1Panel-dev/1Panel/core/init/migration" "github.com/1Panel-dev/1Panel/core/init/router" @@ -33,6 +34,7 @@ func Start() { db.Init() migration.Init() validator.Init() + lang.Init() gob.Register(psession.SessionUser{}) cron.Init() session.Init() diff --git a/core/utils/files/files.go b/core/utils/files/files.go index af35c291e..3456c0d3b 100644 --- a/core/utils/files/files.go +++ b/core/utils/files/files.go @@ -145,6 +145,25 @@ func HandleUnTar(sourceFile, targetDir string, secret string) error { return nil } +func DownloadFile(url, dst string) error { + resp, err := httpUtil.GetHttpRes(url) + if err != nil { + return err + } + defer resp.Body.Close() + + out, err := os.Create(dst) + if err != nil { + return fmt.Errorf("create download file [%s] error, err %s", dst, err.Error()) + } + defer out.Close() + + if _, err = io.Copy(out, resp.Body); err != nil { + return fmt.Errorf("save download file [%s] error, err %s", dst, err.Error()) + } + return nil +} + func DownloadFileWithProxy(url, dst string) error { _, resp, err := httpUtil.HandleGet(url, http.MethodGet, constant.TimeOut5m) if err != nil { diff --git a/frontend/package.json b/frontend/package.json index 0d4de55c6..ee2a542d2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -35,7 +35,7 @@ "codemirror": "^6.0.1", "echarts": "^5.5.0", "element-plus": "^2.7.5", - "fit2cloud-ui-plus": "^1.1.7", + "fit2cloud-ui-plus": "^1.2.0", "highlight.js": "^11.9.0", "js-base64": "^3.7.7", "md-editor-v3": "^2.11.3", diff --git a/frontend/src/App.vue b/frontend/src/App.vue index a95d3595c..fbcd57517 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -10,6 +10,11 @@ import { GlobalStore } from '@/store'; import zhCn from 'element-plus/es/locale/lang/zh-cn'; import zhTw from 'element-plus/es/locale/lang/zh-tw'; import en from 'element-plus/es/locale/lang/en'; +import ja from 'element-plus/es/locale/lang/ja'; +import ms from 'element-plus/es/locale/lang/ms'; +import ptBR from 'element-plus/es/locale/lang/pt-br'; +import ru from 'element-plus/es/locale/lang/ru'; +import ko from 'element-plus/es/locale/lang/ko'; import { useTheme } from '@/global/use-theme'; useTheme(); @@ -22,6 +27,11 @@ const i18nLocale = computed(() => { if (globalStore.language === 'zh') return zhCn; if (globalStore.language === 'tw') return zhTw; if (globalStore.language === 'en') return en; + if (globalStore.language === 'ja') return ja; + if (globalStore.language === 'ms') return ms; + if (globalStore.language === 'ru') return ru; + if (globalStore.language === 'pt-br') return ptBR; + if (globalStore.language === 'ko') return ko; return zhCn; }); diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index 2cb084a5f..2765a3cd5 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -99,7 +99,7 @@ class RequestHttp { response.status, response.data && response.data['message'] ? response.data['message'] : '', ); - return; + return Promise.reject(error); default: globalStore.errStatus = 'code-' + response.status; router.push({ diff --git a/frontend/src/api/interface/cronjob.ts b/frontend/src/api/interface/cronjob.ts index 5da4b1749..21a218e72 100644 --- a/frontend/src/api/interface/cronjob.ts +++ b/frontend/src/api/interface/cronjob.ts @@ -34,6 +34,9 @@ export namespace Cronjob { retainCopies: number; status: string; secret: string; + hasAlert: boolean; + alertCount: number; + alertTitle: string; } export interface Item { val: string; diff --git a/frontend/src/api/interface/file.ts b/frontend/src/api/interface/file.ts index d99c1a602..ac8e7827b 100644 --- a/frontend/src/api/interface/file.ts +++ b/frontend/src/api/interface/file.ts @@ -11,7 +11,7 @@ export namespace File { size: number; isDir: boolean; isSymlink: boolean; - linkPath: boolean; + linkPath: string; type: string; updateTime: string; modTime: string; diff --git a/frontend/src/api/interface/setting.ts b/frontend/src/api/interface/setting.ts index 14d881298..fa3377253 100644 --- a/frontend/src/api/interface/setting.ts +++ b/frontend/src/api/interface/setting.ts @@ -57,6 +57,11 @@ export namespace Setting { proxyUser: string; proxyPasswd: string; proxyPasswdKeep: string; + + apiInterfaceStatus: string; + apiKey: string; + ipWhiteList: string; + apiKeyValidityTime: number; } export interface TerminalInfo { lineHeight: string; @@ -79,6 +84,12 @@ export namespace Setting { proxyPasswd: string; proxyPasswdKeep: string; } + export interface ApiConfig { + apiInterfaceStatus: string; + apiKey: string; + ipWhiteList: string; + apiKeyValidityTime: number; + } export interface SSLUpdate { ssl: string; domain: string; @@ -211,10 +222,14 @@ export namespace Setting { trial: boolean; status: string; message: string; + smsUsed: number; + smsTotal: number; } export interface LicenseStatus { productPro: string; status: string; + smsTotal: number; + smsUsed: number; } export interface NodeItem { id: number; diff --git a/frontend/src/api/interface/toolbox.ts b/frontend/src/api/interface/toolbox.ts index dd94a17ba..3d8535477 100644 --- a/frontend/src/api/interface/toolbox.ts +++ b/frontend/src/api/interface/toolbox.ts @@ -139,6 +139,9 @@ export namespace Toolbox { spec: string; specObj: Cronjob.SpecObj; description: string; + hasAlert: boolean; + alertCount: number; + alertTitle: string; } export interface ClamCreate { name: string; diff --git a/frontend/src/api/modules/auth.ts b/frontend/src/api/modules/auth.ts index 1c388dd1c..f3f3f7644 100644 --- a/frontend/src/api/modules/auth.ts +++ b/frontend/src/api/modules/auth.ts @@ -28,3 +28,7 @@ export const checkIsDemo = () => { export const getLanguage = () => { return http.get(`/core/auth/language`); }; + +export const checkIsIntl = () => { + return http.get('/core/auth/intl'); +}; diff --git a/frontend/src/api/modules/files.ts b/frontend/src/api/modules/files.ts index 4b958bd0b..0804604ab 100644 --- a/frontend/src/api/modules/files.ts +++ b/frontend/src/api/modules/files.ts @@ -74,7 +74,7 @@ export const WgetFile = (params: File.FileWget) => { }; export const MoveFile = (params: File.FileMove) => { - return http.post('files/move', params); + return http.post('files/move', params, TimeoutEnum.T_5M); }; export const DownloadFile = (params: File.FileDownload) => { diff --git a/frontend/src/api/modules/setting.ts b/frontend/src/api/modules/setting.ts index 6d7b18d2b..5cf33a883 100644 --- a/frontend/src/api/modules/setting.ts +++ b/frontend/src/api/modules/setting.ts @@ -150,3 +150,11 @@ export const loadReleaseNotes = (version: string) => { export const upgrade = (version: string) => { return http.post(`/core/settings/upgrade`, { version: version }); }; + +// api config +export const generateApiKey = () => { + return http.post(`/core/settings/api/config/generate/key`); +}; +export const updateApiConfig = (param: Setting.ApiConfig) => { + return http.post(`/core/settings/api/config/update`, param); +}; diff --git a/frontend/src/assets/images/menu-bg.svg b/frontend/src/assets/images/menu-bg.svg new file mode 100644 index 000000000..cf679075e --- /dev/null +++ b/frontend/src/assets/images/menu-bg.svg @@ -0,0 +1 @@ + diff --git a/frontend/src/components/file-list/index.vue b/frontend/src/components/file-list/index.vue index 34e8fbd0b..4866010b9 100644 --- a/frontend/src/components/file-list/index.vue +++ b/frontend/src/components/file-list/index.vue @@ -141,7 +141,7 @@ const data = ref([]); const loading = ref(false); const paths = ref([]); const req = reactive({ path: '/', expand: true, page: 1, pageSize: 300, showHidden: true }); -const selectRow = ref(); +const selectRow = ref({ path: '', name: '' }); const rowRefs = ref(); const popoverVisible = ref(false); const newFolder = ref(); @@ -183,12 +183,12 @@ const selectFile = () => { const closePage = () => { popoverVisible.value = false; - selectRow.value = {}; + selectRow.value = { path: '', name: '' }; }; const openPage = () => { popoverVisible.value = true; - selectRow.value = {}; + selectRow.value.path = props.dir ? props.path || '/' : ''; rowName.value = ''; }; @@ -216,7 +216,7 @@ const open = async (row: File.File) => { } await search(req); } - selectRow.value = {}; + selectRow.value.path = props.dir ? req.path : ''; rowName.value = ''; }; @@ -230,7 +230,7 @@ const jump = async (index: number) => { } path = path || '/'; req.path = path; - selectRow.value = {}; + selectRow.value.path = props.dir ? req.path : ''; rowName.value = ''; await search(req); popoverVisible.value = true; @@ -286,7 +286,7 @@ const cancelFolder = (row: any) => { data.value.shift(); row.isCreate = false; disBtn.value = false; - selectRow.value = {}; + selectRow.value.path = props.dir ? req.path : ''; rowName.value = ''; newFolder.value = ''; }; diff --git a/frontend/src/components/license-import/index.vue b/frontend/src/components/license-import/index.vue index bf5b74768..b9b30a0e8 100644 --- a/frontend/src/components/license-import/index.vue +++ b/frontend/src/components/license-import/index.vue @@ -33,7 +33,7 @@ {{ $t('license.power') }}
- {{ $t('license.knowMorePro') }} + {{ $t('license.knowMorePro') }}
@@ -48,7 +48,7 @@ import { UploadFileData } from '@/api/modules/setting'; import { GlobalStore } from '@/store'; import { UploadFile, UploadFiles, UploadInstance, UploadProps, UploadRawFile, genFileId } from 'element-plus'; import { useTheme } from '@/global/use-theme'; -import { getXpackSetting } from '@/utils/xpack'; +import { getXpackSetting, initFavicon } from '@/utils/xpack'; const globalStore = GlobalStore(); const { switchTheme } = useTheme(); @@ -73,8 +73,12 @@ const handleExceed: UploadProps['onExceed'] = (files) => { uploadRef.value!.handleStart(file); }; -const toHalo = () => { - window.open('https://www.lxware.cn/1panel' + '', '_blank', 'noopener,noreferrer'); +const toLxware = () => { + if (!globalStore.isIntl) { + window.open('https://www.lxware.cn/1panel' + '', '_blank', 'noopener,noreferrer'); + } else { + window.open('https://1panel.hk/pricing' + '', '_blank', 'noopener,noreferrer'); + } }; const submit = async () => { @@ -90,10 +94,12 @@ const submit = async () => { globalStore.isProductPro = true; const xpackRes = await getXpackSetting(); if (xpackRes) { - globalStore.themeConfig.isGold = xpackRes.data.theme === 'dark-gold'; + globalStore.themeConfig.theme = xpackRes.data.theme; + globalStore.themeConfig.themeColor = xpackRes.data.themeColor; } loading.value = false; switchTheme(); + initFavicon(); uploadRef.value!.clearFiles(); uploaderFiles.value = []; open.value = false; diff --git a/frontend/src/components/log-file/index.vue b/frontend/src/components/log-file/index.vue index 024a43f50..f4d81b8f8 100644 --- a/frontend/src/components/log-file/index.vue +++ b/frontend/src/components/log-file/index.vue @@ -322,7 +322,7 @@ defineExpose({ changeTail, onDownload, clearLog }); overflow-y: auto; overflow-x: auto; position: relative; - background-color: #1e1e1e; + background-color: var(--panel-logs-bg-color); margin-top: 10px; } diff --git a/frontend/src/components/router-button/index.vue b/frontend/src/components/router-button/index.vue index 0e31e3193..0eda101a5 100644 --- a/frontend/src/components/router-button/index.vue +++ b/frontend/src/components/router-button/index.vue @@ -1,6 +1,6 @@ diff --git a/frontend/src/views/app-store/index.scss b/frontend/src/views/app-store/index.scss index ab8d82fcc..c4ed82a27 100644 --- a/frontend/src/views/app-store/index.scss +++ b/frontend/src/views/app-store/index.scss @@ -13,19 +13,26 @@ .d-name { height: 20%; .name { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 120px; font-weight: 500; font-size: 18px; color: var(--panel-text-color); } .status { - margin-left: 10px; + margin-left: 5px; } .h-button { float: right; - margin-right: 10px; + margin-left: 5px; } .msg { - margin-left: 10px; + margin-left: 5px; + } + .el-button + .el-button { + margin-left: 6px; } } @@ -38,11 +45,11 @@ .el-tag { margin-right: 5px; } - .description { - margin-top: 10px; - font-size: 14px; - color: var(--el-text-color-regular); - } + } + .description { + margin-top: 10px; + font-size: 14px; + color: var(--el-text-color-regular); } .d-button { margin-top: 10px; diff --git a/frontend/src/views/app-store/installed/check/index.vue b/frontend/src/views/app-store/installed/check/index.vue index 592fbd1a5..e7e3864c1 100644 --- a/frontend/src/views/app-store/installed/check/index.vue +++ b/frontend/src/views/app-store/installed/check/index.vue @@ -9,11 +9,18 @@ show-icon :closable="false" /> -
- - + + {{ map.get(item[0]).toString() }} diff --git a/frontend/src/views/app-store/installed/index.vue b/frontend/src/views/app-store/installed/index.vue index a18174f6d..ebe1f123c 100644 --- a/frontend/src/views/app-store/installed/index.vue +++ b/frontend/src/views/app-store/installed/index.vue @@ -96,11 +96,11 @@ :md="24" :lg="12" :xl="12" - class="install-card-col-12" + :class="mode === 'upgrade' ? 'upgrade-card-col-12' : 'install-card-col-12'" >
- +
- {{ installed.name }} + + {{ installed.name }} +
-
+
{{ $t('app.version') }}:{{ installed.version }} @@ -301,14 +305,14 @@
- {{ $t('app.alreadyRun') }}: + {{ $t('app.alreadyRun') }}{{ $t('commons.colon') }} {{ getAge(installed.createdAt) }}
{ diff --git a/frontend/src/views/container/container/index.vue b/frontend/src/views/container/container/index.vue index 616e45b35..92eaff54e 100644 --- a/frontend/src/views/container/container/index.vue +++ b/frontend/src/views/container/container/index.vue @@ -285,7 +285,7 @@
- + - + - + + @@ -522,8 +550,16 @@ import { weekOptions, } from './../helper'; import { loadUsers } from '@/api/modules/toolbox'; +import { storeToRefs } from 'pinia'; +import { GlobalStore } from '@/store'; +import LicenseImport from '@/components/license-import/index.vue'; const router = useRouter(); +const globalStore = GlobalStore(); +const licenseRef = ref(); +const { isProductPro } = storeToRefs(globalStore); +const alertTypes = ['app', 'website', 'database', 'directory', 'log', 'snapshot']; + interface DialogProps { title: string; rowData?: Cronjob.CronjobInfo; @@ -563,13 +599,6 @@ const acceptParams = (params: DialogProps): void => { dialogData.value.rowData.dbType = 'mysql'; dialogData.value.rowData.isDir = true; } - if (dialogData.value.rowData.sourceAccountIDs) { - dialogData.value.rowData.sourceAccounts = []; - let itemIDs = dialogData.value.rowData.sourceAccountIDs.split(','); - for (const item of itemIDs) { - dialogData.value.rowData.sourceAccounts.push(Number(item)); - } - } dialogData.value.rowData!.command = dialogData.value.rowData!.command || 'sh'; dialogData.value.rowData!.isCustom = dialogData.value.rowData!.command !== 'sh' && @@ -732,6 +761,17 @@ const verifyFiles = (rule: any, value: any, callback: any) => { callback(); }; +const checkSendCount = (rule: any, value: any, callback: any) => { + if (value === '') { + callback(); + } + const regex = /^(?:[1-9]|[12][0-9]|30)$/; + if (!regex.test(value)) { + return callback(new Error(i18n.global.t('commons.rule.numberRange', [1, 30]))); + } + callback(); +}; + const rules = reactive({ name: [Rules.requiredInput, Rules.noSpace], type: [Rules.requiredSelect], @@ -750,6 +790,7 @@ const rules = reactive({ sourceAccounts: [Rules.requiredSelect], downloadAccountID: [Rules.requiredSelect], retainCopies: [Rules.number], + alertCount: [Rules.integerNumber, { validator: checkSendCount, trigger: 'blur' }], }); type FormInstance = InstanceType; @@ -980,7 +1021,18 @@ const onSubmit = async (formEl: FormInstance | undefined) => { if (dialogData.value?.rowData?.exclusionRules) { dialogData.value.rowData.exclusionRules = dialogData.value.rowData.exclusionRules.replaceAll('\n', ','); } + + dialogData.value.rowData.alertCount = + dialogData.value.rowData!.hasAlert && isProductPro.value ? dialogData.value.rowData.alertCount : 0; + dialogData.value.rowData.alertTitle = + dialogData.value.rowData!.hasAlert && isProductPro.value + ? i18n.global.t('cronjob.alertTitle', [ + i18n.global.t('cronjob.' + dialogData.value.rowData.type), + dialogData.value.rowData.name, + ]) + : ''; if (!dialogData.value.rowData) return; + if (dialogData.value.title === 'create') { await addCronjob(dialogData.value.rowData); } @@ -994,35 +1046,17 @@ const onSubmit = async (formEl: FormInstance | undefined) => { }); }; +const toUpload = () => { + licenseRef.value.acceptParams(); +}; + defineExpose({ acceptParams, }); diff --git a/frontend/src/views/login/components/login-form.vue b/frontend/src/views/login/components/login-form.vue index 3d8105805..40add6c8e 100644 --- a/frontend/src/views/login/components/login-form.vue +++ b/frontend/src/views/login/components/login-form.vue @@ -52,9 +52,19 @@ @@ -120,22 +130,15 @@ {{ $t('commons.button.login') }} - - - - - -
- - {{ $t('commons.login.errorAgree') }} - -
+
@@ -155,7 +158,7 @@
@@ -44,6 +45,10 @@ + + + {{ $t('setting.proxyDockerHelper') }} +
+ + + diff --git a/frontend/src/views/terminal/command/index.vue b/frontend/src/views/terminal/command/index.vue index a7ea67799..2889ecbfe 100644 --- a/frontend/src/views/terminal/command/index.vue +++ b/frontend/src/views/terminal/command/index.vue @@ -6,7 +6,7 @@ @@ -408,7 +411,7 @@ defineExpose({ onMounted(() => { if (router.currentRoute.value.query.path) { const path = String(router.currentRoute.value.query.path); - initCmd.value = `cd ${path} \n`; + initCmd.value = `cd "${path}" \n`; } }); @@ -428,12 +431,17 @@ onMounted(() => { z-index: calc(var(--el-index-normal) + 1); } :deep(.el-tabs__item) { - color: #575758; - padding: 0 0px; + padding: 0; } :deep(.el-tabs__item.is-active) { - color: #ebeef5; - background-color: #575758; + color: var(--panel-terminal-tag-active-text-color); + background-color: var(--panel-terminal-tag-active-bg-color); + } + :deep(.el-tabs__item:hover) { + color: var(--panel-terminal-tag-hover-text-color); + } + :deep(.el-tabs__item.is-active:hover) { + color: var(--panel-terminal-tag-active-text-color); } } diff --git a/frontend/src/views/toolbox/clam/index.vue b/frontend/src/views/toolbox/clam/index.vue index 7a3163151..026e17c54 100644 --- a/frontend/src/views/toolbox/clam/index.vue +++ b/frontend/src/views/toolbox/clam/index.vue @@ -130,7 +130,7 @@ { router.push({ path: '/hosts/files', query: { path: folder } }); }; const toDoc = async () => { - window.open('https://1panel.cn/docs/user_manual/toolbox/clam/', '_blank', 'noopener,noreferrer'); + window.open(globalStore.docsUrl + '/user_manual/toolbox/clam/', '_blank', 'noopener,noreferrer'); }; const onChange = async (row: any) => { - await await updateClam(row); + await updateClam(row); MsgSuccess(i18n.global.t('commons.msg.operationSuccess')); }; diff --git a/frontend/src/views/toolbox/clam/operate/index.vue b/frontend/src/views/toolbox/clam/operate/index.vue index 893732d05..bb60508fb 100644 --- a/frontend/src/views/toolbox/clam/operate/index.vue +++ b/frontend/src/views/toolbox/clam/operate/index.vue @@ -42,77 +42,117 @@ + - - {{ $t('toolbox.clam.cronHelper') }} - - {{ $t('license.levelUpPro') }} - - - - - - - - - - - - - - - - - - - - +
+ + + + + + + + + + + + + + + + + + +
+
+ + {{ $t('toolbox.clam.alertHelper') }} + + {{ $t('license.levelUpPro') }} + + +
+
+ + + {{ $t('alert.clamHelper') }} + + + {{ $t('toolbox.clam.alertHelper') }} + + {{ $t('license.levelUpPro') }} + + + + + {{ $t('alert.alertCountHelper') }} + +
@@ -175,6 +215,8 @@ const acceptParams = (params: DialogProps): void => { second: 30, }; } + dialogData.value.rowData.hasAlert = dialogData.value.rowData!.alertCount > 0; + dialogData.value.rowData!.alertCount = dialogData.value.rowData!.alertCount || 3; title.value = i18n.global.t('commons.button.' + dialogData.value.title); drawerVisible.value = true; }; @@ -268,6 +310,17 @@ const verifySpec = (rule: any, value: any, callback: any) => { } callback(); }; + +const checkSendCount = (rule: any, value: any, callback: any) => { + if (value === '') { + callback(); + } + const regex = /^(?:[1-9]|[12][0-9]|30)$/; + if (!regex.test(value)) { + return callback(new Error(i18n.global.t('commons.rule.numberRange', [1, 30]))); + } + callback(); +}; const rules = reactive({ name: [Rules.simpleName], path: [Rules.requiredInput, Rules.noSpace], @@ -275,6 +328,7 @@ const rules = reactive({ { validator: verifySpec, trigger: 'blur', required: true }, { validator: verifySpec, trigger: 'change', required: true }, ], + alertCount: [Rules.integerNumber, { validator: checkSendCount, trigger: 'blur' }], }); type FormInstance = InstanceType; @@ -346,6 +400,18 @@ const onSubmit = async (formEl: FormInstance | undefined) => { } } dialogData.value.rowData.spec = spec; + if (dialogData.value.rowData!.hasAlert) { + dialogData.value.rowData.alertCount = dialogData.value.rowData!.hasAlert + ? dialogData.value.rowData.alertCount + : 0; + dialogData.value.rowData.alertTitle = i18n.global.t('toolbox.clam.alertTitle', [ + dialogData.value.rowData.name, + ]); + } else { + dialogData.value.rowData.alertTitle = ''; + dialogData.value.rowData.alertCount = 0; + dialogData.value.rowData.hasAlert = false; + } if (dialogData.value.title === 'edit') { await updateClam(dialogData.value.rowData) @@ -379,31 +445,3 @@ defineExpose({ acceptParams, }); - - diff --git a/frontend/src/views/toolbox/clam/status/index.vue b/frontend/src/views/toolbox/clam/status/index.vue index e2a0fd54f..a6c30ad55 100644 --- a/frontend/src/views/toolbox/clam/status/index.vue +++ b/frontend/src/views/toolbox/clam/status/index.vue @@ -66,15 +66,15 @@ @@ -87,6 +87,8 @@ import { onMounted, ref } from 'vue'; import { ElMessageBox } from 'element-plus'; import i18n from '@/lang'; import { MsgSuccess } from '@/utils/message'; +import { GlobalStore } from '@/store'; +const globalStore = GlobalStore(); const data = ref({ isExist: false, @@ -107,7 +109,7 @@ const setting = () => { }; const toDoc = async () => { - window.open('https://1panel.cn/docs/user_manual/toolbox/clam/', '_blank', 'noopener,noreferrer'); + window.open(globalStore.docsUrl + '/user_manual/toolbox/clam/', '_blank', 'noopener,noreferrer'); }; const changeShow = (val: boolean) => { diff --git a/frontend/src/views/toolbox/clean/index.vue b/frontend/src/views/toolbox/clean/index.vue index 982244a34..218d1e050 100644 --- a/frontend/src/views/toolbox/clean/index.vue +++ b/frontend/src/views/toolbox/clean/index.vue @@ -26,7 +26,7 @@
-
+
@@ -132,14 +132,16 @@
-
- - {{ $t('clean.totalScan') }} {{ computeSize(totalSize) }} - -
- - {{ $t('clean.selectScan') }} {{ computeSize(selectSize) }} +
+
+ + {{ $t('clean.totalScan') }} {{ computeSize(totalSize) }} +
+ + {{ $t('clean.selectScan') }} {{ computeSize(selectSize) }} + +
@@ -147,124 +149,191 @@
- - - - - - +
+ + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + +
@@ -637,4 +706,47 @@ onMounted(() => { float: right; margin-right: 15px; } + +.tree-container { + width: 100%; + display: flex; + flex-direction: column; + height: 100%; + overflow: auto; +} +.tree-collapse { + flex: 1; + overflow: hidden; +} +.responsive-tree { + width: 100%; + max-height: 100%; + overflow: auto; +} +.tree-node { + display: flex; + align-items: center; + justify-content: start; + gap: 1rem; + width: 100%; + overflow: hidden; +} +.tree-node-label { + flex-shrink: 0; + max-width: 60%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.tree-node-size { + flex-shrink: 0; + max-width: 25%; + white-space: nowrap; +} +.tree-node-tooltip { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: inline-block; +} diff --git a/frontend/src/views/toolbox/device/index.vue b/frontend/src/views/toolbox/device/index.vue index 4ba2dd174..8af349878 100644 --- a/frontend/src/views/toolbox/device/index.vue +++ b/frontend/src/views/toolbox/device/index.vue @@ -9,7 +9,7 @@ :model="form" :label-position="mobile ? 'top' : 'left'" ref="formRef" - label-width="120px" + label-width="130px" > @@ -77,7 +77,7 @@ diff --git a/frontend/src/views/toolbox/fail2ban/index.vue b/frontend/src/views/toolbox/fail2ban/index.vue index 39b755333..797f12e86 100644 --- a/frontend/src/views/toolbox/fail2ban/index.vue +++ b/frontend/src/views/toolbox/fail2ban/index.vue @@ -133,15 +133,15 @@ @@ -173,6 +173,8 @@ import { MsgSuccess } from '@/utils/message'; import { getFail2banConf, getFail2banBase, operateFail2ban, updateFail2banByFile } from '@/api/modules/toolbox'; import { ElMessageBox } from 'element-plus'; import { transTimeUnit } from '@/utils/util'; +import { GlobalStore } from '@/store'; +const globalStore = GlobalStore(); const loading = ref(false); const formRef = ref(); @@ -210,7 +212,7 @@ const onLoadList = async (type: string) => { }; const toDoc = () => { - window.open('https://1panel.cn/docs/user_manual/toolbox/fail2ban/', '_blank', 'noopener,noreferrer'); + window.open(globalStore.docsUrl + '/user_manual/toolbox/fail2ban/', '_blank', 'noopener,noreferrer'); }; const onSaveFile = async () => { diff --git a/frontend/src/views/toolbox/ftp/index.vue b/frontend/src/views/toolbox/ftp/index.vue index ebaa55fd6..6dc58d2ba 100644 --- a/frontend/src/views/toolbox/ftp/index.vue +++ b/frontend/src/views/toolbox/ftp/index.vue @@ -129,15 +129,15 @@ @@ -159,6 +159,8 @@ import OperateDialog from '@/views/toolbox/ftp/operate/index.vue'; import LogDialog from '@/views/toolbox/ftp/log/index.vue'; import { Toolbox } from '@/api/interface/toolbox'; import router from '@/routers'; +import { GlobalStore } from '@/store'; +const globalStore = GlobalStore(); const loading = ref(); const selects = ref([]); @@ -213,7 +215,7 @@ const search = async (column?: any) => { }; const toDoc = () => { - window.open('https://1panel.cn/docs/user_manual/toolbox/ftp/', '_blank', 'noopener,noreferrer'); + window.open(globalStore.docsUrl + '/user_manual/toolbox/ftp/', '_blank', 'noopener,noreferrer'); }; const toFolder = (folder: string) => { diff --git a/frontend/src/views/toolbox/supervisor/status/index.vue b/frontend/src/views/toolbox/supervisor/status/index.vue index 28c386e1d..7b80b2b39 100644 --- a/frontend/src/views/toolbox/supervisor/status/index.vue +++ b/frontend/src/views/toolbox/supervisor/status/index.vue @@ -40,17 +40,21 @@ > @@ -67,6 +71,8 @@ import i18n from '@/lang'; import { MsgSuccess } from '@/utils/message'; import { HostTool } from '@/api/interface/host-tool'; import InitPage from './init/index.vue'; +import { GlobalStore } from '@/store'; +const globalStore = GlobalStore(); let operateReq = reactive({ installId: 0, @@ -91,7 +97,7 @@ const setting = () => { }; const toDoc = async () => { - window.open('https://1panel.cn/docs/user_manual/toolbox/supervisor/', '_blank', 'noopener,noreferrer'); + window.open(globalStore.docsUrl + '/user_manual/toolbox/supervisor/', '_blank', 'noopener,noreferrer'); }; const init = async () => { diff --git a/frontend/src/views/website/runtime/dotnet/index.vue b/frontend/src/views/website/runtime/dotnet/index.vue index fa2a6f68a..b884bb2c1 100644 --- a/frontend/src/views/website/runtime/dotnet/index.vue +++ b/frontend/src/views/website/runtime/dotnet/index.vue @@ -31,7 +31,7 @@ - + - + - + diff --git a/frontend/src/views/website/runtime/go/index.vue b/frontend/src/views/website/runtime/go/index.vue index 412f2df8b..740c83efa 100644 --- a/frontend/src/views/website/runtime/go/index.vue +++ b/frontend/src/views/website/runtime/go/index.vue @@ -31,7 +31,7 @@ - + - + - + diff --git a/frontend/src/views/website/runtime/java/index.vue b/frontend/src/views/website/runtime/java/index.vue index d179b930a..12d8e5e6f 100644 --- a/frontend/src/views/website/runtime/java/index.vue +++ b/frontend/src/views/website/runtime/java/index.vue @@ -31,7 +31,7 @@ - + - + - + diff --git a/frontend/src/views/website/runtime/node/index.vue b/frontend/src/views/website/runtime/node/index.vue index 83acd7a82..975dcc12c 100644 --- a/frontend/src/views/website/runtime/node/index.vue +++ b/frontend/src/views/website/runtime/node/index.vue @@ -31,7 +31,7 @@ - + - + - + diff --git a/frontend/src/views/website/runtime/php/check/index.vue b/frontend/src/views/website/runtime/php/check/index.vue index 972c95898..19e6a905d 100644 --- a/frontend/src/views/website/runtime/php/check/index.vue +++ b/frontend/src/views/website/runtime/php/check/index.vue @@ -10,10 +10,18 @@ :closable="false" />
- - + + {{ map.get(item[0]).toString() }} diff --git a/frontend/src/views/website/runtime/php/create/index.vue b/frontend/src/views/website/runtime/php/create/index.vue index 2e7204e51..6d1be40c2 100644 --- a/frontend/src/views/website/runtime/php/create/index.vue +++ b/frontend/src/views/website/runtime/php/create/index.vue @@ -128,7 +128,7 @@ {{ $t('php.toExtensionsList') }} @@ -188,6 +188,8 @@ import i18n from '@/lang'; import { MsgSuccess } from '@/utils/message'; import { FormInstance } from 'element-plus'; import { reactive, ref } from 'vue'; +import { GlobalStore } from '@/store'; +const globalStore = GlobalStore(); interface OperateRrops { id?: number; @@ -210,6 +212,48 @@ const appReq = reactive({ page: 1, pageSize: 20, }); +const phpSources = globalStore.isIntl + ? [ + { + label: i18n.global.t('runtime.default'), + value: 'dl-cdn.alpinelinux.org', + }, + { + label: i18n.global.t('runtime.xtom'), + value: 'mirrors.xtom.com', + }, + ] + : [ + { + label: i18n.global.t('runtime.ustc'), + value: 'mirrors.ustc.edu.cn', + }, + { + label: i18n.global.t('runtime.netease'), + value: 'mirrors.163.com', + }, + { + label: i18n.global.t('runtime.aliyun'), + value: 'mirrors.aliyun.com', + }, + { + label: i18n.global.t('runtime.tsinghua'), + value: 'mirrors.tuna.tsinghua.edu.cn', + }, + { + label: i18n.global.t('runtime.xtomhk'), + value: 'mirrors.xtom.com.hk', + }, + { + label: i18n.global.t('runtime.xtom'), + value: 'mirrors.xtom.com', + }, + { + label: i18n.global.t('runtime.default'), + value: 'dl-cdn.alpinelinux.org', + }, + ]; + const initData = (type: string) => ({ name: '', appDetailID: undefined, @@ -218,7 +262,7 @@ const initData = (type: string) => ({ type: type, resource: 'appstore', rebuild: false, - source: 'mirrors.ustc.edu.cn', + source: phpSources[0].value, }); const extensions = ref(); const formFields = ref(); diff --git a/frontend/src/views/website/runtime/php/extension-template/operate/index.vue b/frontend/src/views/website/runtime/php/extension-template/operate/index.vue index 38146f25d..512a1ecd4 100644 --- a/frontend/src/views/website/runtime/php/extension-template/operate/index.vue +++ b/frontend/src/views/website/runtime/php/extension-template/operate/index.vue @@ -22,7 +22,7 @@ {{ $t('php.toExtensionsList') }} @@ -50,6 +50,8 @@ import { MsgSuccess } from '@/utils/message'; import { CreatePHPExtensions, UpdatePHPExtensions } from '@/api/modules/runtime'; import i18n from '@/lang'; import { Runtime } from '@/api/interface/runtime'; +import { GlobalStore } from '@/store'; +const globalStore = GlobalStore(); const open = ref(false); const operate = ref('create'); diff --git a/frontend/src/views/website/runtime/python/index.vue b/frontend/src/views/website/runtime/python/index.vue index 994292bcc..78d83e089 100644 --- a/frontend/src/views/website/runtime/python/index.vue +++ b/frontend/src/views/website/runtime/python/index.vue @@ -31,7 +31,7 @@
- + - + - + diff --git a/frontend/src/views/website/ssl/index.vue b/frontend/src/views/website/ssl/index.vue index 7c77e2a06..31528966a 100644 --- a/frontend/src/views/website/ssl/index.vue +++ b/frontend/src/views/website/ssl/index.vue @@ -42,8 +42,15 @@ fix show-overflow-tooltip prop="domains" + min-width="90px" > - + - +