diff --git a/backend/app/api/v1/app.go b/backend/app/api/v1/app.go deleted file mode 100644 index 345dbd1ff..000000000 --- a/backend/app/api/v1/app.go +++ /dev/null @@ -1,197 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/i18n" - "github.com/gin-gonic/gin" -) - -// @Tags App -// @Summary List apps -// @Description 获取应用列表 -// @Accept json -// @Param request body request.AppSearch true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /apps/search [post] -func (b *BaseApi) SearchApp(c *gin.Context) { - var req request.AppSearch - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - list, err := appService.PageApp(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, list) -} - -// @Tags App -// @Summary Sync app list -// @Description 同步应用列表 -// @Success 200 -// @Security ApiKeyAuth -// @Router /apps/sync [post] -// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"应用商店同步","formatEN":"App store synchronization"} -func (b *BaseApi) SyncApp(c *gin.Context) { - go appService.SyncAppListFromLocal() - res, err := appService.GetAppUpdate() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - if !res.CanUpdate { - if res.IsSyncing { - helper.SuccessWithMsg(c, i18n.GetMsgByKey("AppStoreIsSyncing")) - } else { - helper.SuccessWithMsg(c, i18n.GetMsgByKey("AppStoreIsUpToDate")) - } - return - } - go func() { - if err := appService.SyncAppListFromRemote(); err != nil { - global.LOG.Errorf("Synchronization with the App Store failed [%s]", err.Error()) - } - }() - helper.SuccessWithData(c, "") -} - -// @Tags App -// @Summary Search app by key -// @Description 通过 key 获取应用信息 -// @Accept json -// @Param key path string true "app key" -// @Success 200 {object} response.AppDTO -// @Security ApiKeyAuth -// @Router /apps/:key [get] -func (b *BaseApi) GetApp(c *gin.Context) { - appKey, err := helper.GetStrParamByKey(c, "key") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - appDTO, err := appService.GetApp(appKey) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, appDTO) -} - -// @Tags App -// @Summary Search app detail by appid -// @Description 通过 appid 获取应用详情 -// @Accept json -// @Param appId path integer true "app id" -// @Param version path string true "app 版本" -// @Param version path string true "app 类型" -// @Success 200 {object} response.AppDetailDTO -// @Security ApiKeyAuth -// @Router /apps/detail/:appId/:version/:type [get] -func (b *BaseApi) GetAppDetail(c *gin.Context) { - appID, err := helper.GetIntParamByKey(c, "appId") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) - return - } - version := c.Param("version") - appType := c.Param("type") - appDetailDTO, err := appService.GetAppDetail(appID, version, appType) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, appDetailDTO) -} - -// @Tags App -// @Summary Get app detail by id -// @Description 通过 id 获取应用详情 -// @Accept json -// @Param appId path integer true "id" -// @Success 200 {object} response.AppDetailDTO -// @Security ApiKeyAuth -// @Router /apps/details/:id [get] -func (b *BaseApi) GetAppDetailByID(c *gin.Context) { - appDetailID, err := helper.GetIntParamByKey(c, "id") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) - return - } - appDetailDTO, err := appService.GetAppDetailByID(appDetailID) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, appDetailDTO) -} - -// @Tags App -// @Summary Get Ignore App -// @Description 获取忽略的应用版本 -// @Accept json -// @Success 200 {object} response.IgnoredApp -// @Security ApiKeyAuth -// @Router /apps/ignored [get] -func (b *BaseApi) GetIgnoredApp(c *gin.Context) { - res, err := appService.GetIgnoredApp() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags App -// @Summary Install app -// @Description 安装应用 -// @Accept json -// @Param request body request.AppInstallCreate true "request" -// @Success 200 {object} model.AppInstall -// @Security ApiKeyAuth -// @Router /apps/install [post] -// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[{"input_column":"name","input_value":"name","isList":false,"db":"app_installs","output_column":"app_id","output_value":"appId"},{"info":"appId","isList":false,"db":"apps","output_column":"key","output_value":"appKey"}],"formatZH":"安装应用 [appKey]-[name]","formatEN":"Install app [appKey]-[name]"} -func (b *BaseApi) InstallApp(c *gin.Context) { - var req request.AppInstallCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - tx, ctx := helper.GetTxAndContext() - install, err := appService.Install(ctx, req) - if err != nil { - tx.Rollback() - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - tx.Commit() - helper.SuccessWithData(c, install) -} - -func (b *BaseApi) GetAppTags(c *gin.Context) { - tags, err := appService.GetAppTags() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, tags) -} - -// @Tags App -// @Summary Get app list update -// @Description 获取应用更新版本 -// @Success 200 -// @Security ApiKeyAuth -// @Router /apps/checkupdate [get] -func (b *BaseApi) GetAppListUpdate(c *gin.Context) { - res, err := appService.GetAppUpdate() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} diff --git a/backend/app/api/v1/app_install.go b/backend/app/api/v1/app_install.go deleted file mode 100644 index f0b63ab6c..000000000 --- a/backend/app/api/v1/app_install.go +++ /dev/null @@ -1,327 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags App -// @Summary Page app installed -// @Description 分页获取已安装应用列表 -// @Accept json -// @Param request body request.AppInstalledSearch true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /apps/installed/search [post] -func (b *BaseApi) SearchAppInstalled(c *gin.Context) { - var req request.AppInstalledSearch - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if req.All { - list, err := appInstallService.SearchForWebsite(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, list) - } else { - total, list, err := appInstallService.Page(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) - } -} - -// @Tags App -// @Summary List app installed -// @Description 获取已安装应用列表 -// @Accept json -// @Success 200 array dto.AppInstallInfo -// @Security ApiKeyAuth -// @Router /apps/installed/list [get] -func (b *BaseApi) ListAppInstalled(c *gin.Context) { - list, err := appInstallService.GetInstallList() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, list) -} - -// @Tags App -// @Summary Check app installed -// @Description 检查应用安装情况 -// @Accept json -// @Param request body request.AppInstalledInfo true "request" -// @Success 200 {object} response.AppInstalledCheck -// @Security ApiKeyAuth -// @Router /apps/installed/check [post] -func (b *BaseApi) CheckAppInstalled(c *gin.Context) { - var req request.AppInstalledInfo - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - checkData, err := appInstallService.CheckExist(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, checkData) -} - -// @Tags App -// @Summary Search app port by key -// @Description 获取应用端口 -// @Accept json -// @Param request body dto.OperationWithNameAndType true "request" -// @Success 200 {integer} port -// @Security ApiKeyAuth -// @Router /apps/installed/loadport [post] -func (b *BaseApi) LoadPort(c *gin.Context) { - var req dto.OperationWithNameAndType - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - port, err := appInstallService.LoadPort(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, port) -} - -// @Tags App -// @Summary Search app password by key -// @Description 获取应用连接信息 -// @Accept json -// @Param request body dto.OperationWithNameAndType true "request" -// @Success 200 {string} response.DatabaseConn -// @Security ApiKeyAuth -// @Router /apps/installed/conninfo/:key [get] -func (b *BaseApi) LoadConnInfo(c *gin.Context) { - var req dto.OperationWithNameAndType - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - conn, err := appInstallService.LoadConnInfo(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, conn) -} - -// @Tags App -// @Summary Check before delete -// @Description 删除前检查 -// @Accept json -// @Param appInstallId path integer true "App install id" -// @Success 200 {array} dto.AppResource -// @Security ApiKeyAuth -// @Router /apps/installed/delete/check/:appInstallId [get] -func (b *BaseApi) DeleteCheck(c *gin.Context) { - appInstallId, err := helper.GetIntParamByKey(c, "appInstallId") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) - return - } - checkData, err := appInstallService.DeleteCheck(appInstallId) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, checkData) -} - -// Sync app installed -// @Tags App -// @Summary Sync app installed -// @Description 同步已安装应用列表 -// @Success 200 -// @Security ApiKeyAuth -// @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) { - if err := appInstallService.SyncAll(false); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, "") -} - -// @Tags App -// @Summary Operate installed app -// @Description 操作已安装应用 -// @Accept json -// @Param request body request.AppInstalledOperate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.AppInstalledOperate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := appInstallService.Operate(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags App -// @Summary Search app service by key -// @Description 通过 key 获取应用 service -// @Accept json -// @Param key path string true "request" -// @Success 200 {array} response.AppService -// @Security ApiKeyAuth -// @Router /apps/services/:key [get] -func (b *BaseApi) GetServices(c *gin.Context) { - key := c.Param("key") - services, err := appInstallService.GetServices(key) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, services) -} - -// @Tags App -// @Summary Search app update version by install id -// @Description 通过 install id 获取应用更新版本 -// @Accept json -// @Param appInstallId path integer true "request" -// @Success 200 {array} dto.AppVersion -// @Security ApiKeyAuth -// @Router /apps/installed/update/versions [post] -func (b *BaseApi) GetUpdateVersions(c *gin.Context) { - var req request.AppUpdateVersion - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - versions, err := appInstallService.GetUpdateVersions(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, versions) -} - -// @Tags App -// @Summary Change app port -// @Description 修改应用端口 -// @Accept json -// @Param request body request.PortUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.PortUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := appInstallService.ChangeAppPort(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags App -// @Summary Search default config by key -// @Description 通过 key 获取应用默认配置 -// @Accept json -// @Param request body dto.OperationWithNameAndType true "request" -// @Success 200 {string} content -// @Security ApiKeyAuth -// @Router /apps/installed/conf [post] -func (b *BaseApi) GetDefaultConfig(c *gin.Context) { - var req dto.OperationWithNameAndType - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - content, err := appInstallService.GetDefaultConfigByKey(req.Type, req.Name) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, content) -} - -// @Tags App -// @Summary Search params by appInstallId -// @Description 通过 install id 获取应用参数 -// @Accept json -// @Param appInstallId path string true "request" -// @Success 200 {object} response.AppParam -// @Security ApiKeyAuth -// @Router /apps/installed/params/:appInstallId [get] -func (b *BaseApi) GetParams(c *gin.Context) { - appInstallId, err := helper.GetIntParamByKey(c, "appInstallId") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) - return - } - content, err := appInstallService.GetParams(appInstallId) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, content) -} - -// @Tags App -// @Summary Change app params -// @Description 修改应用参数 -// @Accept json -// @Param request body request.AppInstalledUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.AppInstalledUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := appInstallService.Update(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags App -// @Summary ignore App Update -// @Description 忽略应用升级版本 -// @Accept json -// @Param request body request.AppInstalledIgnoreUpgrade true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.AppInstalledIgnoreUpgrade - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := appInstallService.IgnoreUpgrade(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} diff --git a/backend/app/api/v1/backup.go b/backend/app/api/v1/backup.go deleted file mode 100644 index 1849ba568..000000000 --- a/backend/app/api/v1/backup.go +++ /dev/null @@ -1,443 +0,0 @@ -package v1 - -import ( - "encoding/base64" - "fmt" - "path" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Backup Account -// @Summary Create backup account -// @Description 创建备份账号 -// @Accept json -// @Param request body dto.BackupOperate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /settings/backup [post] -// @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建备份账号 [type]","formatEN":"create backup account [type]"} -func (b *BaseApi) CreateBackup(c *gin.Context) { - var req dto.BackupOperate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if len(req.Credential) != 0 { - credential, err := base64.StdEncoding.DecodeString(req.Credential) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.Credential = string(credential) - } - if len(req.AccessKey) != 0 { - accessKey, err := base64.StdEncoding.DecodeString(req.AccessKey) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.AccessKey = string(accessKey) - } - - if err := backupService.Create(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Backup Account -// @Summary Refresh OneDrive token -// @Description 刷新 OneDrive token -// @Success 200 -// @Security ApiKeyAuth -// @Router /settings/backup/refresh/onedrive [post] -func (b *BaseApi) RefreshOneDriveToken(c *gin.Context) { - backupService.Run() - helper.SuccessWithData(c, nil) -} - -// @Tags Backup Account -// @Summary List buckets -// @Description 获取 bucket 列表 -// @Accept json -// @Param request body dto.ForBuckets true "request" -// @Success 200 {array} string -// @Security ApiKeyAuth -// @Router /settings/backup/search [post] -func (b *BaseApi) ListBuckets(c *gin.Context) { - var req dto.ForBuckets - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if len(req.Credential) != 0 { - credential, err := base64.StdEncoding.DecodeString(req.Credential) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.Credential = string(credential) - } - if len(req.AccessKey) != 0 { - accessKey, err := base64.StdEncoding.DecodeString(req.AccessKey) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.AccessKey = string(accessKey) - } - - buckets, err := backupService.GetBuckets(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, buckets) -} - -// @Tags Backup Account -// @Summary Load OneDrive info -// @Description 获取 OneDrive 信息 -// @Accept json -// @Success 200 {object} dto.OneDriveInfo -// @Security ApiKeyAuth -// @Router /settings/backup/onedrive [get] -func (b *BaseApi) LoadOneDriveInfo(c *gin.Context) { - data, err := backupService.LoadOneDriveInfo() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, data) -} - -// @Tags Backup Account -// @Summary Delete backup account -// @Description 删除备份账号 -// @Accept json -// @Param request body dto.OperateByID true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /settings/backup/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) { - var req dto.OperateByID - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := backupService.Delete(req.ID); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Backup Account -// @Summary Page backup records -// @Description 获取备份记录列表分页 -// @Accept json -// @Param request body dto.RecordSearch true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /settings/backup/record/search [post] -func (b *BaseApi) SearchBackupRecords(c *gin.Context) { - var req dto.RecordSearch - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := backupService.SearchRecordsWithPage(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Backup Account -// @Summary Page backup records by cronjob -// @Description 通过计划任务获取备份记录列表分页 -// @Accept json -// @Param request body dto.RecordSearchByCronjob true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /settings/backup/record/search/bycronjob [post] -func (b *BaseApi) SearchBackupRecordsByCronjob(c *gin.Context) { - var req dto.RecordSearchByCronjob - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := backupService.SearchRecordsByCronjobWithPage(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Backup Account -// @Summary Download backup record -// @Description 下载备份记录 -// @Accept json -// @Param request body dto.DownloadRecord true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /settings/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) { - var req dto.DownloadRecord - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - filePath, err := backupService.DownloadRecord(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, filePath) -} - -// @Tags Backup Account -// @Summary Delete backup record -// @Description 删除备份记录 -// @Accept json -// @Param request body dto.BatchDeleteReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /settings/backup/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) { - var req dto.BatchDeleteReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := backupService.BatchDeleteRecord(req.Ids); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Backup Account -// @Summary Update backup account -// @Description 更新备份账号信息 -// @Accept json -// @Param request body dto.BackupOperate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /settings/backup/update [post] -// @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新备份账号 [types]","formatEN":"update backup account [types]"} -func (b *BaseApi) UpdateBackup(c *gin.Context) { - var req dto.BackupOperate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if len(req.Credential) != 0 { - credential, err := base64.StdEncoding.DecodeString(req.Credential) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.Credential = string(credential) - } - if len(req.AccessKey) != 0 { - accessKey, err := base64.StdEncoding.DecodeString(req.AccessKey) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.AccessKey = string(accessKey) - } - - if err := backupService.Update(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Backup Account -// @Summary List backup accounts -// @Description 获取备份账号列表 -// @Success 200 {array} dto.BackupInfo -// @Security ApiKeyAuth -// @Router /settings/backup/search [get] -func (b *BaseApi) ListBackup(c *gin.Context) { - data, err := backupService.List() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, data) -} - -// @Tags Backup Account -// @Summary List files from backup accounts -// @Description 获取备份账号内文件列表 -// @Accept json -// @Param request body dto.BackupSearchFile true "request" -// @Success 200 {array} string -// @Security ApiKeyAuth -// @Router /settings/backup/search/files [post] -func (b *BaseApi) LoadFilesFromBackup(c *gin.Context) { - var req dto.BackupSearchFile - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - data := backupService.ListFiles(req) - helper.SuccessWithData(c, data) -} - -// @Tags Backup Account -// @Summary Backup system data -// @Description 备份系统数据 -// @Accept json -// @Param request body dto.CommonBackup true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /settings/backup/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) { - var req dto.CommonBackup - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - switch req.Type { - case "app": - if _, err := backupService.AppBackup(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - case "mysql", "mariadb": - if err := backupService.MysqlBackup(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - case constant.AppPostgresql: - if err := backupService.PostgresqlBackup(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - case "website": - if err := backupService.WebsiteBackup(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - case "redis": - if err := backupService.RedisBackup(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - } - helper.SuccessWithData(c, nil) -} - -// @Tags Backup Account -// @Summary Recover system data -// @Description 恢复系统数据 -// @Accept json -// @Param request body dto.CommonRecover true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /settings/backup/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) { - var req dto.CommonRecover - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - downloadPath, err := backupService.DownloadRecord(dto.DownloadRecord{Source: req.Source, FileDir: path.Dir(req.File), FileName: path.Base(req.File)}) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, fmt.Errorf("download file failed, err: %v", err)) - return - } - req.File = downloadPath - switch req.Type { - case "mysql", "mariadb": - if err := backupService.MysqlRecover(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - case constant.AppPostgresql: - if err := backupService.PostgresqlRecover(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - case "website": - if err := backupService.WebsiteRecover(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - case "redis": - if err := backupService.RedisRecover(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - case "app": - if err := backupService.AppRecover(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - } - helper.SuccessWithData(c, nil) -} - -// @Tags Backup Account -// @Summary Recover system data by upload -// @Description 从上传恢复系统数据 -// @Accept json -// @Param request body dto.CommonRecover true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /settings/backup/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) { - var req dto.CommonRecover - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - switch req.Type { - case "mysql", "mariadb": - if err := backupService.MysqlRecoverByUpload(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - case constant.AppPostgresql: - if err := backupService.PostgresqlRecoverByUpload(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - case "app": - if err := backupService.AppRecover(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - case "website": - if err := backupService.WebsiteRecover(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - } - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/clam.go b/backend/app/api/v1/clam.go deleted file mode 100644 index 0e4e7cf47..000000000 --- a/backend/app/api/v1/clam.go +++ /dev/null @@ -1,296 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Clam -// @Summary Create clam -// @Description 创建扫描规则 -// @Accept json -// @Param request body dto.ClamCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ClamCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := clamService.Create(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Clam -// @Summary Update clam -// @Description 修改扫描规则 -// @Accept json -// @Param request body dto.ClamUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ClamUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := clamService.Update(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Clam -// @Summary Update clam status -// @Description 修改扫描规则状态 -// @Accept json -// @Param request body dto.ClamUpdateStatus true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ClamUpdateStatus - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := clamService.UpdateStatus(req.ID, req.Status); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Clam -// @Summary Page clam -// @Description 获取扫描规则列表分页 -// @Accept json -// @Param request body dto.SearchClamWithPage true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /toolbox/clam/search [post] -func (b *BaseApi) SearchClam(c *gin.Context) { - var req dto.SearchClamWithPage - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := clamService.SearchWithPage(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Clam -// @Summary Load clam base info -// @Description 获取 Clam 基础信息 -// @Accept json -// @Success 200 {object} dto.ClamBaseInfo -// @Security ApiKeyAuth -// @Router /toolbox/clam/base [get] -func (b *BaseApi) LoadClamBaseInfo(c *gin.Context) { - info, err := clamService.LoadBaseInfo() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, info) -} - -// @Tags Clam -// @Summary Operate Clam -// @Description 修改 Clam 状态 -// @Accept json -// @Param request body dto.Operate true "request" -// @Security ApiKeyAuth -// @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) { - var req dto.Operate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := clamService.Operate(req.Operation); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Clam -// @Summary Clean clam record -// @Description 清空扫描报告 -// @Accept json -// @Param request body dto.OperateByID true "request" -// @Security ApiKeyAuth -// @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) { - var req dto.OperateByID - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := clamService.CleanRecord(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Clam -// @Summary Page clam record -// @Description 获取扫描结果列表分页 -// @Accept json -// @Param request body dto.ClamLogSearch true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /toolbox/clam/record/search [post] -func (b *BaseApi) SearchClamRecord(c *gin.Context) { - var req dto.ClamLogSearch - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := clamService.LoadRecords(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Clam -// @Summary Load clam record detail -// @Description 获取扫描结果详情 -// @Accept json -// @Param request body dto.ClamLogReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /toolbox/clam/record/log [post] -func (b *BaseApi) LoadClamRecordLog(c *gin.Context) { - var req dto.ClamLogReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - content, err := clamService.LoadRecordLog(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, content) -} - -// @Tags Clam -// @Summary Load clam file -// @Description 获取扫描文件 -// @Accept json -// @Param request body dto.ClamFileReq true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /toolbox/clam/file/search [post] -func (b *BaseApi) SearchClamFile(c *gin.Context) { - var req dto.ClamFileReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - content, err := clamService.LoadFile(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, content) -} - -// @Tags Clam -// @Summary Update clam file -// @Description 更新病毒扫描配置文件 -// @Accept json -// @Param request body dto.UpdateByNameAndFile true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /toolbox/clam/file/update [post] -func (b *BaseApi) UpdateFile(c *gin.Context) { - var req dto.UpdateByNameAndFile - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := clamService.UpdateFile(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Clam -// @Summary Delete clam -// @Description 删除扫描规则 -// @Accept json -// @Param request body dto.ClamDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ClamDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := clamService.Delete(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Clam -// @Summary Handle clam scan -// @Description 执行病毒扫描 -// @Accept json -// @Param request body dto.OperateByID true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.OperateByID - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := clamService.HandleOnce(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/command.go b/backend/app/api/v1/command.go deleted file mode 100644 index 3c9926111..000000000 --- a/backend/app/api/v1/command.go +++ /dev/null @@ -1,223 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Command -// @Summary Create command -// @Description 创建快速命令 -// @Accept json -// @Param request body dto.CommandOperate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /hosts/command [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) { - var req dto.CommandOperate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := commandService.Create(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Redis Command -// @Summary Save redis command -// @Description 保存 Redis 快速命令 -// @Accept json -// @Param request body dto.RedisCommand true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /hosts/command/redis [post] -// @x-panel-log {"bodyKeys":["name","command"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"保存 redis 快捷命令 [name][command]","formatEN":"save quick command for redis [name][command]"} -func (b *BaseApi) SaveRedisCommand(c *gin.Context) { - var req dto.RedisCommand - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := commandService.SaveRedisCommand(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Command -// @Summary Page commands -// @Description 获取快速命令列表分页 -// @Accept json -// @Param request body dto.SearchWithPage true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /hosts/command/search [post] -func (b *BaseApi) SearchCommand(c *gin.Context) { - var req dto.SearchCommandWithPage - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := commandService.SearchWithPage(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Redis Command -// @Summary Page redis commands -// @Description 获取 redis 快速命令列表分页 -// @Accept json -// @Param request body dto.SearchWithPage true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /hosts/command/redis/search [post] -func (b *BaseApi) SearchRedisCommand(c *gin.Context) { - var req dto.SearchWithPage - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := commandService.SearchRedisCommandWithPage(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Command -// @Summary Tree commands -// @Description 获取快速命令树 -// @Accept json -// @Success 200 {Array} dto.CommandTree -// @Security ApiKeyAuth -// @Router /hosts/command/tree [get] -func (b *BaseApi) SearchCommandTree(c *gin.Context) { - list, err := commandService.SearchForTree() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, list) -} - -// @Tags Redis Command -// @Summary List redis commands -// @Description 获取 redis 快速命令列表 -// @Success 200 {Array} dto.RedisCommand -// @Security ApiKeyAuth -// @Router /hosts/command/redis [get] -func (b *BaseApi) ListRedisCommand(c *gin.Context) { - list, err := commandService.ListRedisCommand() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, list) -} - -// @Tags Command -// @Summary List commands -// @Description 获取快速命令列表 -// @Success 200 {object} dto.CommandInfo -// @Security ApiKeyAuth -// @Router /hosts/command [get] -func (b *BaseApi) ListCommand(c *gin.Context) { - list, err := commandService.List() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, list) -} - -// @Tags Command -// @Summary Delete command -// @Description 删除快速命令 -// @Accept json -// @Param request body dto.BatchDeleteReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /hosts/command/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) { - var req dto.BatchDeleteReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := commandService.Delete(req.Ids); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Redis Command -// @Summary Delete redis command -// @Description 删除 redis 快速命令 -// @Accept json -// @Param request body dto.BatchDeleteReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /hosts/command/redis/del [post] -// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"redis_commands","output_column":"name","output_value":"names"}],"formatZH":"删除 redis 快捷命令 [names]","formatEN":"delete quick command of redis [names]"} -func (b *BaseApi) DeleteRedisCommand(c *gin.Context) { - var req dto.BatchDeleteReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := commandService.DeleteRedisCommand(req.Ids); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Command -// @Summary Update command -// @Description 更新快速命令 -// @Accept json -// @Param request body dto.CommandOperate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /hosts/command/update [post] -// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新快捷命令 [name]","formatEN":"update quick command [name]"} -func (b *BaseApi) UpdateCommand(c *gin.Context) { - var req dto.CommandOperate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - upMap := make(map[string]interface{}) - upMap["name"] = req.Name - upMap["group_id"] = req.GroupID - upMap["command"] = req.Command - if err := commandService.Update(req.ID, upMap); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/compose_template.go b/backend/app/api/v1/compose_template.go deleted file mode 100644 index 5fcba846d..000000000 --- a/backend/app/api/v1/compose_template.go +++ /dev/null @@ -1,121 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Container Compose-template -// @Summary Create compose template -// @Description 创建容器编排模版 -// @Accept json -// @Param request body dto.ComposeTemplateCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ComposeTemplateCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := composeTemplateService.Create(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container Compose-template -// @Summary Page compose templates -// @Description 获取容器编排模版列表分页 -// @Accept json -// @Param request body dto.SearchWithPage true "request" -// @Produce json -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /containers/template/search [post] -func (b *BaseApi) SearchComposeTemplate(c *gin.Context) { - var req dto.SearchWithPage - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := composeTemplateService.SearchWithPage(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Container Compose-template -// @Summary List compose templates -// @Description 获取容器编排模版列表 -// @Produce json -// @Success 200 {array} dto.ComposeTemplateInfo -// @Security ApiKeyAuth -// @Router /containers/template [get] -func (b *BaseApi) ListComposeTemplate(c *gin.Context) { - list, err := composeTemplateService.List() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, list) -} - -// @Tags Container Compose-template -// @Summary Delete compose template -// @Description 删除容器编排模版 -// @Accept json -// @Param request body dto.BatchDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.BatchDeleteReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := composeTemplateService.Delete(req.Ids); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container Compose-template -// @Summary Update compose template -// @Description 更新容器编排模版 -// @Accept json -// @Param request body dto.ComposeTemplateUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ComposeTemplateUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - upMap := make(map[string]interface{}) - upMap["content"] = req.Content - upMap["description"] = req.Description - if err := composeTemplateService.Update(req.ID, upMap); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/container.go b/backend/app/api/v1/container.go deleted file mode 100644 index 5c8213662..000000000 --- a/backend/app/api/v1/container.go +++ /dev/null @@ -1,699 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/gin-gonic/gin" - "github.com/pkg/errors" - "strconv" -) - -// @Tags Container -// @Summary Page containers -// @Description 获取容器列表分页 -// @Accept json -// @Param request body dto.PageContainer true "request" -// @Produce json -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /containers/search [post] -func (b *BaseApi) SearchContainer(c *gin.Context) { - var req dto.PageContainer - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := containerService.Page(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Container -// @Summary List containers -// @Description 获取容器名称 -// @Accept json -// @Produce json -// @Success 200 -// @Security ApiKeyAuth -// @Router /containers/list [post] -func (b *BaseApi) ListContainer(c *gin.Context) { - list, err := containerService.List() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, list) -} - -// @Tags Container Compose -// @Summary Page composes -// @Description 获取编排列表分页 -// @Accept json -// @Param request body dto.SearchWithPage true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /containers/compose/search [post] -func (b *BaseApi) SearchCompose(c *gin.Context) { - var req dto.SearchWithPage - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := containerService.PageCompose(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Container Compose -// @Summary Test compose -// @Description 测试 compose 是否可用 -// @Accept json -// @Param request body dto.ComposeCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ComposeCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - isOK, err := containerService.TestCompose(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, isOK) -} - -// @Tags Container Compose -// @Summary Create compose -// @Description 创建容器编排 -// @Accept json -// @Param request body dto.ComposeCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ComposeCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - log, err := containerService.CreateCompose(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, log) -} - -// @Tags Container Compose -// @Summary Operate compose -// @Description 容器编排操作 -// @Accept json -// @Param request body dto.ComposeOperation true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ComposeOperation - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := containerService.ComposeOperation(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container -// @Summary Update container -// @Description 更新容器 -// @Accept json -// @Param request body dto.ContainerOperate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ContainerOperate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := containerService.ContainerUpdate(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container -// @Summary Load container info -// @Description 获取容器表单信息 -// @Accept json -// @Param request body dto.OperationWithName true "request" -// @Success 200 {object} dto.ContainerOperate -// @Security ApiKeyAuth -// @Router /containers/info [post] -func (b *BaseApi) ContainerInfo(c *gin.Context) { - var req dto.OperationWithName - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - data, err := containerService.ContainerInfo(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, data) -} - -// @Summary Load container limits -// @Description 获取容器限制 -// @Success 200 {object} dto.ResourceLimit -// @Security ApiKeyAuth -// @Router /containers/limit [get] -func (b *BaseApi) LoadResourceLimit(c *gin.Context) { - data, err := containerService.LoadResourceLimit() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, data) -} - -// @Summary Load container stats -// @Description 获取容器列表资源占用 -// @Success 200 {array} dto.ContainerListStats -// @Security ApiKeyAuth -// @Router /containers/list/stats [get] -func (b *BaseApi) ContainerListStats(c *gin.Context) { - data, err := containerService.ContainerListStats() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, data) -} - -// @Tags Container -// @Summary Create container -// @Description 创建容器 -// @Accept json -// @Param request body dto.ContainerOperate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ContainerOperate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := containerService.ContainerCreate(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container -// @Summary Upgrade container -// @Description 更新容器镜像 -// @Accept json -// @Param request body dto.ContainerUpgrade true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ContainerUpgrade - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := containerService.ContainerUpgrade(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container -// @Summary Clean container -// @Description 容器清理 -// @Accept json -// @Param request body dto.ContainerPrune true "request" -// @Success 200 {object} dto.ContainerPruneReport -// @Security ApiKeyAuth -// @Router /containers/prune [post] -// @x-panel-log {"bodyKeys":["pruneType"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理容器 [pruneType]","formatEN":"clean container [pruneType]"} -func (b *BaseApi) ContainerPrune(c *gin.Context) { - var req dto.ContainerPrune - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - report, err := containerService.Prune(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, report) -} - -// @Tags Container -// @Summary Clean container log -// @Description 清理容器日志 -// @Accept json -// @Param request body dto.OperationWithName true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.OperationWithName - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := containerService.ContainerLogClean(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container -// @Summary Load container log -// @Description 获取容器操作日志 -// @Accept json -// @Param request body dto.OperationWithNameAndType true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /containers/load/log [post] -func (b *BaseApi) LoadContainerLog(c *gin.Context) { - var req dto.OperationWithNameAndType - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - content := containerService.LoadContainerLogs(req) - helper.SuccessWithData(c, content) -} - -// @Tags Container -// @Summary Rename Container -// @Description 容器重命名 -// @Accept json -// @Param request body dto.ContainerRename true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ContainerRename - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := containerService.ContainerRename(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container -// @Summary Commit Container -// @Description 容器提交生成新镜像 -// @Accept json -// @Param request body dto.ContainerCommit true "request" -// @Success 200 -// @Router /containers/commit [post] -func (b *BaseApi) ContainerCommit(c *gin.Context) { - var req dto.ContainerCommit - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := containerService.ContainerCommit(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container -// @Summary Operate Container -// @Description 容器操作 -// @Accept json -// @Param request body dto.ContainerOperation true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ContainerOperation - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := containerService.ContainerOperation(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container -// @Summary Container stats -// @Description 容器监控信息 -// @Param id path integer true "容器id" -// @Success 200 {object} dto.ContainerStats -// @Security ApiKeyAuth -// @Router /containers/stats/:id [get] -func (b *BaseApi) ContainerStats(c *gin.Context) { - containerID, ok := c.Params.Get("id") - if !ok { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error container id in path")) - return - } - - result, err := containerService.ContainerStats(containerID) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, result) -} - -// @Tags Container -// @Summary Container inspect -// @Description 容器详情 -// @Accept json -// @Param request body dto.InspectReq true "request" -// @Success 200 {string} result -// @Security ApiKeyAuth -// @Router /containers/inspect [post] -func (b *BaseApi) Inspect(c *gin.Context) { - var req dto.InspectReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - result, err := containerService.Inspect(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, result) -} - -// @Tags Container -// @Summary Container logs -// @Description 容器日志 -// @Param container query string false "容器名称" -// @Param since query string false "时间筛选" -// @Param follow query string false "是否追踪" -// @Param tail query string false "显示行号" -// @Security ApiKeyAuth -// @Router /containers/search/log [post] -func (b *BaseApi) ContainerLogs(c *gin.Context) { - wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil) - if err != nil { - global.LOG.Errorf("gin context http handler failed, err: %v", err) - return - } - defer wsConn.Close() - - container := c.Query("container") - since := c.Query("since") - follow := c.Query("follow") == "true" - tail := c.Query("tail") - - if err := containerService.ContainerLogs(wsConn, "container", container, since, tail, follow); err != nil { - _ = wsConn.WriteMessage(1, []byte(err.Error())) - return - } -} - -// @Description 下载容器日志 -// @Router /containers/download/log [post] -func (b *BaseApi) DownloadContainerLogs(c *gin.Context) { - var req dto.ContainerLog - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - err := containerService.DownloadContainerLogs(req.ContainerType, req.Container, req.Since, strconv.Itoa(int(req.Tail)), c) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - } -} - -// @Tags Container Network -// @Summary Page networks -// @Description 获取容器网络列表分页 -// @Accept json -// @Param request body dto.SearchWithPage true "request" -// @Produce json -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /containers/network/search [post] -func (b *BaseApi) SearchNetwork(c *gin.Context) { - var req dto.SearchWithPage - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := containerService.PageNetwork(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Container Network -// @Summary List networks -// @Description 获取容器网络列表 -// @Accept json -// @Produce json -// @Success 200 {array} dto.Options -// @Security ApiKeyAuth -// @Router /containers/network [get] -func (b *BaseApi) ListNetwork(c *gin.Context) { - list, err := containerService.ListNetwork() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, list) -} - -// @Tags Container Network -// @Summary Delete network -// @Description 删除容器网络 -// @Accept json -// @Param request body dto.BatchDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.BatchDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := containerService.DeleteNetwork(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container Network -// @Summary Create network -// @Description 创建容器网络 -// @Accept json -// @Param request body dto.NetworkCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.NetworkCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := containerService.CreateNetwork(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container Volume -// @Summary Page volumes -// @Description 获取容器存储卷分页 -// @Accept json -// @Param request body dto.SearchWithPage true "request" -// @Produce json -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /containers/volume/search [post] -func (b *BaseApi) SearchVolume(c *gin.Context) { - var req dto.SearchWithPage - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := containerService.PageVolume(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Container Volume -// @Summary List volumes -// @Description 获取容器存储卷列表 -// @Accept json -// @Produce json -// @Success 200 {array} dto.Options -// @Security ApiKeyAuth -// @Router /containers/volume [get] -func (b *BaseApi) ListVolume(c *gin.Context) { - list, err := containerService.ListVolume() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, list) -} - -// @Tags Container Volume -// @Summary Delete volume -// @Description 删除容器存储卷 -// @Accept json -// @Param request body dto.BatchDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.BatchDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := containerService.DeleteVolume(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container Volume -// @Summary Create volume -// @Description 创建容器存储卷 -// @Accept json -// @Param request body dto.VolumeCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.VolumeCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := containerService.CreateVolume(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container Compose -// @Summary Update compose -// @Description 更新容器编排 -// @Accept json -// @Param request body dto.ComposeUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ComposeUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := containerService.ComposeUpdate(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container Compose -// @Summary Container Compose logs -// @Description docker-compose 日志 -// @Param compose query string false "compose 文件地址" -// @Param since query string false "时间筛选" -// @Param follow query string false "是否追踪" -// @Param tail query string false "显示行号" -// @Security ApiKeyAuth -// @Router /containers/compose/search/log [get] -func (b *BaseApi) ComposeLogs(c *gin.Context) { - wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil) - if err != nil { - global.LOG.Errorf("gin context http handler failed, err: %v", err) - return - } - defer wsConn.Close() - - compose := c.Query("compose") - since := c.Query("since") - follow := c.Query("follow") == "true" - tail := c.Query("tail") - - if err := containerService.ContainerLogs(wsConn, "compose", compose, since, tail, follow); err != nil { - _ = wsConn.WriteMessage(1, []byte(err.Error())) - return - } -} diff --git a/backend/app/api/v1/cronjob.go b/backend/app/api/v1/cronjob.go deleted file mode 100644 index 181a28cd7..000000000 --- a/backend/app/api/v1/cronjob.go +++ /dev/null @@ -1,241 +0,0 @@ -package v1 - -import ( - "time" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/gin-gonic/gin" -) - -// @Tags Cronjob -// @Summary Create cronjob -// @Description 创建计划任务 -// @Accept json -// @Param request body dto.CronjobCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.CronjobCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := cronjobService.Create(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Cronjob -// @Summary Page cronjobs -// @Description 获取计划任务分页 -// @Accept json -// @Param request body dto.PageCronjob true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /cronjobs/search [post] -func (b *BaseApi) SearchCronjob(c *gin.Context) { - var req dto.PageCronjob - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := cronjobService.SearchWithPage(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Cronjob -// @Summary Page job records -// @Description 获取计划任务记录 -// @Accept json -// @Param request body dto.SearchRecord true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /cronjobs/search/records [post] -func (b *BaseApi) SearchJobRecords(c *gin.Context) { - var req dto.SearchRecord - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - loc, _ := time.LoadLocation(common.LoadTimeZone()) - req.StartTime = req.StartTime.In(loc) - req.EndTime = req.EndTime.In(loc) - - total, list, err := cronjobService.SearchRecords(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Cronjob -// @Summary Load Cronjob record log -// @Description 获取计划任务记录日志 -// @Accept json -// @Param request body dto.OperateByID true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /cronjobs/records/log [post] -func (b *BaseApi) LoadRecordLog(c *gin.Context) { - var req dto.OperateByID - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - content := cronjobService.LoadRecordLog(req) - helper.SuccessWithData(c, content) -} - -// @Tags Cronjob -// @Summary Clean job records -// @Description 清空计划任务记录 -// @Accept json -// @Param request body dto.CronjobClean true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.CronjobClean - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := cronjobService.CleanRecord(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Cronjob -// @Summary Delete cronjob -// @Description 删除计划任务 -// @Accept json -// @Param request body dto.CronjobBatchDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.CronjobBatchDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := cronjobService.Delete(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Cronjob -// @Summary Update cronjob -// @Description 更新计划任务 -// @Accept json -// @Param request body dto.CronjobUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.CronjobUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := cronjobService.Update(req.ID, req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Cronjob -// @Summary Update cronjob status -// @Description 更新计划任务状态 -// @Accept json -// @Param request body dto.CronjobUpdateStatus true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.CronjobUpdateStatus - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := cronjobService.UpdateStatus(req.ID, req.Status); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Cronjob -// @Summary Download cronjob records -// @Description 下载计划任务记录 -// @Accept json -// @Param request body dto.CronjobDownload true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.CronjobDownload - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - filePath, err := cronjobService.Download(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - c.File(filePath) -} - -// @Tags Cronjob -// @Summary Handle cronjob once -// @Description 手动执行计划任务 -// @Accept json -// @Param request body dto.OperateByID true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.OperateByID - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := cronjobService.HandleOnce(req.ID); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/dashboard.go b/backend/app/api/v1/dashboard.go deleted file mode 100644 index 0ada8bdb8..000000000 --- a/backend/app/api/v1/dashboard.go +++ /dev/null @@ -1,99 +0,0 @@ -package v1 - -import ( - "errors" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Dashboard -// @Summary Load os info -// @Description 获取服务器基础数据 -// @Accept json -// @Success 200 {object} dto.OsInfo -// @Security ApiKeyAuth -// @Router /dashboard/base/os [get] -func (b *BaseApi) LoadDashboardOsInfo(c *gin.Context) { - data, err := dashboardService.LoadOsInfo() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, data) -} - -// @Tags Dashboard -// @Summary Load dashboard base info -// @Description 获取首页基础数据 -// @Accept json -// @Param ioOption path string true "request" -// @Param netOption path string true "request" -// @Success 200 {object} dto.DashboardBase -// @Security ApiKeyAuth -// @Router /dashboard/base/:ioOption/:netOption [get] -func (b *BaseApi) LoadDashboardBaseInfo(c *gin.Context) { - ioOption, ok := c.Params.Get("ioOption") - if !ok { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error ioOption in path")) - return - } - netOption, ok := c.Params.Get("netOption") - if !ok { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error netOption in path")) - return - } - data, err := dashboardService.LoadBaseInfo(ioOption, netOption) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, data) -} - -// @Tags Dashboard -// @Summary Load dashboard current info -// @Description 获取首页实时数据 -// @Accept json -// @Param ioOption path string true "request" -// @Param netOption path string true "request" -// @Success 200 {object} dto.DashboardCurrent -// @Security ApiKeyAuth -// @Router /dashboard/current/:ioOption/:netOption [get] -func (b *BaseApi) LoadDashboardCurrentInfo(c *gin.Context) { - ioOption, ok := c.Params.Get("ioOption") - if !ok { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error ioOption in path")) - return - } - netOption, ok := c.Params.Get("netOption") - if !ok { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error netOption in path")) - return - } - - data := dashboardService.LoadCurrentInfo(ioOption, netOption) - helper.SuccessWithData(c, data) -} - -// @Tags Dashboard -// @Summary System restart -// @Description 重启服务器/面板 -// @Accept json -// @Param operation path string true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /dashboard/system/restart/:operation [post] -func (b *BaseApi) SystemRestart(c *gin.Context) { - operation, ok := c.Params.Get("operation") - if !ok { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error operation in path")) - return - } - if err := dashboardService.Restart(operation); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/database.go b/backend/app/api/v1/database.go deleted file mode 100644 index 5a198f7c1..000000000 --- a/backend/app/api/v1/database.go +++ /dev/null @@ -1,229 +0,0 @@ -package v1 - -import ( - "encoding/base64" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Database -// @Summary Create database -// @Description 创建远程数据库 -// @Accept json -// @Param request body dto.DatabaseCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.DatabaseCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if req.SSL { - key, _ := base64.StdEncoding.DecodeString(req.ClientKey) - req.ClientKey = string(key) - cert, _ := base64.StdEncoding.DecodeString(req.ClientCert) - req.ClientCert = string(cert) - ca, _ := base64.StdEncoding.DecodeString(req.RootCert) - req.RootCert = string(ca) - } - - if err := databaseService.Create(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Database -// @Summary Check database -// @Description 检测远程数据库连接性 -// @Accept json -// @Param request body dto.DatabaseCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.DatabaseCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if req.SSL { - clientKey, _ := base64.StdEncoding.DecodeString(req.ClientKey) - req.ClientKey = string(clientKey) - clientCert, _ := base64.StdEncoding.DecodeString(req.ClientCert) - req.ClientCert = string(clientCert) - rootCert, _ := base64.StdEncoding.DecodeString(req.RootCert) - req.RootCert = string(rootCert) - } - - helper.SuccessWithData(c, databaseService.CheckDatabase(req)) -} - -// @Tags Database -// @Summary Page databases -// @Description 获取远程数据库列表分页 -// @Accept json -// @Param request body dto.DatabaseSearch true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /databases/db/search [post] -func (b *BaseApi) SearchDatabase(c *gin.Context) { - var req dto.DatabaseSearch - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := databaseService.SearchWithPage(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Database -// @Summary List databases -// @Description 获取远程数据库列表 -// @Success 200 {array} dto.DatabaseOption -// @Security ApiKeyAuth -// @Router /databases/db/list/:type [get] -func (b *BaseApi) ListDatabase(c *gin.Context) { - dbType, err := helper.GetStrParamByKey(c, "type") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - list, err := databaseService.List(dbType) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, list) -} - -// @Tags Database -// @Summary List databases -// @Description 获取数据库列表 -// @Success 200 {array} dto.DatabaseItem -// @Security ApiKeyAuth -// @Router /databases/db/item/:type [get] -func (b *BaseApi) LoadDatabaseItems(c *gin.Context) { - dbType, err := helper.GetStrParamByKey(c, "type") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - list, err := databaseService.LoadItems(dbType) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, list) -} - -// @Tags Database -// @Summary Get databases -// @Description 获取远程数据库 -// @Success 200 {object} dto.DatabaseInfo -// @Security ApiKeyAuth -// @Router /databases/db/:name [get] -func (b *BaseApi) GetDatabase(c *gin.Context) { - name, err := helper.GetStrParamByKey(c, "name") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - data, err := databaseService.Get(name) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, data) -} - -// @Tags Database -// @Summary Check before delete remote database -// @Description Mysql 远程数据库删除前检查 -// @Accept json -// @Param request body dto.OperateByID true "request" -// @Success 200 {array} string -// @Security ApiKeyAuth -// @Router /db/remote/del/check [post] -func (b *BaseApi) DeleteCheckDatabase(c *gin.Context) { - var req dto.OperateByID - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - apps, err := databaseService.DeleteCheck(req.ID) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, apps) -} - -// @Tags Database -// @Summary Delete database -// @Description 删除远程数据库 -// @Accept json -// @Param request body dto.DatabaseDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.DatabaseDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := databaseService.Delete(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Database -// @Summary Update database -// @Description 更新远程数据库 -// @Accept json -// @Param request body dto.DatabaseUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.DatabaseUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if req.SSL { - cKey, _ := base64.StdEncoding.DecodeString(req.ClientKey) - req.ClientKey = string(cKey) - cCert, _ := base64.StdEncoding.DecodeString(req.ClientCert) - req.ClientCert = string(cCert) - ca, _ := base64.StdEncoding.DecodeString(req.RootCert) - req.RootCert = string(ca) - } - - if err := databaseService.Update(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/database_common.go b/backend/app/api/v1/database_common.go deleted file mode 100644 index 5ff57736e..000000000 --- a/backend/app/api/v1/database_common.go +++ /dev/null @@ -1,75 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Database Common -// @Summary Load base info -// @Description 获取数据库基础信息 -// @Accept json -// @Param request body dto.OperationWithNameAndType true "request" -// @Success 200 {object} dto.DBBaseInfo -// @Security ApiKeyAuth -// @Router /databases/common/info [post] -func (b *BaseApi) LoadDBBaseInfo(c *gin.Context) { - var req dto.OperationWithNameAndType - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - data, err := dbCommonService.LoadBaseInfo(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, data) -} - -// @Tags Database Common -// @Summary Load Database conf -// @Description 获取数据库配置文件 -// @Accept json -// @Param request body dto.OperationWithNameAndType true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /databases/common/load/file [post] -func (b *BaseApi) LoadDBFile(c *gin.Context) { - var req dto.OperationWithNameAndType - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - content, err := dbCommonService.LoadDatabaseFile(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, content) -} - -// @Tags Database Common -// @Summary Update conf by upload file -// @Description 上传替换配置文件 -// @Accept json -// @Param request body dto.DBConfUpdateByFile true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.DBConfUpdateByFile - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := dbCommonService.UpdateConfByFile(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/database_mysql.go b/backend/app/api/v1/database_mysql.go deleted file mode 100644 index 1168dad49..000000000 --- a/backend/app/api/v1/database_mysql.go +++ /dev/null @@ -1,350 +0,0 @@ -package v1 - -import ( - "context" - "encoding/base64" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Database Mysql -// @Summary Create mysql database -// @Description 创建 mysql 数据库 -// @Accept json -// @Param request body dto.MysqlDBCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.MysqlDBCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if len(req.Password) != 0 { - password, err := base64.StdEncoding.DecodeString(req.Password) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.Password = string(password) - } - - if _, err := mysqlService.Create(context.Background(), req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Database Mysql -// @Summary Bind user of mysql database -// @Description 绑定 mysql 数据库用户 -// @Accept json -// @Param request body dto.BindUser true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.BindUser - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if len(req.Password) != 0 { - password, err := base64.StdEncoding.DecodeString(req.Password) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.Password = string(password) - } - - if err := mysqlService.BindUser(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Database Mysql -// @Summary Update mysql database description -// @Description 更新 mysql 数据库库描述信息 -// @Accept json -// @Param request body dto.UpdateDescription true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.UpdateDescription - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := mysqlService.UpdateDescription(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Database Mysql -// @Summary Change mysql password -// @Description 修改 mysql 密码 -// @Accept json -// @Param request body dto.ChangeDBInfo true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ChangeDBInfo - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if len(req.Value) != 0 { - value, err := base64.StdEncoding.DecodeString(req.Value) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.Value = string(value) - } - - if err := mysqlService.ChangePassword(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Database Mysql -// @Summary Change mysql access -// @Description 修改 mysql 访问权限 -// @Accept json -// @Param request body dto.ChangeDBInfo true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ChangeDBInfo - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := mysqlService.ChangeAccess(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Database Mysql -// @Summary Update mysql variables -// @Description mysql 性能调优 -// @Accept json -// @Param request body dto.MysqlVariablesUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.MysqlVariablesUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := mysqlService.UpdateVariables(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Database Mysql -// @Summary Page mysql databases -// @Description 获取 mysql 数据库列表分页 -// @Accept json -// @Param request body dto.MysqlDBSearch true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /databases/search [post] -func (b *BaseApi) SearchMysql(c *gin.Context) { - var req dto.MysqlDBSearch - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := mysqlService.SearchWithPage(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Database Mysql -// @Summary List mysql database names -// @Description 获取 mysql 数据库列表 -// @Accept json -// @Param request body dto.PageInfo true "request" -// @Success 200 {array} dto.MysqlOption -// @Security ApiKeyAuth -// @Router /databases/options [get] -func (b *BaseApi) ListDBName(c *gin.Context) { - list, err := mysqlService.ListDBOption() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, list) -} - -// @Tags Database Mysql -// @Summary Load mysql database from remote -// @Description 从服务器获取 -// @Accept json -// @Param request body dto.MysqlLoadDB true "request" -// @Security ApiKeyAuth -// @Router /databases/load [post] -func (b *BaseApi) LoadDBFromRemote(c *gin.Context) { - var req dto.MysqlLoadDB - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := mysqlService.LoadFromRemote(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Database Mysql -// @Summary Check before delete mysql database -// @Description Mysql 数据库删除前检查 -// @Accept json -// @Param request body dto.MysqlDBDeleteCheck true "request" -// @Success 200 {array} string -// @Security ApiKeyAuth -// @Router /databases/del/check [post] -func (b *BaseApi) DeleteCheckMysql(c *gin.Context) { - var req dto.MysqlDBDeleteCheck - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - apps, err := mysqlService.DeleteCheck(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, apps) -} - -// @Tags Database Mysql -// @Summary Delete mysql database -// @Description 删除 mysql 数据库 -// @Accept json -// @Param request body dto.MysqlDBDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.MysqlDBDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - tx, ctx := helper.GetTxAndContext() - if err := mysqlService.Delete(ctx, req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - tx.Rollback() - return - } - tx.Commit() - helper.SuccessWithData(c, nil) -} - -// @Tags Database Mysql -// @Summary Load mysql remote access -// @Description 获取 mysql 远程访问权限 -// @Accept json -// @Param request body dto.OperationWithNameAndType true "request" -// @Success 200 {boolean} isRemote -// @Security ApiKeyAuth -// @Router /databases/remote [post] -func (b *BaseApi) LoadRemoteAccess(c *gin.Context) { - var req dto.OperationWithNameAndType - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - isRemote, err := mysqlService.LoadRemoteAccess(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, isRemote) -} - -// @Tags Database Mysql -// @Summary Load mysql status info -// @Description 获取 mysql 状态信息 -// @Accept json -// @Param request body dto.OperationWithNameAndType true "request" -// @Success 200 {object} dto.MysqlStatus -// @Security ApiKeyAuth -// @Router /databases/status [post] -func (b *BaseApi) LoadStatus(c *gin.Context) { - var req dto.OperationWithNameAndType - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - data, err := mysqlService.LoadStatus(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, data) -} - -// @Tags Database Mysql -// @Summary Load mysql variables info -// @Description 获取 mysql 性能参数信息 -// @Accept json -// @Param request body dto.OperationWithNameAndType true "request" -// @Success 200 {object} dto.MysqlVariables -// @Security ApiKeyAuth -// @Router /databases/variables [post] -func (b *BaseApi) LoadVariables(c *gin.Context) { - var req dto.OperationWithNameAndType - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - data, err := mysqlService.LoadVariables(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, data) -} diff --git a/backend/app/api/v1/database_postgresql.go b/backend/app/api/v1/database_postgresql.go deleted file mode 100644 index 5bd5f093a..000000000 --- a/backend/app/api/v1/database_postgresql.go +++ /dev/null @@ -1,233 +0,0 @@ -package v1 - -import ( - "context" - "encoding/base64" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Database Postgresql -// @Summary Create postgresql database -// @Description 创建 postgresql 数据库 -// @Accept json -// @Param request body dto.PostgresqlDBCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.PostgresqlDBCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if len(req.Password) != 0 { - password, err := base64.StdEncoding.DecodeString(req.Password) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.Password = string(password) - } - - if _, err := postgresqlService.Create(context.Background(), req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Database Postgresql -// @Summary Bind postgresql user -// @Description 绑定 postgresql 数据库用户 -// @Accept json -// @Param request body dto.PostgresqlBindUser true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.PostgresqlBindUser - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := postgresqlService.BindUser(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Database Postgresql -// @Summary Update postgresql database description -// @Description 更新 postgresql 数据库库描述信息 -// @Accept json -// @Param request body dto.UpdateDescription true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.UpdateDescription - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := postgresqlService.UpdateDescription(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Database Postgresql -// @Summary Change postgresql privileges -// @Description 修改 postgresql 用户权限 -// @Accept json -// @Param request body dto.ChangeDBInfo true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.PostgresqlPrivileges - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := postgresqlService.ChangePrivileges(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Database Postgresql -// @Summary Change postgresql password -// @Description 修改 postgresql 密码 -// @Accept json -// @Param request body dto.ChangeDBInfo true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ChangeDBInfo - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if len(req.Value) != 0 { - value, err := base64.StdEncoding.DecodeString(req.Value) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.Value = string(value) - } - - if err := postgresqlService.ChangePassword(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Database Postgresql -// @Summary Page postgresql databases -// @Description 获取 postgresql 数据库列表分页 -// @Accept json -// @Param request body dto.PostgresqlDBSearch true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /databases/pg/search [post] -func (b *BaseApi) SearchPostgresql(c *gin.Context) { - var req dto.PostgresqlDBSearch - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := postgresqlService.SearchWithPage(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Database Postgresql -// @Summary Load postgresql database from remote -// @Description 从服务器获取 -// @Accept json -// @Param request body dto.PostgresqlLoadDB true "request" -// @Security ApiKeyAuth -// @Router /databases/pg/:database/load [post] -func (b *BaseApi) LoadPostgresqlDBFromRemote(c *gin.Context) { - database, err := helper.GetStrParamByKey(c, "database") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - - if err := postgresqlService.LoadFromRemote(database); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Database Postgresql -// @Summary Check before delete postgresql database -// @Description Postgresql 数据库删除前检查 -// @Accept json -// @Param request body dto.PostgresqlDBDeleteCheck true "request" -// @Success 200 {array} string -// @Security ApiKeyAuth -// @Router /databases/pg/del/check [post] -func (b *BaseApi) DeleteCheckPostgresql(c *gin.Context) { - var req dto.PostgresqlDBDeleteCheck - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - apps, err := postgresqlService.DeleteCheck(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, apps) -} - -// @Tags Database Postgresql -// @Summary Delete postgresql database -// @Description 删除 postgresql 数据库 -// @Accept json -// @Param request body dto.PostgresqlDBDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.PostgresqlDBDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - tx, ctx := helper.GetTxAndContext() - if err := postgresqlService.Delete(ctx, req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - tx.Rollback() - return - } - tx.Commit() - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/database_redis.go b/backend/app/api/v1/database_redis.go deleted file mode 100644 index 60b086280..000000000 --- a/backend/app/api/v1/database_redis.go +++ /dev/null @@ -1,170 +0,0 @@ -package v1 - -import ( - "encoding/base64" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Database Redis -// @Summary Load redis status info -// @Description 获取 redis 状态信息 -// @Accept json -// @Param request body dto.OperationWithName true "request" -// @Success 200 {object} dto.RedisStatus -// @Security ApiKeyAuth -// @Router /databases/redis/status [post] -func (b *BaseApi) LoadRedisStatus(c *gin.Context) { - var req dto.OperationWithName - if err := helper.CheckBind(&req, c); err != nil { - return - } - data, err := redisService.LoadStatus(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, data) -} - -// @Tags Database Redis -// @Summary Load redis conf -// @Description 获取 redis 配置信息 -// @Accept json -// @Param request body dto.OperationWithName true "request" -// @Success 200 {object} dto.RedisConf -// @Security ApiKeyAuth -// @Router /databases/redis/conf [post] -func (b *BaseApi) LoadRedisConf(c *gin.Context) { - var req dto.OperationWithName - if err := helper.CheckBind(&req, c); err != nil { - return - } - data, err := redisService.LoadConf(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, data) -} - -// @Tags Database Redis -// @Summary Load redis persistence conf -// @Description 获取 redis 持久化配置 -// @Accept json -// @Param request body dto.OperationWithName true "request" -// @Success 200 {object} dto.RedisPersistence -// @Security ApiKeyAuth -// @Router /databases/redis/persistence/conf [post] -func (b *BaseApi) LoadPersistenceConf(c *gin.Context) { - var req dto.OperationWithName - if err := helper.CheckBind(&req, c); err != nil { - return - } - data, err := redisService.LoadPersistenceConf(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, data) -} - -func (b *BaseApi) CheckHasCli(c *gin.Context) { - helper.SuccessWithData(c, redisService.CheckHasCli()) -} - -// @Tags Database Redis -// @Summary Install redis-cli -// @Description 安装 redis cli -// @Success 200 -// @Security ApiKeyAuth -// @Router /databases/redis/install/cli [post] -func (b *BaseApi) InstallCli(c *gin.Context) { - if err := redisService.InstallCli(); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithOutData(c) -} - -// @Tags Database Redis -// @Summary Update redis conf -// @Description 更新 redis 配置信息 -// @Accept json -// @Param request body dto.RedisConfUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.RedisConfUpdate - if err := helper.CheckBind(&req, c); err != nil { - return - } - - if err := redisService.UpdateConf(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Database Redis -// @Summary Change redis password -// @Description 更新 redis 密码 -// @Accept json -// @Param request body dto.ChangeRedisPass true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ChangeRedisPass - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if len(req.Value) != 0 { - value, err := base64.StdEncoding.DecodeString(req.Value) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.Value = string(value) - } - - if err := redisService.ChangePassword(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Database Redis -// @Summary Update redis persistence conf -// @Description 更新 redis 持久化配置 -// @Accept json -// @Param request body dto.RedisConfPersistenceUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.RedisConfPersistenceUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := redisService.UpdatePersistenceConf(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/device.go b/backend/app/api/v1/device.go deleted file mode 100644 index 4b04e3f5d..000000000 --- a/backend/app/api/v1/device.go +++ /dev/null @@ -1,236 +0,0 @@ -package v1 - -import ( - "encoding/base64" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Device -// @Summary Load device base info -// @Description 获取设备基础信息 -// @Success 200 {object} dto.DeviceBaseInfo -// @Security ApiKeyAuth -// @Router /toolbox/device/base [post] -func (b *BaseApi) LoadDeviceBaseInfo(c *gin.Context) { - data, err := deviceService.LoadBaseInfo() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, data) -} - -// @Tags Device -// @Summary list time zone options -// @Description 获取系统可用时区选项 -// @Accept json -// @Success 200 {Array} string -// @Security ApiKeyAuth -// @Router /toolbox/device/zone/options [get] -func (b *BaseApi) LoadTimeOption(c *gin.Context) { - list, err := deviceService.LoadTimeZone() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, list) -} - -// @Tags Device -// @Summary load conf -// @Description 获取系统配置文件 -// @Accept json -// @Param request body dto.OperationWithName true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /toolbox/device/conf [post] -func (b *BaseApi) LoadDeviceConf(c *gin.Context) { - var req dto.OperationWithName - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - list, err := deviceService.LoadConf(req.Name) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, list) -} - -// @Tags Device -// @Summary Update device conf by file -// @Description 通过文件修改配置 -// @Accept json -// @Param request body dto.UpdateByNameAndFile true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /toolbox/device/update/byconf [post] -func (b *BaseApi) UpdateDeviceByFile(c *gin.Context) { - var req dto.UpdateByNameAndFile - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := deviceService.UpdateByConf(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Device -// @Summary Update device -// @Description 修改系统参数 -// @Accept json -// @Param request body dto.SettingUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.SettingUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := deviceService.Update(req.Key, req.Value); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Device -// @Summary Update device hosts -// @Description 修改系统 hosts -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req []dto.HostHelper - if err := helper.CheckBind(&req, c); err != nil { - return - } - - if err := deviceService.UpdateHosts(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Device -// @Summary Update device passwd -// @Description 修改系统密码 -// @Accept json -// @Param request body dto.ChangePasswd true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /toolbox/device/update/passwd [post] -func (b *BaseApi) UpdateDevicePasswd(c *gin.Context) { - var req dto.ChangePasswd - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if len(req.Passwd) != 0 { - password, err := base64.StdEncoding.DecodeString(req.Passwd) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.Passwd = string(password) - } - if err := deviceService.UpdatePasswd(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Device -// @Summary Update device swap -// @Description 修改系统 Swap -// @Accept json -// @Param request body dto.SwapHelper true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.SwapHelper - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := deviceService.UpdateSwap(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Device -// @Summary Check device DNS conf -// @Description 检查系统 DNS 配置可用性 -// @Accept json -// @Param request body dto.SettingUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /toolbox/device/check/dns [post] -func (b *BaseApi) CheckDNS(c *gin.Context) { - var req dto.SettingUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - data, err := deviceService.CheckDNS(req.Key, req.Value) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, data) -} - -// @Tags Device -// @Summary Scan system -// @Description 扫描系统垃圾文件 -// @Success 200 -// @Security ApiKeyAuth -// @Router /toolbox/scan [post] -// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"扫描系统垃圾文件","formatEN":"scan System Junk Files"} -func (b *BaseApi) ScanSystem(c *gin.Context) { - helper.SuccessWithData(c, deviceService.Scan()) -} - -// @Tags Device -// @Summary Clean system -// @Description 清理系统垃圾文件 -// @Accept json -// @Param request body []dto.Clean true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /toolbox/clean [post] -// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理系统垃圾文件","formatEN":"Clean system junk files"} -func (b *BaseApi) SystemClean(c *gin.Context) { - var req []dto.Clean - if err := helper.CheckBind(&req, c); err != nil { - return - } - - deviceService.Clean(req) - - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/docker.go b/backend/app/api/v1/docker.go deleted file mode 100644 index 79a2e232f..000000000 --- a/backend/app/api/v1/docker.go +++ /dev/null @@ -1,169 +0,0 @@ -package v1 - -import ( - "os" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Container Docker -// @Summary Load docker status -// @Description 获取 docker 服务状态 -// @Produce json -// @Success 200 {string} status -// @Security ApiKeyAuth -// @Router /containers/docker/status [get] -func (b *BaseApi) LoadDockerStatus(c *gin.Context) { - status := dockerService.LoadDockerStatus() - helper.SuccessWithData(c, status) -} - -// @Tags Container Docker -// @Summary Load docker daemon.json -// @Description 获取 docker 配置信息(表单) -// @Produce json -// @Success 200 {object} string -// @Security ApiKeyAuth -// @Router /containers/daemonjson/file [get] -func (b *BaseApi) LoadDaemonJsonFile(c *gin.Context) { - if _, err := os.Stat(constant.DaemonJsonPath); err != nil { - helper.SuccessWithData(c, "daemon.json is not find in path") - return - } - content, err := os.ReadFile(constant.DaemonJsonPath) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, string(content)) -} - -// @Tags Container Docker -// @Summary Load docker daemon.json -// @Description 获取 docker 配置信息 -// @Produce json -// @Success 200 {object} dto.DaemonJsonConf -// @Security ApiKeyAuth -// @Router /containers/daemonjson [get] -func (b *BaseApi) LoadDaemonJson(c *gin.Context) { - conf := dockerService.LoadDockerConf() - helper.SuccessWithData(c, conf) -} - -// @Tags Container Docker -// @Summary Update docker daemon.json -// @Description 修改 docker 配置信息 -// @Accept json -// @Param request body dto.SettingUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.SettingUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := dockerService.UpdateConf(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Container Docker -// @Summary Update docker daemon.json log option -// @Description 修改 docker 日志配置 -// @Accept json -// @Param request body dto.LogOption true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /containers/logoption/update [post] -// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新日志配置","formatEN":"Updated the log option"} -func (b *BaseApi) UpdateLogOption(c *gin.Context) { - var req dto.LogOption - if err := helper.CheckBind(&req, c); err != nil { - return - } - - if err := dockerService.UpdateLogOption(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Container Docker -// @Summary Update docker daemon.json ipv6 option -// @Description 修改 docker ipv6 配置 -// @Accept json -// @Param request body dto.LogOption true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.Ipv6Option - if err := helper.CheckBind(&req, c); err != nil { - return - } - - if err := dockerService.UpdateIpv6Option(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Container Docker -// @Summary Update docker daemon.json by upload file -// @Description 上传替换 docker 配置文件 -// @Accept json -// @Param request body dto.DaemonJsonUpdateByFile true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /containers/daemonjson/update/byfile [post] -// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新配置文件","formatEN":"Updated configuration file"} -func (b *BaseApi) UpdateDaemonJsonByFile(c *gin.Context) { - var req dto.DaemonJsonUpdateByFile - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := dockerService.UpdateConfByFile(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Container Docker -// @Summary Operate docker -// @Description Docker 操作 -// @Accept json -// @Param request body dto.DockerOperation true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.DockerOperation - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := dockerService.OperateDocker(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/entry.go b/backend/app/api/v1/entry.go deleted file mode 100644 index dfec388d8..000000000 --- a/backend/app/api/v1/entry.go +++ /dev/null @@ -1,69 +0,0 @@ -package v1 - -import "github.com/1Panel-dev/1Panel/backend/app/service" - -type ApiGroup struct { - BaseApi -} - -var ApiGroupApp = new(ApiGroup) - -type BaseApi struct{} - -var ( - dashboardService = service.NewIDashboardService() - - appService = service.NewIAppService() - appInstallService = service.NewIAppInstalledService() - - containerService = service.NewIContainerService() - composeTemplateService = service.NewIComposeTemplateService() - imageRepoService = service.NewIImageRepoService() - imageService = service.NewIImageService() - dockerService = service.NewIDockerService() - - dbCommonService = service.NewIDBCommonService() - mysqlService = service.NewIMysqlService() - postgresqlService = service.NewIPostgresqlService() - databaseService = service.NewIDatabaseService() - redisService = service.NewIRedisService() - - cronjobService = service.NewICronjobService() - - hostService = service.NewIHostService() - groupService = service.NewIGroupService() - fileService = service.NewIFileService() - sshService = service.NewISSHService() - firewallService = service.NewIFirewallService() - - deviceService = service.NewIDeviceService() - fail2banService = service.NewIFail2BanService() - ftpService = service.NewIFtpService() - clamService = service.NewIClamService() - - settingService = service.NewISettingService() - backupService = service.NewIBackupService() - - commandService = service.NewICommandService() - - websiteService = service.NewIWebsiteService() - websiteDnsAccountService = service.NewIWebsiteDnsAccountService() - websiteSSLService = service.NewIWebsiteSSLService() - websiteAcmeAccountService = service.NewIWebsiteAcmeAccountService() - - nginxService = service.NewINginxService() - - logService = service.NewILogService() - snapshotService = service.NewISnapshotService() - - runtimeService = service.NewRuntimeService() - processService = service.NewIProcessService() - phpExtensionsService = service.NewIPHPExtensionsService() - - hostToolService = service.NewIHostToolService() - - recycleBinService = service.NewIRecycleBinService() - favoriteService = service.NewIFavoriteService() - - websiteCAService = service.NewIWebsiteCAService() -) diff --git a/backend/app/api/v1/fail2ban.go b/backend/app/api/v1/fail2ban.go deleted file mode 100644 index 5ffd2c3dc..000000000 --- a/backend/app/api/v1/fail2ban.go +++ /dev/null @@ -1,153 +0,0 @@ -package v1 - -import ( - "os" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Fail2ban -// @Summary Load fail2ban base info -// @Description 获取 Fail2ban 基础信息 -// @Success 200 {object} dto.Fail2BanBaseInfo -// @Security ApiKeyAuth -// @Router /toolbox/fail2ban/base [get] -func (b *BaseApi) LoadFail2BanBaseInfo(c *gin.Context) { - data, err := fail2banService.LoadBaseInfo() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, data) -} - -// @Tags Fail2ban -// @Summary Page fail2ban ip list -// @Description 获取 Fail2ban ip -// @Accept json -// @Param request body dto.Fail2BanSearch true "request" -// @Success 200 {Array} string -// @Security ApiKeyAuth -// @Router /toolbox/fail2ban/search [post] -func (b *BaseApi) SearchFail2Ban(c *gin.Context) { - var req dto.Fail2BanSearch - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - list, err := fail2banService.Search(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, list) -} - -// @Tags Fail2ban -// @Summary Operate fail2ban -// @Description 修改 Fail2ban 状态 -// @Accept json -// @Param request body dto.Operate true "request" -// @Security ApiKeyAuth -// @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) { - var req dto.Operate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := fail2banService.Operate(req.Operation); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Fail2ban -// @Summary Operate sshd of fail2ban -// @Description 配置 sshd -// @Accept json -// @Param request body dto.Operate true "request" -// @Security ApiKeyAuth -// @Router /toolbox/fail2ban/operate/sshd [post] -func (b *BaseApi) OperateSSHD(c *gin.Context) { - var req dto.Fail2BanSet - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := fail2banService.OperateSSHD(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Fail2ban -// @Summary Update fail2ban conf -// @Description 修改 Fail2ban 配置 -// @Accept json -// @Param request body dto.Fail2BanUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.Fail2BanUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := fail2banService.UpdateConf(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Fail2ban -// @Summary Load fail2ban conf -// @Description 获取 fail2ban 配置文件 -// @Accept json -// @Success 200 -// @Security ApiKeyAuth -// @Router /toolbox/fail2ban/load/conf [get] -func (b *BaseApi) LoadFail2BanConf(c *gin.Context) { - path := "/etc/fail2ban/jail.local" - file, err := os.ReadFile(path) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, string(file)) -} - -// @Tags Fail2ban -// @Summary Update fail2ban conf by file -// @Description 通过文件修改 fail2ban 配置 -// @Accept json -// @Param request body dto.UpdateByFile true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /toolbox/fail2ban/update/byconf [post] -func (b *BaseApi) UpdateFail2BanConfByFile(c *gin.Context) { - var req dto.UpdateByFile - if err := helper.CheckBind(&req, c); err != nil { - return - } - if err := fail2banService.UpdateConfByFile(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/favorite.go b/backend/app/api/v1/favorite.go deleted file mode 100644 index 5cd1d57fe..000000000 --- a/backend/app/api/v1/favorite.go +++ /dev/null @@ -1,76 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags File -// @Summary List favorites -// @Description 获取收藏列表 -// @Accept json -// @Param request body dto.PageInfo true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /files/favorite/search [post] -func (b *BaseApi) SearchFavorite(c *gin.Context) { - var req dto.PageInfo - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - total, list, err := favoriteService.Page(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Total: total, - Items: list, - }) -} - -// @Tags File -// @Summary Create favorite -// @Description 创建收藏 -// @Accept json -// @Param request body request.FavoriteCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /files/favorite [post] -// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"收藏文件/文件夹 [path]","formatEN":"收藏文件/文件夹 [path]"} -func (b *BaseApi) CreateFavorite(c *gin.Context) { - var req request.FavoriteCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - favorite, err := favoriteService.Create(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, favorite) -} - -// @Tags File -// @Summary Delete favorite -// @Description 删除收藏 -// @Accept json -// @Param request body request.FavoriteDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.FavoriteDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := favoriteService.Delete(req.ID); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} diff --git a/backend/app/api/v1/file.go b/backend/app/api/v1/file.go deleted file mode 100644 index 19b44eb57..000000000 --- a/backend/app/api/v1/file.go +++ /dev/null @@ -1,801 +0,0 @@ -package v1 - -import ( - "errors" - "fmt" - "io" - "net/http" - "net/url" - "os" - "path" - "path/filepath" - "strconv" - "strings" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/files" - websocket2 "github.com/1Panel-dev/1Panel/backend/utils/websocket" - "github.com/gin-gonic/gin" - "github.com/gorilla/websocket" -) - -// @Tags File -// @Summary List files -// @Description 获取文件列表 -// @Accept json -// @Param request body request.FileOption true "request" -// @Success 200 {object} response.FileInfo -// @Security ApiKeyAuth -// @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) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, files) -} - -// @Tags File -// @Summary Page file -// @Description 分页获取上传文件 -// @Accept json -// @Param request body request.SearchUploadWithPage true "request" -// @Success 200 {array} response.FileInfo -// @Security ApiKeyAuth -// @Router /files/upload/search [post] -func (b *BaseApi) SearchUploadWithPage(c *gin.Context) { - var req request.SearchUploadWithPage - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - total, files, err := fileService.SearchUploadWithPage(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Items: files, - Total: total, - }) -} - -// @Tags File -// @Summary Load files tree -// @Description 加载文件树 -// @Accept json -// @Param request body request.FileOption true "request" -// @Success 200 {array} response.FileTree -// @Security ApiKeyAuth -// @Router /files/tree [post] -func (b *BaseApi) GetFileTree(c *gin.Context) { - var req request.FileOption - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - tree, err := fileService.GetFileTree(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, tree) -} - -// @Tags File -// @Summary Create file -// @Description 创建文件/文件夹 -// @Accept json -// @Param request body request.FileCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.FileCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - err := fileService.Create(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags File -// @Summary Delete file -// @Description 删除文件/文件夹 -// @Accept json -// @Param request body request.FileDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.FileDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - err := fileService.Delete(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags File -// @Summary Batch delete file -// @Description 批量删除文件/文件夹 -// @Accept json -// @Param request body request.FileBatchDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.FileBatchDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - err := fileService.BatchDelete(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags File -// @Summary Change file mode -// @Description 修改文件权限 -// @Accept json -// @Param request body request.FileCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.FileCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - err := fileService.ChangeMode(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags File -// @Summary Change file owner -// @Description 修改文件用户/组 -// @Accept json -// @Param request body request.FileRoleUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.FileRoleUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := fileService.ChangeOwner(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags File -// @Summary Compress file -// @Description 压缩文件 -// @Accept json -// @Param request body request.FileCompress true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /files/compress [post] -// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"压缩文件 [name]","formatEN":"Compress file [name]"} -func (b *BaseApi) CompressFile(c *gin.Context) { - var req request.FileCompress - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - err := fileService.Compress(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags File -// @Summary Decompress file -// @Description 解压文件 -// @Accept json -// @Param request body request.FileDeCompress true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /files/decompress [post] -// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"解压 [path]","formatEN":"Decompress file [path]"} -func (b *BaseApi) DeCompressFile(c *gin.Context) { - var req request.FileDeCompress - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - err := fileService.DeCompress(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags File -// @Summary Load file content -// @Description 获取文件内容 -// @Accept json -// @Param request body request.FileContentReq true "request" -// @Success 200 {object} response.FileInfo -// @Security ApiKeyAuth -// @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) { - var req request.FileContentReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - info, err := fileService.GetContent(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, info) -} - -// @Tags File -// @Summary Update file content -// @Description 更新文件内容 -// @Accept json -// @Param request body request.FileEdit true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.FileEdit - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := fileService.SaveContent(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags File -// @Summary Upload file -// @Description 上传文件 -// @Param file formData file true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /files/upload [post] -// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"上传文件 [path]","formatEN":"Upload file [path]"} -func (b *BaseApi) UploadFiles(c *gin.Context) { - form, err := c.MultipartForm() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - uploadFiles := form.File["file"] - paths := form.Value["path"] - - overwrite := true - if ow, ok := form.Value["overwrite"]; ok { - if len(ow) != 0 { - parseBool, _ := strconv.ParseBool(ow[0]) - overwrite = parseBool - } - } - - if len(paths) == 0 || !strings.Contains(paths[0], "/") { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error paths in request")) - return - } - dir := path.Dir(paths[0]) - - _, err = os.Stat(dir) - if err != nil && os.IsNotExist(err) { - mode, err := files.GetParentMode(dir) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - if err = os.MkdirAll(dir, mode); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, fmt.Errorf("mkdir %s failed, err: %v", dir, err)) - return - } - } - info, err := os.Stat(dir) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - mode := info.Mode() - - fileOp := files.NewFileOp() - - success := 0 - failures := make(buserr.MultiErr) - for _, file := range uploadFiles { - dstFilename := path.Join(paths[0], file.Filename) - dstDir := path.Dir(dstFilename) - if !fileOp.Stat(dstDir) { - if err = fileOp.CreateDir(dstDir, mode); err != nil { - e := fmt.Errorf("create dir [%s] failed, err: %v", path.Dir(dstFilename), err) - failures[file.Filename] = e - global.LOG.Error(e) - continue - } - } - tmpFilename := dstFilename + ".tmp" - if err := c.SaveUploadedFile(file, tmpFilename); err != nil { - _ = os.Remove(tmpFilename) - e := fmt.Errorf("upload [%s] file failed, err: %v", file.Filename, err) - failures[file.Filename] = e - global.LOG.Error(e) - continue - } - dstInfo, statErr := os.Stat(dstFilename) - if overwrite { - _ = os.Remove(dstFilename) - } - - err = os.Rename(tmpFilename, dstFilename) - if err != nil { - _ = os.Remove(tmpFilename) - e := fmt.Errorf("upload [%s] file failed, err: %v", file.Filename, err) - failures[file.Filename] = e - global.LOG.Error(e) - continue - } - if statErr == nil { - _ = os.Chmod(dstFilename, dstInfo.Mode()) - } else { - _ = os.Chmod(dstFilename, mode) - } - success++ - } - if success == 0 { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, failures) - } else { - helper.SuccessWithMsg(c, fmt.Sprintf("%d files upload success", success)) - } -} - -// @Tags File -// @Summary Check file exist -// @Description 检测文件是否存在 -// @Accept json -// @Param request body request.FilePathCheck true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /files/check [post] -func (b *BaseApi) CheckFile(c *gin.Context) { - var req request.FilePathCheck - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if _, err := os.Stat(req.Path); err != nil { - helper.SuccessWithData(c, false) - return - } - helper.SuccessWithData(c, true) -} - -// @Tags File -// @Summary Change file name -// @Description 修改文件名称 -// @Accept json -// @Param request body request.FileRename true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.FileRename - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := fileService.ChangeName(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags File -// @Summary Wget file -// @Description 下载远端文件 -// @Accept json -// @Param request body request.FileWget true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.FileWget - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - key, err := fileService.Wget(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, response.FileWgetRes{ - Key: key, - }) -} - -// @Tags File -// @Summary Move file -// @Description 移动文件 -// @Accept json -// @Param request body request.FileMove true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.FileMove - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := fileService.MvFile(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags File -// @Summary Download file -// @Description 下载文件 -// @Accept json -// @Success 200 -// @Security ApiKeyAuth -// @Router /files/download [get] -func (b *BaseApi) Download(c *gin.Context) { - filePath := c.Query("path") - file, err := os.Open(filePath) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - } - defer file.Close() - info, _ := file.Stat() - c.Header("Content-Length", strconv.FormatInt(info.Size(), 10)) - c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(info.Name())) - http.ServeContent(c.Writer, c.Request, info.Name(), info.ModTime(), file) -} - -// @Tags File -// @Summary Chunk Download file -// @Description 分片下载下载文件 -// @Accept json -// @Param request body request.FileDownload true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /files/chunkdownload [post] -// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"下载文件 [name]","formatEN":"Download file [name]"} -func (b *BaseApi) DownloadChunkFiles(c *gin.Context) { - var req request.FileChunkDownload - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - fileOp := files.NewFileOp() - if !fileOp.Stat(req.Path) { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrPathNotFound, nil) - return - } - filePath := req.Path - fstFile, err := fileOp.OpenFile(filePath) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - info, err := fstFile.Stat() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - if info.IsDir() { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrFileDownloadDir, err) - return - } - - c.Writer.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", req.Name)) - c.Writer.Header().Set("Content-Type", "application/octet-stream") - c.Writer.Header().Set("Content-Length", strconv.FormatInt(info.Size(), 10)) - c.Writer.Header().Set("Accept-Ranges", "bytes") - - if c.Request.Header.Get("Range") != "" { - rangeHeader := c.Request.Header.Get("Range") - rangeArr := strings.Split(rangeHeader, "=")[1] - rangeParts := strings.Split(rangeArr, "-") - - startPos, _ := strconv.ParseInt(rangeParts[0], 10, 64) - - var endPos int64 - if rangeParts[1] == "" { - endPos = info.Size() - 1 - } else { - endPos, _ = strconv.ParseInt(rangeParts[1], 10, 64) - } - - c.Writer.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", startPos, endPos, info.Size())) - c.Writer.WriteHeader(http.StatusPartialContent) - - buffer := make([]byte, 1024*1024) - file, err := os.Open(filePath) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - defer file.Close() - - _, _ = file.Seek(startPos, 0) - reader := io.LimitReader(file, endPos-startPos+1) - _, err = io.CopyBuffer(c.Writer, reader, buffer) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - } else { - c.File(filePath) - } -} - -// @Tags File -// @Summary Load file size -// @Description 获取文件夹大小 -// @Accept json -// @Param request body request.DirSizeReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.DirSizeReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - res, err := fileService.DirSize(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -func mergeChunks(fileName string, fileDir string, dstDir string, chunkCount int, overwrite bool) error { - defer func() { - _ = os.RemoveAll(fileDir) - }() - - op := files.NewFileOp() - dstDir = strings.TrimSpace(dstDir) - mode, _ := files.GetParentMode(dstDir) - if mode == 0 { - mode = 0755 - } - if _, err := os.Stat(dstDir); err != nil && os.IsNotExist(err) { - if err = op.CreateDir(dstDir, mode); err != nil { - return err - } - } - dstFileName := filepath.Join(dstDir, fileName) - dstInfo, statErr := os.Stat(dstFileName) - if statErr == nil { - mode = dstInfo.Mode() - } else { - mode = 0644 - } - if overwrite { - _ = os.Remove(dstFileName) - } - targetFile, err := os.OpenFile(dstFileName, os.O_RDWR|os.O_CREATE, mode) - if err != nil { - return err - } - defer targetFile.Close() - for i := 0; i < chunkCount; i++ { - chunkPath := filepath.Join(fileDir, fmt.Sprintf("%s.%d", fileName, i)) - chunkData, err := os.ReadFile(chunkPath) - if err != nil { - return err - } - _, err = targetFile.Write(chunkData) - if err != nil { - return err - } - _ = os.Remove(chunkPath) - } - - return nil -} - -// @Tags File -// @Summary ChunkUpload file -// @Description 分片上传文件 -// @Param file formData file true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /files/chunkupload [post] -func (b *BaseApi) UploadChunkFiles(c *gin.Context) { - var err error - fileForm, err := c.FormFile("chunk") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - uploadFile, err := fileForm.Open() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - defer uploadFile.Close() - chunkIndex, err := strconv.Atoi(c.PostForm("chunkIndex")) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - chunkCount, err := strconv.Atoi(c.PostForm("chunkCount")) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - fileOp := files.NewFileOp() - tmpDir := path.Join(global.CONF.System.TmpDir, "upload") - if !fileOp.Stat(tmpDir) { - if err := fileOp.CreateDir(tmpDir, 0755); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - } - filename := c.PostForm("filename") - fileDir := filepath.Join(tmpDir, filename) - if chunkIndex == 0 { - if fileOp.Stat(fileDir) { - _ = fileOp.DeleteDir(fileDir) - } - _ = os.MkdirAll(fileDir, 0755) - } - filePath := filepath.Join(fileDir, filename) - - defer func() { - if err != nil { - _ = os.Remove(fileDir) - } - }() - var ( - emptyFile *os.File - chunkData []byte - ) - - emptyFile, err = os.Create(filePath) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - defer emptyFile.Close() - - chunkData, err = io.ReadAll(uploadFile) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, buserr.WithMap(constant.ErrFileUpload, map[string]interface{}{"name": filename, "detail": err.Error()}, err)) - return - } - - chunkPath := filepath.Join(fileDir, fmt.Sprintf("%s.%d", filename, chunkIndex)) - err = os.WriteFile(chunkPath, chunkData, 0644) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, buserr.WithMap(constant.ErrFileUpload, map[string]interface{}{"name": filename, "detail": err.Error()}, err)) - return - } - - if chunkIndex+1 == chunkCount { - overwrite := true - if ow := c.PostForm("overwrite"); ow != "" { - overwrite, _ = strconv.ParseBool(ow) - } - err = mergeChunks(filename, fileDir, c.PostForm("path"), chunkCount, overwrite) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, buserr.WithMap(constant.ErrFileUpload, map[string]interface{}{"name": filename, "detail": err.Error()}, err)) - return - } - helper.SuccessWithData(c, true) - } else { - return - } -} - -var wsUpgrade = websocket.Upgrader{ - CheckOrigin: func(r *http.Request) bool { - return true - }, -} - -func (b *BaseApi) Ws(c *gin.Context) { - ws, err := wsUpgrade.Upgrade(c.Writer, c.Request, nil) - if err != nil { - return - } - wsClient := websocket2.NewWsClient("fileClient", ws) - go wsClient.Read() - go wsClient.Write() -} - -func (b *BaseApi) Keys(c *gin.Context) { - res := &response.FileProcessKeys{} - keys, err := global.CACHE.PrefixScanKey("file-wget-") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - res.Keys = keys - helper.SuccessWithData(c, res) -} - -// @Tags File -// @Summary Read file by Line -// @Description 按行读取日志文件 -// @Param request body request.FileReadByLineReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /files/read [post] -func (b *BaseApi) ReadFileByLine(c *gin.Context) { - var req request.FileReadByLineReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - res, err := fileService.ReadLogByLine(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags File -// @Summary Batch change file mode and owner -// @Description 批量修改文件权限和用户/组 -// @Accept json -// @Param request body request.FileRoleReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.FileRoleReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := fileService.BatchChangeModeAndOwner(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - } - helper.SuccessWithOutData(c) -} diff --git a/backend/app/api/v1/firewall.go b/backend/app/api/v1/firewall.go deleted file mode 100644 index b509e7064..000000000 --- a/backend/app/api/v1/firewall.go +++ /dev/null @@ -1,224 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Firewall -// @Summary Load firewall base info -// @Description 获取防火墙基础信息 -// @Success 200 {object} dto.FirewallBaseInfo -// @Security ApiKeyAuth -// @Router /hosts/firewall/base [get] -func (b *BaseApi) LoadFirewallBaseInfo(c *gin.Context) { - data, err := firewallService.LoadBaseInfo() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, data) -} - -// @Tags Firewall -// @Summary Page firewall rules -// @Description 获取防火墙规则列表分页 -// @Accept json -// @Param request body dto.RuleSearch true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /hosts/firewall/search [post] -func (b *BaseApi) SearchFirewallRule(c *gin.Context) { - var req dto.RuleSearch - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := firewallService.SearchWithPage(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Firewall -// @Summary Page firewall status -// @Description 修改防火墙状态 -// @Accept json -// @Param request body dto.FirewallOperation true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /hosts/firewall/operate [post] -// @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operation] 防火墙","formatEN":"[operation] firewall"} -func (b *BaseApi) OperateFirewall(c *gin.Context) { - var req dto.FirewallOperation - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := firewallService.OperateFirewall(req.Operation); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Firewall -// @Summary Create group -// @Description 创建防火墙端口规则 -// @Accept json -// @Param request body dto.PortRuleOperate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.PortRuleOperate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := firewallService.OperatePortRule(req, true); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// OperateForwardRule -// @Tags Firewall -// @Summary Create group -// @Description 更新防火墙端口转发规则 -// @Accept json -// @Param request body dto.ForwardRuleOperate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ForwardRuleOperate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := firewallService.OperateForwardRule(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Firewall -// @Summary Create group -// @Description 创建防火墙 IP 规则 -// @Accept json -// @Param request body dto.AddrRuleOperate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.AddrRuleOperate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := firewallService.OperateAddressRule(req, true); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Firewall -// @Summary Create group -// @Description 批量删除防火墙规则 -// @Accept json -// @Param request body dto.BatchRuleOperate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /hosts/firewall/batch [post] -func (b *BaseApi) BatchOperateRule(c *gin.Context) { - var req dto.BatchRuleOperate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := firewallService.BatchOperateRule(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Firewall -// @Summary Update rule description -// @Description 更新防火墙描述 -// @Accept json -// @Param request body dto.UpdateFirewallDescription true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /hosts/firewall/update/description [post] -func (b *BaseApi) UpdateFirewallDescription(c *gin.Context) { - var req dto.UpdateFirewallDescription - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := firewallService.UpdateDescription(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Firewall -// @Summary Create group -// @Description 更新端口防火墙规则 -// @Accept json -// @Param request body dto.PortRuleUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /hosts/firewall/update/port [post] -func (b *BaseApi) UpdatePortRule(c *gin.Context) { - var req dto.PortRuleUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := firewallService.UpdatePortRule(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Firewall -// @Summary Create group -// @Description 更新 ip 防火墙规则 -// @Accept json -// @Param request body dto.AddrRuleUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /hosts/firewall/update/addr [post] -func (b *BaseApi) UpdateAddrRule(c *gin.Context) { - var req dto.AddrRuleUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := firewallService.UpdateAddrRule(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/ftp.go b/backend/app/api/v1/ftp.go deleted file mode 100644 index 4241013af..000000000 --- a/backend/app/api/v1/ftp.go +++ /dev/null @@ -1,199 +0,0 @@ -package v1 - -import ( - "encoding/base64" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags FTP -// @Summary Load FTP base info -// @Description 获取 FTP 基础信息 -// @Success 200 {object} dto.FtpBaseInfo -// @Security ApiKeyAuth -// @Router /toolbox/ftp/base [get] -func (b *BaseApi) LoadFtpBaseInfo(c *gin.Context) { - data, err := ftpService.LoadBaseInfo() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, data) -} - -// @Tags FTP -// @Summary Load FTP operation log -// @Description 获取 FTP 操作日志 -// @Accept json -// @Param request body dto.FtpLogSearch true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /toolbox/ftp/log/search [post] -func (b *BaseApi) LoadFtpLogInfo(c *gin.Context) { - var req dto.FtpLogSearch - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := ftpService.LoadLog(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags FTP -// @Summary Operate FTP -// @Description 修改 FTP 状态 -// @Accept json -// @Param request body dto.Operate true "request" -// @Security ApiKeyAuth -// @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) { - var req dto.Operate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := ftpService.Operate(req.Operation); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags FTP -// @Summary Page FTP user -// @Description 获取 FTP 账户列表分页 -// @Accept json -// @Param request body dto.SearchWithPage true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /toolbox/ftp/search [post] -func (b *BaseApi) SearchFtp(c *gin.Context) { - var req dto.SearchWithPage - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := ftpService.SearchWithPage(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags FTP -// @Summary Create FTP user -// @Description 创建 FTP 账户 -// @Accept json -// @Param request body dto.FtpCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.FtpCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if len(req.Password) != 0 { - pass, err := base64.StdEncoding.DecodeString(req.Password) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.Password = string(pass) - } - if _, err := ftpService.Create(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags FTP -// @Summary Delete FTP user -// @Description 删除 FTP 账户 -// @Accept json -// @Param request body dto.BatchDeleteReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.BatchDeleteReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := ftpService.Delete(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags FTP -// @Summary Sync FTP user -// @Description 同步 FTP 账户 -// @Accept json -// @Param request body dto.BatchDeleteReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /toolbox/ftp/sync [post] -// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"同步 FTP 账户","formatEN":"sync FTP users"} -func (b *BaseApi) SyncFtp(c *gin.Context) { - if err := ftpService.Sync(); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags FTP -// @Summary Update FTP user -// @Description 修改 FTP 账户 -// @Accept json -// @Param request body dto.FtpUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.FtpUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if len(req.Password) != 0 { - pass, err := base64.StdEncoding.DecodeString(req.Password) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.Password = string(pass) - } - if err := ftpService.Update(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} diff --git a/backend/app/api/v1/group.go b/backend/app/api/v1/group.go deleted file mode 100644 index 95ce11deb..000000000 --- a/backend/app/api/v1/group.go +++ /dev/null @@ -1,97 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags System Group -// @Summary Create group -// @Description 创建系统组 -// @Accept json -// @Param request body dto.GroupCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /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) { - var req dto.GroupCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := groupService.Create(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags System Group -// @Summary Delete group -// @Description 删除系统组 -// @Accept json -// @Param request body dto.OperateByID true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /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) { - var req dto.OperateByID - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := groupService.Delete(req.ID); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags System Group -// @Summary Update group -// @Description 更新系统组 -// @Accept json -// @Param request body dto.GroupUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /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) { - var req dto.GroupUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := groupService.Update(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags System Group -// @Summary List groups -// @Description 查询系统组 -// @Accept json -// @Param request body dto.GroupSearch true "request" -// @Success 200 {array} dto.GroupInfo -// @Security ApiKeyAuth -// @Router /groups/search [post] -func (b *BaseApi) ListGroup(c *gin.Context) { - var req dto.GroupSearch - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - list, err := groupService.List(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, list) -} diff --git a/backend/app/api/v1/helper/helper.go b/backend/app/api/v1/helper/helper.go deleted file mode 100644 index aa4afa8fa..000000000 --- a/backend/app/api/v1/helper/helper.go +++ /dev/null @@ -1,140 +0,0 @@ -package helper - -import ( - "context" - "fmt" - "net/http" - "strconv" - - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/i18n" - "github.com/gin-gonic/gin" - "github.com/pkg/errors" -) - -func ErrorWithDetail(ctx *gin.Context, code int, msgKey string, err error) { - res := dto.Response{ - Code: code, - Message: "", - } - if msgKey == constant.ErrTypeInternalServer { - switch { - case errors.Is(err, constant.ErrRecordExist): - res.Message = i18n.GetMsgWithMap("ErrRecordExist", nil) - case errors.Is(constant.ErrRecordNotFound, err): - res.Message = i18n.GetMsgWithMap("ErrRecordNotFound", nil) - case errors.Is(constant.ErrInvalidParams, err): - res.Message = i18n.GetMsgWithMap("ErrInvalidParams", nil) - case errors.Is(constant.ErrStructTransform, err): - res.Message = i18n.GetMsgWithMap("ErrStructTransform", map[string]interface{}{"detail": err}) - case errors.Is(constant.ErrCaptchaCode, err): - res.Code = constant.CodeAuth - res.Message = "ErrCaptchaCode" - case errors.Is(constant.ErrAuth, err): - res.Code = constant.CodeAuth - res.Message = "ErrAuth" - case errors.Is(constant.ErrInitialPassword, err): - res.Message = i18n.GetMsgWithMap("ErrInitialPassword", map[string]interface{}{"detail": err}) - case errors.As(err, &buserr.BusinessError{}): - res.Message = err.Error() - default: - res.Message = i18n.GetMsgWithMap(msgKey, map[string]interface{}{"detail": err}) - } - } else { - res.Message = i18n.GetMsgWithMap(msgKey, map[string]interface{}{"detail": err}) - } - ctx.JSON(http.StatusOK, res) - ctx.Abort() -} - -func SuccessWithData(ctx *gin.Context, data interface{}) { - if data == nil { - data = gin.H{} - } - res := dto.Response{ - Code: constant.CodeSuccess, - Data: data, - } - ctx.JSON(http.StatusOK, res) - ctx.Abort() -} - -func SuccessWithOutData(ctx *gin.Context) { - res := dto.Response{ - Code: constant.CodeSuccess, - Message: "success", - } - ctx.JSON(http.StatusOK, res) - ctx.Abort() -} - -func SuccessWithMsg(ctx *gin.Context, msg string) { - res := dto.Response{ - Code: constant.CodeSuccess, - Message: msg, - } - ctx.JSON(http.StatusOK, res) - ctx.Abort() -} - -func GetParamID(c *gin.Context) (uint, error) { - idParam, ok := c.Params.Get("id") - if !ok { - return 0, errors.New("error id in path") - } - intNum, _ := strconv.Atoi(idParam) - return uint(intNum), nil -} - -func GetIntParamByKey(c *gin.Context, key string) (uint, error) { - idParam, ok := c.Params.Get(key) - if !ok { - return 0, fmt.Errorf("error %s in path", key) - } - intNum, _ := strconv.Atoi(idParam) - return uint(intNum), nil -} - -func GetStrParamByKey(c *gin.Context, key string) (string, error) { - idParam, ok := c.Params.Get(key) - if !ok { - return "", fmt.Errorf("error %s in path", key) - } - return idParam, nil -} - -func GetTxAndContext() (tx *gorm.DB, ctx context.Context) { - tx = global.DB.Begin() - ctx = context.WithValue(context.Background(), constant.DB, tx) - return -} - -func CheckBindAndValidate(req interface{}, c *gin.Context) error { - if err := c.ShouldBindJSON(req); err != nil { - ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return err - } - if err := global.VALID.Struct(req); err != nil { - ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return err - } - return nil -} - -func CheckBind(req interface{}, c *gin.Context) error { - if err := c.ShouldBindJSON(&req); err != nil { - ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return err - } - return nil -} - -func ErrResponse(ctx *gin.Context, code int) { - ctx.JSON(code, nil) - ctx.Abort() -} diff --git a/backend/app/api/v1/host.go b/backend/app/api/v1/host.go deleted file mode 100644 index 1789b028f..000000000 --- a/backend/app/api/v1/host.go +++ /dev/null @@ -1,230 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/encrypt" - "github.com/gin-gonic/gin" -) - -// @Tags Host -// @Summary Create host -// @Description 创建主机 -// @Accept json -// @Param request body dto.HostOperate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /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) { - var req dto.HostOperate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - host, err := hostService.Create(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, host) -} - -// @Tags Host -// @Summary Test host conn by info -// @Description 测试主机连接 -// @Accept json -// @Param request body dto.HostConnTest true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /hosts/test/byinfo [post] -func (b *BaseApi) TestByInfo(c *gin.Context) { - var req dto.HostConnTest - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - connStatus := hostService.TestByInfo(req) - helper.SuccessWithData(c, connStatus) -} - -// @Tags Host -// @Summary Test host conn by host id -// @Description 测试主机连接 -// @Accept json -// @Param id path integer true "request" -// @Success 200 {boolean} connStatus -// @Security ApiKeyAuth -// @Router /hosts/test/byid/:id [post] -func (b *BaseApi) TestByID(c *gin.Context) { - id, err := helper.GetParamID(c) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - - connStatus := hostService.TestLocalConn(id) - helper.SuccessWithData(c, connStatus) -} - -// @Tags Host -// @Summary Load host tree -// @Description 加载主机树 -// @Accept json -// @Param request body dto.SearchForTree true "request" -// @Success 200 {array} dto.HostTree -// @Security ApiKeyAuth -// @Router /hosts/tree [post] -func (b *BaseApi) HostTree(c *gin.Context) { - var req dto.SearchForTree - if err := helper.CheckBind(&req, c); err != nil { - return - } - - data, err := hostService.SearchForTree(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, data) -} - -// @Tags Host -// @Summary Page host -// @Description 获取主机列表分页 -// @Accept json -// @Param request body dto.SearchHostWithPage true "request" -// @Success 200 {array} dto.HostTree -// @Security ApiKeyAuth -// @Router /hosts/search [post] -func (b *BaseApi) SearchHost(c *gin.Context) { - var req dto.SearchHostWithPage - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := hostService.SearchWithPage(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Host -// @Summary Delete host -// @Description 删除主机 -// @Accept json -// @Param request body dto.BatchDeleteReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /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) { - var req dto.BatchDeleteReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := hostService.Delete(req.Ids); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Host -// @Summary Update host -// @Description 更新主机 -// @Accept json -// @Param request body dto.HostOperate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /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) { - var req dto.HostOperate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - var err error - if len(req.Password) != 0 && req.AuthMode == "password" { - req.Password, err = hostService.EncryptHost(req.Password) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.PrivateKey = "" - req.PassPhrase = "" - } - if len(req.PrivateKey) != 0 && req.AuthMode == "key" { - req.PrivateKey, err = hostService.EncryptHost(req.PrivateKey) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - if len(req.PassPhrase) != 0 { - req.PassPhrase, err = encrypt.StringEncrypt(req.PassPhrase) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - } - req.Password = "" - } - - upMap := make(map[string]interface{}) - upMap["name"] = req.Name - upMap["group_id"] = req.GroupID - upMap["addr"] = req.Addr - upMap["port"] = req.Port - upMap["user"] = req.User - upMap["auth_mode"] = req.AuthMode - upMap["remember_password"] = req.RememberPassword - if req.AuthMode == "password" { - upMap["password"] = req.Password - upMap["private_key"] = "" - upMap["pass_phrase"] = "" - } else { - upMap["password"] = "" - upMap["private_key"] = req.PrivateKey - upMap["pass_phrase"] = req.PassPhrase - } - upMap["description"] = req.Description - if err := hostService.Update(req.ID, upMap); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Host -// @Summary Update host group -// @Description 切换分组 -// @Accept json -// @Param request body dto.ChangeHostGroup true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /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) { - var req dto.ChangeHostGroup - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - upMap := make(map[string]interface{}) - upMap["group_id"] = req.GroupID - if err := hostService.Update(req.ID, upMap); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/host_tool.go b/backend/app/api/v1/host_tool.go deleted file mode 100644 index c55fb9bd8..000000000 --- a/backend/app/api/v1/host_tool.go +++ /dev/null @@ -1,180 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Host tool -// @Summary Get tool -// @Description 获取主机工具状态 -// @Accept json -// @Param request body request.HostToolReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /host/tool [post] -func (b *BaseApi) GetToolStatus(c *gin.Context) { - var req request.HostToolReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - config, err := hostToolService.GetToolStatus(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, config) -} - -// @Tags Host tool -// @Summary Create Host tool Config -// @Description 创建主机工具配置 -// @Accept json -// @Param request body request.HostToolCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.HostToolCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := hostToolService.CreateToolConfig(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Host tool -// @Summary Operate tool -// @Description 操作主机工具 -// @Accept json -// @Param request body request.HostToolReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.HostToolReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - err := hostToolService.OperateTool(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Host tool -// @Summary Get tool config -// @Description 操作主机工具配置文件 -// @Accept json -// @Param request body request.HostToolConfig true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.HostToolConfig - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - config, err := hostToolService.OperateToolConfig(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, config) -} - -// @Tags Host tool -// @Summary Get tool -// @Description 获取主机工具日志 -// @Accept json -// @Param request body request.HostToolLogReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /host/tool/log [post] -func (b *BaseApi) GetToolLog(c *gin.Context) { - var req request.HostToolLogReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - logContent, err := hostToolService.GetToolLog(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, logContent) -} - -// @Tags Host tool -// @Summary Create Supervisor process -// @Description 操作守护进程 -// @Accept json -// @Param request body request.SupervisorProcessConfig true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.SupervisorProcessConfig - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - err := hostToolService.OperateSupervisorProcess(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Host tool -// @Summary Get Supervisor process config -// @Description 获取 Supervisor 进程配置 -// @Accept json -// @Success 200 -// @Security ApiKeyAuth -// @Router /host/tool/supervisor/process [get] -func (b *BaseApi) GetProcess(c *gin.Context) { - configs, err := hostToolService.GetSupervisorProcessConfig() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, configs) -} - -// @Tags Host tool -// @Summary Get Supervisor process config -// @Description 操作 Supervisor 进程文件 -// @Accept json -// @Param request body request.SupervisorProcessFileReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.SupervisorProcessFileReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - content, err := hostToolService.OperateSupervisorProcessFile(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, content) -} diff --git a/backend/app/api/v1/image.go b/backend/app/api/v1/image.go deleted file mode 100644 index 6f3743eb3..000000000 --- a/backend/app/api/v1/image.go +++ /dev/null @@ -1,231 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Container Image -// @Summary Page images -// @Description 获取镜像列表分页 -// @Accept json -// @Param request body dto.SearchWithPage true "request" -// @Produce json -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /containers/image/search [post] -func (b *BaseApi) SearchImage(c *gin.Context) { - var req dto.SearchWithPage - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := imageService.Page(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Container Image -// @Summary List all images -// @Description 获取所有镜像列表 -// @Produce json -// @Success 200 {array} dto.ImageInfo -// @Security ApiKeyAuth -// @Router /containers/image/all [get] -func (b *BaseApi) ListAllImage(c *gin.Context) { - list, err := imageService.ListAll() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, list) -} - -// @Tags Container Image -// @Summary load images options -// @Description 获取镜像名称列表 -// @Produce json -// @Success 200 {array} dto.Options -// @Security ApiKeyAuth -// @Router /containers/image [get] -func (b *BaseApi) ListImage(c *gin.Context) { - list, err := imageService.List() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, list) -} - -// @Tags Container Image -// @Summary Build image -// @Description 构建镜像 -// @Accept json -// @Param request body dto.ImageBuild true "request" -// @Success 200 {string} log -// @Security ApiKeyAuth -// @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) { - var req dto.ImageBuild - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - log, err := imageService.ImageBuild(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, log) -} - -// @Tags Container Image -// @Summary Pull image -// @Description 拉取镜像 -// @Accept json -// @Param request body dto.ImagePull true "request" -// @Success 200 {string} log -// @Security ApiKeyAuth -// @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) { - var req dto.ImagePull - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - logPath, err := imageService.ImagePull(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, logPath) -} - -// @Tags Container Image -// @Summary Push image -// @Description 推送镜像 -// @Accept json -// @Param request body dto.ImagePush true "request" -// @Success 200 {string} log -// @Security ApiKeyAuth -// @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) { - var req dto.ImagePush - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - logPath, err := imageService.ImagePush(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, logPath) -} - -// @Tags Container Image -// @Summary Delete image -// @Description 删除镜像 -// @Accept json -// @Param request body dto.BatchDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.BatchDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := imageService.ImageRemove(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Container Image -// @Summary Save image -// @Description 导出镜像 -// @Accept json -// @Param request body dto.ImageSave true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ImageSave - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := imageService.ImageSave(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Container Image -// @Summary Tag image -// @Description Tag 镜像 -// @Accept json -// @Param request body dto.ImageTag true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ImageTag - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := imageService.ImageTag(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -// @Tags Container Image -// @Summary Load image -// @Description 导入镜像 -// @Accept json -// @Param request body dto.ImageLoad true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ImageLoad - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := imageService.ImageLoad(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/image_repo.go b/backend/app/api/v1/image_repo.go deleted file mode 100644 index b6e1c5c42..000000000 --- a/backend/app/api/v1/image_repo.go +++ /dev/null @@ -1,143 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Container Image-repo -// @Summary Page image repos -// @Description 获取镜像仓库列表分页 -// @Accept json -// @Param request body dto.SearchWithPage true "request" -// @Produce json -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /containers/repo/search [post] -func (b *BaseApi) SearchRepo(c *gin.Context) { - var req dto.SearchWithPage - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, list, err := imageRepoService.Page(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags Container Image-repo -// @Summary List image repos -// @Description 获取镜像仓库列表 -// @Produce json -// @Success 200 {array} dto.ImageRepoOption -// @Security ApiKeyAuth -// @Router /containers/repo [get] -func (b *BaseApi) ListRepo(c *gin.Context) { - list, err := imageRepoService.List() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, list) -} - -// @Tags Container Image-repo -// @Summary Load repo status -// @Description 获取 docker 仓库状态 -// @Accept json -// @Param request body dto.OperateByID true "request" -// @Produce json -// @Success 200 -// @Security ApiKeyAuth -// @Router /containers/repo/status [get] -func (b *BaseApi) CheckRepoStatus(c *gin.Context) { - var req dto.OperateByID - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := imageRepoService.Login(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container Image-repo -// @Summary Create image repo -// @Description 创建镜像仓库 -// @Accept json -// @Param request body dto.ImageRepoDelete true "request" -// @Produce json -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ImageRepoCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := imageRepoService.Create(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container Image-repo -// @Summary Delete image repo -// @Description 删除镜像仓库 -// @Accept json -// @Param request body dto.ImageRepoDelete true "request" -// @Produce json -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ImageRepoDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := imageRepoService.BatchDelete(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Container Image-repo -// @Summary Update image repo -// @Description 更新镜像仓库 -// @Accept json -// @Param request body dto.ImageRepoUpdate true "request" -// @Produce json -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.ImageRepoUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := imageRepoService.Update(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/logs.go b/backend/app/api/v1/logs.go deleted file mode 100644 index 311b5159b..000000000 --- a/backend/app/api/v1/logs.go +++ /dev/null @@ -1,45 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Logs -// @Summary Load system log files -// @Description 获取系统日志文件列表 -// @Success 200 -// @Security ApiKeyAuth -// @Router /logs/system/files [get] -func (b *BaseApi) GetSystemFiles(c *gin.Context) { - data, err := logService.ListSystemLogFile() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, data) -} - -// @Tags Logs -// @Summary Load system logs -// @Description 获取系统日志 -// @Success 200 -// @Security ApiKeyAuth -// @Router /logs/system [post] -func (b *BaseApi) GetSystemLogs(c *gin.Context) { - var req dto.OperationWithName - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - data, err := logService.LoadSystemLog(req.Name) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, data) -} diff --git a/backend/app/api/v1/monitor.go b/backend/app/api/v1/monitor.go deleted file mode 100644 index 0f7a6e767..000000000 --- a/backend/app/api/v1/monitor.go +++ /dev/null @@ -1,134 +0,0 @@ -package v1 - -import ( - "sort" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/gin-gonic/gin" - "github.com/shirou/gopsutil/v3/disk" - "github.com/shirou/gopsutil/v3/net" -) - -// @Tags Monitor -// @Summary Load monitor datas -// @Description 获取监控数据 -// @Param request body dto.MonitorSearch true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /hosts/monitor/search [post] -func (b *BaseApi) LoadMonitor(c *gin.Context) { - var req dto.MonitorSearch - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - loc, _ := time.LoadLocation(common.LoadTimeZone()) - req.StartTime = req.StartTime.In(loc) - req.EndTime = req.EndTime.In(loc) - - var backdatas []dto.MonitorData - if req.Param == "all" || req.Param == "cpu" || req.Param == "memory" || req.Param == "load" { - var bases []model.MonitorBase - if err := global.MonitorDB. - Where("created_at > ? AND created_at < ?", req.StartTime, req.EndTime). - Find(&bases).Error; err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - var itemData dto.MonitorData - itemData.Param = "base" - for _, base := range bases { - itemData.Date = append(itemData.Date, base.CreatedAt) - itemData.Value = append(itemData.Value, base) - } - backdatas = append(backdatas, itemData) - } - if req.Param == "all" || req.Param == "io" { - var bases []model.MonitorIO - if err := global.MonitorDB. - Where("created_at > ? AND created_at < ?", req.StartTime, req.EndTime). - Find(&bases).Error; err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - var itemData dto.MonitorData - itemData.Param = "io" - for _, base := range bases { - itemData.Date = append(itemData.Date, base.CreatedAt) - itemData.Value = append(itemData.Value, base) - } - backdatas = append(backdatas, itemData) - } - if req.Param == "all" || req.Param == "network" { - var bases []model.MonitorNetwork - if err := global.MonitorDB. - Where("name = ? AND created_at > ? AND created_at < ?", req.Info, req.StartTime, req.EndTime). - Find(&bases).Error; err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - var itemData dto.MonitorData - itemData.Param = "network" - for _, base := range bases { - itemData.Date = append(itemData.Date, base.CreatedAt) - itemData.Value = append(itemData.Value, base) - } - backdatas = append(backdatas, itemData) - } - helper.SuccessWithData(c, backdatas) -} - -// @Tags Monitor -// @Summary Clean monitor datas -// @Description 清空监控数据 -// @Success 200 -// @Security ApiKeyAuth -// @Router /hosts/monitor/clean [post] -// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清空监控数据","formatEN":"clean monitor datas"} -func (b *BaseApi) CleanMonitor(c *gin.Context) { - if err := global.MonitorDB.Exec("DELETE FROM monitor_bases").Error; err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - if err := global.MonitorDB.Exec("DELETE FROM monitor_ios").Error; err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - if err := global.MonitorDB.Exec("DELETE FROM monitor_networks").Error; err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - - helper.SuccessWithData(c, nil) -} - -func (b *BaseApi) GetNetworkOptions(c *gin.Context) { - netStat, _ := net.IOCounters(true) - var options []string - options = append(options, "all") - for _, net := range netStat { - options = append(options, net.Name) - } - sort.Strings(options) - helper.SuccessWithData(c, options) -} - -func (b *BaseApi) GetIOOptions(c *gin.Context) { - diskStat, _ := disk.IOCounters() - var options []string - options = append(options, "all") - for _, net := range diskStat { - options = append(options, net.Name) - } - sort.Strings(options) - helper.SuccessWithData(c, options) -} diff --git a/backend/app/api/v1/nginx.go b/backend/app/api/v1/nginx.go deleted file mode 100644 index 8249f19dc..000000000 --- a/backend/app/api/v1/nginx.go +++ /dev/null @@ -1,118 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags OpenResty -// @Summary Load OpenResty conf -// @Description 获取 OpenResty 配置信息 -// @Success 200 {object} response.FileInfo -// @Security ApiKeyAuth -// @Router /openresty [get] -func (b *BaseApi) GetNginx(c *gin.Context) { - fileInfo, err := nginxService.GetNginxConfig() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, fileInfo) -} - -// @Tags OpenResty -// @Summary Load partial OpenResty conf -// @Description 获取部分 OpenResty 配置信息 -// @Accept json -// @Param request body request.NginxScopeReq true "request" -// @Success 200 {array} response.NginxParam -// @Security ApiKeyAuth -// @Router /openresty/scope [post] -func (b *BaseApi) GetNginxConfigByScope(c *gin.Context) { - var req request.NginxScopeReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - params, err := nginxService.GetConfigByScope(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, params) -} - -// @Tags OpenResty -// @Summary Update OpenResty conf -// @Description 更新 OpenResty 配置信息 -// @Accept json -// @Param request body request.NginxConfigUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.NginxConfigUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := nginxService.UpdateConfigByScope(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags OpenResty -// @Summary Load OpenResty status info -// @Description 获取 OpenResty 状态信息 -// @Success 200 {object} response.NginxStatus -// @Security ApiKeyAuth -// @Router /openresty/status [get] -func (b *BaseApi) GetNginxStatus(c *gin.Context) { - res, err := nginxService.GetStatus() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags OpenResty -// @Summary Update OpenResty conf by upload file -// @Description 上传更新 OpenResty 配置文件 -// @Accept json -// @Param request body request.NginxConfigFileUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /openresty/file [post] -// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 nginx 配置","formatEN":"Update nginx conf"} -func (b *BaseApi) UpdateNginxFile(c *gin.Context) { - var req request.NginxConfigFileUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := nginxService.UpdateConfigFile(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags OpenResty -// @Summary Clear OpenResty proxy cache -// @Description 清理 OpenResty 代理缓存 -// @Success 200 -// @Security ApiKeyAuth -// @Router /openresty/clear [post] -// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理 Openresty 代理缓存","formatEN":"Clear nginx proxy cache"} -func (b *BaseApi) ClearNginxProxyCache(c *gin.Context) { - if err := nginxService.ClearProxyCache(); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} diff --git a/backend/app/api/v1/php_extensions.go b/backend/app/api/v1/php_extensions.go deleted file mode 100644 index 9af31f4f1..000000000 --- a/backend/app/api/v1/php_extensions.go +++ /dev/null @@ -1,103 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags PHP Extensions -// @Summary Page Extensions -// @Description Page Extensions -// @Accept json -// @Param request body request.PHPExtensionsSearch true "request" -// @Success 200 {array} response.PHPExtensionsDTO -// @Security ApiKeyAuth -// @Router /runtimes/php/extensions/search [post] -func (b *BaseApi) PagePHPExtensions(c *gin.Context) { - var req request.PHPExtensionsSearch - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if req.All { - list, err := phpExtensionsService.List() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, list) - } else { - total, list, err := phpExtensionsService.Page(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Total: total, - Items: list, - }) - } - -} - -// @Tags PHP Extensions -// @Summary Create Extensions -// @Description Create Extensions -// @Accept json -// @Param request body request.PHPExtensionsCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /runtimes/php/extensions [post] -func (b *BaseApi) CreatePHPExtensions(c *gin.Context) { - var req request.PHPExtensionsCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := phpExtensionsService.Create(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags PHP Extensions -// @Summary Update Extensions -// @Description Update Extensions -// @Accept json -// @Param request body request.PHPExtensionsUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /runtimes/php/extensions/update [post] -func (b *BaseApi) UpdatePHPExtensions(c *gin.Context) { - var req request.PHPExtensionsUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := phpExtensionsService.Update(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags PHP Extensions -// @Summary Delete Extensions -// @Description Delete Extensions -// @Accept json -// @Param request body request.PHPExtensionsDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /runtimes/php/extensions/del [post] -func (b *BaseApi) DeletePHPExtensions(c *gin.Context) { - var req request.PHPExtensionsDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := phpExtensionsService.Delete(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} diff --git a/backend/app/api/v1/process.go b/backend/app/api/v1/process.go deleted file mode 100644 index 70666ac09..000000000 --- a/backend/app/api/v1/process.go +++ /dev/null @@ -1,39 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/constant" - websocket2 "github.com/1Panel-dev/1Panel/backend/utils/websocket" - "github.com/gin-gonic/gin" -) - -func (b *BaseApi) ProcessWs(c *gin.Context) { - ws, err := wsUpgrade.Upgrade(c.Writer, c.Request, nil) - if err != nil { - return - } - wsClient := websocket2.NewWsClient("processClient", ws) - go wsClient.Read() - go wsClient.Write() -} - -// @Tags Process -// @Summary Stop Process -// @Description 停止进程 -// @Param request body request.ProcessReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /process/stop [post] -// @x-panel-log {"bodyKeys":["PID"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"结束进程 [PID]","formatEN":"结束进程 [PID]"} -func (b *BaseApi) StopProcess(c *gin.Context) { - var req request.ProcessReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := processService.StopProcess(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - helper.SuccessWithOutData(c) -} diff --git a/backend/app/api/v1/recycle_bin.go b/backend/app/api/v1/recycle_bin.go deleted file mode 100644 index 0c7794e01..000000000 --- a/backend/app/api/v1/recycle_bin.go +++ /dev/null @@ -1,86 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags File -// @Summary List RecycleBin files -// @Description 获取回收站文件列表 -// @Accept json -// @Param request body dto.PageInfo true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /files/recycle/search [post] -func (b *BaseApi) SearchRecycleBinFile(c *gin.Context) { - var req dto.PageInfo - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - total, list, err := recycleBinService.Page(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - -// @Tags File -// @Summary Reduce RecycleBin files -// @Description 还原回收站文件 -// @Accept json -// @Param request body request.RecycleBinReduce true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.RecycleBinReduce - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := recycleBinService.Reduce(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags File -// @Summary Clear RecycleBin files -// @Description 清空回收站文件 -// @Accept json -// @Success 200 -// @Security ApiKeyAuth -// @Router /files/recycle/clear [post] -// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清空回收站","formatEN":"清空回收站"} -func (b *BaseApi) ClearRecycleBinFile(c *gin.Context) { - if err := recycleBinService.Clear(); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags File -// @Summary Get RecycleBin status -// @Description 获取回收站状态 -// @Accept json -// @Success 200 -// @Security ApiKeyAuth -// @Router /files/recycle/status [get] -func (b *BaseApi) GetRecycleStatus(c *gin.Context) { - settingInfo, err := settingService.GetSettingInfo() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, settingInfo.FileRecycleBin) -} diff --git a/backend/app/api/v1/runtime.go b/backend/app/api/v1/runtime.go deleted file mode 100644 index e4eef9e86..000000000 --- a/backend/app/api/v1/runtime.go +++ /dev/null @@ -1,235 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Runtime -// @Summary List runtimes -// @Description 获取运行环境列表 -// @Accept json -// @Param request body request.RuntimeSearch true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /runtimes/search [post] -func (b *BaseApi) SearchRuntimes(c *gin.Context) { - var req request.RuntimeSearch - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - total, items, err := runtimeService.Page(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Total: total, - Items: items, - }) -} - -// @Tags Runtime -// @Summary Create runtime -// @Description 创建运行环境 -// @Accept json -// @Param request body request.RuntimeCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /runtimes [post] -// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建运行环境 [name]","formatEN":"Create runtime [name]"} -func (b *BaseApi) CreateRuntime(c *gin.Context) { - var req request.RuntimeCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - ssl, err := runtimeService.Create(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, ssl) -} - -// @Tags Website -// @Summary Delete runtime -// @Description 删除运行环境 -// @Accept json -// @Param request body request.RuntimeDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /runtimes/del [post] -// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除网站 [name]","formatEN":"Delete website [name]"} -func (b *BaseApi) DeleteRuntime(c *gin.Context) { - var req request.RuntimeDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - err := runtimeService.Delete(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -func (b *BaseApi) DeleteRuntimeCheck(c *gin.Context) { - runTimeId, err := helper.GetIntParamByKey(c, "runTimeId") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) - return - } - checkData, err := runtimeService.DeleteCheck(runTimeId) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, checkData) -} - -// @Tags Runtime -// @Summary Update runtime -// @Description 更新运行环境 -// @Accept json -// @Param request body request.RuntimeUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /runtimes/update [post] -// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新运行环境 [name]","formatEN":"Update runtime [name]"} -func (b *BaseApi) UpdateRuntime(c *gin.Context) { - var req request.RuntimeUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := runtimeService.Update(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Runtime -// @Summary Get runtime -// @Description 获取运行环境 -// @Accept json -// @Param id path string true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /runtimes/:id [get] -func (b *BaseApi) GetRuntime(c *gin.Context) { - id, err := helper.GetIntParamByKey(c, "id") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) - return - } - res, err := runtimeService.Get(id) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags Runtime -// @Summary Get Node package scripts -// @Description 获取 Node 项目的 scripts -// @Accept json -// @Param request body request.NodePackageReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /runtimes/node/package [post] -func (b *BaseApi) GetNodePackageRunScript(c *gin.Context) { - var req request.NodePackageReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - res, err := runtimeService.GetNodePackageRunScript(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags Runtime -// @Summary Operate runtime -// @Description 操作运行环境 -// @Accept json -// @Param request body request.RuntimeOperate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /runtimes/operate [post] -// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"操作运行环境 [name]","formatEN":"Operate runtime [name]"} -func (b *BaseApi) OperateRuntime(c *gin.Context) { - var req request.RuntimeOperate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - err := runtimeService.OperateRuntime(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Runtime -// @Summary Get Node modules -// @Description 获取 Node 项目的 modules -// @Accept json -// @Param request body request.NodeModuleReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /runtimes/node/modules [post] -func (b *BaseApi) GetNodeModules(c *gin.Context) { - var req request.NodeModuleReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - res, err := runtimeService.GetNodeModules(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags Runtime -// @Summary Operate Node modules -// @Description 操作 Node 项目 modules -// @Accept json -// @Param request body request.NodeModuleReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /runtimes/node/modules/operate [post] -func (b *BaseApi) OperateNodeModules(c *gin.Context) { - var req request.NodeModuleOperateReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - err := runtimeService.OperateNodeModules(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Runtime -// @Summary Sync runtime status -// @Description 同步运行环境状态 -// @Accept json -// @Success 200 -// @Security ApiKeyAuth -// @Router /runtimes/sync [post] -func (b *BaseApi) SyncStatus(c *gin.Context) { - err := runtimeService.SyncRuntimeStatus() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} diff --git a/backend/app/api/v1/setting.go b/backend/app/api/v1/setting.go deleted file mode 100644 index 561882cf0..000000000 --- a/backend/app/api/v1/setting.go +++ /dev/null @@ -1,66 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/gin-gonic/gin" -) - -// @Tags System Setting -// @Summary Load system setting info -// @Description 加载系统配置信息 -// @Success 200 {object} dto.SettingInfo -// @Security ApiKeyAuth -// @Router /settings/search [post] -func (b *BaseApi) GetSettingInfo(c *gin.Context) { - setting, err := settingService.GetSettingInfo() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, setting) -} - -// @Tags System Setting -// @Summary Load system available status -// @Description 获取系统可用状态 -// @Success 200 -// @Security ApiKeyAuth -// @Router /settings/search/available [get] -func (b *BaseApi) GetSystemAvailable(c *gin.Context) { - helper.SuccessWithData(c, nil) -} - -// @Tags System Setting -// @Summary Update system setting -// @Description 更新系统配置 -// @Accept json -// @Param request body dto.SettingUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.SettingUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := settingService.Update(req.Key, req.Value); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags System Setting -// @Summary Load local backup dir -// @Description 获取安装根目录 -// @Success 200 {string} path -// @Security ApiKeyAuth -// @Router /settings/basedir [get] -func (b *BaseApi) LoadBaseDir(c *gin.Context) { - helper.SuccessWithData(c, global.CONF.System.DataDir) -} diff --git a/backend/app/api/v1/snapshot.go b/backend/app/api/v1/snapshot.go deleted file mode 100644 index 3f79be8ac..000000000 --- a/backend/app/api/v1/snapshot.go +++ /dev/null @@ -1,187 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags System Setting -// @Summary Create system snapshot -// @Description 创建系统快照 -// @Accept json -// @Param request body dto.SnapshotCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.SnapshotCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := snapshotService.SnapshotCreate(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags System Setting -// @Summary Import system snapshot -// @Description 导入已有快照 -// @Accept json -// @Param request body dto.SnapshotImport true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.SnapshotImport - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := snapshotService.SnapshotImport(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags System Setting -// @Summary Load Snapshot status -// @Description 获取快照状态 -// @Accept json -// @Param request body dto.OperateByID true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /settings/snapshot/status [post] -func (b *BaseApi) LoadSnapShotStatus(c *gin.Context) { - var req dto.OperateByID - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - data, err := snapshotService.LoadSnapShotStatus(req.ID) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, data) -} - -// @Tags System Setting -// @Summary Update snapshot description -// @Description 更新快照描述信息 -// @Accept json -// @Param request body dto.UpdateDescription true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.UpdateDescription - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := snapshotService.UpdateDescription(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags System Setting -// @Summary Page system snapshot -// @Description 获取系统快照列表分页 -// @Accept json -// @Param request body dto.SearchWithPage true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /settings/snapshot/search [post] -func (b *BaseApi) SearchSnapshot(c *gin.Context) { - var req dto.SearchWithPage - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - total, accounts, err := snapshotService.SearchWithPage(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Total: total, - Items: accounts, - }) -} - -// @Tags System Setting -// @Summary Recover system backup -// @Description 从系统快照恢复 -// @Accept json -// @Param request body dto.SnapshotRecover true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.SnapshotRecover - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := snapshotService.SnapshotRecover(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags System Setting -// @Summary Rollback system backup -// @Description 从系统快照回滚 -// @Accept json -// @Param request body dto.SnapshotRecover true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.SnapshotRecover - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := snapshotService.SnapshotRollback(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags System Setting -// @Summary Delete system backup -// @Description 删除系统快照 -// @Accept json -// @Param request body dto.SnapshotBatchDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.SnapshotBatchDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := snapshotService.Delete(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/ssh.go b/backend/app/api/v1/ssh.go deleted file mode 100644 index b522a42b5..000000000 --- a/backend/app/api/v1/ssh.go +++ /dev/null @@ -1,169 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags SSH -// @Summary Load host SSH setting info -// @Description 加载 SSH 配置信息 -// @Success 200 {object} dto.SSHInfo -// @Security ApiKeyAuth -// @Router /host/ssh/search [post] -func (b *BaseApi) GetSSHInfo(c *gin.Context) { - info, err := sshService.GetSSHInfo() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, info) -} - -// @Tags SSH -// @Summary Operate SSH -// @Description 修改 SSH 服务状态 -// @Accept json -// @Param request body dto.Operate true "request" -// @Security ApiKeyAuth -// @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) { - var req dto.Operate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := sshService.OperateSSH(req.Operation); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags SSH -// @Summary Update host SSH setting -// @Description 更新 SSH 配置 -// @Accept json -// @Param request body dto.SSHUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req dto.SSHUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := sshService.Update(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags SSH -// @Summary Update host SSH setting by file -// @Description 上传文件更新 SSH 配置 -// @Accept json -// @Param request body dto.SSHConf true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /host/conffile/update [post] -// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置文件","formatEN":"update SSH conf"} -func (b *BaseApi) UpdateSSHByfile(c *gin.Context) { - var req dto.SSHConf - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := sshService.UpdateByFile(req.File); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags SSH -// @Summary Generate host SSH secret -// @Description 生成 SSH 密钥 -// @Accept json -// @Param request body dto.GenerateSSH true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /host/ssh/generate [post] -// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"生成 SSH 密钥 ","formatEN":"generate SSH secret"} -func (b *BaseApi) GenerateSSH(c *gin.Context) { - var req dto.GenerateSSH - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := sshService.GenerateSSH(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags SSH -// @Summary Load host SSH secret -// @Description 获取 SSH 密钥 -// @Accept json -// @Param request body dto.GenerateLoad true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /host/ssh/secret [post] -func (b *BaseApi) LoadSSHSecret(c *gin.Context) { - var req dto.GenerateLoad - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - data, err := sshService.LoadSSHSecret(req.EncryptionMode) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, data) -} - -// @Tags SSH -// @Summary Load host SSH logs -// @Description 获取 SSH 登录日志 -// @Accept json -// @Param request body dto.SearchSSHLog true "request" -// @Success 200 {object} dto.SSHLog -// @Security ApiKeyAuth -// @Router /host/ssh/log [post] -func (b *BaseApi) LoadSSHLogs(c *gin.Context) { - var req dto.SearchSSHLog - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - data, err := sshService.LoadLog(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, data) -} - -// @Tags SSH -// @Summary Load host SSH conf -// @Description 获取 SSH 配置文件 -// @Success 200 -// @Security ApiKeyAuth -// @Router /host/ssh/conf [get] -func (b *BaseApi) LoadSSHConf(c *gin.Context) { - data, err := sshService.LoadSSHConf() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, data) -} diff --git a/backend/app/api/v1/terminal.go b/backend/app/api/v1/terminal.go deleted file mode 100644 index f79b66a3c..000000000 --- a/backend/app/api/v1/terminal.go +++ /dev/null @@ -1,285 +0,0 @@ -package v1 - -import ( - "encoding/base64" - "encoding/json" - "fmt" - "net/http" - "strconv" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/copier" - "github.com/1Panel-dev/1Panel/backend/utils/ssh" - "github.com/1Panel-dev/1Panel/backend/utils/terminal" - "github.com/gin-gonic/gin" - "github.com/gorilla/websocket" - "github.com/pkg/errors" -) - -func (b *BaseApi) WsSsh(c *gin.Context) { - wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil) - if err != nil { - global.LOG.Errorf("gin context http handler failed, err: %v", err) - return - } - defer wsConn.Close() - - id, err := strconv.Atoi(c.Query("id")) - if wshandleError(wsConn, errors.WithMessage(err, "invalid param id in request")) { - return - } - cols, err := strconv.Atoi(c.DefaultQuery("cols", "80")) - if wshandleError(wsConn, errors.WithMessage(err, "invalid param cols in request")) { - return - } - rows, err := strconv.Atoi(c.DefaultQuery("rows", "40")) - if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) { - return - } - host, err := hostService.GetHostInfo(uint(id)) - if wshandleError(wsConn, errors.WithMessage(err, "load host info by id failed")) { - return - } - var connInfo ssh.ConnInfo - _ = copier.Copy(&connInfo, &host) - connInfo.PrivateKey = []byte(host.PrivateKey) - if len(host.PassPhrase) != 0 { - connInfo.PassPhrase = []byte(host.PassPhrase) - } - - client, err := connInfo.NewClient() - if wshandleError(wsConn, errors.WithMessage(err, "failed to set up the connection. Please check the host information")) { - return - } - defer client.Close() - sws, err := terminal.NewLogicSshWsSession(cols, rows, true, connInfo.Client, wsConn) - if wshandleError(wsConn, err) { - return - } - defer sws.Close() - - quitChan := make(chan bool, 3) - sws.Start(quitChan) - go sws.Wait(quitChan) - - <-quitChan - - if wshandleError(wsConn, err) { - return - } -} - -func (b *BaseApi) RedisWsSsh(c *gin.Context) { - wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil) - if err != nil { - global.LOG.Errorf("gin context http handler failed, err: %v", err) - return - } - defer wsConn.Close() - - if global.CONF.System.IsDemo { - if wshandleError(wsConn, errors.New(" demo server, prohibit this operation!")) { - return - } - } - - cols, err := strconv.Atoi(c.DefaultQuery("cols", "80")) - if wshandleError(wsConn, errors.WithMessage(err, "invalid param cols in request")) { - return - } - rows, err := strconv.Atoi(c.DefaultQuery("rows", "40")) - if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) { - return - } - name := c.Query("name") - from := c.Query("from") - commands := []string{"redis-cli"} - database, err := databaseService.Get(name) - if wshandleError(wsConn, errors.WithMessage(err, "no such database in db")) { - return - } - if from == "local" { - redisInfo, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Name: name, Type: "redis"}) - if wshandleError(wsConn, errors.WithMessage(err, "no such database in db")) { - return - } - name = redisInfo.ContainerName - if len(database.Password) != 0 { - commands = []string{"redis-cli", "-a", database.Password, "--no-auth-warning"} - } - } else { - itemPort := fmt.Sprintf("%v", database.Port) - commands = []string{"redis-cli", "-h", database.Address, "-p", itemPort} - if len(database.Password) != 0 { - commands = []string{"redis-cli", "-h", database.Address, "-p", itemPort, "-a", database.Password, "--no-auth-warning"} - } - name = "1Panel-redis-cli-tools" - } - - pidMap := loadMapFromDockerTop(name) - itemCmds := append([]string{"exec", "-it", name}, commands...) - slave, err := terminal.NewCommand(itemCmds) - if wshandleError(wsConn, err) { - return - } - defer killBash(name, strings.Join(commands, " "), pidMap) - defer slave.Close() - - tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false) - if wshandleError(wsConn, err) { - return - } - - quitChan := make(chan bool, 3) - tty.Start(quitChan) - go slave.Wait(quitChan) - - <-quitChan - - global.LOG.Info("websocket finished") - if wshandleError(wsConn, err) { - return - } -} - -func (b *BaseApi) ContainerWsSsh(c *gin.Context) { - wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil) - if err != nil { - global.LOG.Errorf("gin context http handler failed, err: %v", err) - return - } - defer wsConn.Close() - - if global.CONF.System.IsDemo { - if wshandleError(wsConn, errors.New(" demo server, prohibit this operation!")) { - return - } - } - - containerID := c.Query("containerid") - command := c.Query("command") - user := c.Query("user") - if len(command) == 0 || len(containerID) == 0 { - if wshandleError(wsConn, errors.New("error param of command or containerID")) { - return - } - } - cols, err := strconv.Atoi(c.DefaultQuery("cols", "80")) - if wshandleError(wsConn, errors.WithMessage(err, "invalid param cols in request")) { - return - } - rows, err := strconv.Atoi(c.DefaultQuery("rows", "40")) - if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) { - return - } - - cmds := []string{"exec", containerID, command} - if len(user) != 0 { - cmds = []string{"exec", "-u", user, containerID, command} - } - if cmd.CheckIllegal(user, containerID, command) { - if wshandleError(wsConn, errors.New(" The command contains illegal characters.")) { - return - } - } - stdout, err := cmd.ExecWithCheck("docker", cmds...) - if wshandleError(wsConn, errors.WithMessage(err, stdout)) { - return - } - - commands := []string{"exec", "-it", containerID, command} - if len(user) != 0 { - commands = []string{"exec", "-it", "-u", user, containerID, command} - } - pidMap := loadMapFromDockerTop(containerID) - slave, err := terminal.NewCommand(commands) - if wshandleError(wsConn, err) { - return - } - defer killBash(containerID, command, pidMap) - defer slave.Close() - - tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, true) - if wshandleError(wsConn, err) { - return - } - - quitChan := make(chan bool, 3) - tty.Start(quitChan) - go slave.Wait(quitChan) - - <-quitChan - - global.LOG.Info("websocket finished") - if wshandleError(wsConn, err) { - return - } -} - -func wshandleError(ws *websocket.Conn, err error) bool { - if err != nil { - global.LOG.Errorf("handler ws faled:, err: %v", err) - dt := time.Now().Add(time.Second) - if ctlerr := ws.WriteControl(websocket.CloseMessage, []byte(err.Error()), dt); ctlerr != nil { - wsData, err := json.Marshal(terminal.WsMsg{ - Type: terminal.WsMsgCmd, - Data: base64.StdEncoding.EncodeToString([]byte(err.Error())), - }) - if err != nil { - _ = ws.WriteMessage(websocket.TextMessage, []byte("{\"type\":\"cmd\",\"data\":\"failed to encoding to json\"}")) - } else { - _ = ws.WriteMessage(websocket.TextMessage, wsData) - } - } - return true - } - return false -} - -func loadMapFromDockerTop(containerID string) map[string]string { - pidMap := make(map[string]string) - sudo := cmd.SudoHandleCmd() - - stdout, err := cmd.Execf("%s docker top %s -eo pid,command ", sudo, containerID) - if err != nil { - return pidMap - } - lines := strings.Split(stdout, "\n") - for _, line := range lines { - parts := strings.Fields(line) - if len(parts) < 2 { - continue - } - pidMap[parts[0]] = strings.Join(parts[1:], " ") - } - return pidMap -} - -func killBash(containerID, comm string, pidMap map[string]string) { - sudo := cmd.SudoHandleCmd() - newPidMap := loadMapFromDockerTop(containerID) - for pid, command := range newPidMap { - isOld := false - for pid2 := range pidMap { - if pid == pid2 { - isOld = true - break - } - } - if !isOld && command == comm { - _, _ = cmd.Execf("%s kill -9 %s", sudo, pid) - } - } -} - -var upGrader = websocket.Upgrader{ - ReadBufferSize: 1024, - WriteBufferSize: 1024 * 1024 * 10, - CheckOrigin: func(r *http.Request) bool { - return true - }, -} diff --git a/backend/app/api/v1/website.go b/backend/app/api/v1/website.go deleted file mode 100644 index caef8f261..000000000 --- a/backend/app/api/v1/website.go +++ /dev/null @@ -1,822 +0,0 @@ -package v1 - -import ( - "encoding/base64" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Website -// @Summary Page websites -// @Description 获取网站列表分页 -// @Accept json -// @Param request body request.WebsiteSearch true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /websites/search [post] -func (b *BaseApi) PageWebsite(c *gin.Context) { - var req request.WebsiteSearch - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - total, websites, err := websiteService.PageWebsite(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Total: total, - Items: websites, - }) -} - -// @Tags Website -// @Summary List websites -// @Description 获取网站列表 -// @Success 200 {array} response.WebsiteDTO -// @Security ApiKeyAuth -// @Router /websites/list [get] -func (b *BaseApi) GetWebsites(c *gin.Context) { - websites, err := websiteService.GetWebsites() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, websites) -} - -// @Tags Website -// @Summary List website names -// @Description 获取网站列表 -// @Success 200 {array} string -// @Security ApiKeyAuth -// @Router /websites/options [get] -func (b *BaseApi) GetWebsiteOptions(c *gin.Context) { - websites, err := websiteService.GetWebsiteOptions() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, websites) -} - -// @Tags Website -// @Summary Create website -// @Description 创建网站 -// @Accept json -// @Param request body request.WebsiteCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites [post] -// @x-panel-log {"bodyKeys":["primaryDomain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 [primaryDomain]","formatEN":"Create website [primaryDomain]"} -func (b *BaseApi) CreateWebsite(c *gin.Context) { - var req request.WebsiteCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if len(req.FtpPassword) != 0 { - pass, err := base64.StdEncoding.DecodeString(req.FtpPassword) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.FtpPassword = string(pass) - } - err := websiteService.CreateWebsite(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website -// @Summary Operate website -// @Description 操作网站 -// @Accept json -// @Param request body request.WebsiteOp true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteOp - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - err := websiteService.OpWebsite(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website -// @Summary Delete website -// @Description 删除网站 -// @Accept json -// @Param request body request.WebsiteDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - err := websiteService.DeleteWebsite(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website -// @Summary Update website -// @Description 更新网站 -// @Accept json -// @Param request body request.WebsiteUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/update [post] -// @x-panel-log {"bodyKeys":["primaryDomain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新网站 [primaryDomain]","formatEN":"Update website [primaryDomain]"} -func (b *BaseApi) UpdateWebsite(c *gin.Context) { - var req request.WebsiteUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.UpdateWebsite(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website -// @Summary Search website by id -// @Description 通过 id 查询网站 -// @Accept json -// @Param id path integer true "request" -// @Success 200 {object} response.WebsiteDTO -// @Security ApiKeyAuth -// @Router /websites/:id [get] -func (b *BaseApi) GetWebsite(c *gin.Context) { - id, err := helper.GetParamID(c) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) - return - } - website, err := websiteService.GetWebsite(id) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, website) -} - -// @Tags Website Nginx -// @Summary Search website nginx by id -// @Description 通过 id 查询网站 nginx -// @Accept json -// @Param id path integer true "request" -// @Success 200 {object} response.FileInfo -// @Security ApiKeyAuth -// @Router /websites/:id/config/:type [get] -func (b *BaseApi) GetWebsiteNginx(c *gin.Context) { - id, err := helper.GetParamID(c) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) - return - } - configType := c.Param("type") - - fileInfo, err := websiteService.GetWebsiteNginxConfig(id, configType) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, fileInfo) -} - -// @Tags Website Nginx -// @Summary Load nginx conf -// @Description 获取 nginx 配置 -// @Accept json -// @Param request body request.NginxScopeReq true "request" -// @Success 200 {object} response.WebsiteNginxConfig -// @Security ApiKeyAuth -// @Router /websites/config [post] -func (b *BaseApi) GetNginxConfig(c *gin.Context) { - var req request.NginxScopeReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - config, err := websiteService.GetNginxConfigByScope(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, config) -} - -// @Tags Website Nginx -// @Summary Update nginx conf -// @Description 更新 nginx 配置 -// @Accept json -// @Param request body request.NginxConfigUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.NginxConfigUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.UpdateNginxConfigByScope(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website HTTPS -// @Summary Load https conf -// @Description 获取 https 配置 -// @Accept json -// @Param id path integer true "request" -// @Success 200 {object} response.WebsiteHTTPS -// @Security ApiKeyAuth -// @Router /websites/:id/https [get] -func (b *BaseApi) GetHTTPSConfig(c *gin.Context) { - id, err := helper.GetParamID(c) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) - return - } - res, err := websiteService.GetWebsiteHTTPS(id) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags Website HTTPS -// @Summary Update https conf -// @Description 更新 https 配置 -// @Accept json -// @Param request body request.WebsiteHTTPSOp true "request" -// @Success 200 {object} response.WebsiteHTTPS -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteHTTPSOp - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - tx, ctx := helper.GetTxAndContext() - res, err := websiteService.OpWebsiteHTTPS(ctx, req) - if err != nil { - tx.Rollback() - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - tx.Commit() - helper.SuccessWithData(c, res) -} - -// @Tags Website -// @Summary Check before create website -// @Description 网站创建前检查 -// @Accept json -// @Param request body request.WebsiteInstallCheckReq true "request" -// @Success 200 {array} response.WebsitePreInstallCheck -// @Security ApiKeyAuth -// @Router /websites/check [post] -func (b *BaseApi) CreateWebsiteCheck(c *gin.Context) { - var req request.WebsiteInstallCheckReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - data, err := websiteService.PreInstallCheck(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, data) -} - -// @Tags Website Nginx -// @Summary Update website nginx conf -// @Description 更新 网站 nginx 配置 -// @Accept json -// @Param request body request.WebsiteNginxUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteNginxUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.UpdateNginxConfigFile(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website -// @Summary Operate website log -// @Description 操作网站日志 -// @Accept json -// @Param request body request.WebsiteLogReq true "request" -// @Success 200 {object} response.WebsiteLog -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteLogReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - res, err := websiteService.OpWebsiteLog(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags Website -// @Summary Change default server -// @Description 操作网站日志 -// @Accept json -// @Param request body request.WebsiteDefaultUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteDefaultUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.ChangeDefaultServer(req.ID); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website -// @Summary Load website php conf -// @Description 获取网站 php 配置 -// @Accept json -// @Param id path integer true "request" -// @Success 200 {object} response.PHPConfig -// @Security ApiKeyAuth -// @Router /websites/php/config/:id [get] -func (b *BaseApi) GetWebsitePHPConfig(c *gin.Context) { - id, err := helper.GetParamID(c) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) - return - } - data, err := websiteService.GetPHPConfig(id) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, data) -} - -// @Tags Website PHP -// @Summary Update website php conf -// @Description 更新 网站 PHP 配置 -// @Accept json -// @Param request body request.WebsitePHPConfigUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/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) UpdateWebsitePHPConfig(c *gin.Context) { - var req request.WebsitePHPConfigUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.UpdatePHPConfig(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website PHP -// @Summary Update php conf -// @Description 更新 php 配置文件 -// @Accept json -// @Param request body request.WebsitePHPFileUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/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) { - var req request.WebsitePHPFileUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.UpdatePHPConfigFile(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website PHP -// @Summary Update php version -// @Description 变更 php 版本 -// @Accept json -// @Param request body request.WebsitePHPVersionReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsitePHPVersionReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.ChangePHPVersion(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Website -// @Summary Get rewrite conf -// @Description 获取伪静态配置 -// @Accept json -// @Param request body request.NginxRewriteReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/rewrite [post] -func (b *BaseApi) GetRewriteConfig(c *gin.Context) { - var req request.NginxRewriteReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - res, err := websiteService.GetRewriteConfig(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags Website -// @Summary Update rewrite conf -// @Description 更新伪静态配置 -// @Accept json -// @Param request body request.NginxRewriteUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.NginxRewriteUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.UpdateRewriteConfig(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website -// @Summary Update Site Dir -// @Description 更新网站目录 -// @Accept json -// @Param request body request.WebsiteUpdateDir true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteUpdateDir - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.UpdateSiteDir(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Website -// @Summary Update Site Dir permission -// @Description 更新网站目录权限 -// @Accept json -// @Param request body request.WebsiteUpdateDirPermission true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteUpdateDirPermission - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.UpdateSitePermission(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Website -// @Summary Get proxy conf -// @Description 获取反向代理配置 -// @Accept json -// @Param request body request.WebsiteProxyReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/proxies [post] -func (b *BaseApi) GetProxyConfig(c *gin.Context) { - var req request.WebsiteProxyReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - res, err := websiteService.GetProxies(req.ID) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags Website -// @Summary Update proxy conf -// @Description 修改反向代理配置 -// @Accept json -// @Param request body request.WebsiteProxyConfig true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteProxyConfig - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - err := websiteService.OperateProxy(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Website -// @Summary Update proxy file -// @Description 更新反向代理文件 -// @Accept json -// @Param request body request.NginxProxyUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.NginxProxyUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.UpdateProxyFile(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Website -// @Summary Get AuthBasic conf -// @Description 获取密码访问配置 -// @Accept json -// @Param request body request.NginxAuthReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/auths [post] -func (b *BaseApi) GetAuthConfig(c *gin.Context) { - var req request.NginxAuthReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - res, err := websiteService.GetAuthBasics(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags Website -// @Summary Get AuthBasic conf -// @Description 更新密码访问配置 -// @Accept json -// @Param request body request.NginxAuthUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/auths/update [post] -func (b *BaseApi) UpdateAuthConfig(c *gin.Context) { - var req request.NginxAuthUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.UpdateAuthBasic(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Website -// @Summary Get AntiLeech conf -// @Description 获取防盗链配置 -// @Accept json -// @Param request body request.NginxCommonReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/leech [post] -func (b *BaseApi) GetAntiLeech(c *gin.Context) { - var req request.NginxCommonReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - res, err := websiteService.GetAntiLeech(req.WebsiteID) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags Website -// @Summary Update AntiLeech -// @Description 更新防盗链配置 -// @Accept json -// @Param request body request.NginxAntiLeechUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/leech/update [post] -func (b *BaseApi) UpdateAntiLeech(c *gin.Context) { - var req request.NginxAntiLeechUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.UpdateAntiLeech(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Website -// @Summary Update redirect conf -// @Description 修改重定向配置 -// @Accept json -// @Param request body request.NginxRedirectReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.NginxRedirectReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - err := websiteService.OperateRedirect(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Website -// @Summary Get redirect conf -// @Description 获取重定向配置 -// @Accept json -// @Param request body request.WebsiteProxyReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/redirect [post] -func (b *BaseApi) GetRedirectConfig(c *gin.Context) { - var req request.WebsiteRedirectReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - res, err := websiteService.GetRedirect(req.WebsiteID) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags Website -// @Summary Update redirect file -// @Description 更新重定向文件 -// @Accept json -// @Param request body request.NginxRedirectUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.NginxRedirectUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.UpdateRedirectFile(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Website -// @Summary Get website dir -// @Description 获取网站目录配置 -// @Accept json -// @Param request body request.WebsiteCommonReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/dir [post] -func (b *BaseApi) GetDirConfig(c *gin.Context) { - var req request.WebsiteCommonReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - res, err := websiteService.LoadWebsiteDirConfig(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags Website -// @Summary Get default html -// @Description 获取默认 html -// @Accept json -// @Success 200 {object} response.FileInfo -// @Security ApiKeyAuth -// @Router /websites/default/html/:type [get] -func (b *BaseApi) GetDefaultHtml(c *gin.Context) { - resourceType, err := helper.GetStrParamByKey(c, "type") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) - return - } - fileInfo, err := websiteService.GetDefaultHtml(resourceType) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, fileInfo) -} - -// @Tags Website -// @Summary Update default html -// @Description 更新默认 html -// @Accept json -// @Param request body request.WebsiteHtmlUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteHtmlUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.UpdateDefaultHtml(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} diff --git a/backend/app/api/v1/website_acme_account.go b/backend/app/api/v1/website_acme_account.go deleted file mode 100644 index 8360edb52..000000000 --- a/backend/app/api/v1/website_acme_account.go +++ /dev/null @@ -1,76 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Website Acme -// @Summary Page website acme accounts -// @Description 获取网站 acme 列表分页 -// @Accept json -// @Param request body dto.PageInfo true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /websites/acme/search [post] -func (b *BaseApi) PageWebsiteAcmeAccount(c *gin.Context) { - var req dto.PageInfo - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - total, accounts, err := websiteAcmeAccountService.Page(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Total: total, - Items: accounts, - }) -} - -// @Tags Website Acme -// @Summary Create website acme account -// @Description 创建网站 acme -// @Accept json -// @Param request body request.WebsiteAcmeAccountCreate true "request" -// @Success 200 {object} response.WebsiteAcmeAccountDTO -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteAcmeAccountCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - res, err := websiteAcmeAccountService.Create(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags Website Acme -// @Summary Delete website acme account -// @Description 删除网站 acme -// @Accept json -// @Param request body request.WebsiteResourceReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteResourceReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteAcmeAccountService.Delete(req.ID); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/website_ca.go b/backend/app/api/v1/website_ca.go deleted file mode 100644 index 986b6fa9f..000000000 --- a/backend/app/api/v1/website_ca.go +++ /dev/null @@ -1,177 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" - "net/http" - "net/url" - "strconv" -) - -// @Tags Website CA -// @Summary Page website ca -// @Description 获取网站 ca 列表分页 -// @Accept json -// @Param request body request.WebsiteCASearch true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /websites/ca/search [post] -func (b *BaseApi) PageWebsiteCA(c *gin.Context) { - var req request.WebsiteCASearch - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - total, cas, err := websiteCAService.Page(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Total: total, - Items: cas, - }) -} - -// @Tags Website CA -// @Summary Create website ca -// @Description 创建网站 ca -// @Accept json -// @Param request body request.WebsiteCACreate true "request" -// @Success 200 {object} request.WebsiteCACreate -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteCACreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - res, err := websiteCAService.Create(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags Website CA -// @Summary Get website ca -// @Description 获取网站 ca -// @Accept json -// @Param id path int true "id" -// @Success 200 {object} response.WebsiteCADTO -// @Security ApiKeyAuth -// @Router /websites/ca/{id} [get] -func (b *BaseApi) GetWebsiteCA(c *gin.Context) { - id, err := helper.GetParamID(c) - if err != nil { - return - } - res, err := websiteCAService.GetCA(id) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags Website CA -// @Summary Delete website ca -// @Description 删除网站 ca -// @Accept json -// @Param request body request.WebsiteCommonReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteCommonReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteCAService.Delete(req.ID); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Website CA -// @Summary Obtain SSL -// @Description 自签 SSL 证书 -// @Accept json -// @Param request body request.WebsiteCAObtain true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteCAObtain - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if _, err := websiteCAService.ObtainSSL(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Website CA -// @Summary Obtain SSL -// @Description 续签 SSL 证书 -// @Accept json -// @Param request body request.WebsiteCAObtain true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteCARenew - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if _, err := websiteCAService.ObtainSSL(request.WebsiteCAObtain{ - SSLID: req.SSLID, - Renew: true, - Unit: "year", - Time: 1, - }); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Website CA -// @Summary Download CA file -// @Description 下载 CA 证书文件 -// @Accept json -// @Param request body request.WebsiteResourceReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteResourceReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - file, err := websiteCAService.DownloadFile(req.ID) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - defer file.Close() - info, err := file.Stat() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - c.Header("Content-Length", strconv.FormatInt(info.Size(), 10)) - c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(info.Name())) - http.ServeContent(c.Writer, c.Request, info.Name(), info.ModTime(), file) -} diff --git a/backend/app/api/v1/website_dns_account.go b/backend/app/api/v1/website_dns_account.go deleted file mode 100644 index 09ecdb7da..000000000 --- a/backend/app/api/v1/website_dns_account.go +++ /dev/null @@ -1,96 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Website DNS -// @Summary Page website dns accounts -// @Description 获取网站 dns 列表分页 -// @Accept json -// @Param request body dto.PageInfo true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /websites/dns/search [post] -func (b *BaseApi) PageWebsiteDnsAccount(c *gin.Context) { - var req dto.PageInfo - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - total, accounts, err := websiteDnsAccountService.Page(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Total: total, - Items: accounts, - }) -} - -// @Tags Website DNS -// @Summary Create website dns account -// @Description 创建网站 dns -// @Accept json -// @Param request body request.WebsiteDnsAccountCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteDnsAccountCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if _, err := websiteDnsAccountService.Create(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website DNS -// @Summary Update website dns account -// @Description 更新网站 dns -// @Accept json -// @Param request body request.WebsiteDnsAccountUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteDnsAccountUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if _, err := websiteDnsAccountService.Update(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website DNS -// @Summary Delete website dns account -// @Description 删除网站 dns -// @Accept json -// @Param request body request.WebsiteResourceReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteResourceReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteDnsAccountService.Delete(req.ID); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/website_domain.go b/backend/app/api/v1/website_domain.go deleted file mode 100644 index d50433435..000000000 --- a/backend/app/api/v1/website_domain.go +++ /dev/null @@ -1,73 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Website Domain -// @Summary Delete website domain -// @Description 删除网站域名 -// @Accept json -// @Param request body request.WebsiteDomainDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteDomainDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.DeleteWebsiteDomain(req.ID); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website Domain -// @Summary Create website domain -// @Description 创建网站域名 -// @Accept json -// @Param request body request.WebsiteDomainCreate true "request" -// @Success 200 {object} model.WebsiteDomain -// @Security ApiKeyAuth -// @Router /websites/domains [post] -// @x-panel-log {"bodyKeys":["domain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建域名 [domain]","formatEN":"Create domain [domain]"} -func (b *BaseApi) CreateWebDomain(c *gin.Context) { - var req request.WebsiteDomainCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - domain, err := websiteService.CreateWebsiteDomain(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, domain) -} - -// @Tags Website Domain -// @Summary Search website domains by websiteId -// @Description 通过网站 id 查询域名 -// @Accept json -// @Param websiteId path integer true "request" -// @Success 200 {array} model.WebsiteDomain -// @Security ApiKeyAuth -// @Router /websites/domains/:websiteId [get] -func (b *BaseApi) GetWebDomains(c *gin.Context) { - websiteId, err := helper.GetIntParamByKey(c, "websiteId") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) - return - } - list, err := websiteService.GetWebsiteDomain(websiteId) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, list) -} diff --git a/backend/app/api/v1/website_ssl.go b/backend/app/api/v1/website_ssl.go deleted file mode 100644 index d0420087d..000000000 --- a/backend/app/api/v1/website_ssl.go +++ /dev/null @@ -1,248 +0,0 @@ -package v1 - -import ( - "net/http" - "net/url" - "reflect" - "strconv" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Website SSL -// @Summary Page website ssl -// @Description 获取网站 ssl 列表分页 -// @Accept json -// @Param request body request.WebsiteSSLSearch true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/ssl/search [post] -func (b *BaseApi) PageWebsiteSSL(c *gin.Context) { - var req request.WebsiteSSLSearch - if err := helper.CheckBind(&req, c); err != nil { - return - } - if !reflect.DeepEqual(req.PageInfo, dto.PageInfo{}) { - total, accounts, err := websiteSSLService.Page(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Total: total, - Items: accounts, - }) - } else { - list, err := websiteSSLService.Search(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, list) - } -} - -// @Tags Website SSL -// @Summary Create website ssl -// @Description 创建网站 ssl -// @Accept json -// @Param request body request.WebsiteSSLCreate true "request" -// @Success 200 {object} request.WebsiteSSLCreate -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteSSLCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - res, err := websiteSSLService.Create(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags Website SSL -// @Summary Apply ssl -// @Description 申请证书 -// @Accept json -// @Param request body request.WebsiteSSLApply true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteSSLApply - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteSSLService.ObtainSSL(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithOutData(c) -} - -// @Tags Website SSL -// @Summary Resolve website ssl -// @Description 解析网站 ssl -// @Accept json -// @Param request body request.WebsiteDNSReq true "request" -// @Success 200 {array} response.WebsiteDNSRes -// @Security ApiKeyAuth -// @Router /websites/ssl/resolve [post] -func (b *BaseApi) GetDNSResolve(c *gin.Context) { - var req request.WebsiteDNSReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - res, err := websiteSSLService.GetDNSResolve(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - -// @Tags Website SSL -// @Summary Delete website ssl -// @Description 删除网站 ssl -// @Accept json -// @Param request body request.WebsiteBatchDelReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteBatchDelReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteSSLService.Delete(req.IDs); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website SSL -// @Summary Search website ssl by website id -// @Description 通过网站 id 查询 ssl -// @Accept json -// @Param websiteId path integer true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/ssl/website/:websiteId [get] -func (b *BaseApi) GetWebsiteSSLByWebsiteId(c *gin.Context) { - websiteId, err := helper.GetIntParamByKey(c, "websiteId") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - websiteSSL, err := websiteSSLService.GetWebsiteSSL(websiteId) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, websiteSSL) -} - -// @Tags Website SSL -// @Summary Search website ssl by id -// @Description 通过 id 查询 ssl -// @Accept json -// @Param id path integer true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/ssl/:id [get] -func (b *BaseApi) GetWebsiteSSLById(c *gin.Context) { - id, err := helper.GetParamID(c) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - websiteSSL, err := websiteSSLService.GetSSL(id) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, websiteSSL) -} - -// @Tags Website SSL -// @Summary Update ssl -// @Description 更新 ssl -// @Accept json -// @Param request body request.WebsiteSSLUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteSSLUpdate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteSSLService.Update(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website SSL -// @Summary Upload ssl -// @Description 上传 ssl -// @Accept json -// @Param request body request.WebsiteSSLUpload true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteSSLUpload - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteSSLService.Upload(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website SSL -// @Summary Download SSL file -// @Description 下载证书文件 -// @Accept json -// @Param request body request.WebsiteResourceReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @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) { - var req request.WebsiteResourceReq - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - file, err := websiteSSLService.DownloadFile(req.ID) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - defer file.Close() - info, err := file.Stat() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - c.Header("Content-Length", strconv.FormatInt(info.Size(), 10)) - c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(info.Name())) - http.ServeContent(c.Writer, c.Request, info.Name(), info.ModTime(), file) -} diff --git a/backend/app/dto/app.go b/backend/app/dto/app.go deleted file mode 100644 index 73b075c91..000000000 --- a/backend/app/dto/app.go +++ /dev/null @@ -1,149 +0,0 @@ -package dto - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" -) - -type AppDatabase struct { - ServiceName string `json:"PANEL_DB_HOST"` - DbName string `json:"PANEL_DB_NAME"` - DbUser string `json:"PANEL_DB_USER"` - Password string `json:"PANEL_DB_USER_PASSWORD"` -} - -type AuthParam struct { - RootPassword string `json:"PANEL_DB_ROOT_PASSWORD"` - RootUser string `json:"PANEL_DB_ROOT_USER"` -} - -type RedisAuthParam struct { - RootPassword string `json:"PANEL_REDIS_ROOT_PASSWORD"` -} - -type MinioAuthParam struct { - RootPassword string `json:"PANEL_MINIO_ROOT_PASSWORD"` - RootUser string `json:"PANEL_MINIO_ROOT_USER"` -} - -type ContainerExec struct { - ContainerName string `json:"containerName"` - DbParam AppDatabase `json:"dbParam"` - Auth AuthParam `json:"auth"` -} - -type AppOssConfig struct { - Version string `json:"version"` - Package string `json:"package"` -} - -type AppVersion struct { - Version string `json:"version"` - DetailId uint `json:"detailId"` - DockerCompose string `json:"dockerCompose"` -} - -type AppList struct { - Valid bool `json:"valid"` - Violations []string `json:"violations"` - LastModified int `json:"lastModified"` - - Apps []AppDefine `json:"apps"` - Extra ExtraProperties `json:"additionalProperties"` -} - -type AppDefine struct { - Icon string `json:"icon"` - Name string `json:"name"` - ReadMe string `json:"readMe"` - LastModified int `json:"lastModified"` - - AppProperty AppProperty `json:"additionalProperties"` - Versions []AppConfigVersion `json:"versions"` -} - -type LocalAppAppDefine struct { - AppProperty model.App `json:"additionalProperties" yaml:"additionalProperties"` -} - -type LocalAppParam struct { - AppParams LocalAppInstallDefine `json:"additionalProperties" yaml:"additionalProperties"` -} - -type LocalAppInstallDefine struct { - FormFields interface{} `json:"formFields" yaml:"formFields"` -} - -type ExtraProperties struct { - Tags []Tag `json:"tags"` - Version string `json:"version"` -} - -type AppProperty struct { - Name string `json:"name"` - Type string `json:"type"` - Tags []string `json:"tags"` - ShortDescZh string `json:"shortDescZh"` - ShortDescEn string `json:"shortDescEn"` - Key string `json:"key"` - Required []string `json:"Required"` - CrossVersionUpdate bool `json:"crossVersionUpdate"` - Limit int `json:"limit"` - Recommend int `json:"recommend"` - Website string `json:"website"` - Github string `json:"github"` - Document string `json:"document"` -} - -type AppConfigVersion struct { - Name string `json:"name"` - LastModified int `json:"lastModified"` - DownloadUrl string `json:"downloadUrl"` - DownloadCallBackUrl string `json:"downloadCallBackUrl"` - AppForm interface{} `json:"additionalProperties"` -} - -type Tag struct { - Key string `json:"key"` - Name string `json:"name"` - Sort int `json:"sort"` -} - -type AppForm struct { - FormFields []AppFormFields `json:"formFields"` -} - -type AppFormFields struct { - Type string `json:"type"` - LabelZh string `json:"labelZh"` - LabelEn string `json:"labelEn"` - Required bool `json:"required"` - Default interface{} `json:"default"` - EnvKey string `json:"envKey"` - Disabled bool `json:"disabled"` - Edit bool `json:"edit"` - Rule string `json:"rule"` - Multiple bool `json:"multiple"` - Child interface{} `json:"child"` - Values []AppFormValue `json:"values"` -} - -type AppFormValue struct { - Label string `json:"label"` - Value string `json:"value"` -} - -type AppResource struct { - Type string `json:"type"` - Name string `json:"name"` -} - -var AppToolMap = map[string]string{ - "mysql": "phpmyadmin", - "redis": "redis-commander", -} - -type AppInstallInfo struct { - ID uint `json:"id"` - Key string `json:"key"` - Name string `json:"name"` -} diff --git a/backend/app/dto/backup.go b/backend/app/dto/backup.go deleted file mode 100644 index 971c06519..000000000 --- a/backend/app/dto/backup.go +++ /dev/null @@ -1,82 +0,0 @@ -package dto - -import "time" - -type BackupOperate struct { - ID uint `json:"id"` - Type string `json:"type" validate:"required"` - Bucket string `json:"bucket"` - AccessKey string `json:"accessKey"` - Credential string `json:"credential"` - BackupPath string `json:"backupPath"` - Vars string `json:"vars" validate:"required"` -} - -type BackupInfo struct { - ID uint `json:"id"` - CreatedAt time.Time `json:"createdAt"` - Type string `json:"type"` - Bucket string `json:"bucket"` - BackupPath string `json:"backupPath"` - Vars string `json:"vars"` -} - -type OneDriveInfo struct { - ClientID string `json:"client_id"` - ClientSecret string `json:"client_secret"` - RedirectUri string `json:"redirect_uri"` -} - -type BackupSearchFile struct { - Type string `json:"type" validate:"required"` -} - -type CommonBackup struct { - Type string `json:"type" validate:"required,oneof=app mysql mariadb redis website postgresql"` - Name string `json:"name"` - DetailName string `json:"detailName"` - Secret string `json:"secret"` -} -type CommonRecover struct { - Source string `json:"source" validate:"required,oneof=OSS S3 SFTP MINIO LOCAL COS KODO OneDrive WebDAV"` - Type string `json:"type" validate:"required,oneof=app mysql mariadb redis website postgresql"` - Name string `json:"name"` - DetailName string `json:"detailName"` - File string `json:"file"` - Secret string `json:"secret"` -} - -type RecordSearch struct { - PageInfo - Type string `json:"type" validate:"required"` - Name string `json:"name"` - DetailName string `json:"detailName"` -} - -type RecordSearchByCronjob struct { - PageInfo - CronjobID uint `json:"cronjobID" validate:"required"` -} - -type BackupRecords struct { - ID uint `json:"id"` - CreatedAt time.Time `json:"createdAt"` - Source string `json:"source"` - BackupType string `json:"backupType"` - FileDir string `json:"fileDir"` - FileName string `json:"fileName"` - Size int64 `json:"size"` -} - -type DownloadRecord struct { - Source string `json:"source" validate:"required,oneof=OSS S3 SFTP MINIO LOCAL COS KODO OneDrive WebDAV"` - FileDir string `json:"fileDir" validate:"required"` - FileName string `json:"fileName" validate:"required"` -} - -type ForBuckets struct { - Type string `json:"type" validate:"required"` - AccessKey string `json:"accessKey"` - Credential string `json:"credential" validate:"required"` - Vars string `json:"vars" validate:"required"` -} diff --git a/backend/app/dto/clam.go b/backend/app/dto/clam.go deleted file mode 100644 index 964db15ee..000000000 --- a/backend/app/dto/clam.go +++ /dev/null @@ -1,96 +0,0 @@ -package dto - -import ( - "time" -) - -type SearchClamWithPage struct { - PageInfo - Info string `json:"info"` - OrderBy string `json:"orderBy" validate:"required,oneof=name status created_at"` - Order string `json:"order" validate:"required,oneof=null ascending descending"` -} - -type ClamBaseInfo struct { - Version string `json:"version"` - IsActive bool `json:"isActive"` - IsExist bool `json:"isExist"` - - FreshVersion string `json:"freshVersion"` - FreshIsActive bool `json:"freshIsActive"` - FreshIsExist bool `json:"freshIsExist"` -} - -type ClamInfo struct { - ID uint `json:"id"` - CreatedAt time.Time `json:"createdAt"` - - Name string `json:"name"` - Status string `json:"status"` - Path string `json:"path"` - InfectedStrategy string `json:"infectedStrategy"` - InfectedDir string `json:"infectedDir"` - LastHandleDate string `json:"lastHandleDate"` - Spec string `json:"spec"` - Description string `json:"description"` -} - -type ClamLogSearch struct { - PageInfo - - ClamID uint `json:"clamID"` - StartTime time.Time `json:"startTime"` - EndTime time.Time `json:"endTime"` -} - -type ClamLogReq struct { - Tail string `json:"tail"` - ClamName string `json:"clamName"` - RecordName string `json:"recordName"` -} - -type ClamFileReq struct { - Tail string `json:"tail"` - Name string `json:"name" validate:"required"` -} - -type ClamLog struct { - Name string `json:"name"` - ScanDate string `json:"scanDate"` - ScanTime string `json:"scanTime"` - InfectedFiles string `json:"infectedFiles"` - TotalError string `json:"totalError"` - Status string `json:"status"` -} - -type ClamCreate struct { - Name string `json:"name"` - Status string `json:"status"` - Path string `json:"path"` - InfectedStrategy string `json:"infectedStrategy"` - InfectedDir string `json:"infectedDir"` - Spec string `json:"spec"` - Description string `json:"description"` -} - -type ClamUpdate struct { - ID uint `json:"id"` - - Name string `json:"name"` - Path string `json:"path"` - InfectedStrategy string `json:"infectedStrategy"` - InfectedDir string `json:"infectedDir"` - Spec string `json:"spec"` - Description string `json:"description"` -} - -type ClamUpdateStatus struct { - ID uint `json:"id"` - Status string `json:"status"` -} - -type ClamDelete struct { - RemoveRecord bool `json:"removeRecord"` - RemoveInfected bool `json:"removeInfected"` - Ids []uint `json:"ids" validate:"required"` -} diff --git a/backend/app/dto/command.go b/backend/app/dto/command.go deleted file mode 100644 index b085ce66f..000000000 --- a/backend/app/dto/command.go +++ /dev/null @@ -1,38 +0,0 @@ -package dto - -type SearchCommandWithPage struct { - PageInfo - OrderBy string `json:"orderBy" validate:"required,oneof=name command created_at"` - Order string `json:"order" validate:"required,oneof=null ascending descending"` - GroupID uint `json:"groupID"` - Info string `json:"info"` - Name string `json:"name"` -} - -type CommandOperate struct { - ID uint `json:"id"` - GroupID uint `json:"groupID"` - GroupBelong string `json:"groupBelong"` - Name string `json:"name" validate:"required"` - Command string `json:"command" validate:"required"` -} - -type CommandInfo struct { - ID uint `json:"id"` - GroupID uint `json:"groupID"` - Name string `json:"name"` - Command string `json:"command"` - GroupBelong string `json:"groupBelong"` -} - -type CommandTree struct { - ID uint `json:"id"` - Label string `json:"label"` - Children []CommandInfo `json:"children"` -} - -type RedisCommand struct { - ID uint `json:"id"` - Name string `json:"name"` - Command string `json:"command"` -} diff --git a/backend/app/dto/common_req.go b/backend/app/dto/common_req.go deleted file mode 100644 index b493fac55..000000000 --- a/backend/app/dto/common_req.go +++ /dev/null @@ -1,54 +0,0 @@ -package dto - -type SearchWithPage struct { - PageInfo - Info string `json:"info"` -} - -type PageInfo struct { - Page int `json:"page" validate:"required,number"` - PageSize int `json:"pageSize" validate:"required,number"` -} - -type UpdateDescription struct { - ID uint `json:"id" validate:"required"` - Description string `json:"description" validate:"max=256"` -} - -type OperationWithName struct { - Name string `json:"name" validate:"required"` -} - -type OperateByID struct { - ID uint `json:"id" validate:"required"` -} - -type Operate struct { - Operation string `json:"operation" validate:"required"` -} - -type BatchDeleteReq struct { - Ids []uint `json:"ids" validate:"required"` -} - -type FilePath struct { - Path string `json:"path" validate:"required"` -} - -type DeleteByName struct { - Name string `json:"name" validate:"required"` -} - -type UpdateByFile struct { - File string `json:"file"` -} - -type UpdateByNameAndFile struct { - Name string `json:"name"` - File string `json:"file"` -} - -type OperationWithNameAndType struct { - Name string `json:"name"` - Type string `json:"type" validate:"required"` -} diff --git a/backend/app/dto/common_res.go b/backend/app/dto/common_res.go deleted file mode 100644 index 5c7c11193..000000000 --- a/backend/app/dto/common_res.go +++ /dev/null @@ -1,16 +0,0 @@ -package dto - -type PageResult struct { - Total int64 `json:"total"` - Items interface{} `json:"items"` -} - -type Response struct { - Code int `json:"code"` - Message string `json:"message"` - Data interface{} `json:"data"` -} - -type Options struct { - Option string `json:"option"` -} diff --git a/backend/app/dto/compose_template.go b/backend/app/dto/compose_template.go deleted file mode 100644 index de3832ab0..000000000 --- a/backend/app/dto/compose_template.go +++ /dev/null @@ -1,23 +0,0 @@ -package dto - -import "time" - -type ComposeTemplateCreate struct { - Name string `json:"name" validate:"required"` - Description string `json:"description"` - Content string `json:"content"` -} - -type ComposeTemplateUpdate struct { - ID uint `json:"id"` - Description string `json:"description"` - Content string `json:"content"` -} - -type ComposeTemplateInfo struct { - ID uint `json:"id"` - CreatedAt time.Time `json:"createdAt"` - Name string `json:"name"` - Description string `json:"description"` - Content string `json:"content"` -} diff --git a/backend/app/dto/container.go b/backend/app/dto/container.go deleted file mode 100644 index 90a351768..000000000 --- a/backend/app/dto/container.go +++ /dev/null @@ -1,234 +0,0 @@ -package dto - -import ( - "time" -) - -type PageContainer struct { - PageInfo - Name string `json:"name"` - State string `json:"state" validate:"required,oneof=all created running paused restarting removing exited dead"` - OrderBy string `json:"orderBy" validate:"required,oneof=name state created_at"` - Order string `json:"order" validate:"required,oneof=null ascending descending"` - Filters string `json:"filters"` - ExcludeAppStore bool `json:"excludeAppStore"` -} - -type InspectReq struct { - ID string `json:"id" validate:"required"` - Type string `json:"type" validate:"required"` -} - -type ContainerInfo struct { - ContainerID string `json:"containerID"` - Name string `json:"name"` - ImageId string `json:"imageID"` - ImageName string `json:"imageName"` - CreateTime string `json:"createTime"` - State string `json:"state"` - RunTime string `json:"runTime"` - - Network []string `json:"network"` - Ports []string `json:"ports"` - - IsFromApp bool `json:"isFromApp"` - IsFromCompose bool `json:"isFromCompose"` - - AppName string `json:"appName"` - AppInstallName string `json:"appInstallName"` - Websites []string `json:"websites"` -} - -type ResourceLimit struct { - CPU int `json:"cpu"` - Memory uint64 `json:"memory"` -} - -type ContainerOperate struct { - ContainerID string `json:"containerID"` - ForcePull bool `json:"forcePull"` - Name string `json:"name" validate:"required"` - Image string `json:"image" validate:"required"` - Network string `json:"network"` - Ipv4 string `json:"ipv4"` - Ipv6 string `json:"ipv6"` - PublishAllPorts bool `json:"publishAllPorts"` - ExposedPorts []PortHelper `json:"exposedPorts"` - Tty bool `json:"tty"` - OpenStdin bool `json:"openStdin"` - Cmd []string `json:"cmd"` - Entrypoint []string `json:"entrypoint"` - CPUShares int64 `json:"cpuShares"` - NanoCPUs float64 `json:"nanoCPUs"` - Memory float64 `json:"memory"` - Privileged bool `json:"privileged"` - AutoRemove bool `json:"autoRemove"` - Volumes []VolumeHelper `json:"volumes"` - Labels []string `json:"labels"` - Env []string `json:"env"` - RestartPolicy string `json:"restartPolicy"` -} - -type ContainerUpgrade struct { - Name string `json:"name" validate:"required"` - Image string `json:"image" validate:"required"` - ForcePull bool `json:"forcePull"` -} - -type ContainerListStats struct { - ContainerID string `json:"containerID"` - - CPUTotalUsage uint64 `json:"cpuTotalUsage"` - SystemUsage uint64 `json:"systemUsage"` - CPUPercent float64 `json:"cpuPercent"` - PercpuUsage int `json:"percpuUsage"` - - MemoryCache uint64 `json:"memoryCache"` - MemoryUsage uint64 `json:"memoryUsage"` - MemoryLimit uint64 `json:"memoryLimit"` - MemoryPercent float64 `json:"memoryPercent"` -} - -type ContainerStats struct { - CPUPercent float64 `json:"cpuPercent"` - Memory float64 `json:"memory"` - Cache float64 `json:"cache"` - IORead float64 `json:"ioRead"` - IOWrite float64 `json:"ioWrite"` - NetworkRX float64 `json:"networkRX"` - NetworkTX float64 `json:"networkTX"` - - ShotTime time.Time `json:"shotTime"` -} - -type VolumeHelper struct { - Type string `json:"type"` - SourceDir string `json:"sourceDir"` - ContainerDir string `json:"containerDir"` - Mode string `json:"mode"` -} -type PortHelper struct { - HostIP string `json:"hostIP"` - HostPort string `json:"hostPort"` - ContainerPort string `json:"containerPort"` - Protocol string `json:"protocol"` -} - -type ContainerOperation struct { - Names []string `json:"names" validate:"required"` - Operation string `json:"operation" validate:"required,oneof=start stop restart kill pause unpause remove"` -} - -type ContainerRename struct { - Name string `json:"name" validate:"required"` - NewName string `json:"newName" validate:"required"` -} - -type ContainerCommit struct { - ContainerId string `json:"containerID" validate:"required"` - ContainerName string `json:"containerName"` - NewImageName string `json:"newImageName"` - Comment string `json:"comment"` - Author string `json:"author"` - Pause bool `json:"pause"` -} - -type ContainerPrune struct { - PruneType string `json:"pruneType" validate:"required,oneof=container image volume network buildcache"` - WithTagAll bool `json:"withTagAll"` -} - -type ContainerPruneReport struct { - DeletedNumber int `json:"deletedNumber"` - SpaceReclaimed int `json:"spaceReclaimed"` -} - -type Network struct { - ID string `json:"id"` - Name string `json:"name"` - Labels []string `json:"labels"` - Driver string `json:"driver"` - IPAMDriver string `json:"ipamDriver"` - Subnet string `json:"subnet"` - Gateway string `json:"gateway"` - CreatedAt time.Time `json:"createdAt"` - Attachable bool `json:"attachable"` -} -type NetworkCreate struct { - Name string `json:"name" validate:"required"` - Driver string `json:"driver" validate:"required"` - Options []string `json:"options"` - Ipv4 bool `json:"ipv4"` - Subnet string `json:"subnet"` - Gateway string `json:"gateway"` - IPRange string `json:"ipRange"` - AuxAddress []SettingUpdate `json:"auxAddress"` - - Ipv6 bool `json:"ipv6"` - SubnetV6 string `json:"subnetV6"` - GatewayV6 string `json:"gatewayV6"` - IPRangeV6 string `json:"ipRangeV6"` - AuxAddressV6 []SettingUpdate `json:"auxAddressV6"` - Labels []string `json:"labels"` -} - -type Volume struct { - Name string `json:"name"` - Labels []string `json:"labels"` - Driver string `json:"driver"` - Mountpoint string `json:"mountpoint"` - CreatedAt time.Time `json:"createdAt"` -} -type VolumeCreate struct { - Name string `json:"name" validate:"required"` - Driver string `json:"driver" validate:"required"` - Options []string `json:"options"` - Labels []string `json:"labels"` -} - -type BatchDelete struct { - Force bool `json:"force"` - Names []string `json:"names" validate:"required"` -} - -type ComposeInfo struct { - Name string `json:"name"` - CreatedAt string `json:"createdAt"` - CreatedBy string `json:"createdBy"` - ContainerNumber int `json:"containerNumber"` - ConfigFile string `json:"configFile"` - Workdir string `json:"workdir"` - Path string `json:"path"` - Containers []ComposeContainer `json:"containers"` -} -type ComposeContainer struct { - ContainerID string `json:"containerID"` - Name string `json:"name"` - CreateTime string `json:"createTime"` - State string `json:"state"` -} -type ComposeCreate struct { - Name string `json:"name"` - From string `json:"from" validate:"required,oneof=edit path template"` - File string `json:"file"` - Path string `json:"path"` - Template uint `json:"template"` -} -type ComposeOperation struct { - Name string `json:"name" validate:"required"` - Path string `json:"path" validate:"required"` - Operation string `json:"operation" validate:"required,oneof=start stop down"` - WithFile bool `json:"withFile"` -} -type ComposeUpdate struct { - Name string `json:"name" validate:"required"` - Path string `json:"path" validate:"required"` - Content string `json:"content" validate:"required"` -} - -type ContainerLog struct { - Container string `json:"container" validate:"required"` - Since string `json:"since"` - Tail uint `json:"tail"` - ContainerType string `json:"containerType"` -} diff --git a/backend/app/dto/cronjob.go b/backend/app/dto/cronjob.go deleted file mode 100644 index 9189a7e09..000000000 --- a/backend/app/dto/cronjob.go +++ /dev/null @@ -1,121 +0,0 @@ -package dto - -import ( - "time" -) - -type PageCronjob struct { - PageInfo - Info string `json:"info"` - OrderBy string `json:"orderBy" validate:"required,oneof=name status created_at"` - Order string `json:"order" validate:"required,oneof=null ascending descending"` -} - -type CronjobCreate struct { - Name string `json:"name" validate:"required"` - Type string `json:"type" validate:"required"` - Spec string `json:"spec" validate:"required"` - - Script string `json:"script"` - Command string `json:"command"` - ContainerName string `json:"containerName"` - AppID string `json:"appID"` - Website string `json:"website"` - ExclusionRules string `json:"exclusionRules"` - DBType string `json:"dbType"` - DBName string `json:"dbName"` - URL string `json:"url"` - SourceDir string `json:"sourceDir"` - - BackupAccounts string `json:"backupAccounts"` - DefaultDownload string `json:"defaultDownload"` - RetainCopies int `json:"retainCopies" validate:"number,min=1"` - Secret string `json:"secret"` -} - -type CronjobUpdate struct { - ID uint `json:"id" validate:"required"` - Name string `json:"name" validate:"required"` - Spec string `json:"spec" validate:"required"` - - Script string `json:"script"` - Command string `json:"command"` - ContainerName string `json:"containerName"` - AppID string `json:"appID"` - Website string `json:"website"` - ExclusionRules string `json:"exclusionRules"` - DBType string `json:"dbType"` - DBName string `json:"dbName"` - URL string `json:"url"` - SourceDir string `json:"sourceDir"` - - BackupAccounts string `json:"backupAccounts"` - DefaultDownload string `json:"defaultDownload"` - RetainCopies int `json:"retainCopies" validate:"number,min=1"` - Secret string `json:"secret"` -} - -type CronjobUpdateStatus struct { - ID uint `json:"id" validate:"required"` - Status string `json:"status" validate:"required"` -} - -type CronjobDownload struct { - RecordID uint `json:"recordID" validate:"required"` - BackupAccountID uint `json:"backupAccountID" validate:"required"` -} - -type CronjobClean struct { - IsDelete bool `json:"isDelete"` - CleanData bool `json:"cleanData"` - CronjobID uint `json:"cronjobID" validate:"required"` -} - -type CronjobBatchDelete struct { - CleanData bool `json:"cleanData"` - IDs []uint `json:"ids" validate:"required"` -} - -type CronjobInfo struct { - ID uint `json:"id"` - Name string `json:"name"` - Type string `json:"type"` - Spec string `json:"spec"` - - Script string `json:"script"` - Command string `json:"command"` - ContainerName string `json:"containerName"` - AppID string `json:"appID"` - Website string `json:"website"` - ExclusionRules string `json:"exclusionRules"` - DBType string `json:"dbType"` - DBName string `json:"dbName"` - URL string `json:"url"` - SourceDir string `json:"sourceDir"` - BackupAccounts string `json:"backupAccounts"` - DefaultDownload string `json:"defaultDownload"` - RetainCopies int `json:"retainCopies"` - - LastRecordTime string `json:"lastRecordTime"` - Status string `json:"status"` - Secret string `json:"secret"` -} - -type SearchRecord struct { - PageInfo - CronjobID int `json:"cronjobID"` - StartTime time.Time `json:"startTime"` - EndTime time.Time `json:"endTime"` - Status string `json:"status"` -} - -type Record struct { - ID uint `json:"id"` - StartTime string `json:"startTime"` - Records string `json:"records"` - Status string `json:"status"` - Message string `json:"message"` - TargetPath string `json:"targetPath"` - Interval int `json:"interval"` - File string `json:"file"` -} diff --git a/backend/app/dto/dashboard.go b/backend/app/dto/dashboard.go deleted file mode 100644 index a7d3a5c95..000000000 --- a/backend/app/dto/dashboard.go +++ /dev/null @@ -1,107 +0,0 @@ -package dto - -import "time" - -type DashboardBase struct { - WebsiteNumber int `json:"websiteNumber"` - DatabaseNumber int `json:"databaseNumber"` - CronjobNumber int `json:"cronjobNumber"` - AppInstalledNumber int `json:"appInstalledNumber"` - - Hostname string `json:"hostname"` - OS string `json:"os"` - Platform string `json:"platform"` - PlatformFamily string `json:"platformFamily"` - PlatformVersion string `json:"platformVersion"` - KernelArch string `json:"kernelArch"` - KernelVersion string `json:"kernelVersion"` - VirtualizationSystem string `json:"virtualizationSystem"` - - CPUCores int `json:"cpuCores"` - CPULogicalCores int `json:"cpuLogicalCores"` - CPUModelName string `json:"cpuModelName"` - - CurrentInfo DashboardCurrent `json:"currentInfo"` -} - -type OsInfo struct { - OS string `json:"os"` - Platform string `json:"platform"` - PlatformFamily string `json:"platformFamily"` - KernelArch string `json:"kernelArch"` - KernelVersion string `json:"kernelVersion"` - - DiskSize int64 `json:"diskSize"` -} - -type DashboardCurrent struct { - Uptime uint64 `json:"uptime"` - TimeSinceUptime string `json:"timeSinceUptime"` - - Procs uint64 `json:"procs"` - - Load1 float64 `json:"load1"` - Load5 float64 `json:"load5"` - Load15 float64 `json:"load15"` - LoadUsagePercent float64 `json:"loadUsagePercent"` - - CPUPercent []float64 `json:"cpuPercent"` - CPUUsedPercent float64 `json:"cpuUsedPercent"` - CPUUsed float64 `json:"cpuUsed"` - CPUTotal int `json:"cpuTotal"` - - MemoryTotal uint64 `json:"memoryTotal"` - MemoryAvailable uint64 `json:"memoryAvailable"` - MemoryUsed uint64 `json:"memoryUsed"` - MemoryUsedPercent float64 `json:"memoryUsedPercent"` - - SwapMemoryTotal uint64 `json:"swapMemoryTotal"` - SwapMemoryAvailable uint64 `json:"swapMemoryAvailable"` - SwapMemoryUsed uint64 `json:"swapMemoryUsed"` - SwapMemoryUsedPercent float64 `json:"swapMemoryUsedPercent"` - - IOReadBytes uint64 `json:"ioReadBytes"` - IOWriteBytes uint64 `json:"ioWriteBytes"` - IOCount uint64 `json:"ioCount"` - IOReadTime uint64 `json:"ioReadTime"` - IOWriteTime uint64 `json:"ioWriteTime"` - - DiskData []DiskInfo `json:"diskData"` - - NetBytesSent uint64 `json:"netBytesSent"` - NetBytesRecv uint64 `json:"netBytesRecv"` - - GPUData []GPUInfo `json:"gpuData"` - - ShotTime time.Time `json:"shotTime"` -} - -type DiskInfo struct { - Path string `json:"path"` - Type string `json:"type"` - Device string `json:"device"` - Total uint64 `json:"total"` - Free uint64 `json:"free"` - Used uint64 `json:"used"` - UsedPercent float64 `json:"usedPercent"` - - InodesTotal uint64 `json:"inodesTotal"` - InodesUsed uint64 `json:"inodesUsed"` - InodesFree uint64 `json:"inodesFree"` - InodesUsedPercent float64 `json:"inodesUsedPercent"` -} - -type GPUInfo struct { - Index uint `json:"index"` - ProductName string `json:"productName"` - GPUUtil string `json:"gpuUtil"` - Temperature string `json:"temperature"` - PerformanceState string `json:"performanceState"` - PowerUsage string `json:"powerUsage"` - PowerDraw string `json:"powerDraw"` - MaxPowerLimit string `json:"maxPowerLimit"` - MemoryUsage string `json:"memoryUsage"` - MemUsed string `json:"memUsed"` - MemTotal string `json:"memTotal"` - FanSpeed string `json:"fanSpeed"` -} diff --git a/backend/app/dto/database.go b/backend/app/dto/database.go deleted file mode 100644 index acfb3b09e..000000000 --- a/backend/app/dto/database.go +++ /dev/null @@ -1,321 +0,0 @@ -package dto - -import "time" - -// common -type DBConfUpdateByFile struct { - Type string `json:"type" validate:"required,oneof=mysql mariadb postgresql redis"` - Database string `json:"database" validate:"required"` - File string `json:"file"` -} -type ChangeDBInfo struct { - ID uint `json:"id"` - From string `json:"from" validate:"required,oneof=local remote"` - Type string `json:"type" validate:"required,oneof=mysql mariadb postgresql"` - Database string `json:"database" validate:"required"` - Value string `json:"value" validate:"required"` -} - -type DBBaseInfo struct { - Name string `json:"name"` - ContainerName string `json:"containerName"` - Port int64 `json:"port"` -} - -// mysql -type MysqlDBSearch struct { - PageInfo - Info string `json:"info"` - Database string `json:"database" validate:"required"` - OrderBy string `json:"orderBy" validate:"required,oneof=name created_at"` - Order string `json:"order" validate:"required,oneof=null ascending descending"` -} - -type MysqlDBInfo struct { - ID uint `json:"id"` - CreatedAt time.Time `json:"createdAt"` - Name string `json:"name"` - From string `json:"from"` - MysqlName string `json:"mysqlName"` - Format string `json:"format"` - Username string `json:"username"` - Password string `json:"password"` - Permission string `json:"permission"` - IsDelete bool `json:"isDelete"` - Description string `json:"description"` -} - -type MysqlOption struct { - ID uint `json:"id"` - From string `json:"from"` - Type string `json:"type"` - Database string `json:"database"` - Name string `json:"name"` -} - -type MysqlDBCreate struct { - Name string `json:"name" validate:"required"` - From string `json:"from" validate:"required,oneof=local remote"` - Database string `json:"database" validate:"required"` - Format string `json:"format" validate:"required,oneof=utf8mb4 utf8 gbk big5"` - Username string `json:"username" validate:"required"` - Password string `json:"password" validate:"required"` - Permission string `json:"permission" validate:"required"` - Description string `json:"description"` -} - -type BindUser struct { - Database string `json:"database" validate:"required"` - DB string `json:"db" validate:"required"` - Username string `json:"username" validate:"required"` - Password string `json:"password" validate:"required"` - Permission string `json:"permission" validate:"required"` -} - -type MysqlLoadDB struct { - From string `json:"from" validate:"required,oneof=local remote"` - Type string `json:"type" validate:"required,oneof=mysql mariadb"` - Database string `json:"database" validate:"required"` -} - -type MysqlDBDeleteCheck struct { - ID uint `json:"id" validate:"required"` - Type string `json:"type" validate:"required,oneof=mysql mariadb"` - Database string `json:"database" validate:"required"` -} - -type MysqlDBDelete struct { - ID uint `json:"id" validate:"required"` - Type string `json:"type" validate:"required,oneof=mysql mariadb"` - Database string `json:"database" validate:"required"` - ForceDelete bool `json:"forceDelete"` - DeleteBackup bool `json:"deleteBackup"` -} - -type MysqlStatus struct { - AbortedClients string `json:"Aborted_clients"` - AbortedConnects string `json:"Aborted_connects"` - BytesReceived string `json:"Bytes_received"` - BytesSent string `json:"Bytes_sent"` - ComCommit string `json:"Com_commit"` - ComRollback string `json:"Com_rollback"` - Connections string `json:"Connections"` - CreatedTmpDiskTables string `json:"Created_tmp_disk_tables"` - CreatedTmpTables string `json:"Created_tmp_tables"` - InnodbBufferPoolPagesDirty string `json:"Innodb_buffer_pool_pages_dirty"` - InnodbBufferPoolReadRequests string `json:"Innodb_buffer_pool_read_requests"` - InnodbBufferPoolReads string `json:"Innodb_buffer_pool_reads"` - KeyReadRequests string `json:"Key_read_requests"` - KeyReads string `json:"Key_reads"` - KeyWriteEequests string `json:"Key_write_requests"` - KeyWrites string `json:"Key_writes"` - MaxUsedConnections string `json:"Max_used_connections"` - OpenTables string `json:"Open_tables"` - OpenedFiles string `json:"Opened_files"` - OpenedTables string `json:"Opened_tables"` - QcacheHits string `json:"Qcache_hits"` - QcacheInserts string `json:"Qcache_inserts"` - Questions string `json:"Questions"` - SelectFullJoin string `json:"Select_full_join"` - SelectRangeCheck string `json:"Select_range_check"` - SortMergePasses string `json:"Sort_merge_passes"` - TableLocksWaited string `json:"Table_locks_waited"` - ThreadsCached string `json:"Threads_cached"` - ThreadsConnected string `json:"Threads_connected"` - ThreadsCreated string `json:"Threads_created"` - ThreadsRunning string `json:"Threads_running"` - Uptime string `json:"Uptime"` - Run string `json:"Run"` - File string `json:"File"` - Position string `json:"Position"` -} - -type MysqlVariables struct { - BinlogCacheSize string `json:"binlog_cache_size"` - InnodbBufferPoolSize string `json:"innodb_buffer_pool_size"` - InnodbLogBufferSize string `json:"innodb_log_buffer_size"` - JoinBufferSize string `json:"join_buffer_size"` - KeyBufferSize string `json:"key_buffer_size"` - MaxConnections string `json:"max_connections"` - MaxHeapTableSize string `json:"max_heap_table_size"` - QueryCacheSize string `json:"query_cache_size"` - QueryCacheType string `json:"query_cache_type"` - ReadBufferSize string `json:"read_buffer_size"` - ReadRndBufferSize string `json:"read_rnd_buffer_size"` - SortBufferSize string `json:"sort_buffer_size"` - TableOpenCache string `json:"table_open_cache"` - ThreadCacheSize string `json:"thread_cache_size"` - ThreadStack string `json:"thread_stack"` - TmpTableSize string `json:"tmp_table_size"` - - SlowQueryLog string `json:"slow_query_log"` - LongQueryTime string `json:"long_query_time"` -} - -type MysqlVariablesUpdate struct { - Type string `json:"type" validate:"required,oneof=mysql mariadb"` - Database string `json:"database" validate:"required"` - Variables []MysqlVariablesUpdateHelper `json:"variables"` -} - -type MysqlVariablesUpdateHelper struct { - Param string `json:"param"` - Value interface{} `json:"value"` -} - -// redis -type ChangeRedisPass struct { - Database string `json:"database" validate:"required"` - Value string `json:"value"` -} - -type RedisConfUpdate struct { - Database string `json:"database" validate:"required"` - Timeout string `json:"timeout"` - Maxclients string `json:"maxclients"` - Maxmemory string `json:"maxmemory"` -} -type RedisConfPersistenceUpdate struct { - Database string `json:"database" validate:"required"` - Type string `json:"type" validate:"required,oneof=aof rbd"` - Appendonly string `json:"appendonly"` - Appendfsync string `json:"appendfsync"` - Save string `json:"save"` -} - -type RedisConf struct { - Database string `json:"database" validate:"required"` - Name string `json:"name"` - Port int64 `json:"port"` - ContainerName string `json:"containerName"` - Timeout string `json:"timeout"` - Maxclients string `json:"maxclients"` - Requirepass string `json:"requirepass"` - Maxmemory string `json:"maxmemory"` -} - -type RedisPersistence struct { - Database string `json:"database" validate:"required"` - Appendonly string `json:"appendonly"` - Appendfsync string `json:"appendfsync"` - Save string `json:"save"` -} - -type RedisStatus struct { - Database string `json:"database" validate:"required"` - TcpPort string `json:"tcp_port"` - UptimeInDays string `json:"uptime_in_days"` - ConnectedClients string `json:"connected_clients"` - UsedMemory string `json:"used_memory"` - UsedMemoryRss string `json:"used_memory_rss"` - UsedMemoryPeak string `json:"used_memory_peak"` - MemFragmentationRatio string `json:"mem_fragmentation_ratio"` - TotalConnectionsReceived string `json:"total_connections_received"` - TotalCommandsProcessed string `json:"total_commands_processed"` - InstantaneousOpsPerSec string `json:"instantaneous_ops_per_sec"` - KeyspaceHits string `json:"keyspace_hits"` - KeyspaceMisses string `json:"keyspace_misses"` - LatestForkUsec string `json:"latest_fork_usec"` -} - -type DatabaseFileRecords struct { - Database string `json:"database" validate:"required"` - FileName string `json:"fileName"` - FileDir string `json:"fileDir"` - CreatedAt string `json:"createdAt"` - Size int `json:"size"` -} -type RedisBackupRecover struct { - Database string `json:"database" validate:"required"` - FileName string `json:"fileName"` - FileDir string `json:"fileDir"` -} - -// database -type DatabaseSearch struct { - PageInfo - Info string `json:"info"` - Type string `json:"type"` - OrderBy string `json:"orderBy" validate:"required,oneof=name created_at"` - Order string `json:"order" validate:"required,oneof=null ascending descending"` -} - -type DatabaseInfo struct { - ID uint `json:"id"` - CreatedAt time.Time `json:"createdAt"` - Name string `json:"name" validate:"max=256"` - From string `json:"from"` - Type string `json:"type"` - Version string `json:"version"` - Address string `json:"address"` - Port uint `json:"port"` - Username string `json:"username"` - Password string `json:"password"` - - SSL bool `json:"ssl"` - RootCert string `json:"rootCert"` - ClientKey string `json:"clientKey"` - ClientCert string `json:"clientCert"` - SkipVerify bool `json:"skipVerify"` - - Description string `json:"description"` -} - -type DatabaseOption struct { - ID uint `json:"id"` - Type string `json:"type"` - From string `json:"from"` - Database string `json:"database"` - Version string `json:"version"` - Address string `json:"address"` -} - -type DatabaseItem struct { - ID uint `json:"id"` - From string `json:"from"` - Database string `json:"database"` - Name string `json:"name"` -} - -type DatabaseCreate struct { - Name string `json:"name" validate:"required,max=256"` - Type string `json:"type" validate:"required"` - From string `json:"from" validate:"required,oneof=local remote"` - Version string `json:"version" validate:"required"` - Address string `json:"address"` - Port uint `json:"port"` - Username string `json:"username" validate:"required"` - Password string `json:"password"` - - SSL bool `json:"ssl"` - RootCert string `json:"rootCert"` - ClientKey string `json:"clientKey"` - ClientCert string `json:"clientCert"` - SkipVerify bool `json:"skipVerify"` - - Description string `json:"description"` -} - -type DatabaseUpdate struct { - ID uint `json:"id"` - Type string `json:"type" validate:"required"` - Version string `json:"version" validate:"required"` - Address string `json:"address"` - Port uint `json:"port"` - Username string `json:"username" validate:"required"` - Password string `json:"password"` - - SSL bool `json:"ssl"` - RootCert string `json:"rootCert"` - ClientKey string `json:"clientKey"` - ClientCert string `json:"clientCert"` - SkipVerify bool `json:"skipVerify"` - - Description string `json:"description"` -} - -type DatabaseDelete struct { - ID uint `json:"id" validate:"required"` - ForceDelete bool `json:"forceDelete"` - DeleteBackup bool `json:"deleteBackup"` -} diff --git a/backend/app/dto/database_postgresql.go b/backend/app/dto/database_postgresql.go deleted file mode 100644 index 825ff3af5..000000000 --- a/backend/app/dto/database_postgresql.go +++ /dev/null @@ -1,85 +0,0 @@ -package dto - -import "time" - -type PostgresqlDBSearch struct { - PageInfo - Info string `json:"info"` - Database string `json:"database" validate:"required"` - OrderBy string `json:"orderBy" validate:"required,oneof=name created_at"` - Order string `json:"order" validate:"required,oneof=null ascending descending"` -} - -type PostgresqlDBInfo struct { - ID uint `json:"id"` - CreatedAt time.Time `json:"createdAt"` - Name string `json:"name"` - From string `json:"from"` - PostgresqlName string `json:"postgresqlName"` - Format string `json:"format"` - Username string `json:"username"` - Password string `json:"password"` - SuperUser bool `json:"superUser"` - IsDelete bool `json:"isDelete"` - Description string `json:"description"` -} - -type PostgresqlOption struct { - ID uint `json:"id"` - From string `json:"from"` - Type string `json:"type"` - Database string `json:"database"` - Name string `json:"name"` -} - -type PostgresqlDBCreate struct { - Name string `json:"name" validate:"required"` - From string `json:"from" validate:"required,oneof=local remote"` - Database string `json:"database" validate:"required"` - Format string `json:"format"` - Username string `json:"username" validate:"required"` - Password string `json:"password" validate:"required"` - SuperUser bool `json:"superUser"` - Description string `json:"description"` -} - -type PostgresqlBindUser struct { - Name string `json:"name" validate:"required"` - Database string `json:"database" validate:"required"` - Username string `json:"username" validate:"required"` - Password string `json:"password" validate:"required"` - SuperUser bool `json:"superUser"` -} - -type PostgresqlPrivileges struct { - Name string `json:"name" validate:"required"` - Database string `json:"database" validate:"required"` - Username string `json:"username" validate:"required"` - SuperUser bool `json:"superUser"` -} - -type PostgresqlLoadDB struct { - From string `json:"from" validate:"required,oneof=local remote"` - Type string `json:"type" validate:"required,oneof=postgresql"` - Database string `json:"database" validate:"required"` -} - -type PostgresqlDBDeleteCheck struct { - ID uint `json:"id" validate:"required"` - Type string `json:"type" validate:"required,oneof=postgresql"` - Database string `json:"database" validate:"required"` -} - -type PostgresqlDBDelete struct { - ID uint `json:"id" validate:"required"` - Type string `json:"type" validate:"required,oneof=postgresql"` - Database string `json:"database" validate:"required"` - ForceDelete bool `json:"forceDelete"` - DeleteBackup bool `json:"deleteBackup"` -} - -type PostgresqlConfUpdateByFile struct { - Type string `json:"type" validate:"required,oneof=postgresql mariadb"` - Database string `json:"database" validate:"required"` - File string `json:"file"` -} diff --git a/backend/app/dto/device.go b/backend/app/dto/device.go deleted file mode 100644 index ca05cc5cb..000000000 --- a/backend/app/dto/device.go +++ /dev/null @@ -1,41 +0,0 @@ -package dto - -type DeviceBaseInfo struct { - DNS []string `json:"dns"` - Hosts []HostHelper `json:"hosts"` - Hostname string `json:"hostname"` - TimeZone string `json:"timeZone"` - LocalTime string `json:"localTime"` - Ntp string `json:"ntp"` - User string `json:"user"` - - SwapMemoryTotal uint64 `json:"swapMemoryTotal"` - SwapMemoryAvailable uint64 `json:"swapMemoryAvailable"` - SwapMemoryUsed uint64 `json:"swapMemoryUsed"` - MaxSize uint64 `json:"maxSize"` - - SwapDetails []SwapHelper `json:"swapDetails"` -} - -type HostHelper struct { - IP string `json:"ip"` - Host string `json:"host"` -} - -type SwapHelper struct { - Path string `json:"path" validate:"required"` - Size uint64 `json:"size"` - Used string `json:"used"` - - IsNew bool `json:"isNew"` -} - -type TimeZoneOptions struct { - From string `json:"from"` - Zones []string `json:"zones"` -} - -type ChangePasswd struct { - User string `json:"user"` - Passwd string `json:"passwd"` -} diff --git a/backend/app/dto/docker.go b/backend/app/dto/docker.go deleted file mode 100644 index bfabacc41..000000000 --- a/backend/app/dto/docker.go +++ /dev/null @@ -1,39 +0,0 @@ -package dto - -type DaemonJsonUpdateByFile struct { - File string `json:"file"` -} - -type DaemonJsonConf struct { - IsSwarm bool `json:"isSwarm"` - Status string `json:"status"` - Version string `json:"version"` - Mirrors []string `json:"registryMirrors"` - Registries []string `json:"insecureRegistries"` - LiveRestore bool `json:"liveRestore"` - IPTables bool `json:"iptables"` - CgroupDriver string `json:"cgroupDriver"` - - Ipv6 bool `json:"ipv6"` - FixedCidrV6 string `json:"fixedCidrV6"` - Ip6Tables bool `json:"ip6Tables"` - Experimental bool `json:"experimental"` - - LogMaxSize string `json:"logMaxSize"` - LogMaxFile string `json:"logMaxFile"` -} - -type LogOption struct { - LogMaxSize string `json:"logMaxSize"` - LogMaxFile string `json:"logMaxFile"` -} - -type Ipv6Option struct { - FixedCidrV6 string `json:"fixedCidrV6"` - Ip6Tables bool `json:"ip6Tables" validate:"required"` - Experimental bool `json:"experimental"` -} - -type DockerOperation struct { - Operation string `json:"operation" validate:"required,oneof=start restart stop"` -} diff --git a/backend/app/dto/fail2ban.go b/backend/app/dto/fail2ban.go deleted file mode 100644 index 8c8351b82..000000000 --- a/backend/app/dto/fail2ban.go +++ /dev/null @@ -1,29 +0,0 @@ -package dto - -type Fail2BanBaseInfo struct { - IsEnable bool `json:"isEnable"` - IsActive bool `json:"isActive"` - IsExist bool `json:"isExist"` - Version string `json:"version"` - - Port int `json:"port"` - MaxRetry int `json:"maxRetry"` - BanTime string `json:"banTime"` - FindTime string `json:"findTime"` - BanAction string `json:"banAction"` - LogPath string `json:"logPath"` -} - -type Fail2BanSearch struct { - Status string `json:"status" validate:"required,oneof=banned ignore"` -} - -type Fail2BanUpdate struct { - Key string `json:"key" validate:"required,oneof=port bantime findtime maxretry banaction logpath port"` - Value string `json:"value"` -} - -type Fail2BanSet struct { - IPs []string `json:"ips"` - Operate string `json:"operate" validate:"required,oneof=banned ignore"` -} diff --git a/backend/app/dto/firewall.go b/backend/app/dto/firewall.go deleted file mode 100644 index c3d3646e1..000000000 --- a/backend/app/dto/firewall.go +++ /dev/null @@ -1,74 +0,0 @@ -package dto - -type FirewallBaseInfo struct { - Name string `json:"name"` - Status string `json:"status"` - Version string `json:"version"` - PingStatus string `json:"pingStatus"` -} - -type RuleSearch struct { - PageInfo - Info string `json:"info"` - Status string `json:"status"` - Strategy string `json:"strategy"` - Type string `json:"type" validate:"required"` -} - -type FirewallOperation struct { - Operation string `json:"operation" validate:"required,oneof=start stop restart disablePing enablePing"` -} - -type PortRuleOperate struct { - Operation string `json:"operation" validate:"required,oneof=add remove"` - Address string `json:"address"` - Port string `json:"port" validate:"required"` - Protocol string `json:"protocol" validate:"required,oneof=tcp udp tcp/udp"` - Strategy string `json:"strategy" validate:"required,oneof=accept drop"` - - Description string `json:"description"` -} - -type ForwardRuleOperate struct { - Rules []struct { - Operation string `json:"operation" validate:"required,oneof=add remove"` - Num string `json:"num"` - Protocol string `json:"protocol" validate:"required,oneof=tcp udp tcp/udp"` - Port string `json:"port" validate:"required"` - TargetIP string `json:"targetIP"` - TargetPort string `json:"targetPort" validate:"required"` - } `json:"rules"` -} - -type UpdateFirewallDescription struct { - Type string `json:"type"` - Address string `json:"address"` - Port string `json:"port"` - Protocol string `json:"protocol"` - Strategy string `json:"strategy" validate:"required,oneof=accept drop"` - - Description string `json:"description"` -} - -type AddrRuleOperate struct { - Operation string `json:"operation" validate:"required,oneof=add remove"` - Address string `json:"address" validate:"required"` - Strategy string `json:"strategy" validate:"required,oneof=accept drop"` - - Description string `json:"description"` -} - -type PortRuleUpdate struct { - OldRule PortRuleOperate `json:"oldRule"` - NewRule PortRuleOperate `json:"newRule"` -} - -type AddrRuleUpdate struct { - OldRule AddrRuleOperate `json:"oldRule"` - NewRule AddrRuleOperate `json:"newRule"` -} - -type BatchRuleOperate struct { - Type string `json:"type" validate:"required"` - Rules []PortRuleOperate `json:"rules"` -} diff --git a/backend/app/dto/ftp.go b/backend/app/dto/ftp.go deleted file mode 100644 index fad9376d0..000000000 --- a/backend/app/dto/ftp.go +++ /dev/null @@ -1,43 +0,0 @@ -package dto - -import ( - "time" -) - -type FtpInfo struct { - ID uint `json:"id"` - CreatedAt time.Time `json:"createdAt"` - - User string `json:"user"` - Password string `json:"password"` - Path string `json:"path"` - Status string `json:"status"` - Description string `json:"description"` -} - -type FtpBaseInfo struct { - IsActive bool `json:"isActive"` - IsExist bool `json:"isExist"` -} - -type FtpLogSearch struct { - PageInfo - User string `json:"user"` - Operation string `json:"operation"` -} - -type FtpCreate struct { - User string `json:"user" validate:"required"` - Password string `json:"password" validate:"required"` - Path string `json:"path" validate:"required"` - Description string `json:"description"` -} - -type FtpUpdate struct { - ID uint `json:"id"` - - Password string `json:"password" validate:"required"` - Path string `json:"path" validate:"required"` - Status string `json:"status"` - Description string `json:"description"` -} diff --git a/backend/app/dto/group.go b/backend/app/dto/group.go deleted file mode 100644 index 60179d7ac..000000000 --- a/backend/app/dto/group.go +++ /dev/null @@ -1,25 +0,0 @@ -package dto - -type GroupCreate struct { - ID uint `json:"id"` - Name string `json:"name" validate:"required"` - Type string `json:"type" validate:"required"` -} - -type GroupSearch struct { - Type string `json:"type" validate:"required"` -} - -type GroupUpdate struct { - ID uint `json:"id"` - Name string `json:"name"` - Type string `json:"type" validate:"required"` - IsDefault bool `json:"isDefault"` -} - -type GroupInfo struct { - ID uint `json:"id"` - Name string `json:"name"` - Type string `json:"type"` - IsDefault bool `json:"isDefault"` -} diff --git a/backend/app/dto/host.go b/backend/app/dto/host.go deleted file mode 100644 index 9853d8f34..000000000 --- a/backend/app/dto/host.go +++ /dev/null @@ -1,75 +0,0 @@ -package dto - -import ( - "time" -) - -type HostOperate struct { - ID uint `json:"id"` - GroupID uint `json:"groupID"` - Name string `json:"name"` - Addr string `json:"addr" validate:"required"` - Port uint `json:"port" validate:"required,number,max=65535,min=1"` - User string `json:"user" validate:"required"` - AuthMode string `json:"authMode" validate:"oneof=password key"` - Password string `json:"password"` - PrivateKey string `json:"privateKey"` - PassPhrase string `json:"passPhrase"` - RememberPassword bool `json:"rememberPassword"` - - Description string `json:"description"` -} - -type HostConnTest struct { - Addr string `json:"addr" validate:"required"` - Port uint `json:"port" validate:"required,number,max=65535,min=1"` - User string `json:"user" validate:"required"` - AuthMode string `json:"authMode" validate:"oneof=password key"` - Password string `json:"password"` - PrivateKey string `json:"privateKey"` - PassPhrase string `json:"passPhrase"` -} - -type SearchHostWithPage struct { - PageInfo - GroupID uint `json:"groupID"` - Info string `json:"info"` -} - -type SearchForTree struct { - Info string `json:"info"` -} - -type ChangeHostGroup struct { - ID uint `json:"id" validate:"required"` - GroupID uint `json:"groupID" validate:"required"` -} - -type HostInfo struct { - ID uint `json:"id"` - CreatedAt time.Time `json:"createdAt"` - GroupID uint `json:"groupID"` - GroupBelong string `json:"groupBelong"` - Name string `json:"name"` - Addr string `json:"addr"` - Port uint `json:"port"` - User string `json:"user"` - AuthMode string `json:"authMode"` - Password string `json:"password"` - PrivateKey string `json:"privateKey"` - PassPhrase string `json:"passPhrase"` - RememberPassword bool `json:"rememberPassword"` - - Description string `json:"description"` -} - -type HostTree struct { - ID uint `json:"id"` - Label string `json:"label"` - Children []TreeChild `json:"children"` -} - -type TreeChild struct { - ID uint `json:"id"` - Label string `json:"label"` -} diff --git a/backend/app/dto/image.go b/backend/app/dto/image.go deleted file mode 100644 index 541c5ffb0..000000000 --- a/backend/app/dto/image.go +++ /dev/null @@ -1,44 +0,0 @@ -package dto - -import "time" - -type ImageInfo struct { - ID string `json:"id"` - CreatedAt time.Time `json:"createdAt"` - IsUsed bool `json:"isUsed"` - Tags []string `json:"tags"` - Size string `json:"size"` -} - -type ImageLoad struct { - Path string `json:"path" validate:"required"` -} - -type ImageBuild struct { - From string `json:"from" validate:"required"` - Name string `json:"name" validate:"required"` - Dockerfile string `json:"dockerfile" validate:"required"` - Tags []string `json:"tags"` -} - -type ImagePull struct { - RepoID uint `json:"repoID"` - ImageName string `json:"imageName" validate:"required"` -} - -type ImageTag struct { - SourceID string `json:"sourceID" validate:"required"` - TargetName string `json:"targetName" validate:"required"` -} - -type ImagePush struct { - RepoID uint `json:"repoID" validate:"required"` - TagName string `json:"tagName" validate:"required"` - Name string `json:"name" validate:"required"` -} - -type ImageSave struct { - TagName string `json:"tagName" validate:"required"` - Path string `json:"path" validate:"required"` - Name string `json:"name" validate:"required"` -} diff --git a/backend/app/dto/image_repo.go b/backend/app/dto/image_repo.go deleted file mode 100644 index ea5275106..000000000 --- a/backend/app/dto/image_repo.go +++ /dev/null @@ -1,44 +0,0 @@ -package dto - -import "time" - -type ImageRepoCreate struct { - Name string `json:"name" validate:"required"` - DownloadUrl string `json:"downloadUrl"` - Protocol string `json:"protocol"` - Username string `json:"username" validate:"max=256"` - Password string `json:"password" validate:"max=256"` - Auth bool `json:"auth"` -} - -type ImageRepoUpdate struct { - ID uint `json:"id"` - DownloadUrl string `json:"downloadUrl"` - Protocol string `json:"protocol"` - Username string `json:"username" validate:"max=256"` - Password string `json:"password" validate:"max=256"` - Auth bool `json:"auth"` -} - -type ImageRepoInfo struct { - ID uint `json:"id"` - CreatedAt time.Time `json:"createdAt"` - Name string `json:"name"` - DownloadUrl string `json:"downloadUrl"` - Protocol string `json:"protocol"` - Username string `json:"username"` - Auth bool `json:"auth"` - - Status string `json:"status"` - Message string `json:"message"` -} - -type ImageRepoOption struct { - ID uint `json:"id"` - Name string `json:"name"` - DownloadUrl string `json:"downloadUrl"` -} - -type ImageRepoDelete struct { - Ids []uint `json:"ids" validate:"required"` -} diff --git a/backend/app/dto/logs.go b/backend/app/dto/logs.go deleted file mode 100644 index 8831801db..000000000 --- a/backend/app/dto/logs.go +++ /dev/null @@ -1,50 +0,0 @@ -package dto - -import ( - "time" -) - -type OperationLog struct { - ID uint `json:"id"` - Source string `json:"source"` - - IP string `json:"ip"` - Path string `json:"path"` - Method string `json:"method"` - UserAgent string `json:"userAgent"` - - Latency time.Duration `json:"latency"` - Status string `json:"status"` - Message string `json:"message"` - - DetailZH string `json:"detailZH"` - DetailEN string `json:"detailEN"` - CreatedAt time.Time `json:"createdAt"` -} - -type SearchOpLogWithPage struct { - PageInfo - Source string `json:"source"` - Status string `json:"status"` - Operation string `json:"operation"` -} - -type SearchLgLogWithPage struct { - PageInfo - IP string `json:"ip"` - Status string `json:"status"` -} - -type LoginLog struct { - ID uint `json:"id"` - IP string `json:"ip"` - Address string `json:"address"` - Agent string `json:"agent"` - Status string `json:"status"` - Message string `json:"message"` - CreatedAt time.Time `json:"createdAt"` -} - -type CleanLog struct { - LogType string `json:"logType" validate:"required,oneof=login operation"` -} diff --git a/backend/app/dto/monitor.go b/backend/app/dto/monitor.go deleted file mode 100644 index 780b1c790..000000000 --- a/backend/app/dto/monitor.go +++ /dev/null @@ -1,16 +0,0 @@ -package dto - -import "time" - -type MonitorSearch struct { - Param string `json:"param" validate:"required,oneof=all cpu memory load io network"` - Info string `json:"info"` - StartTime time.Time `json:"startTime"` - EndTime time.Time `json:"endTime"` -} - -type MonitorData struct { - Param string `json:"param" validate:"required,oneof=cpu memory load io network"` - Date []time.Time `json:"date"` - Value []interface{} `json:"value"` -} diff --git a/backend/app/dto/nginx.go b/backend/app/dto/nginx.go deleted file mode 100644 index 9e9a1f364..000000000 --- a/backend/app/dto/nginx.go +++ /dev/null @@ -1,59 +0,0 @@ -package dto - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/utils/nginx/components" -) - -type NginxFull struct { - Install model.AppInstall - Website model.Website - ConfigDir string - ConfigFile string - SiteDir string - Dir string - RootConfig NginxConfig - SiteConfig NginxConfig -} - -type NginxConfig struct { - FilePath string - Config *components.Config - OldContent string -} - -type NginxParam struct { - UpdateScope string - Name string - Params []string -} - -type NginxAuth struct { - Username string `json:"username"` - Remark string `json:"remark"` -} - -type NginxKey string - -const ( - Index NginxKey = "index" - LimitConn NginxKey = "limit-conn" - SSL NginxKey = "ssl" - CACHE NginxKey = "cache" - HttpPer NginxKey = "http-per" - ProxyCache NginxKey = "proxy-cache" -) - -var ScopeKeyMap = map[NginxKey][]string{ - Index: {"index"}, - LimitConn: {"limit_conn", "limit_rate", "limit_conn_zone"}, - SSL: {"ssl_certificate", "ssl_certificate_key"}, - HttpPer: {"server_names_hash_bucket_size", "client_header_buffer_size", "client_max_body_size", "keepalive_timeout", "gzip", "gzip_min_length", "gzip_comp_level"}, -} - -var StaticFileKeyMap = map[NginxKey]struct { -}{ - SSL: {}, - CACHE: {}, - ProxyCache: {}, -} diff --git a/backend/app/dto/request/app.go b/backend/app/dto/request/app.go deleted file mode 100644 index e6e61870d..000000000 --- a/backend/app/dto/request/app.go +++ /dev/null @@ -1,104 +0,0 @@ -package request - -import ( - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" -) - -type AppSearch struct { - dto.PageInfo - Name string `json:"name"` - Tags []string `json:"tags"` - Type string `json:"type"` - Recommend bool `json:"recommend"` - Resource string `json:"resource"` -} - -type AppInstallCreate struct { - AppDetailId uint `json:"appDetailId" validate:"required"` - Params map[string]interface{} `json:"params"` - Name string `json:"name" validate:"required"` - Services map[string]string `json:"services"` - AppContainerConfig -} - -type AppContainerConfig struct { - Advanced bool `json:"advanced"` - CpuQuota float64 `json:"cpuQuota"` - MemoryLimit float64 `json:"memoryLimit"` - MemoryUnit string `json:"memoryUnit"` - ContainerName string `json:"containerName"` - AllowPort bool `json:"allowPort"` - EditCompose bool `json:"editCompose"` - DockerCompose string `json:"dockerCompose"` - HostMode bool `json:"hostMode"` - PullImage bool `json:"pullImage"` -} - -type AppInstalledSearch struct { - dto.PageInfo - Type string `json:"type"` - Name string `json:"name"` - Tags []string `json:"tags"` - Update bool `json:"update"` - Unused bool `json:"unused"` - All bool `json:"all"` - Sync bool `json:"sync"` -} - -type AppInstalledInfo struct { - Key string `json:"key" validate:"required"` - Name string `json:"name"` -} - -type AppBackupSearch struct { - dto.PageInfo - AppInstallID uint `json:"appInstallID"` -} - -type AppBackupDelete struct { - Ids []uint `json:"ids"` -} - -type AppInstalledOperate struct { - InstallId uint `json:"installId" validate:"required"` - BackupId uint `json:"backupId"` - DetailId uint `json:"detailId"` - Operate constant.AppOperate `json:"operate" validate:"required"` - ForceDelete bool `json:"forceDelete"` - DeleteBackup bool `json:"deleteBackup"` - DeleteDB bool `json:"deleteDB"` - Backup bool `json:"backup"` - PullImage bool `json:"pullImage"` - DockerCompose string `json:"dockerCompose"` -} - -type AppInstallUpgrade struct { - InstallID uint `json:"installId"` - DetailID uint `json:"detailId"` - Backup bool `json:"backup"` - PullImage bool `json:"pullImage"` - DockerCompose string `json:"dockerCompose"` -} - -type AppInstalledUpdate struct { - InstallId uint `json:"installId" validate:"required"` - Params map[string]interface{} `json:"params" validate:"required"` - AppContainerConfig -} - -type AppInstalledIgnoreUpgrade struct { - DetailID uint `json:"detailID" validate:"required"` - Operate string `json:"operate" validate:"required,oneof=cancel ignore"` -} - -type PortUpdate struct { - Key string `json:"key"` - Name string `json:"name"` - Port int64 `json:"port"` -} - -type AppUpdateVersion struct { - AppInstallID uint `json:"appInstallID" validate:"required"` - UpdateVersion string `json:"updateVersion"` -} diff --git a/backend/app/dto/request/favorite.go b/backend/app/dto/request/favorite.go deleted file mode 100644 index 70280929c..000000000 --- a/backend/app/dto/request/favorite.go +++ /dev/null @@ -1,9 +0,0 @@ -package request - -type FavoriteCreate struct { - Path string `json:"path" validate:"required"` -} - -type FavoriteDelete struct { - ID uint `json:"id" validate:"required"` -} diff --git a/backend/app/dto/request/file.go b/backend/app/dto/request/file.go deleted file mode 100644 index 96c771dab..000000000 --- a/backend/app/dto/request/file.go +++ /dev/null @@ -1,136 +0,0 @@ -package request - -import ( - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/utils/files" -) - -type FileOption struct { - files.FileOption -} - -type FileContentReq struct { - Path string `json:"path" validate:"required"` - IsDetail bool `json:"isDetail"` -} - -type SearchUploadWithPage struct { - dto.PageInfo - Path string `json:"path" validate:"required"` -} - -type FileCreate struct { - Path string `json:"path" validate:"required"` - Content string `json:"content"` - IsDir bool `json:"isDir"` - Mode int64 `json:"mode"` - IsLink bool `json:"isLink"` - IsSymlink bool `json:"isSymlink"` - LinkPath string `json:"linkPath"` - Sub bool `json:"sub"` -} - -type FileRoleReq struct { - Paths []string `json:"paths" validate:"required"` - Mode int64 `json:"mode" validate:"required"` - User string `json:"user" validate:"required"` - Group string `json:"group" validate:"required"` - Sub bool `json:"sub"` -} - -type FileDelete struct { - Path string `json:"path" validate:"required"` - IsDir bool `json:"isDir"` - ForceDelete bool `json:"forceDelete"` -} - -type FileBatchDelete struct { - Paths []string `json:"paths" validate:"required"` - IsDir bool `json:"isDir"` -} - -type FileCompress struct { - Files []string `json:"files" validate:"required"` - Dst string `json:"dst" validate:"required"` - Type string `json:"type" validate:"required"` - Name string `json:"name" validate:"required"` - Replace bool `json:"replace"` - Secret string `json:"secret"` -} - -type FileDeCompress struct { - Dst string `json:"dst" validate:"required"` - Type string `json:"type" validate:"required"` - Path string `json:"path" validate:"required"` - Secret string `json:"secret"` -} - -type FileEdit struct { - Path string `json:"path" validate:"required"` - Content string `json:"content"` -} - -type FileRename struct { - OldName string `json:"oldName" validate:"required"` - NewName string `json:"newName" validate:"required"` -} - -type FilePathCheck struct { - Path string `json:"path" validate:"required"` -} - -type FileWget struct { - Url string `json:"url" validate:"required"` - Path string `json:"path" validate:"required"` - Name string `json:"name" validate:"required"` - IgnoreCertificate bool `json:"ignoreCertificate"` -} - -type FileMove struct { - Type string `json:"type" validate:"required"` - OldPaths []string `json:"oldPaths" validate:"required"` - NewPath string `json:"newPath" validate:"required"` - Name string `json:"name"` - Cover bool `json:"cover"` -} - -type FileDownload struct { - Paths []string `json:"paths" validate:"required"` - Type string `json:"type" validate:"required"` - Name string `json:"name" validate:"required"` - Compress bool `json:"compress"` -} - -type FileChunkDownload struct { - Path string `json:"path" validate:"required"` - Name string `json:"name" validate:"required"` -} - -type DirSizeReq struct { - Path string `json:"path" validate:"required"` -} - -type FileProcessReq struct { - Key string `json:"key"` -} - -type FileRoleUpdate struct { - Path string `json:"path" validate:"required"` - User string `json:"user" validate:"required"` - Group string `json:"group" validate:"required"` - Sub bool `json:"sub"` -} - -type FileReadByLineReq struct { - Page int `json:"page" validate:"required"` - PageSize int `json:"pageSize" validate:"required"` - Type string `json:"type" validate:"required"` - ID uint `json:"ID"` - Name string `json:"name"` - Latest bool `json:"latest"` -} - -type FileExistReq struct { - Name string `json:"name" validate:"required"` - Dir string `json:"dir" validate:"required"` -} diff --git a/backend/app/dto/request/host_tool.go b/backend/app/dto/request/host_tool.go deleted file mode 100644 index aef43182d..000000000 --- a/backend/app/dto/request/host_tool.go +++ /dev/null @@ -1,41 +0,0 @@ -package request - -type HostToolReq struct { - Type string `json:"type" validate:"required,oneof=supervisord"` - Operate string `json:"operate" validate:"oneof=status restart start stop"` -} - -type HostToolCreate struct { - Type string `json:"type" validate:"required"` - SupervisorConfig -} - -type SupervisorConfig struct { - ConfigPath string `json:"configPath"` - ServiceName string `json:"serviceName"` -} - -type HostToolLogReq struct { - Type string `json:"type" validate:"required,oneof=supervisord"` -} - -type HostToolConfig struct { - Type string `json:"type" validate:"required,oneof=supervisord"` - Operate string `json:"operate" validate:"oneof=get set"` - Content string `json:"content"` -} - -type SupervisorProcessConfig struct { - Name string `json:"name"` - Operate string `json:"operate"` - Command string `json:"command"` - User string `json:"user"` - Dir string `json:"dir"` - Numprocs string `json:"numprocs"` -} -type SupervisorProcessFileReq struct { - Name string `json:"name" validate:"required"` - Operate string `json:"operate" validate:"required,oneof=get clear update" ` - Content string `json:"content"` - File string `json:"file" validate:"required,oneof=out.log err.log config"` -} diff --git a/backend/app/dto/request/nginx.go b/backend/app/dto/request/nginx.go deleted file mode 100644 index fd2b68111..000000000 --- a/backend/app/dto/request/nginx.go +++ /dev/null @@ -1,87 +0,0 @@ -package request - -import "github.com/1Panel-dev/1Panel/backend/app/dto" - -type NginxConfigFileUpdate struct { - Content string `json:"content" validate:"required"` - Backup bool `json:"backup"` -} - -type NginxScopeReq struct { - Scope dto.NginxKey `json:"scope" validate:"required"` - WebsiteID uint `json:"websiteId"` -} - -type NginxConfigUpdate struct { - Scope dto.NginxKey `json:"scope"` - Operate string `json:"operate" validate:"required,oneof=add update delete"` - WebsiteID uint `json:"websiteId"` - Params interface{} `json:"params"` -} - -type NginxRewriteReq struct { - WebsiteID uint `json:"websiteId" validate:"required"` - Name string `json:"name" validate:"required"` -} - -type NginxRewriteUpdate struct { - WebsiteID uint `json:"websiteId" validate:"required"` - Name string `json:"name" validate:"required"` - Content string `json:"content"` -} - -type NginxProxyUpdate struct { - WebsiteID uint `json:"websiteID" validate:"required"` - Content string `json:"content" validate:"required"` - Name string `json:"name" validate:"required"` -} - -type NginxAuthUpdate struct { - WebsiteID uint `json:"websiteID" validate:"required"` - Operate string `json:"operate" validate:"required"` - Username string `json:"username"` - Password string `json:"password"` - Remark string `json:"remark"` -} - -type NginxAuthReq struct { - WebsiteID uint `json:"websiteID" validate:"required"` -} - -type NginxCommonReq struct { - WebsiteID uint `json:"websiteID" validate:"required"` -} - -type NginxAntiLeechUpdate struct { - WebsiteID uint `json:"websiteID" validate:"required"` - Extends string `json:"extends" validate:"required"` - Return string `json:"return" validate:"required"` - Enable bool `json:"enable" ` - ServerNames []string `json:"serverNames"` - Cache bool `json:"cache"` - CacheTime int `json:"cacheTime"` - CacheUint string `json:"cacheUint"` - NoneRef bool `json:"noneRef"` - LogEnable bool `json:"logEnable"` - Blocked bool `json:"blocked"` -} - -type NginxRedirectReq struct { - Name string `json:"name" validate:"required"` - WebsiteID uint `json:"websiteID" validate:"required"` - Domains []string `json:"domains"` - KeepPath bool `json:"keepPath"` - Enable bool `json:"enable"` - Type string `json:"type" validate:"required"` - Redirect string `json:"redirect" validate:"required"` - Path string `json:"path"` - Target string `json:"target" validate:"required"` - Operate string `json:"operate" validate:"required"` - RedirectRoot bool `json:"redirectRoot"` -} - -type NginxRedirectUpdate struct { - WebsiteID uint `json:"websiteID" validate:"required"` - Content string `json:"content" validate:"required"` - Name string `json:"name" validate:"required"` -} diff --git a/backend/app/dto/request/php_extensions.go b/backend/app/dto/request/php_extensions.go deleted file mode 100644 index a163859ff..000000000 --- a/backend/app/dto/request/php_extensions.go +++ /dev/null @@ -1,22 +0,0 @@ -package request - -import "github.com/1Panel-dev/1Panel/backend/app/dto" - -type PHPExtensionsSearch struct { - dto.PageInfo - All bool `json:"all"` -} - -type PHPExtensionsCreate struct { - Name string `json:"name" validate:"required"` - Extensions string `json:"extensions" validate:"required"` -} - -type PHPExtensionsUpdate struct { - ID uint `json:"id" validate:"required"` - Extensions string `json:"extensions" validate:"required"` -} - -type PHPExtensionsDelete struct { - ID uint `json:"id" validate:"required"` -} diff --git a/backend/app/dto/request/process.go b/backend/app/dto/request/process.go deleted file mode 100644 index 9269c4c7d..000000000 --- a/backend/app/dto/request/process.go +++ /dev/null @@ -1,5 +0,0 @@ -package request - -type ProcessReq struct { - PID int32 `json:"PID" validate:"required"` -} diff --git a/backend/app/dto/request/recycle_bin.go b/backend/app/dto/request/recycle_bin.go deleted file mode 100644 index 4870a735e..000000000 --- a/backend/app/dto/request/recycle_bin.go +++ /dev/null @@ -1,11 +0,0 @@ -package request - -type RecycleBinCreate struct { - SourcePath string `json:"sourcePath" validate:"required"` -} - -type RecycleBinReduce struct { - From string `json:"from" validate:"required"` - RName string `json:"rName" validate:"required"` - Name string `json:"name"` -} diff --git a/backend/app/dto/request/runtime.go b/backend/app/dto/request/runtime.go deleted file mode 100644 index d9c218500..000000000 --- a/backend/app/dto/request/runtime.go +++ /dev/null @@ -1,72 +0,0 @@ -package request - -import "github.com/1Panel-dev/1Panel/backend/app/dto" - -type RuntimeSearch struct { - dto.PageInfo - Type string `json:"type"` - Name string `json:"name"` - Status string `json:"status"` -} - -type RuntimeCreate struct { - AppDetailID uint `json:"appDetailId"` - Name string `json:"name"` - Params map[string]interface{} `json:"params"` - Resource string `json:"resource"` - Image string `json:"image"` - Type string `json:"type"` - Version string `json:"version"` - Source string `json:"source"` - CodeDir string `json:"codeDir"` - NodeConfig -} - -type NodeConfig struct { - Install bool `json:"install"` - Clean bool `json:"clean"` - Port int `json:"port"` - ExposedPorts []ExposedPort `json:"exposedPorts"` -} - -type ExposedPort struct { - HostPort int `json:"hostPort"` - ContainerPort int `json:"containerPort"` -} - -type RuntimeDelete struct { - ID uint `json:"id"` - ForceDelete bool `json:"forceDelete"` -} - -type RuntimeUpdate struct { - Name string `json:"name"` - ID uint `json:"id"` - Params map[string]interface{} `json:"params"` - Image string `json:"image"` - Version string `json:"version"` - Rebuild bool `json:"rebuild"` - Source string `json:"source"` - CodeDir string `json:"codeDir"` - NodeConfig -} - -type NodePackageReq struct { - CodeDir string `json:"codeDir"` -} - -type RuntimeOperate struct { - Operate string `json:"operate"` - ID uint `json:"ID"` -} - -type NodeModuleOperateReq struct { - Operate string `json:"operate" validate:"oneof=install uninstall update"` - ID uint `json:"ID" validate:"required"` - Module string `json:"module"` - PkgManager string `json:"pkgManager" validate:"oneof=npm yarn"` -} - -type NodeModuleReq struct { - ID uint `json:"ID" validate:"required"` -} diff --git a/backend/app/dto/request/website.go b/backend/app/dto/request/website.go deleted file mode 100644 index aac5baca1..000000000 --- a/backend/app/dto/request/website.go +++ /dev/null @@ -1,220 +0,0 @@ -package request - -import ( - "github.com/1Panel-dev/1Panel/backend/app/dto" -) - -type WebsiteSearch struct { - dto.PageInfo - Name string `json:"name"` - OrderBy string `json:"orderBy" validate:"required,oneof=primary_domain type status created_at expire_date"` - Order string `json:"order" validate:"required,oneof=null ascending descending"` - WebsiteGroupID uint `json:"websiteGroupId"` -} - -type WebsiteCreate struct { - PrimaryDomain string `json:"primaryDomain" validate:"required"` - Type string `json:"type" validate:"required"` - Alias string `json:"alias" validate:"required"` - Remark string `json:"remark"` - OtherDomains string `json:"otherDomains"` - Proxy string `json:"proxy"` - WebsiteGroupID uint `json:"webSiteGroupID" validate:"required"` - IPV6 bool `json:"IPV6"` - - AppType string `json:"appType" validate:"oneof=new installed"` - AppInstall NewAppInstall `json:"appInstall"` - AppID uint `json:"appID"` - AppInstallID uint `json:"appInstallID"` - - FtpUser string `json:"ftpUser"` - FtpPassword string `json:"ftpPassword"` - - RuntimeID uint `json:"runtimeID"` - RuntimeConfig -} - -type RuntimeConfig struct { - ProxyType string `json:"proxyType"` - Port int `json:"port"` -} - -type NewAppInstall struct { - Name string `json:"name"` - AppDetailId uint `json:"appDetailID"` - Params map[string]interface{} `json:"params"` - - AppContainerConfig -} - -type WebsiteInstallCheckReq struct { - InstallIds []uint `json:"InstallIds"` -} - -type WebsiteUpdate struct { - ID uint `json:"id" validate:"required"` - PrimaryDomain string `json:"primaryDomain" validate:"required"` - Remark string `json:"remark"` - WebsiteGroupID uint `json:"webSiteGroupID"` - ExpireDate string `json:"expireDate"` - IPV6 bool `json:"IPV6"` -} - -type WebsiteDelete struct { - ID uint `json:"id" validate:"required"` - DeleteApp bool `json:"deleteApp"` - DeleteBackup bool `json:"deleteBackup"` - ForceDelete bool `json:"forceDelete"` -} - -type WebsiteOp struct { - ID uint `json:"id" validate:"required"` - Operate string `json:"operate"` -} - -type WebsiteRedirectUpdate struct { - WebsiteID uint `json:"websiteId" validate:"required"` - Key string `json:"key" validate:"required"` - Enable bool `json:"enable"` -} - -type WebsiteRecover struct { - WebsiteName string `json:"websiteName" validate:"required"` - Type string `json:"type" validate:"required"` - BackupName string `json:"backupName" validate:"required"` -} - -type WebsiteRecoverByFile struct { - WebsiteName string `json:"websiteName" validate:"required"` - Type string `json:"type" validate:"required"` - FileDir string `json:"fileDir" validate:"required"` - FileName string `json:"fileName" validate:"required"` -} - -type WebsiteGroupCreate struct { - Name string `json:"name" validate:"required"` -} - -type WebsiteGroupUpdate struct { - ID uint `json:"id" validate:"required"` - Name string `json:"name"` - Default bool `json:"default"` -} - -type WebsiteDomainCreate struct { - WebsiteID uint `json:"websiteID" validate:"required"` - Domains string `json:"domains" validate:"required"` -} - -type WebsiteDomainDelete struct { - ID uint `json:"id" validate:"required"` -} - -type WebsiteHTTPSOp struct { - WebsiteID uint `json:"websiteId" validate:"required"` - Enable bool `json:"enable"` - WebsiteSSLID uint `json:"websiteSSLId"` - Type string `json:"type" validate:"oneof=existed auto manual"` - PrivateKey string `json:"privateKey"` - Certificate string `json:"certificate"` - PrivateKeyPath string `json:"privateKeyPath"` - CertificatePath string `json:"certificatePath"` - ImportType string `json:"importType"` - HttpConfig string `json:"httpConfig" validate:"oneof=HTTPSOnly HTTPAlso HTTPToHTTPS"` - SSLProtocol []string `json:"SSLProtocol"` - Algorithm string `json:"algorithm"` - Hsts bool `json:"hsts"` -} - -type WebsiteNginxUpdate struct { - ID uint `json:"id" validate:"required"` - Content string `json:"content" validate:"required"` -} - -type WebsiteLogReq struct { - ID uint `json:"id" validate:"required"` - Operate string `json:"operate" validate:"required"` - LogType string `json:"logType" validate:"required"` - Page int `json:"page"` - PageSize int `json:"pageSize"` -} - -type WebsiteDefaultUpdate struct { - ID uint `json:"id"` -} - -type WebsitePHPConfigUpdate struct { - ID uint `json:"id" validate:"required"` - Params map[string]string `json:"params"` - Scope string `json:"scope" validate:"required"` - DisableFunctions []string `json:"disableFunctions"` - UploadMaxSize string `json:"uploadMaxSize"` -} - -type WebsitePHPFileUpdate struct { - ID uint `json:"id" validate:"required"` - Type string `json:"type" validate:"required"` - Content string `json:"content" validate:"required"` -} - -type WebsitePHPVersionReq struct { - WebsiteID uint `json:"websiteID" validate:"required"` - RuntimeID uint `json:"runtimeID" validate:"required"` - RetainConfig bool `json:"retainConfig" ` -} - -type WebsiteUpdateDir struct { - ID uint `json:"id" validate:"required"` - SiteDir string `json:"siteDir" validate:"required"` -} - -type WebsiteUpdateDirPermission struct { - ID uint `json:"id" validate:"required"` - User string `json:"user" validate:"required"` - Group string `json:"group" validate:"required"` -} - -type WebsiteProxyConfig struct { - ID uint `json:"id" validate:"required"` - Operate string `json:"operate" validate:"required"` - Enable bool `json:"enable" ` - Cache bool `json:"cache" ` - CacheTime int `json:"cacheTime" ` - CacheUnit string `json:"cacheUnit"` - Name string `json:"name" validate:"required"` - Modifier string `json:"modifier"` - Match string `json:"match" validate:"required"` - ProxyPass string `json:"proxyPass" validate:"required"` - ProxyHost string `json:"proxyHost" validate:"required"` - Content string `json:"content"` - FilePath string `json:"filePath"` - Replaces map[string]string `json:"replaces"` - SNI bool `json:"sni"` -} - -type WebsiteProxyReq struct { - ID uint `json:"id" validate:"required"` -} - -type WebsiteRedirectReq struct { - WebsiteID uint `json:"websiteId" validate:"required"` -} - -type WebsiteCommonReq struct { - ID uint `json:"id" validate:"required"` -} - -type WafWebsite struct { - Key string `json:"key"` - Domains []string `json:"domains"` - Host []string `json:"host"` -} - -type WebsiteHtmlReq struct { - Type string `json:"type" validate:"required"` -} - -type WebsiteHtmlUpdate struct { - Type string `json:"type" validate:"required"` - Content string `json:"content" validate:"required"` -} diff --git a/backend/app/dto/request/website_ssl.go b/backend/app/dto/request/website_ssl.go deleted file mode 100644 index 509aed434..000000000 --- a/backend/app/dto/request/website_ssl.go +++ /dev/null @@ -1,139 +0,0 @@ -package request - -import "github.com/1Panel-dev/1Panel/backend/app/dto" - -type WebsiteSSLSearch struct { - dto.PageInfo - AcmeAccountID string `json:"acmeAccountID"` -} - -type WebsiteSSLCreate struct { - PrimaryDomain string `json:"primaryDomain" validate:"required"` - OtherDomains string `json:"otherDomains"` - Provider string `json:"provider" validate:"required"` - AcmeAccountID uint `json:"acmeAccountId" validate:"required"` - DnsAccountID uint `json:"dnsAccountId"` - AutoRenew bool `json:"autoRenew"` - KeyType string `json:"keyType"` - Apply bool `json:"apply"` - PushDir bool `json:"pushDir"` - Dir string `json:"dir"` - ID uint `json:"id"` - Description string `json:"description"` - DisableCNAME bool `json:"disableCNAME"` - SkipDNS bool `json:"skipDNS"` - Nameserver1 string `json:"nameserver1"` - Nameserver2 string `json:"nameserver2"` - ExecShell bool `json:"execShell"` - Shell string `json:"shell"` -} - -type WebsiteDNSReq struct { - Domains []string `json:"domains" validate:"required"` - AcmeAccountID uint `json:"acmeAccountId" validate:"required"` -} - -type WebsiteSSLRenew struct { - SSLID uint `json:"SSLId" validate:"required"` -} - -type WebsiteSSLApply struct { - ID uint `json:"ID" validate:"required"` - SkipDNSCheck bool `json:"skipDNSCheck"` - Nameservers []string `json:"nameservers"` -} - -type WebsiteAcmeAccountCreate struct { - Email string `json:"email" validate:"required"` - Type string `json:"type" validate:"required,oneof=letsencrypt zerossl buypass google"` - KeyType string `json:"keyType" validate:"required,oneof=P256 P384 2048 3072 4096 8192"` - EabKid string `json:"eabKid"` - EabHmacKey string `json:"eabHmacKey"` -} - -type WebsiteDnsAccountCreate struct { - Name string `json:"name" validate:"required"` - Type string `json:"type" validate:"required"` - Authorization map[string]string `json:"authorization" validate:"required"` -} - -type WebsiteDnsAccountUpdate struct { - ID uint `json:"id" validate:"required"` - Name string `json:"name" validate:"required"` - Type string `json:"type" validate:"required"` - Authorization map[string]string `json:"authorization" validate:"required"` -} - -type WebsiteResourceReq struct { - ID uint `json:"id" validate:"required"` -} - -type WebsiteBatchDelReq struct { - IDs []uint `json:"ids" validate:"required"` -} - -type WebsiteSSLUpdate struct { - ID uint `json:"id" validate:"required"` - AutoRenew bool `json:"autoRenew"` - Description string `json:"description"` - PrimaryDomain string `json:"primaryDomain" validate:"required"` - OtherDomains string `json:"otherDomains"` - Provider string `json:"provider" validate:"required"` - AcmeAccountID uint `json:"acmeAccountId"` - DnsAccountID uint `json:"dnsAccountId"` - KeyType string `json:"keyType"` - Apply bool `json:"apply"` - PushDir bool `json:"pushDir"` - Dir string `json:"dir"` - DisableCNAME bool `json:"disableCNAME"` - SkipDNS bool `json:"skipDNS"` - Nameserver1 string `json:"nameserver1"` - Nameserver2 string `json:"nameserver2"` - ExecShell bool `json:"execShell"` - Shell string `json:"shell"` -} - -type WebsiteSSLUpload struct { - PrivateKey string `json:"privateKey"` - Certificate string `json:"certificate"` - PrivateKeyPath string `json:"privateKeyPath"` - CertificatePath string `json:"certificatePath"` - Type string `json:"type" validate:"required,oneof=paste local"` - SSLID uint `json:"sslID"` - Description string `json:"description"` -} - -type WebsiteCASearch struct { - dto.PageInfo -} - -type WebsiteCACreate struct { - CommonName string `json:"commonName" validate:"required"` - Country string `json:"country" validate:"required"` - Organization string `json:"organization" validate:"required"` - OrganizationUint string `json:"organizationUint"` - Name string `json:"name" validate:"required"` - KeyType string `json:"keyType" validate:"required,oneof=P256 P384 2048 3072 4096 8192"` - Province string `json:"province" ` - City string `json:"city"` -} - -type WebsiteCAObtain struct { - ID uint `json:"id" validate:"required"` - Domains string `json:"domains" validate:"required"` - KeyType string `json:"keyType" validate:"required,oneof=P256 P384 2048 3072 4096 8192"` - Time int `json:"time" validate:"required"` - Unit string `json:"unit" validate:"required"` - PushDir bool `json:"pushDir"` - Dir string `json:"dir"` - AutoRenew bool `json:"autoRenew"` - Renew bool `json:"renew"` - SSLID uint `json:"sslID"` - Description string `json:"description"` - ExecShell bool `json:"execShell"` - Shell string `json:"shell"` -} - -type WebsiteCARenew struct { - SSLID uint `json:"SSLID" validate:"required"` -} diff --git a/backend/app/dto/response/app.go b/backend/app/dto/response/app.go deleted file mode 100644 index 2cbced1ef..000000000 --- a/backend/app/dto/response/app.go +++ /dev/null @@ -1,154 +0,0 @@ -package response - -import ( - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - - "github.com/1Panel-dev/1Panel/backend/app/model" -) - -type AppRes struct { - Items []*AppDto `json:"items"` - Total int64 `json:"total"` -} - -type AppUpdateRes struct { - CanUpdate bool `json:"canUpdate"` - IsSyncing bool `json:"isSyncing"` - AppStoreLastModified int `json:"appStoreLastModified"` - AppList *dto.AppList `json:"appList"` -} - -type AppDTO struct { - model.App - Installed bool `json:"installed"` - Versions []string `json:"versions"` - Tags []model.Tag `json:"tags"` -} - -type AppDto struct { - Name string `json:"name"` - Key string `json:"key"` - ID uint `json:"id"` - ShortDescZh string `json:"shortDescZh"` - ShortDescEn string `json:"shortDescEn"` - Icon string `json:"icon"` - Type string `json:"type"` - Status string `json:"status"` - Resource string `json:"resource"` - Installed bool `json:"installed"` - Versions []string `json:"versions"` - Limit int `json:"limit"` - Tags []model.Tag `json:"tags"` -} - -type TagDTO struct { - model.Tag -} - -type AppInstalledCheck struct { - IsExist bool `json:"isExist"` - Name string `json:"name"` - App string `json:"app"` - Version string `json:"version"` - Status string `json:"status"` - CreatedAt time.Time `json:"createdAt"` - LastBackupAt string `json:"lastBackupAt"` - AppInstallID uint `json:"appInstallId"` - ContainerName string `json:"containerName"` - InstallPath string `json:"installPath"` - HttpPort int `json:"httpPort"` - HttpsPort int `json:"httpsPort"` -} - -type AppDetailDTO struct { - model.AppDetail - Enable bool `json:"enable"` - Params interface{} `json:"params"` - Image string `json:"image"` - HostMode bool `json:"hostMode"` -} - -type IgnoredApp struct { - Icon string `json:"icon"` - Name string `json:"name"` - Version string `json:"version"` - DetailID uint `json:"detailID"` -} - -type AppInstalledDTO struct { - model.AppInstall - Total int `json:"total"` - Ready int `json:"ready"` - AppName string `json:"appName"` - Icon string `json:"icon"` - CanUpdate bool `json:"canUpdate"` - Path string `json:"path"` -} - -type AppDetail struct { - Website string `json:"website"` - Document string `json:"document"` - Github string `json:"github"` -} - -type AppInstallDTO struct { - ID uint `json:"id"` - Name string `json:"name"` - AppID uint `json:"appID"` - AppDetailID uint `json:"appDetailID"` - Version string `json:"version"` - Status string `json:"status"` - Message string `json:"message"` - HttpPort int `json:"httpPort"` - HttpsPort int `json:"httpsPort"` - Path string `json:"path"` - CanUpdate bool `json:"canUpdate"` - Icon string `json:"icon"` - AppName string `json:"appName"` - Ready int `json:"ready"` - Total int `json:"total"` - AppKey string `json:"appKey"` - AppType string `json:"appType"` - AppStatus string `json:"appStatus"` - DockerCompose string `json:"dockerCompose"` - CreatedAt time.Time `json:"createdAt"` - App AppDetail `json:"app"` -} - -type DatabaseConn struct { - Status string `json:"status"` - Username string `json:"username"` - Password string `json:"password"` - ContainerName string `json:"containerName"` - ServiceName string `json:"serviceName"` - Port int64 `json:"port"` -} - -type AppService struct { - Label string `json:"label"` - Value string `json:"value"` - Config interface{} `json:"config"` - From string `json:"from"` -} - -type AppParam struct { - Value interface{} `json:"value"` - Edit bool `json:"edit"` - Key string `json:"key"` - Rule string `json:"rule"` - LabelZh string `json:"labelZh"` - LabelEn string `json:"labelEn"` - Type string `json:"type"` - Values interface{} `json:"values"` - ShowValue string `json:"showValue"` - Required bool `json:"required"` - Multiple bool `json:"multiple"` -} - -type AppConfig struct { - Params []AppParam `json:"params"` - request.AppContainerConfig -} diff --git a/backend/app/dto/response/favorite.go b/backend/app/dto/response/favorite.go deleted file mode 100644 index b00a6c475..000000000 --- a/backend/app/dto/response/favorite.go +++ /dev/null @@ -1,7 +0,0 @@ -package response - -import "github.com/1Panel-dev/1Panel/backend/app/model" - -type FavoriteDTO struct { - model.Favorite -} diff --git a/backend/app/dto/response/file.go b/backend/app/dto/response/file.go deleted file mode 100644 index 288260800..000000000 --- a/backend/app/dto/response/file.go +++ /dev/null @@ -1,47 +0,0 @@ -package response - -import ( - "github.com/1Panel-dev/1Panel/backend/utils/files" -) - -type FileInfo struct { - files.FileInfo -} - -type UploadInfo struct { - Name string `json:"name"` - Size int `json:"size"` - CreatedAt string `json:"createdAt"` -} - -type FileTree struct { - ID string `json:"id"` - Name string `json:"name"` - Path string `json:"path"` - IsDir bool `json:"isDir"` - Extension string `json:"extension"` - Children []FileTree `json:"children"` -} - -type DirSizeRes struct { - Size float64 `json:"size" validate:"required"` -} - -type FileProcessKeys struct { - Keys []string `json:"keys"` -} - -type FileWgetRes struct { - Key string `json:"key"` -} - -type FileLineContent struct { - Content string `json:"content"` - End bool `json:"end"` - Path string `json:"path"` - Total int `json:"total"` -} - -type FileExist struct { - Exist bool `json:"exist"` -} diff --git a/backend/app/dto/response/host_tool.go b/backend/app/dto/response/host_tool.go deleted file mode 100644 index e97a675d8..000000000 --- a/backend/app/dto/response/host_tool.go +++ /dev/null @@ -1,41 +0,0 @@ -package response - -type HostToolRes struct { - Type string `json:"type"` - Config interface{} `json:"config"` -} - -type Supervisor struct { - ConfigPath string `json:"configPath"` - IncludeDir string `json:"includeDir"` - LogPath string `json:"logPath"` - IsExist bool `json:"isExist"` - Init bool `json:"init"` - Msg string `json:"msg"` - Version string `json:"version"` - Status string `json:"status"` - CtlExist bool `json:"ctlExist"` - ServiceName string `json:"serviceName"` -} - -type HostToolConfig struct { - Content string `json:"content"` -} - -type SupervisorProcessConfig struct { - Name string `json:"name"` - Command string `json:"command"` - User string `json:"user"` - Dir string `json:"dir"` - Numprocs string `json:"numprocs"` - Msg string `json:"msg"` - Status []ProcessStatus `json:"status"` -} - -type ProcessStatus struct { - Name string `json:"name"` - Status string `json:"status"` - PID string `json:"PID"` - Uptime string `json:"uptime"` - Msg string `json:"msg"` -} diff --git a/backend/app/dto/response/nginx.go b/backend/app/dto/response/nginx.go deleted file mode 100644 index c40521a68..000000000 --- a/backend/app/dto/response/nginx.go +++ /dev/null @@ -1,55 +0,0 @@ -package response - -import "github.com/1Panel-dev/1Panel/backend/app/dto" - -type NginxStatus struct { - Active string `json:"active"` - Accepts string `json:"accepts"` - Handled string `json:"handled"` - Requests string `json:"requests"` - Reading string `json:"reading"` - Writing string `json:"writing"` - Waiting string `json:"waiting"` -} - -type NginxParam struct { - Name string `json:"name"` - Params []string `json:"params"` -} - -type NginxAuthRes struct { - Enable bool `json:"enable"` - Items []dto.NginxAuth `json:"items"` -} - -type NginxAntiLeechRes struct { - Enable bool `json:"enable"` - Extends string `json:"extends"` - Return string `json:"return"` - ServerNames []string `json:"serverNames"` - Cache bool `json:"cache"` - CacheTime int `json:"cacheTime"` - CacheUint string `json:"cacheUint"` - NoneRef bool `json:"noneRef"` - LogEnable bool `json:"logEnable"` - Blocked bool `json:"blocked"` -} - -type NginxRedirectConfig struct { - WebsiteID uint `json:"websiteID"` - Name string `json:"name"` - Domains []string `json:"domains"` - KeepPath bool `json:"keepPath"` - Enable bool `json:"enable"` - Type string `json:"type"` - Redirect string `json:"redirect"` - Path string `json:"path"` - Target string `json:"target"` - FilePath string `json:"filePath"` - Content string `json:"content"` - RedirectRoot bool `json:"redirectRoot"` -} - -type NginxFile struct { - Content string `json:"content"` -} diff --git a/backend/app/dto/response/php_extensions.go b/backend/app/dto/response/php_extensions.go deleted file mode 100644 index 91a96f0d2..000000000 --- a/backend/app/dto/response/php_extensions.go +++ /dev/null @@ -1,7 +0,0 @@ -package response - -import "github.com/1Panel-dev/1Panel/backend/app/model" - -type PHPExtensionsDTO struct { - model.PHPExtensions -} diff --git a/backend/app/dto/response/recycle_bin.go b/backend/app/dto/response/recycle_bin.go deleted file mode 100644 index b5a040358..000000000 --- a/backend/app/dto/response/recycle_bin.go +++ /dev/null @@ -1,14 +0,0 @@ -package response - -import "time" - -type RecycleBinDTO struct { - Name string `json:"name"` - Size int `json:"size"` - Type string `json:"type"` - DeleteTime time.Time `json:"deleteTime"` - RName string `json:"rName"` - SourcePath string `json:"sourcePath"` - IsDir bool `json:"isDir"` - From string `json:"from"` -} diff --git a/backend/app/dto/response/runtime.go b/backend/app/dto/response/runtime.go deleted file mode 100644 index d743a24c9..000000000 --- a/backend/app/dto/response/runtime.go +++ /dev/null @@ -1,58 +0,0 @@ -package response - -import ( - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/model" - "time" -) - -type RuntimeDTO struct { - ID uint `json:"id"` - Name string `json:"name"` - Resource string `json:"resource"` - AppDetailID uint `json:"appDetailID"` - AppID uint `json:"appID"` - Source string `json:"source"` - Status string `json:"status"` - Type string `json:"type"` - Image string `json:"image"` - Params map[string]interface{} `json:"params"` - Message string `json:"message"` - Version string `json:"version"` - CreatedAt time.Time `json:"createdAt"` - CodeDir string `json:"codeDir"` - AppParams []AppParam `json:"appParams"` - Port int `json:"port"` - Path string `json:"path"` - ExposedPorts []request.ExposedPort `json:"exposedPorts"` -} - -type PackageScripts struct { - Name string `json:"name"` - Script string `json:"script"` -} - -func NewRuntimeDTO(runtime model.Runtime) RuntimeDTO { - return RuntimeDTO{ - ID: runtime.ID, - Name: runtime.Name, - Resource: runtime.Resource, - AppDetailID: runtime.AppDetailID, - Status: runtime.Status, - Type: runtime.Type, - Image: runtime.Image, - Message: runtime.Message, - CreatedAt: runtime.CreatedAt, - CodeDir: runtime.CodeDir, - Version: runtime.Version, - Port: runtime.Port, - Path: runtime.GetPath(), - } -} - -type NodeModule struct { - Name string `json:"name"` - Version string `json:"version"` - License string `json:"license"` - Description string `json:"description"` -} diff --git a/backend/app/dto/response/website.go b/backend/app/dto/response/website.go deleted file mode 100644 index 8a31b69e8..000000000 --- a/backend/app/dto/response/website.go +++ /dev/null @@ -1,88 +0,0 @@ -package response - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" - "time" -) - -type WebsiteDTO struct { - model.Website - ErrorLogPath string `json:"errorLogPath"` - AccessLogPath string `json:"accessLogPath"` - SitePath string `json:"sitePath"` - AppName string `json:"appName"` - RuntimeName string `json:"runtimeName"` - SiteDir string `gorm:"type:varchar;" json:"siteDir"` -} - -type WebsiteRes struct { - ID uint `json:"id"` - CreatedAt time.Time `json:"createdAt"` - Protocol string `json:"protocol"` - PrimaryDomain string `json:"primaryDomain"` - Type string `json:"type"` - Alias string `json:"alias"` - Remark string `json:"remark"` - Status string `json:"status"` - ExpireDate time.Time `json:"expireDate"` - SitePath string `json:"sitePath"` - AppName string `json:"appName"` - RuntimeName string `json:"runtimeName"` - SSLExpireDate time.Time `json:"sslExpireDate"` - SSLStatus string `json:"sslStatus"` -} - -type WebsiteOption struct { - ID uint `json:"id"` - PrimaryDomain string `json:"primaryDomain"` - Alias string `json:"alias"` -} - -type WebsitePreInstallCheck struct { - Name string `json:"name"` - Status string `json:"status"` - Version string `json:"version"` - AppName string `json:"appName"` -} - -type WebsiteNginxConfig struct { - Enable bool `json:"enable"` - Params []NginxParam `json:"params"` -} - -type WebsiteHTTPS struct { - Enable bool `json:"enable"` - HttpConfig string `json:"httpConfig"` - SSL model.WebsiteSSL `json:"SSL"` - SSLProtocol []string `json:"SSLProtocol"` - Algorithm string `json:"algorithm"` - Hsts bool `json:"hsts"` -} - -type WebsiteLog struct { - Enable bool `json:"enable"` - Content string `json:"content"` - End bool `json:"end"` - Path string `json:"path"` -} - -type PHPConfig struct { - Params map[string]string `json:"params"` - DisableFunctions []string `json:"disableFunctions"` - UploadMaxSize string `json:"uploadMaxSize"` -} - -type NginxRewriteRes struct { - Content string `json:"content"` -} - -type WebsiteDirConfig struct { - Dirs []string `json:"dirs"` - User string `json:"user"` - UserGroup string `json:"userGroup"` - Msg string `json:"msg"` -} - -type WebsiteHtmlRes struct { - Content string `json:"content"` -} diff --git a/backend/app/dto/response/website_ssl.go b/backend/app/dto/response/website_ssl.go deleted file mode 100644 index 1cb4062ce..000000000 --- a/backend/app/dto/response/website_ssl.go +++ /dev/null @@ -1,34 +0,0 @@ -package response - -import "github.com/1Panel-dev/1Panel/backend/app/model" - -type WebsiteSSLDTO struct { - model.WebsiteSSL - LogPath string `json:"logPath"` -} - -type WebsiteDNSRes struct { - Key string `json:"resolve"` - Value string `json:"value"` - Domain string `json:"domain"` - Err string `json:"err"` -} - -type WebsiteAcmeAccountDTO struct { - model.WebsiteAcmeAccount -} - -type WebsiteDnsAccountDTO struct { - model.WebsiteDnsAccount - Authorization map[string]string `json:"authorization"` -} - -type WebsiteCADTO struct { - model.WebsiteCA - CommonName string `json:"commonName" ` - Country string `json:"country"` - Organization string `json:"organization"` - OrganizationUint string `json:"organizationUint"` - Province string `json:"province" ` - City string `json:"city"` -} diff --git a/backend/app/dto/setting.go b/backend/app/dto/setting.go deleted file mode 100644 index 66c510c4e..000000000 --- a/backend/app/dto/setting.go +++ /dev/null @@ -1,124 +0,0 @@ -package dto - -import "time" - -type SettingInfo struct { - SystemIP string `json:"systemIP"` - DockerSockPath string `json:"dockerSockPath"` - SystemVersion string `json:"systemVersion"` - - LocalTime string `json:"localTime"` - TimeZone string `json:"timeZone"` - NtpSite string `json:"ntpSite"` - - DefaultNetwork string `json:"defaultNetwork"` - LastCleanTime string `json:"lastCleanTime"` - LastCleanSize string `json:"lastCleanSize"` - LastCleanData string `json:"lastCleanData"` - - MonitorStatus string `json:"monitorStatus"` - MonitorInterval string `json:"monitorInterval"` - MonitorStoreDays string `json:"monitorStoreDays"` - - AppStoreVersion string `json:"appStoreVersion"` - AppStoreLastModified string `json:"appStoreLastModified"` - AppStoreSyncStatus string `json:"appStoreSyncStatus"` - - FileRecycleBin string `json:"fileRecycleBin"` - - SnapshotIgnore string `json:"snapshotIgnore"` -} - -type SettingUpdate struct { - Key string `json:"key" validate:"required"` - Value string `json:"value"` -} - -type SnapshotStatus struct { - Panel string `json:"panel"` - PanelInfo string `json:"panelInfo"` - DaemonJson string `json:"daemonJson"` - AppData string `json:"appData"` - PanelData string `json:"panelData"` - BackupData string `json:"backupData"` - - Compress string `json:"compress"` - Size string `json:"size"` - Upload string `json:"upload"` -} - -type SnapshotCreate struct { - ID uint `json:"id"` - From string `json:"from" validate:"required"` - DefaultDownload string `json:"defaultDownload" validate:"required"` - Description string `json:"description" validate:"max=256"` - Secret string `json:"secret"` -} -type SnapshotRecover struct { - IsNew bool `json:"isNew"` - ReDownload bool `json:"reDownload"` - ID uint `json:"id" validate:"required"` - Secret string `json:"secret"` -} -type SnapshotBatchDelete struct { - DeleteWithFile bool `json:"deleteWithFile"` - Ids []uint `json:"ids" validate:"required"` -} - -type SnapshotImport struct { - From string `json:"from"` - Names []string `json:"names"` - Description string `json:"description" validate:"max=256"` -} - -type SnapshotInfo struct { - ID uint `json:"id"` - Name string `json:"name"` - Description string `json:"description" validate:"max=256"` - From string `json:"from"` - DefaultDownload string `json:"defaultDownload"` - Status string `json:"status"` - Message string `json:"message"` - CreatedAt time.Time `json:"createdAt"` - Version string `json:"version"` - Size int64 `json:"size"` - - InterruptStep string `json:"interruptStep"` - RecoverStatus string `json:"recoverStatus"` - RecoverMessage string `json:"recoverMessage"` - LastRecoveredAt string `json:"lastRecoveredAt"` - RollbackStatus string `json:"rollbackStatus"` - RollbackMessage string `json:"rollbackMessage"` - LastRollbackedAt string `json:"lastRollbackedAt"` -} - -type SyncTime struct { - NtpSite string `json:"ntpSite" validate:"required"` -} - -type CleanData struct { - SystemClean []CleanTree `json:"systemClean"` - UploadClean []CleanTree `json:"uploadClean"` - DownloadClean []CleanTree `json:"downloadClean"` - SystemLogClean []CleanTree `json:"systemLogClean"` - ContainerClean []CleanTree `json:"containerClean"` -} - -type CleanTree struct { - ID string `json:"id"` - Label string `json:"label"` - Children []CleanTree `json:"children"` - - Type string `json:"type"` - Name string `json:"name"` - - Size uint64 `json:"size"` - IsCheck bool `json:"isCheck"` - IsRecommend bool `json:"isRecommend"` -} - -type Clean struct { - TreeType string `json:"treeType"` - Name string `json:"name"` - Size uint64 `json:"size"` -} diff --git a/backend/app/dto/ssh.go b/backend/app/dto/ssh.go deleted file mode 100644 index c07a3f4e9..000000000 --- a/backend/app/dto/ssh.go +++ /dev/null @@ -1,57 +0,0 @@ -package dto - -import "time" - -type SSHUpdate struct { - Key string `json:"key" validate:"required"` - OldValue string `json:"oldValue"` - NewValue string `json:"newValue"` -} - -type SSHInfo struct { - AutoStart bool `json:"autoStart"` - Status string `json:"status"` - Message string `json:"message"` - Port string `json:"port"` - ListenAddress string `json:"listenAddress"` - PasswordAuthentication string `json:"passwordAuthentication"` - PubkeyAuthentication string `json:"pubkeyAuthentication"` - PermitRootLogin string `json:"permitRootLogin"` - UseDNS string `json:"useDNS"` -} - -type GenerateSSH struct { - EncryptionMode string `json:"encryptionMode" validate:"required,oneof=rsa ed25519 ecdsa dsa"` - Password string `json:"password"` -} - -type GenerateLoad struct { - EncryptionMode string `json:"encryptionMode" validate:"required,oneof=rsa ed25519 ecdsa dsa"` -} - -type SSHConf struct { - File string `json:"file"` -} -type SearchSSHLog struct { - PageInfo - Info string `json:"info"` - Status string `json:"Status" validate:"required,oneof=Success Failed All"` -} -type SSHLog struct { - Logs []SSHHistory `json:"logs"` - TotalCount int `json:"totalCount"` - SuccessfulCount int `json:"successfulCount"` - FailedCount int `json:"failedCount"` -} - -type SSHHistory struct { - Date time.Time `json:"date"` - DateStr string `json:"dateStr"` - Area string `json:"area"` - User string `json:"user"` - AuthMode string `json:"authMode"` - Address string `json:"address"` - Port string `json:"port"` - Status string `json:"status"` - Message string `json:"message"` -} diff --git a/backend/app/model/app.go b/backend/app/model/app.go deleted file mode 100644 index 3e67391e8..000000000 --- a/backend/app/model/app.go +++ /dev/null @@ -1,43 +0,0 @@ -package model - -import ( - "github.com/1Panel-dev/1Panel/backend/constant" - "path/filepath" - "strings" -) - -type App struct { - BaseModel - Name string `json:"name" gorm:"type:varchar(64);not null"` - Key string `json:"key" gorm:"type:varchar(64);not null;"` - ShortDescZh string `json:"shortDescZh" yaml:"shortDescZh" gorm:"type:longtext;"` - ShortDescEn string `json:"shortDescEn" yaml:"shortDescEn" gorm:"type:longtext;"` - Icon string `json:"icon" gorm:"type:longtext;"` - Type string `json:"type" gorm:"type:varchar(64);not null"` - Status string `json:"status" gorm:"type:varchar(64);not null"` - Required string `json:"required" gorm:"type:varchar(64);"` - CrossVersionUpdate bool `json:"crossVersionUpdate" yaml:"crossVersionUpdate"` - Limit int `json:"limit" gorm:"type:Integer;not null"` - Website string `json:"website" gorm:"type:varchar(64);not null"` - Github string `json:"github" gorm:"type:varchar(64);not null"` - Document string `json:"document" gorm:"type:varchar(64);not null"` - Recommend int `json:"recommend" gorm:"type:Integer;not null"` - Resource string `json:"resource" gorm:"type:varchar;not null;default:remote"` - ReadMe string `json:"readMe" gorm:"type:varchar;"` - LastModified int `json:"lastModified" gorm:"type:Integer;"` - - Details []AppDetail `json:"-" gorm:"-:migration"` - TagsKey []string `json:"tags" yaml:"tags" gorm:"-"` - AppTags []AppTag `json:"-" gorm:"-:migration"` -} - -func (i *App) IsLocalApp() bool { - return i.Resource == constant.ResourceLocal -} -func (i *App) GetAppResourcePath() string { - if i.IsLocalApp() { - //这里要去掉本地应用的local前缀 - return filepath.Join(constant.LocalAppResourceDir, strings.TrimPrefix(i.Key, "local")) - } - return filepath.Join(constant.RemoteAppResourceDir, i.Key) -} diff --git a/backend/app/model/app_detail.go b/backend/app/model/app_detail.go deleted file mode 100644 index d6b958284..000000000 --- a/backend/app/model/app_detail.go +++ /dev/null @@ -1,16 +0,0 @@ -package model - -type AppDetail struct { - BaseModel - AppId uint `json:"appId" gorm:"type:integer;not null"` - Version string `json:"version" gorm:"type:varchar(64);not null"` - Params string `json:"-" gorm:"type:longtext;"` - DockerCompose string `json:"dockerCompose" gorm:"type:longtext;"` - Status string `json:"status" gorm:"type:varchar(64);not null"` - LastVersion string `json:"lastVersion" gorm:"type:varchar(64);"` - LastModified int `json:"lastModified" gorm:"type:integer;"` - DownloadUrl string `json:"downloadUrl" gorm:"type:varchar;"` - DownloadCallBackUrl string `json:"downloadCallBackUrl" gorm:"type:longtext;"` - Update bool `json:"update"` - IgnoreUpgrade bool `json:"ignoreUpgrade"` -} diff --git a/backend/app/model/app_install.go b/backend/app/model/app_install.go deleted file mode 100644 index 539b131ba..000000000 --- a/backend/app/model/app_install.go +++ /dev/null @@ -1,47 +0,0 @@ -package model - -import ( - "path" - "strings" - - "github.com/1Panel-dev/1Panel/backend/constant" -) - -type AppInstall struct { - BaseModel - Name string `json:"name" gorm:"type:varchar(64);not null;UNIQUE"` - AppId uint `json:"appId" gorm:"type:integer;not null"` - AppDetailId uint `json:"appDetailId" gorm:"type:integer;not null"` - Version string `json:"version" gorm:"type:varchar(64);not null"` - Param string `json:"param" gorm:"type:longtext;"` - Env string `json:"env" gorm:"type:longtext;"` - DockerCompose string `json:"dockerCompose" gorm:"type:longtext;"` - Status string `json:"status" gorm:"type:varchar(256);not null"` - Description string `json:"description" gorm:"type:varchar(256);"` - Message string `json:"message" gorm:"type:longtext;"` - ContainerName string `json:"containerName" gorm:"type:varchar(256);not null"` - ServiceName string `json:"serviceName" gorm:"type:varchar(256);not null"` - HttpPort int `json:"httpPort" gorm:"type:integer;not null"` - HttpsPort int `json:"httpsPort" gorm:"type:integer;not null"` - App App `json:"app" gorm:"-:migration"` -} - -func (i *AppInstall) GetPath() string { - return path.Join(i.GetAppPath(), i.Name) -} - -func (i *AppInstall) GetComposePath() string { - return path.Join(i.GetAppPath(), i.Name, "docker-compose.yml") -} - -func (i *AppInstall) GetEnvPath() string { - return path.Join(i.GetAppPath(), i.Name, ".env") -} - -func (i *AppInstall) GetAppPath() string { - if i.App.Resource == constant.AppResourceLocal { - return path.Join(constant.LocalAppInstallDir, strings.TrimPrefix(i.App.Key, constant.AppResourceLocal)) - } else { - return path.Join(constant.AppInstallDir, i.App.Key) - } -} diff --git a/backend/app/model/app_install_resource.go b/backend/app/model/app_install_resource.go deleted file mode 100644 index 863090459..000000000 --- a/backend/app/model/app_install_resource.go +++ /dev/null @@ -1,10 +0,0 @@ -package model - -type AppInstallResource struct { - BaseModel - AppInstallId uint `json:"appInstallId" gorm:"type:integer;not null;"` - LinkId uint `json:"linkId" gorm:"type:integer;not null;"` - ResourceId uint `json:"resourceId" gorm:"type:integer;"` - Key string `json:"key" gorm:"type:varchar(64);not null"` - From string `json:"from" gorm:"type:varchar(64);not null;default:local"` -} diff --git a/backend/app/model/app_tag.go b/backend/app/model/app_tag.go deleted file mode 100644 index 1d55b956a..000000000 --- a/backend/app/model/app_tag.go +++ /dev/null @@ -1,7 +0,0 @@ -package model - -type AppTag struct { - BaseModel - AppId uint `json:"appId" gorm:"type:integer;not null"` - TagId uint `json:"tagId" gorm:"type:integer;not null"` -} diff --git a/backend/app/model/backup.go b/backend/app/model/backup.go deleted file mode 100644 index 50690dcaa..000000000 --- a/backend/app/model/backup.go +++ /dev/null @@ -1,24 +0,0 @@ -package model - -type BackupAccount struct { - BaseModel - Type string `gorm:"type:varchar(64);unique;not null" json:"type"` - Bucket string `gorm:"type:varchar(256)" json:"bucket"` - AccessKey string `gorm:"type:varchar(256)" json:"accessKey"` - Credential string `gorm:"type:varchar(256)" json:"credential"` - BackupPath string `gorm:"type:varchar(256)" json:"backupPath"` - Vars string `gorm:"type:longText" json:"vars"` -} - -type BackupRecord struct { - BaseModel - From string `gorm:"type:varchar(64)" json:"from"` - CronjobID uint `gorm:"type:decimal" json:"cronjobID"` - Type string `gorm:"type:varchar(64);not null" json:"type"` - Name string `gorm:"type:varchar(64);not null" json:"name"` - DetailName string `gorm:"type:varchar(256)" json:"detailName"` - Source string `gorm:"type:varchar(256)" json:"source"` - BackupType string `gorm:"type:varchar(256)" json:"backupType"` - FileDir string `gorm:"type:varchar(256)" json:"fileDir"` - FileName string `gorm:"type:varchar(256)" json:"fileName"` -} diff --git a/backend/app/model/base.go b/backend/app/model/base.go deleted file mode 100644 index 69921d41d..000000000 --- a/backend/app/model/base.go +++ /dev/null @@ -1,9 +0,0 @@ -package model - -import "time" - -type BaseModel struct { - ID uint `gorm:"primarykey;AUTO_INCREMENT" json:"id"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` -} diff --git a/backend/app/model/clam.go b/backend/app/model/clam.go deleted file mode 100644 index ff1a73e67..000000000 --- a/backend/app/model/clam.go +++ /dev/null @@ -1,14 +0,0 @@ -package model - -type Clam struct { - BaseModel - - Name string `gorm:"type:varchar(64);not null" json:"name"` - Status string `gorm:"type:varchar(64)" json:"status"` - Path string `gorm:"type:varchar(64);not null" json:"path"` - InfectedStrategy string `gorm:"type:varchar(64)" json:"infectedStrategy"` - InfectedDir string `gorm:"type:varchar(64)" json:"infectedDir"` - Spec string `gorm:"type:varchar(64)" json:"spec"` - EntryID int `gorm:"type:varchar(64)" json:"entryID"` - Description string `gorm:"type:varchar(64)" json:"description"` -} diff --git a/backend/app/model/command.go b/backend/app/model/command.go deleted file mode 100644 index 9f00558d4..000000000 --- a/backend/app/model/command.go +++ /dev/null @@ -1,14 +0,0 @@ -package model - -type Command struct { - BaseModel - Name string `gorm:"type:varchar(64);unique;not null" json:"name"` - GroupID uint `gorm:"type:decimal" json:"groupID"` - Command string `gorm:"type:varchar(256);not null" json:"command"` -} - -type RedisCommand struct { - BaseModel - Name string `gorm:"type:varchar(64);unique;not null" json:"name"` - Command string `gorm:"type:varchar(256);not null" json:"command"` -} diff --git a/backend/app/model/compose_template.go b/backend/app/model/compose_template.go deleted file mode 100644 index 5d5192eb3..000000000 --- a/backend/app/model/compose_template.go +++ /dev/null @@ -1,15 +0,0 @@ -package model - -type ComposeTemplate struct { - BaseModel - - Name string `gorm:"type:varchar(64);not null;unique" json:"name"` - Description string `gorm:"type:varchar(256)" json:"description"` - Content string `gorm:"type:longtext" json:"content"` -} - -type Compose struct { - BaseModel - - Name string `gorm:"type:varchar(256)" json:"name"` -} diff --git a/backend/app/model/cronjob.go b/backend/app/model/cronjob.go deleted file mode 100644 index b9ff73546..000000000 --- a/backend/app/model/cronjob.go +++ /dev/null @@ -1,50 +0,0 @@ -package model - -import ( - "time" -) - -type Cronjob struct { - BaseModel - - Name string `gorm:"type:varchar(64);not null" json:"name"` - Type string `gorm:"type:varchar(64);not null" json:"type"` - Spec string `gorm:"type:varchar(64);not null" json:"spec"` - - Command string `gorm:"type:varchar(64)" json:"command"` - ContainerName string `gorm:"type:varchar(64)" json:"containerName"` - Script string `gorm:"longtext" json:"script"` - Website string `gorm:"type:varchar(64)" json:"website"` - AppID string `gorm:"type:varchar(64)" json:"appID"` - DBType string `gorm:"type:varchar(64)" json:"dbType"` - DBName string `gorm:"type:varchar(64)" json:"dbName"` - URL string `gorm:"type:varchar(256)" json:"url"` - SourceDir string `gorm:"type:varchar(256)" json:"sourceDir"` - ExclusionRules string `gorm:"longtext" json:"exclusionRules"` - - // 已废弃 - KeepLocal bool `gorm:"type:varchar(64)" json:"keepLocal"` - TargetDirID uint64 `gorm:"type:decimal" json:"targetDirID"` - - BackupAccounts string `gorm:"type:varchar(64)" json:"backupAccounts"` - DefaultDownload string `gorm:"type:varchar(64)" json:"defaultDownload"` - RetainCopies uint64 `gorm:"type:decimal" json:"retainCopies"` - - Status string `gorm:"type:varchar(64)" json:"status"` - EntryIDs string `gorm:"type:varchar(64)" json:"entryIDs"` - Records []JobRecords `json:"records"` - Secret string `gorm:"type:varchar(64)" json:"secret"` -} - -type JobRecords struct { - BaseModel - - CronjobID uint `gorm:"type:decimal" json:"cronjobID"` - StartTime time.Time `gorm:"type:datetime" json:"startTime"` - Interval float64 `gorm:"type:float" json:"interval"` - Records string `gorm:"longtext" json:"records"` - FromLocal bool `gorm:"type:varchar(64)" json:"source"` - File string `gorm:"type:varchar(256)" json:"file"` - Status string `gorm:"type:varchar(64)" json:"status"` - Message string `gorm:"longtext" json:"message"` -} diff --git a/backend/app/model/database.go b/backend/app/model/database.go deleted file mode 100644 index f4d0ff0fc..000000000 --- a/backend/app/model/database.go +++ /dev/null @@ -1,22 +0,0 @@ -package model - -type Database struct { - BaseModel - AppInstallID uint `json:"appInstallID" gorm:"type:decimal"` - Name string `json:"name" gorm:"type:varchar(64);not null;unique"` - Type string `json:"type" gorm:"type:varchar(64);not null"` - Version string `json:"version" gorm:"type:varchar(64);not null"` - From string `json:"from" gorm:"type:varchar(64);not null"` - Address string `json:"address" gorm:"type:varchar(64);not null"` - Port uint `json:"port" gorm:"type:decimal;not null"` - Username string `json:"username" gorm:"type:varchar(64)"` - Password string `json:"password" gorm:"type:varchar(64)"` - - SSL bool `json:"ssl"` - RootCert string `json:"rootCert" gorm:"type:longText"` - ClientKey string `json:"clientKey" gorm:"type:longText"` - ClientCert string `json:"clientCert" gorm:"type:longText"` - SkipVerify bool `json:"skipVerify"` - - Description string `json:"description" gorm:"type:varchar(256);"` -} diff --git a/backend/app/model/database_mysql.go b/backend/app/model/database_mysql.go deleted file mode 100644 index 0a8734848..000000000 --- a/backend/app/model/database_mysql.go +++ /dev/null @@ -1,14 +0,0 @@ -package model - -type DatabaseMysql struct { - BaseModel - Name string `json:"name" gorm:"type:varchar(256);not null"` - From string `json:"from" gorm:"type:varchar(256);not null;default:local"` - MysqlName string `json:"mysqlName" gorm:"type:varchar(64);not null"` - Format string `json:"format" gorm:"type:varchar(64);not null"` - Username string `json:"username" gorm:"type:varchar(256);not null"` - Password string `json:"password" gorm:"type:varchar(256);not null"` - Permission string `json:"permission" gorm:"type:varchar(256);not null"` - IsDelete bool `json:"isDelete" gorm:"type:varchar(64)"` - Description string `json:"description" gorm:"type:varchar(256);"` -} diff --git a/backend/app/model/database_postgresql.go b/backend/app/model/database_postgresql.go deleted file mode 100644 index 7ea4ee59e..000000000 --- a/backend/app/model/database_postgresql.go +++ /dev/null @@ -1,14 +0,0 @@ -package model - -type DatabasePostgresql struct { - BaseModel - Name string `json:"name" gorm:"type:varchar(256);not null"` - From string `json:"from" gorm:"type:varchar(256);not null;default:local"` - PostgresqlName string `json:"postgresqlName" gorm:"type:varchar(64);not null"` - Format string `json:"format" gorm:"type:varchar(64);not null"` - Username string `json:"username" gorm:"type:varchar(256);not null"` - Password string `json:"password" gorm:"type:varchar(256);not null"` - SuperUser bool `json:"superUser" gorm:"type:varchar(64)"` - IsDelete bool `json:"isDelete" gorm:"type:varchar(64)"` - Description string `json:"description" gorm:"type:varchar(256);"` -} diff --git a/backend/app/model/favorite.go b/backend/app/model/favorite.go deleted file mode 100644 index 6e5421dcf..000000000 --- a/backend/app/model/favorite.go +++ /dev/null @@ -1,10 +0,0 @@ -package model - -type Favorite struct { - BaseModel - Name string `gorm:"type:varchar(256);not null;" json:"name" ` - Path string `gorm:"type:varchar(256);not null;unique" json:"path"` - Type string `gorm:"type:varchar(64);" json:"type"` - IsDir bool `json:"isDir"` - IsTxt bool `json:"isTxt"` -} diff --git a/backend/app/model/firewall.go b/backend/app/model/firewall.go deleted file mode 100644 index d4979a05d..000000000 --- a/backend/app/model/firewall.go +++ /dev/null @@ -1,21 +0,0 @@ -package model - -type Firewall struct { - BaseModel - - Type string `gorm:"type:varchar(64);not null" json:"type"` - Port string `gorm:"type:varchar(64);not null" json:"port"` - Protocol string `gorm:"type:varchar(64);not null" json:"protocol"` - Address string `gorm:"type:varchar(64);not null" json:"address"` - Strategy string `gorm:"type:varchar(64);not null" json:"strategy"` - Description string `gorm:"type:varchar(64);not null" json:"description"` -} - -type Forward struct { - BaseModel - - Protocol string `gorm:"type:varchar(64);not null" json:"protocol"` - Port string `gorm:"type:varchar(64);not null" json:"port"` - TargetIP string `gorm:"type:varchar(64);not null" json:"targetIP"` - TargetPort string `gorm:"type:varchar(64);not null" json:"targetPort"` -} diff --git a/backend/app/model/ftp.go b/backend/app/model/ftp.go deleted file mode 100644 index 291e765c6..000000000 --- a/backend/app/model/ftp.go +++ /dev/null @@ -1,11 +0,0 @@ -package model - -type Ftp struct { - BaseModel - - User string `gorm:"type:varchar(64);not null" json:"user"` - Password string `gorm:"type:varchar(64);not null" json:"password"` - Status string `gorm:"type:varchar(64);not null" json:"status"` - Path string `gorm:"type:varchar(64);not null" json:"path"` - Description string `gorm:"type:varchar(64);not null" json:"description"` -} diff --git a/backend/app/model/group.go b/backend/app/model/group.go deleted file mode 100644 index 1479e035a..000000000 --- a/backend/app/model/group.go +++ /dev/null @@ -1,8 +0,0 @@ -package model - -type Group struct { - BaseModel - IsDefault bool `json:"isDefault"` - Name string `gorm:"type:varchar(64);not null" json:"name"` - Type string `gorm:"type:varchar(16);not null" json:"type"` -} diff --git a/backend/app/model/host.go b/backend/app/model/host.go deleted file mode 100644 index a4fe6aedd..000000000 --- a/backend/app/model/host.go +++ /dev/null @@ -1,18 +0,0 @@ -package model - -type Host struct { - BaseModel - - GroupID uint `gorm:"type:decimal;not null" json:"group_id"` - Name string `gorm:"type:varchar(64);not null" json:"name"` - Addr string `gorm:"type:varchar(16);not null" json:"addr"` - Port int `gorm:"type:decimal;not null" json:"port"` - User string `gorm:"type:varchar(64);not null" json:"user"` - AuthMode string `gorm:"type:varchar(16);not null" json:"authMode"` - Password string `gorm:"type:varchar(64)" json:"password"` - PrivateKey string `gorm:"type:varchar(256)" json:"privateKey"` - PassPhrase string `gorm:"type:varchar(256)" json:"passPhrase"` - RememberPassword bool `json:"rememberPassword"` - - Description string `gorm:"type:varchar(256)" json:"description"` -} diff --git a/backend/app/model/image_repo.go b/backend/app/model/image_repo.go deleted file mode 100644 index 8d16dbff1..000000000 --- a/backend/app/model/image_repo.go +++ /dev/null @@ -1,15 +0,0 @@ -package model - -type ImageRepo struct { - BaseModel - - Name string `gorm:"type:varchar(64);not null" json:"name"` - DownloadUrl string `gorm:"type:varchar(256)" json:"downloadUrl"` - Protocol string `gorm:"type:varchar(64)" json:"protocol"` - Username string `gorm:"type:varchar(256)" json:"username"` - Password string `gorm:"type:varchar(256)" json:"password"` - Auth bool `gorm:"type:varchar(256)" json:"auth"` - - Status string `gorm:"type:varchar(64)" json:"status"` - Message string `gorm:"type:varchar(256)" json:"message"` -} diff --git a/backend/app/model/monitor.go b/backend/app/model/monitor.go deleted file mode 100644 index 1207c98af..000000000 --- a/backend/app/model/monitor.go +++ /dev/null @@ -1,29 +0,0 @@ -package model - -type MonitorBase struct { - BaseModel - Cpu float64 `gorm:"type:float" json:"cpu"` - - LoadUsage float64 `gorm:"type:float" json:"loadUsage"` - CpuLoad1 float64 `gorm:"type:float" json:"cpuLoad1"` - CpuLoad5 float64 `gorm:"type:float" json:"cpuLoad5"` - CpuLoad15 float64 `gorm:"type:float" json:"cpuLoad15"` - - Memory float64 `gorm:"type:float" json:"memory"` -} - -type MonitorIO struct { - BaseModel - Name string `json:"name"` - Read uint64 `json:"read"` - Write uint64 `json:"write"` - Count uint64 `json:"count"` - Time uint64 `json:"time"` -} - -type MonitorNetwork struct { - BaseModel - Name string `json:"name"` - Up float64 `gorm:"type:float" json:"up"` - Down float64 `gorm:"type:float" json:"down"` -} diff --git a/backend/app/model/php_extensions.go b/backend/app/model/php_extensions.go deleted file mode 100644 index 0055bd258..000000000 --- a/backend/app/model/php_extensions.go +++ /dev/null @@ -1,7 +0,0 @@ -package model - -type PHPExtensions struct { - BaseModel - Name string ` json:"name" gorm:"not null"` - Extensions string `json:"extensions" gorm:"not null"` -} diff --git a/backend/app/model/runtime.go b/backend/app/model/runtime.go deleted file mode 100644 index d71051a44..000000000 --- a/backend/app/model/runtime.go +++ /dev/null @@ -1,40 +0,0 @@ -package model - -import ( - "github.com/1Panel-dev/1Panel/backend/constant" - "path" -) - -type Runtime struct { - BaseModel - Name string `gorm:"type:varchar;not null" json:"name"` - AppDetailID uint `gorm:"type:integer" json:"appDetailId"` - Image string `gorm:"type:varchar" json:"image"` - WorkDir string `gorm:"type:varchar" json:"workDir"` - DockerCompose string `gorm:"type:varchar" json:"dockerCompose"` - Env string `gorm:"type:varchar" json:"env"` - Params string `gorm:"type:varchar" json:"params"` - Version string `gorm:"type:varchar;not null" json:"version"` - Type string `gorm:"type:varchar;not null" json:"type"` - Status string `gorm:"type:varchar;not null" json:"status"` - Resource string `gorm:"type:varchar;not null" json:"resource"` - Port int `gorm:"type:integer;" json:"port"` - Message string `gorm:"type:longtext;" json:"message"` - CodeDir string `gorm:"type:varchar;" json:"codeDir"` -} - -func (r *Runtime) GetComposePath() string { - return path.Join(r.GetPath(), "docker-compose.yml") -} - -func (r *Runtime) GetEnvPath() string { - return path.Join(r.GetPath(), ".env") -} - -func (r *Runtime) GetPath() string { - return path.Join(constant.RuntimeDir, r.Type, r.Name) -} - -func (r *Runtime) GetLogPath() string { - return path.Join(r.GetPath(), "build.log") -} diff --git a/backend/app/model/setting.go b/backend/app/model/setting.go deleted file mode 100644 index e9791b79b..000000000 --- a/backend/app/model/setting.go +++ /dev/null @@ -1,8 +0,0 @@ -package model - -type Setting struct { - BaseModel - 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"` -} diff --git a/backend/app/model/snapshot.go b/backend/app/model/snapshot.go deleted file mode 100644 index 09574ca65..000000000 --- a/backend/app/model/snapshot.go +++ /dev/null @@ -1,35 +0,0 @@ -package model - -type Snapshot struct { - BaseModel - Name string `json:"name" gorm:"type:varchar(64);not null;unique"` - Description string `json:"description" gorm:"type:varchar(256)"` - From string `json:"from"` - DefaultDownload string `json:"defaultDownload" gorm:"type:varchar(64)"` - Status string `json:"status" gorm:"type:varchar(64)"` - Message string `json:"message" gorm:"type:varchar(256)"` - Version string `json:"version" gorm:"type:varchar(256)"` - - InterruptStep string `json:"interruptStep" gorm:"type:varchar(64)"` - RecoverStatus string `json:"recoverStatus" gorm:"type:varchar(64)"` - RecoverMessage string `json:"recoverMessage" gorm:"type:varchar(256)"` - LastRecoveredAt string `json:"lastRecoveredAt" gorm:"type:varchar(64)"` - RollbackStatus string `json:"rollbackStatus" gorm:"type:varchar(64)"` - RollbackMessage string `json:"rollbackMessage" gorm:"type:varchar(256)"` - LastRollbackedAt string `json:"lastRollbackedAt" gorm:"type:varchar(64)"` -} - -type SnapshotStatus struct { - BaseModel - SnapID uint `gorm:"type:decimal" json:"snapID"` - Panel string `json:"panel" gorm:"type:varchar(64);default:Running"` - PanelInfo string `json:"panelInfo" gorm:"type:varchar(64);default:Running"` - DaemonJson string `json:"daemonJson" gorm:"type:varchar(64);default:Running"` - AppData string `json:"appData" gorm:"type:varchar(64);default:Running"` - PanelData string `json:"panelData" gorm:"type:varchar(64);default:Running"` - BackupData string `json:"backupData" gorm:"type:varchar(64);default:Running"` - - Compress string `json:"compress" gorm:"type:varchar(64);default:Waiting"` - Size string `json:"size" gorm:"type:varchar(64)"` - Upload string `json:"upload" gorm:"type:varchar(64);default:Waiting"` -} diff --git a/backend/app/model/tag.go b/backend/app/model/tag.go deleted file mode 100644 index adc8d6ec4..000000000 --- a/backend/app/model/tag.go +++ /dev/null @@ -1,8 +0,0 @@ -package model - -type Tag struct { - BaseModel - Key string `json:"key" gorm:"type:varchar(64);not null"` - Name string `json:"name" gorm:"type:varchar(64);not null"` - Sort int `json:"sort" gorm:"type:int;not null;default:1"` -} diff --git a/backend/app/model/website.go b/backend/app/model/website.go deleted file mode 100644 index 34dc72ab4..000000000 --- a/backend/app/model/website.go +++ /dev/null @@ -1,40 +0,0 @@ -package model - -import "time" - -type Website struct { - BaseModel - Protocol string `gorm:"type:varchar;not null" json:"protocol"` - PrimaryDomain string `gorm:"type:varchar;not null" json:"primaryDomain"` - Type string `gorm:"type:varchar;not null" json:"type"` - Alias string `gorm:"type:varchar;not null" json:"alias"` - Remark string `gorm:"type:longtext;" json:"remark"` - Status string `gorm:"type:varchar;not null" json:"status"` - HttpConfig string `gorm:"type:varchar;not null" json:"httpConfig"` - ExpireDate time.Time `json:"expireDate"` - - Proxy string `gorm:"type:varchar;" json:"proxy"` - ProxyType string `gorm:"type:varchar;" json:"proxyType"` - SiteDir string `gorm:"type:varchar;" json:"siteDir"` - ErrorLog bool `json:"errorLog"` - AccessLog bool `json:"accessLog"` - DefaultServer bool `json:"defaultServer"` - IPV6 bool `json:"IPV6"` - Rewrite string `gorm:"type:varchar" json:"rewrite"` - - WebsiteGroupID uint `gorm:"type:integer" json:"webSiteGroupId"` - WebsiteSSLID uint `gorm:"type:integer" json:"webSiteSSLId"` - RuntimeID uint `gorm:"type:integer" json:"runtimeID"` - AppInstallID uint `gorm:"type:integer" json:"appInstallId"` - FtpID uint `gorm:"type:integer" json:"ftpId"` - - User string `gorm:"type:varchar;" json:"user"` - Group string `gorm:"type:varchar;" json:"group"` - - Domains []WebsiteDomain `json:"domains" gorm:"-:migration"` - WebsiteSSL WebsiteSSL `json:"webSiteSSL" gorm:"-:migration"` -} - -func (w Website) TableName() string { - return "websites" -} diff --git a/backend/app/model/website_acme_account.go b/backend/app/model/website_acme_account.go deleted file mode 100644 index eeafc0187..000000000 --- a/backend/app/model/website_acme_account.go +++ /dev/null @@ -1,16 +0,0 @@ -package model - -type WebsiteAcmeAccount struct { - BaseModel - Email string `gorm:"not null" json:"email"` - URL string `gorm:"not null" json:"url"` - PrivateKey string `gorm:"not null" json:"-"` - Type string `gorm:"not null;default:letsencrypt" json:"type"` - EabKid string `gorm:"default:null;" json:"eabKid"` - EabHmacKey string `gorm:"default:null" json:"eabHmacKey"` - KeyType string `gorm:"not null;default:2048" json:"keyType"` -} - -func (w WebsiteAcmeAccount) TableName() string { - return "website_acme_accounts" -} diff --git a/backend/app/model/website_ca.go b/backend/app/model/website_ca.go deleted file mode 100644 index 74b029637..000000000 --- a/backend/app/model/website_ca.go +++ /dev/null @@ -1,9 +0,0 @@ -package model - -type WebsiteCA struct { - BaseModel - CSR string `gorm:"not null;" json:"csr"` - Name string `gorm:"not null;" json:"name"` - PrivateKey string `gorm:"not null" json:"privateKey"` - KeyType string `gorm:"not null;default:2048" json:"keyType"` -} diff --git a/backend/app/model/website_dns_account.go b/backend/app/model/website_dns_account.go deleted file mode 100644 index de7ae8dee..000000000 --- a/backend/app/model/website_dns_account.go +++ /dev/null @@ -1,12 +0,0 @@ -package model - -type WebsiteDnsAccount struct { - BaseModel - Name string `gorm:"type:varchar(64);not null" json:"name"` - Type string `gorm:"type:varchar(64);not null" json:"type"` - Authorization string `gorm:"type:varchar(256);not null" json:"-"` -} - -func (w WebsiteDnsAccount) TableName() string { - return "website_dns_accounts" -} diff --git a/backend/app/model/website_domain.go b/backend/app/model/website_domain.go deleted file mode 100644 index e6fb77e93..000000000 --- a/backend/app/model/website_domain.go +++ /dev/null @@ -1,12 +0,0 @@ -package model - -type WebsiteDomain struct { - BaseModel - WebsiteID uint `gorm:"column:website_id;type:varchar(64);not null;" json:"websiteId"` - Domain string `gorm:"type:varchar(256);not null" json:"domain"` - Port int `gorm:"type:integer" json:"port"` -} - -func (w WebsiteDomain) TableName() string { - return "website_domains" -} diff --git a/backend/app/model/website_ssl.go b/backend/app/model/website_ssl.go deleted file mode 100644 index 15fbb8c4b..000000000 --- a/backend/app/model/website_ssl.go +++ /dev/null @@ -1,50 +0,0 @@ -package model - -import ( - "fmt" - "github.com/1Panel-dev/1Panel/backend/constant" - "path" - "time" -) - -type WebsiteSSL struct { - BaseModel - PrimaryDomain string `json:"primaryDomain"` - PrivateKey string `json:"privateKey"` - Pem string `json:"pem"` - Domains string `json:"domains"` - CertURL string `json:"certURL"` - Type string `json:"type"` - Provider string `json:"provider"` - Organization string `json:"organization"` - DnsAccountID uint `json:"dnsAccountId"` - AcmeAccountID uint `gorm:"column:acme_account_id" json:"acmeAccountId" ` - CaID uint `json:"caId"` - AutoRenew bool `json:"autoRenew"` - ExpireDate time.Time `json:"expireDate"` - StartDate time.Time `json:"startDate"` - Status string `json:"status"` - Message string `json:"message"` - KeyType string `json:"keyType"` - PushDir bool `json:"pushDir"` - Dir string `json:"dir"` - Description string `json:"description"` - SkipDNS bool `json:"skipDNS"` - Nameserver1 string `json:"nameserver1"` - Nameserver2 string `json:"nameserver2"` - DisableCNAME bool `json:"disableCNAME"` - ExecShell bool `json:"execShell"` - Shell string `json:"shell"` - - AcmeAccount WebsiteAcmeAccount `json:"acmeAccount" gorm:"-:migration"` - DnsAccount WebsiteDnsAccount `json:"dnsAccount" gorm:"-:migration"` - Websites []Website `json:"websites" gorm:"-:migration"` -} - -func (w WebsiteSSL) TableName() string { - return "website_ssls" -} - -func (w WebsiteSSL) GetLogPath() string { - return path.Join(constant.SSLLogDir, fmt.Sprintf("%s-ssl-%d.log", w.PrimaryDomain, w.ID)) -} diff --git a/backend/app/repo/app.go b/backend/app/repo/app.go deleted file mode 100644 index 9eb0c8ece..000000000 --- a/backend/app/repo/app.go +++ /dev/null @@ -1,123 +0,0 @@ -package repo - -import ( - "context" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "gorm.io/gorm" - "gorm.io/gorm/clause" -) - -type AppRepo struct { -} - -type IAppRepo interface { - WithKey(key string) DBOption - WithType(typeStr string) DBOption - OrderByRecommend() DBOption - GetRecommend() DBOption - WithResource(resource string) DBOption - WithLikeName(name string) DBOption - Page(page, size int, opts ...DBOption) (int64, []model.App, error) - GetFirst(opts ...DBOption) (model.App, error) - GetBy(opts ...DBOption) ([]model.App, error) - BatchCreate(ctx context.Context, apps []model.App) error - GetByKey(ctx context.Context, key string) (model.App, error) - Create(ctx context.Context, app *model.App) error - Save(ctx context.Context, app *model.App) error - BatchDelete(ctx context.Context, apps []model.App) error -} - -func NewIAppRepo() IAppRepo { - return &AppRepo{} -} - -func (a AppRepo) WithLikeName(name string) DBOption { - return func(g *gorm.DB) *gorm.DB { - if len(name) == 0 { - return g - } - return g.Where("name like ? or short_desc_zh like ? or short_desc_en like ?", "%"+name+"%", "%"+name+"%", "%"+name+"%") - } -} - -func (a AppRepo) WithKey(key string) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("key = ?", key) - } -} - -func (a AppRepo) WithType(typeStr string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("type = ?", typeStr) - } -} - -func (a AppRepo) OrderByRecommend() DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Order("recommend asc") - } -} - -func (a AppRepo) GetRecommend() DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("recommend < 9999") - } -} - -func (a AppRepo) WithResource(resource string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("resource = ?", resource) - } -} - -func (a AppRepo) Page(page, size int, opts ...DBOption) (int64, []model.App, error) { - var apps []model.App - db := getDb(opts...).Model(&model.App{}) - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Preload("AppTags").Find(&apps).Error - return count, apps, err -} - -func (a AppRepo) GetFirst(opts ...DBOption) (model.App, error) { - var app model.App - db := getDb(opts...).Model(&model.App{}) - if err := db.Preload("AppTags").First(&app).Error; err != nil { - return app, err - } - return app, nil -} - -func (a AppRepo) GetBy(opts ...DBOption) ([]model.App, error) { - var apps []model.App - db := getDb(opts...).Model(&model.App{}) - if err := db.Preload("Details").Preload("AppTags").Find(&apps).Error; err != nil { - return apps, err - } - return apps, nil -} - -func (a AppRepo) BatchCreate(ctx context.Context, apps []model.App) error { - return getTx(ctx).Omit(clause.Associations).Create(&apps).Error -} - -func (a AppRepo) GetByKey(ctx context.Context, key string) (model.App, error) { - var app model.App - if err := getTx(ctx).Where("key = ?", key).First(&app).Error; err != nil { - return app, err - } - return app, nil -} - -func (a AppRepo) Create(ctx context.Context, app *model.App) error { - return getTx(ctx).Omit(clause.Associations).Create(app).Error -} - -func (a AppRepo) Save(ctx context.Context, app *model.App) error { - return getTx(ctx).Omit(clause.Associations).Save(app).Error -} - -func (a AppRepo) BatchDelete(ctx context.Context, apps []model.App) error { - return getTx(ctx).Omit(clause.Associations).Delete(&apps).Error -} diff --git a/backend/app/repo/app_detail.go b/backend/app/repo/app_detail.go deleted file mode 100644 index c813ea5e9..000000000 --- a/backend/app/repo/app_detail.go +++ /dev/null @@ -1,82 +0,0 @@ -package repo - -import ( - "context" - "github.com/1Panel-dev/1Panel/backend/app/model" - "gorm.io/gorm" - "gorm.io/gorm/clause" -) - -type AppDetailRepo struct { -} - -type IAppDetailRepo interface { - WithVersion(version string) DBOption - WithAppId(id uint) DBOption - WithIgnored() DBOption - GetFirst(opts ...DBOption) (model.AppDetail, error) - Update(ctx context.Context, detail model.AppDetail) error - BatchCreate(ctx context.Context, details []model.AppDetail) error - DeleteByAppIds(ctx context.Context, appIds []uint) error - GetBy(opts ...DBOption) ([]model.AppDetail, error) - BatchUpdateBy(maps map[string]interface{}, opts ...DBOption) error - BatchDelete(ctx context.Context, appDetails []model.AppDetail) error -} - -func NewIAppDetailRepo() IAppDetailRepo { - return &AppDetailRepo{} -} - -func (a AppDetailRepo) WithVersion(version string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("version = ?", version) - } -} - -func (a AppDetailRepo) WithAppId(id uint) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("app_id = ?", id) - } -} - -func (a AppDetailRepo) WithIgnored() DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("ignore_upgrade = 1") - } -} - -func (a AppDetailRepo) GetFirst(opts ...DBOption) (model.AppDetail, error) { - var detail model.AppDetail - err := getDb(opts...).Model(&model.AppDetail{}).Find(&detail).Error - return detail, err -} - -func (a AppDetailRepo) Update(ctx context.Context, detail model.AppDetail) error { - return getTx(ctx).Save(&detail).Error -} - -func (a AppDetailRepo) BatchCreate(ctx context.Context, details []model.AppDetail) error { - return getTx(ctx).Model(&model.AppDetail{}).Create(&details).Error -} - -func (a AppDetailRepo) DeleteByAppIds(ctx context.Context, appIds []uint) error { - return getTx(ctx).Where("app_id in (?)", appIds).Delete(&model.AppDetail{}).Error -} - -func (a AppDetailRepo) GetBy(opts ...DBOption) ([]model.AppDetail, error) { - var details []model.AppDetail - err := getDb(opts...).Find(&details).Error - return details, err -} - -func (a AppDetailRepo) BatchUpdateBy(maps map[string]interface{}, opts ...DBOption) error { - db := getDb(opts...).Model(&model.AppDetail{}) - if len(opts) == 0 { - db = db.Where("1=1") - } - return db.Updates(&maps).Error -} - -func (a AppDetailRepo) BatchDelete(ctx context.Context, appDetails []model.AppDetail) error { - return getTx(ctx).Omit(clause.Associations).Delete(&appDetails).Error -} diff --git a/backend/app/repo/app_install.go b/backend/app/repo/app_install.go deleted file mode 100644 index 7de128f4d..000000000 --- a/backend/app/repo/app_install.go +++ /dev/null @@ -1,241 +0,0 @@ -package repo - -import ( - "context" - "encoding/json" - - "github.com/1Panel-dev/1Panel/backend/constant" - - "gorm.io/gorm/clause" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm" -) - -type AppInstallRepo struct{} - -type IAppInstallRepo interface { - WithDetailIdsIn(detailIds []uint) DBOption - WithDetailIdNotIn(detailIds []uint) DBOption - WithAppId(appId uint) DBOption - WithAppIdsIn(appIds []uint) DBOption - WithStatus(status string) DBOption - WithServiceName(serviceName string) DBOption - WithContainerName(containerName string) DBOption - WithPort(port int) DBOption - WithIdNotInWebsite() DBOption - WithIDNotIs(id uint) DBOption - ListBy(opts ...DBOption) ([]model.AppInstall, error) - GetFirst(opts ...DBOption) (model.AppInstall, error) - Create(ctx context.Context, install *model.AppInstall) error - Save(ctx context.Context, install *model.AppInstall) error - DeleteBy(opts ...DBOption) error - Delete(ctx context.Context, install model.AppInstall) error - Page(page, size int, opts ...DBOption) (int64, []model.AppInstall, error) - BatchUpdateBy(maps map[string]interface{}, opts ...DBOption) error - LoadBaseInfo(key string, name string) (*RootInfo, error) - GetFirstByCtx(ctx context.Context, opts ...DBOption) (model.AppInstall, error) -} - -func NewIAppInstallRepo() IAppInstallRepo { - return &AppInstallRepo{} -} - -func (a *AppInstallRepo) WithDetailIdsIn(detailIds []uint) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("app_detail_id in (?)", detailIds) - } -} - -func (a *AppInstallRepo) WithDetailIdNotIn(detailIds []uint) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("app_detail_id not in (?)", detailIds) - } -} - -func (a *AppInstallRepo) WithAppId(appId uint) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("app_id = ?", appId) - } -} - -func (a *AppInstallRepo) WithIDNotIs(id uint) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("id != ?", id) - } -} - -func (a *AppInstallRepo) WithAppIdsIn(appIds []uint) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("app_id in (?)", appIds) - } -} - -func (a *AppInstallRepo) WithStatus(status string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("status = ?", status) - } -} - -func (a *AppInstallRepo) WithServiceName(serviceName string) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("service_name = ?", serviceName) - } -} - -func (a *AppInstallRepo) WithContainerName(containerName string) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("container_name = ?", containerName) - } -} - -func (a *AppInstallRepo) WithPort(port int) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("https_port = ? or http_port = ?", port, port) - } -} - -func (a *AppInstallRepo) WithIdNotInWebsite() DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("id not in (select app_install_id from websites)") - } -} - -func (a *AppInstallRepo) ListBy(opts ...DBOption) ([]model.AppInstall, error) { - var install []model.AppInstall - db := getDb(opts...).Model(&model.AppInstall{}) - err := db.Preload("App").Find(&install).Error - return install, err -} - -func (a *AppInstallRepo) GetFirst(opts ...DBOption) (model.AppInstall, error) { - var install model.AppInstall - db := getDb(opts...).Model(&model.AppInstall{}) - err := db.Preload("App").First(&install).Error - return install, err -} - -func (a *AppInstallRepo) GetFirstByCtx(ctx context.Context, opts ...DBOption) (model.AppInstall, error) { - var install model.AppInstall - db := getTx(ctx, opts...).Model(&model.AppInstall{}) - err := db.Preload("App").First(&install).Error - return install, err -} - -func (a *AppInstallRepo) Create(ctx context.Context, install *model.AppInstall) error { - db := getTx(ctx).Model(&model.AppInstall{}) - return db.Omit(clause.Associations).Create(&install).Error -} - -func (a *AppInstallRepo) Save(ctx context.Context, install *model.AppInstall) error { - return getTx(ctx).Save(&install).Error -} - -func (a *AppInstallRepo) DeleteBy(opts ...DBOption) error { - return getDb(opts...).Delete(&model.AppInstall{}).Error -} - -func (a *AppInstallRepo) Delete(ctx context.Context, install model.AppInstall) error { - db := getTx(ctx).Model(&model.AppInstall{}) - return db.Delete(&install).Error -} - -func (a *AppInstallRepo) Page(page, size int, opts ...DBOption) (int64, []model.AppInstall, error) { - var apps []model.AppInstall - db := getDb(opts...).Model(&model.AppInstall{}) - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Preload("App").Find(&apps).Error - return count, apps, err -} - -func (a *AppInstallRepo) BatchUpdateBy(maps map[string]interface{}, opts ...DBOption) error { - db := getDb(opts...).Model(&model.AppInstall{}) - if len(opts) == 0 { - db = db.Where("1=1") - } - return db.Updates(&maps).Error -} - -type RootInfo struct { - ID uint `json:"id"` - Name string `json:"name"` - Status string `json:"status"` - Port int64 `json:"port"` - HttpsPort int64 `json:"httpsPort"` - UserName string `json:"userName"` - Password string `json:"password"` - UserPassword string `json:"userPassword"` - ContainerName string `json:"containerName"` - ServiceName string `json:"serviceName"` - Param string `json:"param"` - Env string `json:"env"` - Key string `json:"key"` - Version string `json:"version"` - AppPath string `json:"app_path"` -} - -func (a *AppInstallRepo) LoadBaseInfo(key string, name string) (*RootInfo, error) { - var ( - app model.App - appInstall model.AppInstall - info RootInfo - ) - if err := global.DB.Where("key = ?", key).First(&app).Error; err != nil { - return nil, err - } - if len(name) == 0 { - if err := global.DB.Where("app_id = ?", app.ID).First(&appInstall).Error; err != nil { - return nil, err - } - } else { - if err := global.DB.Where("app_id = ? AND name = ?", app.ID, name).First(&appInstall).Error; err != nil { - return nil, err - } - } - envMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(appInstall.Env), &envMap); err != nil { - return nil, err - } - switch app.Key { - case "mysql", "mariadb": - password, ok := envMap["PANEL_DB_ROOT_PASSWORD"].(string) - if ok { - info.Password = password - } - case "redis": - password, ok := envMap["PANEL_REDIS_ROOT_PASSWORD"].(string) - if ok { - info.Password = password - } - case "mongodb", constant.AppPostgresql: - user, ok := envMap["PANEL_DB_ROOT_USER"].(string) - if ok { - info.UserName = user - } - password, ok := envMap["PANEL_DB_ROOT_PASSWORD"].(string) - if ok { - info.Password = password - } - } - - userPassword, ok := envMap["PANEL_DB_USER_PASSWORD"].(string) - if ok { - info.UserPassword = userPassword - } - info.Port = int64(appInstall.HttpPort) - info.HttpsPort = int64(appInstall.HttpsPort) - info.ID = appInstall.ID - info.ServiceName = appInstall.ServiceName - info.ContainerName = appInstall.ContainerName - info.Name = appInstall.Name - info.Env = appInstall.Env - info.Param = appInstall.Param - info.Version = appInstall.Version - info.Key = app.Key - appInstall.App = app - info.AppPath = appInstall.GetAppPath() - info.Status = appInstall.Status - return &info, nil -} diff --git a/backend/app/repo/app_install_resource.go b/backend/app/repo/app_install_resource.go deleted file mode 100644 index e57bbf87d..000000000 --- a/backend/app/repo/app_install_resource.go +++ /dev/null @@ -1,82 +0,0 @@ -package repo - -import ( - "context" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm" -) - -type AppInstallResourceRpo struct { -} - -type IAppInstallResourceRpo interface { - WithAppInstallId(appInstallId uint) DBOption - WithLinkId(linkId uint) DBOption - WithResourceId(resourceId uint) DBOption - GetBy(opts ...DBOption) ([]model.AppInstallResource, error) - GetFirst(opts ...DBOption) (model.AppInstallResource, error) - Create(ctx context.Context, resource *model.AppInstallResource) error - DeleteBy(ctx context.Context, opts ...DBOption) error - BatchUpdateBy(maps map[string]interface{}, opts ...DBOption) error -} - -func NewIAppInstallResourceRpo() IAppInstallResourceRpo { - return &AppInstallResourceRpo{} -} - -func (a AppInstallResourceRpo) WithAppInstallId(appInstallId uint) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("app_install_id = ?", appInstallId) - } -} - -func (a AppInstallResourceRpo) WithLinkId(linkId uint) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("link_id = ?", linkId) - } -} - -func (a AppInstallResourceRpo) WithResourceId(resourceId uint) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("resource_id = ?", resourceId) - } -} - -func (a AppInstallResourceRpo) GetBy(opts ...DBOption) ([]model.AppInstallResource, error) { - db := global.DB.Model(&model.AppInstallResource{}) - var resources []model.AppInstallResource - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&resources).Error - return resources, err -} - -func (a AppInstallResourceRpo) GetFirst(opts ...DBOption) (model.AppInstallResource, error) { - db := global.DB.Model(&model.AppInstallResource{}) - var resources model.AppInstallResource - for _, opt := range opts { - db = opt(db) - } - err := db.First(&resources).Error - return resources, err -} - -func (a AppInstallResourceRpo) Create(ctx context.Context, resource *model.AppInstallResource) error { - db := getTx(ctx).Model(&model.AppInstallResource{}) - return db.Create(&resource).Error -} - -func (a AppInstallResourceRpo) DeleteBy(ctx context.Context, opts ...DBOption) error { - return getTx(ctx, opts...).Delete(&model.AppInstallResource{}).Error -} - -func (a *AppInstallResourceRpo) BatchUpdateBy(maps map[string]interface{}, opts ...DBOption) error { - db := getDb(opts...).Model(&model.AppInstallResource{}) - if len(opts) == 0 { - db = db.Where("1=1") - } - return db.Updates(&maps).Error -} diff --git a/backend/app/repo/app_tag.go b/backend/app/repo/app_tag.go deleted file mode 100644 index 0f65c91a3..000000000 --- a/backend/app/repo/app_tag.go +++ /dev/null @@ -1,49 +0,0 @@ -package repo - -import ( - "context" - "github.com/1Panel-dev/1Panel/backend/app/model" -) - -type AppTagRepo struct { -} - -type IAppTagRepo interface { - BatchCreate(ctx context.Context, tags []*model.AppTag) error - DeleteByAppIds(ctx context.Context, appIds []uint) error - DeleteAll(ctx context.Context) error - GetByAppId(appId uint) ([]model.AppTag, error) - GetByTagIds(tagIds []uint) ([]model.AppTag, error) -} - -func NewIAppTagRepo() IAppTagRepo { - return &AppTagRepo{} -} - -func (a AppTagRepo) BatchCreate(ctx context.Context, tags []*model.AppTag) error { - return getTx(ctx).Create(&tags).Error -} - -func (a AppTagRepo) DeleteByAppIds(ctx context.Context, appIds []uint) error { - return getTx(ctx).Where("app_id in (?)", appIds).Delete(&model.AppTag{}).Error -} - -func (a AppTagRepo) DeleteAll(ctx context.Context) error { - return getTx(ctx).Where("1 = 1").Delete(&model.AppTag{}).Error -} - -func (a AppTagRepo) GetByAppId(appId uint) ([]model.AppTag, error) { - var appTags []model.AppTag - if err := getDb().Where("app_id = ?", appId).Find(&appTags).Error; err != nil { - return nil, err - } - return appTags, nil -} - -func (a AppTagRepo) GetByTagIds(tagIds []uint) ([]model.AppTag, error) { - var appTags []model.AppTag - if err := getDb().Where("tag_id in (?)", tagIds).Find(&appTags).Error; err != nil { - return nil, err - } - return appTags, nil -} diff --git a/backend/app/repo/backup.go b/backend/app/repo/backup.go deleted file mode 100644 index 7548ba8ba..000000000 --- a/backend/app/repo/backup.go +++ /dev/null @@ -1,135 +0,0 @@ -package repo - -import ( - "context" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm" -) - -type BackupRepo struct{} - -type IBackupRepo interface { - Get(opts ...DBOption) (model.BackupAccount, error) - ListRecord(opts ...DBOption) ([]model.BackupRecord, error) - PageRecord(page, size int, opts ...DBOption) (int64, []model.BackupRecord, error) - List(opts ...DBOption) ([]model.BackupAccount, error) - Create(backup *model.BackupAccount) error - CreateRecord(record *model.BackupRecord) error - Update(id uint, vars map[string]interface{}) error - Delete(opts ...DBOption) error - DeleteRecord(ctx context.Context, opts ...DBOption) error - UpdateRecord(record *model.BackupRecord) error - WithByDetailName(detailName string) DBOption - WithByFileName(fileName string) DBOption - WithByType(backupType string) DBOption - WithByCronID(cronjobID uint) DBOption -} - -func NewIBackupRepo() IBackupRepo { - return &BackupRepo{} -} - -func (u *BackupRepo) Get(opts ...DBOption) (model.BackupAccount, error) { - var backup model.BackupAccount - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.First(&backup).Error - return backup, err -} - -func (u *BackupRepo) ListRecord(opts ...DBOption) ([]model.BackupRecord, error) { - var users []model.BackupRecord - db := global.DB.Model(&model.BackupRecord{}) - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&users).Error - return users, err -} - -func (u *BackupRepo) PageRecord(page, size int, opts ...DBOption) (int64, []model.BackupRecord, error) { - var users []model.BackupRecord - db := global.DB.Model(&model.BackupRecord{}) - for _, opt := range opts { - db = opt(db) - } - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&users).Error - return count, users, err -} - -func (u *BackupRepo) WithByDetailName(detailName string) DBOption { - return func(g *gorm.DB) *gorm.DB { - if len(detailName) == 0 { - return g - } - return g.Where("detail_name = ?", detailName) - } -} - -func (u *BackupRepo) WithByFileName(fileName string) DBOption { - return func(g *gorm.DB) *gorm.DB { - if len(fileName) == 0 { - return g - } - return g.Where("file_name = ?", fileName) - } -} - -func (u *BackupRepo) WithByType(backupType string) DBOption { - return func(g *gorm.DB) *gorm.DB { - if len(backupType) == 0 { - return g - } - return g.Where("type = ?", backupType) - } -} - -func (u *BackupRepo) List(opts ...DBOption) ([]model.BackupAccount, error) { - var ops []model.BackupAccount - db := global.DB.Model(&model.BackupAccount{}) - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&ops).Error - return ops, err -} - -func (u *BackupRepo) Create(backup *model.BackupAccount) error { - return global.DB.Create(backup).Error -} - -func (u *BackupRepo) CreateRecord(record *model.BackupRecord) error { - return global.DB.Create(record).Error -} - -func (u *BackupRepo) UpdateRecord(record *model.BackupRecord) error { - return global.DB.Save(record).Error -} - -func (u *BackupRepo) Update(id uint, vars map[string]interface{}) error { - return global.DB.Model(&model.BackupAccount{}).Where("id = ?", id).Updates(vars).Error -} - -func (u *BackupRepo) Delete(opts ...DBOption) error { - db := global.DB - for _, opt := range opts { - db = opt(db) - } - return db.Delete(&model.BackupAccount{}).Error -} - -func (u *BackupRepo) DeleteRecord(ctx context.Context, opts ...DBOption) error { - return getTx(ctx, opts...).Delete(&model.BackupRecord{}).Error -} - -func (u *BackupRepo) WithByCronID(cronjobID uint) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("cronjob_id = ?", cronjobID) - } -} diff --git a/backend/app/repo/clam.go b/backend/app/repo/clam.go deleted file mode 100644 index 4fd212c8c..000000000 --- a/backend/app/repo/clam.go +++ /dev/null @@ -1,69 +0,0 @@ -package repo - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" -) - -type ClamRepo struct{} - -type IClamRepo interface { - Page(limit, offset int, opts ...DBOption) (int64, []model.Clam, error) - Create(clam *model.Clam) error - Update(id uint, vars map[string]interface{}) error - Delete(opts ...DBOption) error - Get(opts ...DBOption) (model.Clam, error) - List(opts ...DBOption) ([]model.Clam, error) -} - -func NewIClamRepo() IClamRepo { - return &ClamRepo{} -} - -func (u *ClamRepo) Get(opts ...DBOption) (model.Clam, error) { - var clam model.Clam - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.First(&clam).Error - return clam, err -} - -func (u *ClamRepo) List(opts ...DBOption) ([]model.Clam, error) { - var clam []model.Clam - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&clam).Error - return clam, err -} - -func (u *ClamRepo) Page(page, size int, opts ...DBOption) (int64, []model.Clam, error) { - var users []model.Clam - db := global.DB.Model(&model.Clam{}) - for _, opt := range opts { - db = opt(db) - } - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&users).Error - return count, users, err -} - -func (u *ClamRepo) Create(clam *model.Clam) error { - return global.DB.Create(clam).Error -} - -func (u *ClamRepo) Update(id uint, vars map[string]interface{}) error { - return global.DB.Model(&model.Clam{}).Where("id = ?", id).Updates(vars).Error -} - -func (u *ClamRepo) Delete(opts ...DBOption) error { - db := global.DB - for _, opt := range opts { - db = opt(db) - } - return db.Delete(&model.Clam{}).Error -} diff --git a/backend/app/repo/command.go b/backend/app/repo/command.go deleted file mode 100644 index c68ad618a..000000000 --- a/backend/app/repo/command.go +++ /dev/null @@ -1,141 +0,0 @@ -package repo - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm" -) - -type CommandRepo struct{} - -type ICommandRepo interface { - GetList(opts ...DBOption) ([]model.Command, error) - Page(limit, offset int, opts ...DBOption) (int64, []model.Command, error) - WithByInfo(info string) DBOption - Create(command *model.Command) error - Update(id uint, vars map[string]interface{}) error - Delete(opts ...DBOption) error - Get(opts ...DBOption) (model.Command, error) - WithLikeName(name string) DBOption - - PageRedis(limit, offset int, opts ...DBOption) (int64, []model.RedisCommand, error) - GetRedis(opts ...DBOption) (model.RedisCommand, error) - GetRedisList(opts ...DBOption) ([]model.RedisCommand, error) - SaveRedis(command *model.RedisCommand) error - DeleteRedis(opts ...DBOption) error -} - -func NewICommandRepo() ICommandRepo { - return &CommandRepo{} -} - -func (u *CommandRepo) Get(opts ...DBOption) (model.Command, error) { - var command model.Command - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.First(&command).Error - return command, err -} - -func (u *CommandRepo) GetRedis(opts ...DBOption) (model.RedisCommand, error) { - var command model.RedisCommand - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.First(&command).Error - return command, err -} - -func (u *CommandRepo) Page(page, size int, opts ...DBOption) (int64, []model.Command, error) { - var users []model.Command - db := global.DB.Model(&model.Command{}) - for _, opt := range opts { - db = opt(db) - } - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&users).Error - return count, users, err -} - -func (u *CommandRepo) PageRedis(page, size int, opts ...DBOption) (int64, []model.RedisCommand, error) { - var users []model.RedisCommand - db := global.DB.Model(&model.RedisCommand{}) - for _, opt := range opts { - db = opt(db) - } - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&users).Error - return count, users, err -} - -func (u *CommandRepo) GetList(opts ...DBOption) ([]model.Command, error) { - var commands []model.Command - db := global.DB.Model(&model.Command{}) - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&commands).Error - return commands, err -} - -func (u *CommandRepo) GetRedisList(opts ...DBOption) ([]model.RedisCommand, error) { - var commands []model.RedisCommand - db := global.DB.Model(&model.RedisCommand{}) - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&commands).Error - return commands, err -} - -func (c *CommandRepo) WithByInfo(info string) DBOption { - return func(g *gorm.DB) *gorm.DB { - if len(info) == 0 { - return g - } - infoStr := "%" + info + "%" - return g.Where("name LIKE ? OR addr LIKE ?", infoStr, infoStr) - } -} - -func (u *CommandRepo) Create(command *model.Command) error { - return global.DB.Create(command).Error -} - -func (u *CommandRepo) SaveRedis(command *model.RedisCommand) error { - return global.DB.Save(command).Error -} - -func (u *CommandRepo) Update(id uint, vars map[string]interface{}) error { - return global.DB.Model(&model.Command{}).Where("id = ?", id).Updates(vars).Error -} - -func (u *CommandRepo) Delete(opts ...DBOption) error { - db := global.DB - for _, opt := range opts { - db = opt(db) - } - return db.Delete(&model.Command{}).Error -} - -func (u *CommandRepo) DeleteRedis(opts ...DBOption) error { - db := global.DB - for _, opt := range opts { - db = opt(db) - } - return db.Delete(&model.RedisCommand{}).Error -} - -func (a CommandRepo) WithLikeName(name string) DBOption { - return func(g *gorm.DB) *gorm.DB { - if len(name) == 0 { - return g - } - return g.Where("name like ? or command like ?", "%"+name+"%", "%"+name+"%") - } -} diff --git a/backend/app/repo/common.go b/backend/app/repo/common.go deleted file mode 100644 index e6cf0b23f..000000000 --- a/backend/app/repo/common.go +++ /dev/null @@ -1,149 +0,0 @@ -package repo - -import ( - "context" - "fmt" - "time" - - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm" -) - -type DBOption func(*gorm.DB) *gorm.DB - -type ICommonRepo interface { - WithByID(id uint) DBOption - WithByName(name string) DBOption - WithByType(tp string) DBOption - WithOrderBy(orderStr string) DBOption - WithOrderRuleBy(orderBy, order string) DBOption - WithByGroupID(groupID uint) DBOption - WithLikeName(name string) DBOption - WithIdsIn(ids []uint) DBOption - WithByDate(startTime, endTime time.Time) DBOption - WithByStartDate(startTime time.Time) DBOption - WithByStatus(status string) DBOption - WithByFrom(from string) DBOption -} - -type CommonRepo struct{} - -func NewCommonRepo() ICommonRepo { - return &CommonRepo{} -} - -func (c *CommonRepo) WithByID(id uint) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("id = ?", id) - } -} - -func (c *CommonRepo) WithByName(name string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("name = ?", name) - } -} - -func (c *CommonRepo) WithByDate(startTime, endTime time.Time) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("start_time > ? AND start_time < ?", startTime, endTime) - } -} - -func (c *CommonRepo) WithByStartDate(startTime time.Time) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("start_time < ?", startTime) - } -} - -func (c *CommonRepo) WithByType(tp string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("type = ?", tp) - } -} - -func (c *CommonRepo) WithByGroupID(groupID uint) DBOption { - return func(g *gorm.DB) *gorm.DB { - if groupID == 0 { - return g - } - return g.Where("group_id = ?", groupID) - } -} - -func (c *CommonRepo) WithByStatus(status string) DBOption { - return func(g *gorm.DB) *gorm.DB { - if len(status) == 0 { - return g - } - return g.Where("status = ?", status) - } -} - -func (c *CommonRepo) WithByFrom(from string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("`from` = ?", from) - } -} - -func (c *CommonRepo) WithLikeName(name string) DBOption { - return func(g *gorm.DB) *gorm.DB { - if len(name) == 0 { - return g - } - return g.Where("name like ?", "%"+name+"%") - } -} - -func (c *CommonRepo) WithOrderBy(orderStr string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Order(orderStr) - } -} - -func (c *CommonRepo) WithOrderRuleBy(orderBy, order string) DBOption { - switch order { - case constant.OrderDesc: - order = "desc" - case constant.OrderAsc: - order = "asc" - default: - orderBy = "created_at" - order = "desc" - } - return func(g *gorm.DB) *gorm.DB { - return g.Order(fmt.Sprintf("%s %s", orderBy, order)) - } -} - -func (c *CommonRepo) WithIdsIn(ids []uint) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("id in (?)", ids) - } -} - -func (c *CommonRepo) WithIdsNotIn(ids []uint) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("id not in (?)", ids) - } -} - -func getTx(ctx context.Context, opts ...DBOption) *gorm.DB { - tx, ok := ctx.Value(constant.DB).(*gorm.DB) - if ok { - for _, opt := range opts { - tx = opt(tx) - } - return tx - } - return getDb(opts...) -} - -func getDb(opts ...DBOption) *gorm.DB { - db := global.DB - for _, opt := range opts { - db = opt(db) - } - return db -} diff --git a/backend/app/repo/compose_template.go b/backend/app/repo/compose_template.go deleted file mode 100644 index 4259e2fb5..000000000 --- a/backend/app/repo/compose_template.go +++ /dev/null @@ -1,104 +0,0 @@ -package repo - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" -) - -type ComposeTemplateRepo struct{} - -type IComposeTemplateRepo interface { - Get(opts ...DBOption) (model.ComposeTemplate, error) - List(opts ...DBOption) ([]model.ComposeTemplate, error) - Page(limit, offset int, opts ...DBOption) (int64, []model.ComposeTemplate, error) - Create(compose *model.ComposeTemplate) error - Update(id uint, vars map[string]interface{}) error - Delete(opts ...DBOption) error - - GetRecord(opts ...DBOption) (model.Compose, error) - CreateRecord(compose *model.Compose) error - DeleteRecord(opts ...DBOption) error - ListRecord() ([]model.Compose, error) -} - -func NewIComposeTemplateRepo() IComposeTemplateRepo { - return &ComposeTemplateRepo{} -} - -func (u *ComposeTemplateRepo) Get(opts ...DBOption) (model.ComposeTemplate, error) { - var compose model.ComposeTemplate - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.First(&compose).Error - return compose, err -} - -func (u *ComposeTemplateRepo) Page(page, size int, opts ...DBOption) (int64, []model.ComposeTemplate, error) { - var users []model.ComposeTemplate - db := global.DB.Model(&model.ComposeTemplate{}) - for _, opt := range opts { - db = opt(db) - } - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&users).Error - return count, users, err -} - -func (u *ComposeTemplateRepo) List(opts ...DBOption) ([]model.ComposeTemplate, error) { - var composes []model.ComposeTemplate - db := global.DB.Model(&model.ComposeTemplate{}) - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&composes).Error - return composes, err -} - -func (u *ComposeTemplateRepo) Create(compose *model.ComposeTemplate) error { - return global.DB.Create(compose).Error -} - -func (u *ComposeTemplateRepo) Update(id uint, vars map[string]interface{}) error { - return global.DB.Model(&model.ComposeTemplate{}).Where("id = ?", id).Updates(vars).Error -} - -func (u *ComposeTemplateRepo) Delete(opts ...DBOption) error { - db := global.DB - for _, opt := range opts { - db = opt(db) - } - return db.Delete(&model.ComposeTemplate{}).Error -} - -func (u *ComposeTemplateRepo) GetRecord(opts ...DBOption) (model.Compose, error) { - var compose model.Compose - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.First(&compose).Error - return compose, err -} - -func (u *ComposeTemplateRepo) ListRecord() ([]model.Compose, error) { - var composes []model.Compose - if err := global.DB.Find(&composes).Error; err != nil { - return nil, err - } - return composes, nil -} - -func (u *ComposeTemplateRepo) CreateRecord(compose *model.Compose) error { - return global.DB.Create(compose).Error -} - -func (u *ComposeTemplateRepo) DeleteRecord(opts ...DBOption) error { - db := global.DB - for _, opt := range opts { - db = opt(db) - } - return db.Delete(&model.Compose{}).Error -} diff --git a/backend/app/repo/cronjob.go b/backend/app/repo/cronjob.go deleted file mode 100644 index 867fc6283..000000000 --- a/backend/app/repo/cronjob.go +++ /dev/null @@ -1,192 +0,0 @@ -package repo - -import ( - "time" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm" -) - -type CronjobRepo struct{} - -type ICronjobRepo interface { - Get(opts ...DBOption) (model.Cronjob, error) - GetRecord(opts ...DBOption) (model.JobRecords, error) - RecordFirst(id uint) (model.JobRecords, error) - ListRecord(opts ...DBOption) ([]model.JobRecords, error) - List(opts ...DBOption) ([]model.Cronjob, error) - Page(limit, offset int, opts ...DBOption) (int64, []model.Cronjob, error) - Create(cronjob *model.Cronjob) error - WithByJobID(id int) DBOption - WithByDbName(name string) DBOption - WithByDefaultDownload(account string) DBOption - WithByRecordDropID(id int) DBOption - WithByRecordFile(file string) DBOption - Save(id uint, cronjob model.Cronjob) error - Update(id uint, vars map[string]interface{}) error - Delete(opts ...DBOption) error - DeleteRecord(opts ...DBOption) error - StartRecords(cronjobID uint, fromLocal bool, targetPath string) model.JobRecords - UpdateRecords(id uint, vars map[string]interface{}) error - EndRecords(record model.JobRecords, status, message, records string) - PageRecords(page, size int, opts ...DBOption) (int64, []model.JobRecords, error) -} - -func NewICronjobRepo() ICronjobRepo { - return &CronjobRepo{} -} - -func (u *CronjobRepo) Get(opts ...DBOption) (model.Cronjob, error) { - var cronjob model.Cronjob - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.First(&cronjob).Error - return cronjob, err -} - -func (u *CronjobRepo) GetRecord(opts ...DBOption) (model.JobRecords, error) { - var record model.JobRecords - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.First(&record).Error - return record, err -} - -func (u *CronjobRepo) List(opts ...DBOption) ([]model.Cronjob, error) { - var cronjobs []model.Cronjob - db := global.DB.Model(&model.Cronjob{}) - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&cronjobs).Error - return cronjobs, err -} - -func (u *CronjobRepo) ListRecord(opts ...DBOption) ([]model.JobRecords, error) { - var cronjobs []model.JobRecords - db := global.DB.Model(&model.JobRecords{}) - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&cronjobs).Error - return cronjobs, err -} - -func (u *CronjobRepo) Page(page, size int, opts ...DBOption) (int64, []model.Cronjob, error) { - var cronjobs []model.Cronjob - db := global.DB.Model(&model.Cronjob{}) - for _, opt := range opts { - db = opt(db) - } - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&cronjobs).Error - return count, cronjobs, err -} - -func (u *CronjobRepo) RecordFirst(id uint) (model.JobRecords, error) { - var record model.JobRecords - err := global.DB.Where("cronjob_id = ?", id).Order("created_at desc").First(&record).Error - return record, err -} - -func (u *CronjobRepo) PageRecords(page, size int, opts ...DBOption) (int64, []model.JobRecords, error) { - var cronjobs []model.JobRecords - db := global.DB.Model(&model.JobRecords{}) - for _, opt := range opts { - db = opt(db) - } - count := int64(0) - db = db.Count(&count) - err := db.Order("created_at desc").Limit(size).Offset(size * (page - 1)).Find(&cronjobs).Error - return count, cronjobs, err -} - -func (u *CronjobRepo) Create(cronjob *model.Cronjob) error { - return global.DB.Create(cronjob).Error -} - -func (c *CronjobRepo) WithByJobID(id int) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("cronjob_id = ?", id) - } -} - -func (c *CronjobRepo) WithByDbName(name string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("db_name = ?", name) - } -} - -func (c *CronjobRepo) WithByDefaultDownload(account string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("default_download = ?", account) - } -} - -func (c *CronjobRepo) WithByRecordFile(file string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("records = ?", file) - } -} - -func (c *CronjobRepo) WithByRecordDropID(id int) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("id < ?", id) - } -} - -func (u *CronjobRepo) StartRecords(cronjobID uint, fromLocal bool, targetPath string) model.JobRecords { - var record model.JobRecords - record.StartTime = time.Now() - record.CronjobID = cronjobID - record.FromLocal = fromLocal - record.Status = constant.StatusWaiting - if err := global.DB.Create(&record).Error; err != nil { - global.LOG.Errorf("create record status failed, err: %v", err) - } - return record -} -func (u *CronjobRepo) EndRecords(record model.JobRecords, status, message, records string) { - errMap := make(map[string]interface{}) - errMap["records"] = records - errMap["status"] = status - errMap["file"] = record.File - errMap["message"] = message - errMap["interval"] = time.Since(record.StartTime).Milliseconds() - if err := global.DB.Model(&model.JobRecords{}).Where("id = ?", record.ID).Updates(errMap).Error; err != nil { - global.LOG.Errorf("update record status failed, err: %v", err) - } -} - -func (u *CronjobRepo) Save(id uint, cronjob model.Cronjob) error { - return global.DB.Model(&model.Cronjob{}).Where("id = ?", id).Save(&cronjob).Error -} -func (u *CronjobRepo) Update(id uint, vars map[string]interface{}) error { - return global.DB.Model(&model.Cronjob{}).Where("id = ?", id).Updates(vars).Error -} - -func (u *CronjobRepo) UpdateRecords(id uint, vars map[string]interface{}) error { - return global.DB.Model(&model.JobRecords{}).Where("id = ?", id).Updates(vars).Error -} - -func (u *CronjobRepo) Delete(opts ...DBOption) error { - db := global.DB - for _, opt := range opts { - db = opt(db) - } - return db.Delete(&model.Cronjob{}).Error -} -func (u *CronjobRepo) DeleteRecord(opts ...DBOption) error { - db := global.DB - for _, opt := range opts { - db = opt(db) - } - return db.Delete(&model.JobRecords{}).Error -} diff --git a/backend/app/repo/database.go b/backend/app/repo/database.go deleted file mode 100644 index bd7749532..000000000 --- a/backend/app/repo/database.go +++ /dev/null @@ -1,143 +0,0 @@ -package repo - -import ( - "context" - "fmt" - "strings" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/encrypt" - "gorm.io/gorm" -) - -type DatabaseRepo struct{} - -type IDatabaseRepo interface { - GetList(opts ...DBOption) ([]model.Database, error) - Page(limit, offset int, opts ...DBOption) (int64, []model.Database, error) - Create(ctx context.Context, database *model.Database) error - Update(id uint, vars map[string]interface{}) error - Delete(ctx context.Context, opts ...DBOption) error - Get(opts ...DBOption) (model.Database, error) - WithByFrom(from string) DBOption - WithoutByFrom(from string) DBOption - WithAppInstallID(appInstallID uint) DBOption - WithTypeList(dbType string) DBOption -} - -func NewIDatabaseRepo() IDatabaseRepo { - return &DatabaseRepo{} -} - -func (d *DatabaseRepo) Get(opts ...DBOption) (model.Database, error) { - var database model.Database - db := global.DB - for _, opt := range opts { - db = opt(db) - } - if err := db.First(&database).Error; err != nil { - return database, err - } - pass, err := encrypt.StringDecrypt(database.Password) - if err != nil { - global.LOG.Errorf("decrypt database %s password failed, err: %v", database.Name, err) - } - database.Password = pass - return database, nil -} - -func (d *DatabaseRepo) Page(page, size int, opts ...DBOption) (int64, []model.Database, error) { - var databases []model.Database - db := global.DB.Model(&model.Database{}) - for _, opt := range opts { - db = opt(db) - } - count := int64(0) - db = db.Count(&count) - if err := db.Limit(size).Offset(size * (page - 1)).Find(&databases).Error; err != nil { - return count, databases, err - } - for i := 0; i < len(databases); i++ { - pass, err := encrypt.StringDecrypt(databases[i].Password) - if err != nil { - global.LOG.Errorf("decrypt database db %s password failed, err: %v", databases[i].Name, err) - } - databases[i].Password = pass - } - return count, databases, nil -} - -func (d *DatabaseRepo) GetList(opts ...DBOption) ([]model.Database, error) { - var databases []model.Database - db := global.DB.Model(&model.Database{}) - for _, opt := range opts { - db = opt(db) - } - if err := db.Find(&databases).Error; err != nil { - return databases, err - } - for i := 0; i < len(databases); i++ { - pass, err := encrypt.StringDecrypt(databases[i].Password) - if err != nil { - global.LOG.Errorf("decrypt database db %s password failed, err: %v", databases[i].Name, err) - } - databases[i].Password = pass - } - return databases, nil -} - -func (d *DatabaseRepo) WithByFrom(from string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("`from` = ?", from) - } -} - -func (d *DatabaseRepo) WithoutByFrom(from string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("`from` != ?", from) - } -} - -func (d *DatabaseRepo) WithTypeList(dbType string) DBOption { - return func(g *gorm.DB) *gorm.DB { - if !strings.Contains(dbType, ",") { - return g.Where("`type` = ?", dbType) - } - types := strings.Split(dbType, ",") - var ( - rules []string - values []interface{} - ) - for _, ty := range types { - if len(ty) != 0 { - rules = append(rules, "`type` = ?") - values = append(values, ty) - } - } - return g.Where(strings.Join(rules, " OR "), values...) - } -} - -func (d *DatabaseRepo) WithAppInstallID(appInstallID uint) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("app_install_id = ?", appInstallID) - } -} - -func (d *DatabaseRepo) Create(ctx context.Context, database *model.Database) error { - pass, err := encrypt.StringEncrypt(database.Password) - if err != nil { - return fmt.Errorf("decrypt database db %s password failed, err: %v", database.Name, err) - } - database.Password = pass - return getTx(ctx).Create(database).Error -} - -func (d *DatabaseRepo) Update(id uint, vars map[string]interface{}) error { - return global.DB.Model(&model.Database{}).Where("id = ?", id).Updates(vars).Error -} - -func (d *DatabaseRepo) Delete(ctx context.Context, opts ...DBOption) error { - return getTx(ctx, opts...).Delete(&model.Database{}).Error -} diff --git a/backend/app/repo/database_mysql.go b/backend/app/repo/database_mysql.go deleted file mode 100644 index 47d107379..000000000 --- a/backend/app/repo/database_mysql.go +++ /dev/null @@ -1,123 +0,0 @@ -package repo - -import ( - "context" - "fmt" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/encrypt" - "gorm.io/gorm" -) - -type MysqlRepo struct{} - -type IMysqlRepo interface { - Get(opts ...DBOption) (model.DatabaseMysql, error) - WithByMysqlName(mysqlName string) DBOption - WithByFrom(from string) DBOption - List(opts ...DBOption) ([]model.DatabaseMysql, error) - Page(limit, offset int, opts ...DBOption) (int64, []model.DatabaseMysql, error) - Create(ctx context.Context, mysql *model.DatabaseMysql) error - Delete(ctx context.Context, opts ...DBOption) error - Update(id uint, vars map[string]interface{}) error - DeleteLocal(ctx context.Context) error -} - -func NewIMysqlRepo() IMysqlRepo { - return &MysqlRepo{} -} - -func (u *MysqlRepo) Get(opts ...DBOption) (model.DatabaseMysql, error) { - var mysql model.DatabaseMysql - db := global.DB - for _, opt := range opts { - db = opt(db) - } - if err := db.First(&mysql).Error; err != nil { - return mysql, err - } - - pass, err := encrypt.StringDecrypt(mysql.Password) - if err != nil { - global.LOG.Errorf("decrypt database db %s password failed, err: %v", mysql.Name, err) - } - mysql.Password = pass - return mysql, err -} - -func (u *MysqlRepo) List(opts ...DBOption) ([]model.DatabaseMysql, error) { - var mysqls []model.DatabaseMysql - db := global.DB.Model(&model.DatabaseMysql{}) - for _, opt := range opts { - db = opt(db) - } - if err := db.Find(&mysqls).Error; err != nil { - return mysqls, err - } - for i := 0; i < len(mysqls); i++ { - pass, err := encrypt.StringDecrypt(mysqls[i].Password) - if err != nil { - global.LOG.Errorf("decrypt database db %s password failed, err: %v", mysqls[i].Name, err) - } - mysqls[i].Password = pass - } - return mysqls, nil -} - -func (u *MysqlRepo) Page(page, size int, opts ...DBOption) (int64, []model.DatabaseMysql, error) { - var mysqls []model.DatabaseMysql - db := global.DB.Model(&model.DatabaseMysql{}) - for _, opt := range opts { - db = opt(db) - } - count := int64(0) - db = db.Count(&count) - if err := db.Limit(size).Offset(size * (page - 1)).Find(&mysqls).Error; err != nil { - return count, mysqls, err - } - for i := 0; i < len(mysqls); i++ { - pass, err := encrypt.StringDecrypt(mysqls[i].Password) - if err != nil { - global.LOG.Errorf("decrypt database db %s password failed, err: %v", mysqls[i].Name, err) - } - mysqls[i].Password = pass - } - return count, mysqls, nil -} - -func (u *MysqlRepo) Create(ctx context.Context, mysql *model.DatabaseMysql) error { - pass, err := encrypt.StringEncrypt(mysql.Password) - if err != nil { - return fmt.Errorf("decrypt database db %s password failed, err: %v", mysql.Name, err) - } - mysql.Password = pass - return getTx(ctx).Create(mysql).Error -} - -func (u *MysqlRepo) Delete(ctx context.Context, opts ...DBOption) error { - return getTx(ctx, opts...).Delete(&model.DatabaseMysql{}).Error -} - -func (u *MysqlRepo) DeleteLocal(ctx context.Context) error { - return getTx(ctx).Where("`from` = ?", "local").Delete(&model.DatabaseMysql{}).Error -} - -func (u *MysqlRepo) Update(id uint, vars map[string]interface{}) error { - return global.DB.Model(&model.DatabaseMysql{}).Where("id = ?", id).Updates(vars).Error -} - -func (u *MysqlRepo) WithByMysqlName(mysqlName string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("mysql_name = ?", mysqlName) - } -} - -func (u *MysqlRepo) WithByFrom(from string) DBOption { - return func(g *gorm.DB) *gorm.DB { - if len(from) != 0 { - return g.Where("`from` = ?", from) - } - return g - } -} diff --git a/backend/app/repo/database_postgresql.go b/backend/app/repo/database_postgresql.go deleted file mode 100644 index 23a89eb4c..000000000 --- a/backend/app/repo/database_postgresql.go +++ /dev/null @@ -1,123 +0,0 @@ -package repo - -import ( - "context" - "fmt" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/encrypt" - "gorm.io/gorm" -) - -type PostgresqlRepo struct{} - -type IPostgresqlRepo interface { - Get(opts ...DBOption) (model.DatabasePostgresql, error) - WithByPostgresqlName(postgresqlName string) DBOption - WithByFrom(from string) DBOption - List(opts ...DBOption) ([]model.DatabasePostgresql, error) - Page(limit, offset int, opts ...DBOption) (int64, []model.DatabasePostgresql, error) - Create(ctx context.Context, postgresql *model.DatabasePostgresql) error - Delete(ctx context.Context, opts ...DBOption) error - Update(id uint, vars map[string]interface{}) error - DeleteLocal(ctx context.Context) error -} - -func NewIPostgresqlRepo() IPostgresqlRepo { - return &PostgresqlRepo{} -} - -func (u *PostgresqlRepo) Get(opts ...DBOption) (model.DatabasePostgresql, error) { - var postgresql model.DatabasePostgresql - db := global.DB - for _, opt := range opts { - db = opt(db) - } - if err := db.First(&postgresql).Error; err != nil { - return postgresql, err - } - - pass, err := encrypt.StringDecrypt(postgresql.Password) - if err != nil { - global.LOG.Errorf("decrypt database db %s password failed, err: %v", postgresql.Name, err) - } - postgresql.Password = pass - return postgresql, err -} - -func (u *PostgresqlRepo) List(opts ...DBOption) ([]model.DatabasePostgresql, error) { - var postgresqls []model.DatabasePostgresql - db := global.DB.Model(&model.DatabasePostgresql{}) - for _, opt := range opts { - db = opt(db) - } - if err := db.Find(&postgresqls).Error; err != nil { - return postgresqls, err - } - for i := 0; i < len(postgresqls); i++ { - pass, err := encrypt.StringDecrypt(postgresqls[i].Password) - if err != nil { - global.LOG.Errorf("decrypt database db %s password failed, err: %v", postgresqls[i].Name, err) - } - postgresqls[i].Password = pass - } - return postgresqls, nil -} - -func (u *PostgresqlRepo) Page(page, size int, opts ...DBOption) (int64, []model.DatabasePostgresql, error) { - var postgresqls []model.DatabasePostgresql - db := global.DB.Model(&model.DatabasePostgresql{}) - for _, opt := range opts { - db = opt(db) - } - count := int64(0) - db = db.Count(&count) - if err := db.Limit(size).Offset(size * (page - 1)).Find(&postgresqls).Error; err != nil { - return count, postgresqls, err - } - for i := 0; i < len(postgresqls); i++ { - pass, err := encrypt.StringDecrypt(postgresqls[i].Password) - if err != nil { - global.LOG.Errorf("decrypt database db %s password failed, err: %v", postgresqls[i].Name, err) - } - postgresqls[i].Password = pass - } - return count, postgresqls, nil -} - -func (u *PostgresqlRepo) Create(ctx context.Context, postgresql *model.DatabasePostgresql) error { - pass, err := encrypt.StringEncrypt(postgresql.Password) - if err != nil { - return fmt.Errorf("decrypt database db %s password failed, err: %v", postgresql.Name, err) - } - postgresql.Password = pass - return getTx(ctx).Create(postgresql).Error -} - -func (u *PostgresqlRepo) Delete(ctx context.Context, opts ...DBOption) error { - return getTx(ctx, opts...).Delete(&model.DatabasePostgresql{}).Error -} - -func (u *PostgresqlRepo) DeleteLocal(ctx context.Context) error { - return getTx(ctx).Where("`from` = ?", "local").Delete(&model.DatabasePostgresql{}).Error -} - -func (u *PostgresqlRepo) Update(id uint, vars map[string]interface{}) error { - return global.DB.Model(&model.DatabasePostgresql{}).Where("id = ?", id).Updates(vars).Error -} - -func (u *PostgresqlRepo) WithByPostgresqlName(postgresqlName string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("postgresql_name = ?", postgresqlName) - } -} - -func (u *PostgresqlRepo) WithByFrom(from string) DBOption { - return func(g *gorm.DB) *gorm.DB { - if len(from) != 0 { - return g.Where("`from` = ?", from) - } - return g - } -} diff --git a/backend/app/repo/favorite.go b/backend/app/repo/favorite.go deleted file mode 100644 index 01d2ba1ac..000000000 --- a/backend/app/repo/favorite.go +++ /dev/null @@ -1,66 +0,0 @@ -package repo - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm" -) - -type FavoriteRepo struct{} - -type IFavoriteRepo interface { - Page(page, size int, opts ...DBOption) (int64, []model.Favorite, error) - Create(group *model.Favorite) error - Delete(opts ...DBOption) error - GetFirst(opts ...DBOption) (model.Favorite, error) - All() ([]model.Favorite, error) - WithByPath(path string) DBOption -} - -func NewIFavoriteRepo() IFavoriteRepo { - return &FavoriteRepo{} -} - -func (f *FavoriteRepo) WithByPath(path string) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("path = ?", path) - } -} - -func (f *FavoriteRepo) Page(page, size int, opts ...DBOption) (int64, []model.Favorite, error) { - var ( - favorites []model.Favorite - count int64 - ) - count = int64(0) - db := getDb(opts...).Model(&model.Favorite{}) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&favorites).Error - return count, favorites, err -} - -func (f *FavoriteRepo) Create(favorite *model.Favorite) error { - return global.DB.Create(favorite).Error -} - -func (f *FavoriteRepo) GetFirst(opts ...DBOption) (model.Favorite, error) { - var favorite model.Favorite - db := getDb(opts...).Model(&model.Favorite{}) - if err := db.First(&favorite).Error; err != nil { - return favorite, err - } - return favorite, nil -} - -func (f *FavoriteRepo) Delete(opts ...DBOption) error { - db := getDb(opts...).Model(&model.Favorite{}) - return db.Delete(&model.Favorite{}).Error -} - -func (f *FavoriteRepo) All() ([]model.Favorite, error) { - var favorites []model.Favorite - if err := getDb().Find(&favorites).Error; err != nil { - return nil, err - } - return favorites, nil -} diff --git a/backend/app/repo/ftp.go b/backend/app/repo/ftp.go deleted file mode 100644 index c9732ec13..000000000 --- a/backend/app/repo/ftp.go +++ /dev/null @@ -1,80 +0,0 @@ -package repo - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm" -) - -type FtpRepo struct{} - -type IFtpRepo interface { - Get(opts ...DBOption) (model.Ftp, error) - GetList(opts ...DBOption) ([]model.Ftp, error) - Page(limit, offset int, opts ...DBOption) (int64, []model.Ftp, error) - Create(ftp *model.Ftp) error - Update(id uint, vars map[string]interface{}) error - Delete(opts ...DBOption) error - WithByUser(user string) DBOption -} - -func NewIFtpRepo() IFtpRepo { - return &FtpRepo{} -} - -func (u *FtpRepo) Get(opts ...DBOption) (model.Ftp, error) { - var ftp model.Ftp - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.First(&ftp).Error - return ftp, err -} - -func (h *FtpRepo) WithByUser(user string) DBOption { - return func(g *gorm.DB) *gorm.DB { - if len(user) == 0 { - return g - } - return g.Where("user like ?", "%"+user+"%") - } -} - -func (u *FtpRepo) GetList(opts ...DBOption) ([]model.Ftp, error) { - var ftps []model.Ftp - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&ftps).Error - return ftps, err -} - -func (h *FtpRepo) Page(page, size int, opts ...DBOption) (int64, []model.Ftp, error) { - var users []model.Ftp - db := global.DB.Model(&model.Ftp{}) - for _, opt := range opts { - db = opt(db) - } - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&users).Error - return count, users, err -} - -func (h *FtpRepo) Create(ftp *model.Ftp) error { - return global.DB.Create(ftp).Error -} - -func (h *FtpRepo) Update(id uint, vars map[string]interface{}) error { - return global.DB.Model(&model.Ftp{}).Where("id = ?", id).Updates(vars).Error -} - -func (h *FtpRepo) Delete(opts ...DBOption) error { - db := global.DB - for _, opt := range opts { - db = opt(db) - } - return db.Delete(&model.Ftp{}).Error -} diff --git a/backend/app/repo/group.go b/backend/app/repo/group.go deleted file mode 100644 index 5384e188d..000000000 --- a/backend/app/repo/group.go +++ /dev/null @@ -1,69 +0,0 @@ -package repo - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm" -) - -type GroupRepo struct{} - -type IGroupRepo interface { - Get(opts ...DBOption) (model.Group, error) - GetList(opts ...DBOption) ([]model.Group, error) - Create(group *model.Group) error - Update(id uint, vars map[string]interface{}) error - Delete(opts ...DBOption) error - CancelDefault(groupType string) error - WithByHostDefault() DBOption -} - -func NewIGroupRepo() IGroupRepo { - return &GroupRepo{} -} - -func (u *GroupRepo) Get(opts ...DBOption) (model.Group, error) { - var group model.Group - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.First(&group).Error - return group, err -} - -func (u *GroupRepo) GetList(opts ...DBOption) ([]model.Group, error) { - var groups []model.Group - db := global.DB.Model(&model.Group{}) - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&groups).Error - return groups, err -} - -func (u *GroupRepo) Create(group *model.Group) error { - return global.DB.Create(group).Error -} - -func (u *GroupRepo) Update(id uint, vars map[string]interface{}) error { - return global.DB.Model(&model.Group{}).Where("id = ?", id).Updates(vars).Error -} - -func (u *GroupRepo) WithByHostDefault() DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("is_default = ? AND type = ?", 1, "host") - } -} - -func (u *GroupRepo) Delete(opts ...DBOption) error { - db := global.DB - for _, opt := range opts { - db = opt(db) - } - return db.Delete(&model.Group{}).Error -} - -func (u *GroupRepo) CancelDefault(groupType string) error { - return global.DB.Model(&model.Group{}).Where("is_default = ? AND type = ?", 1, groupType).Updates(map[string]interface{}{"is_default": 0}).Error -} diff --git a/backend/app/repo/host.go b/backend/app/repo/host.go deleted file mode 100644 index 0ca114a1c..000000000 --- a/backend/app/repo/host.go +++ /dev/null @@ -1,159 +0,0 @@ -package repo - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm" -) - -type HostRepo struct{} - -type IHostRepo interface { - Get(opts ...DBOption) (model.Host, error) - GetList(opts ...DBOption) ([]model.Host, error) - Page(limit, offset int, opts ...DBOption) (int64, []model.Host, error) - WithByInfo(info string) DBOption - WithByPort(port uint) DBOption - WithByUser(user string) DBOption - WithByAddr(addr string) DBOption - Create(host *model.Host) error - Update(id uint, vars map[string]interface{}) error - Delete(opts ...DBOption) error - - GetFirewallRecord(opts ...DBOption) (model.Firewall, error) - ListFirewallRecord() ([]model.Firewall, error) - SaveFirewallRecord(firewall *model.Firewall) error - DeleteFirewallRecordByID(id uint) error - DeleteFirewallRecord(fType, port, protocol, address, strategy string) error -} - -func NewIHostRepo() IHostRepo { - return &HostRepo{} -} - -func (h *HostRepo) Get(opts ...DBOption) (model.Host, error) { - var host model.Host - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.First(&host).Error - return host, err -} - -func (h *HostRepo) GetList(opts ...DBOption) ([]model.Host, error) { - var hosts []model.Host - db := global.DB.Model(&model.Host{}) - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&hosts).Error - return hosts, err -} - -func (h *HostRepo) Page(page, size int, opts ...DBOption) (int64, []model.Host, error) { - var users []model.Host - db := global.DB.Model(&model.Host{}) - for _, opt := range opts { - db = opt(db) - } - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&users).Error - return count, users, err -} - -func (h *HostRepo) WithByInfo(info string) DBOption { - return func(g *gorm.DB) *gorm.DB { - if len(info) == 0 { - return g - } - infoStr := "%" + info + "%" - return g.Where("name LIKE ? OR addr LIKE ?", infoStr, infoStr) - } -} - -func (h *HostRepo) WithByPort(port uint) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("port = ?", port) - } -} -func (h *HostRepo) WithByUser(user string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("user = ?", user) - } -} -func (h *HostRepo) WithByAddr(addr string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("addr = ?", addr) - } -} -func (h *HostRepo) WithByGroup(group string) DBOption { - return func(g *gorm.DB) *gorm.DB { - if len(group) == 0 { - return g - } - return g.Where("group_belong = ?", group) - } -} - -func (h *HostRepo) Create(host *model.Host) error { - return global.DB.Create(host).Error -} - -func (h *HostRepo) Update(id uint, vars map[string]interface{}) error { - return global.DB.Model(&model.Host{}).Where("id = ?", id).Updates(vars).Error -} - -func (h *HostRepo) Delete(opts ...DBOption) error { - db := global.DB - for _, opt := range opts { - db = opt(db) - } - return db.Delete(&model.Host{}).Error -} - -func (h *HostRepo) GetFirewallRecord(opts ...DBOption) (model.Firewall, error) { - var firewall model.Firewall - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.First(&firewall).Error - return firewall, err -} - -func (h *HostRepo) ListFirewallRecord() ([]model.Firewall, error) { - var datas []model.Firewall - if err := global.DB.Find(&datas).Error; err != nil { - return datas, nil - } - return datas, nil -} - -func (h *HostRepo) SaveFirewallRecord(firewall *model.Firewall) error { - if firewall.ID != 0 { - return global.DB.Save(firewall).Error - } - var data model.Firewall - if firewall.Type == "port" { - _ = global.DB.Where("type = ? AND port = ? AND protocol = ? AND address = ? AND strategy = ?", "port", firewall.Port, firewall.Protocol, firewall.Address, firewall.Strategy).First(&data) - if data.ID != 0 { - firewall.ID = data.ID - } - } else { - _ = global.DB.Where("type = ? AND address = ? AND strategy = ?", "address", firewall.Address, firewall.Strategy).First(&data) - if data.ID != 0 { - firewall.ID = data.ID - } - } - return global.DB.Save(firewall).Error -} - -func (h *HostRepo) DeleteFirewallRecordByID(id uint) error { - return global.DB.Where("id = ?", id).Delete(&model.Firewall{}).Error -} - -func (h *HostRepo) DeleteFirewallRecord(fType, port, protocol, address, strategy string) error { - return global.DB.Where("type = ? AND port = ? AND protocol = ? AND address = ? AND strategy = ?", fType, port, protocol, address, strategy).Delete(&model.Firewall{}).Error -} diff --git a/backend/app/repo/image_repo.go b/backend/app/repo/image_repo.go deleted file mode 100644 index 79e7e95c9..000000000 --- a/backend/app/repo/image_repo.go +++ /dev/null @@ -1,71 +0,0 @@ -package repo - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" -) - -type ImageRepoRepo struct{} - -type IImageRepoRepo interface { - Get(opts ...DBOption) (model.ImageRepo, error) - Page(limit, offset int, opts ...DBOption) (int64, []model.ImageRepo, error) - List(opts ...DBOption) ([]model.ImageRepo, error) - Create(imageRepo *model.ImageRepo) error - Update(id uint, vars map[string]interface{}) error - Delete(opts ...DBOption) error -} - -func NewIImageRepoRepo() IImageRepoRepo { - return &ImageRepoRepo{} -} - -func (u *ImageRepoRepo) Get(opts ...DBOption) (model.ImageRepo, error) { - var imageRepo model.ImageRepo - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.First(&imageRepo).Error - return imageRepo, err -} - -func (u *ImageRepoRepo) Page(page, size int, opts ...DBOption) (int64, []model.ImageRepo, error) { - var ops []model.ImageRepo - db := global.DB.Model(&model.ImageRepo{}) - for _, opt := range opts { - db = opt(db) - } - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&ops).Error - return count, ops, err -} - -func (u *ImageRepoRepo) List(opts ...DBOption) ([]model.ImageRepo, error) { - var ops []model.ImageRepo - db := global.DB.Model(&model.ImageRepo{}) - for _, opt := range opts { - db = opt(db) - } - count := int64(0) - db = db.Count(&count) - err := db.Find(&ops).Error - return ops, err -} - -func (u *ImageRepoRepo) Create(imageRepo *model.ImageRepo) error { - return global.DB.Create(imageRepo).Error -} - -func (u *ImageRepoRepo) Update(id uint, vars map[string]interface{}) error { - return global.DB.Model(&model.ImageRepo{}).Where("id = ?", id).Updates(vars).Error -} - -func (u *ImageRepoRepo) Delete(opts ...DBOption) error { - db := global.DB - for _, opt := range opts { - db = opt(db) - } - return db.Delete(&model.ImageRepo{}).Error -} diff --git a/backend/app/repo/php_extensions.go b/backend/app/repo/php_extensions.go deleted file mode 100644 index 81da5f364..000000000 --- a/backend/app/repo/php_extensions.go +++ /dev/null @@ -1,59 +0,0 @@ -package repo - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" -) - -type PHPExtensionsRepo struct { -} - -type IPHPExtensionsRepo interface { - Page(page, size int, opts ...DBOption) (int64, []model.PHPExtensions, error) - Save(extension *model.PHPExtensions) error - Create(extension *model.PHPExtensions) error - GetFirst(opts ...DBOption) (model.PHPExtensions, error) - DeleteBy(opts ...DBOption) error - List() ([]model.PHPExtensions, error) -} - -func NewIPHPExtensionsRepo() IPHPExtensionsRepo { - return &PHPExtensionsRepo{} -} - -func (p *PHPExtensionsRepo) Page(page, size int, opts ...DBOption) (int64, []model.PHPExtensions, error) { - var ( - phpExtensions []model.PHPExtensions - ) - db := getDb(opts...).Model(&model.PHPExtensions{}) - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&phpExtensions).Error - return count, phpExtensions, err -} - -func (p *PHPExtensionsRepo) List() ([]model.PHPExtensions, error) { - var ( - phpExtensions []model.PHPExtensions - ) - err := getDb().Model(&model.PHPExtensions{}).Find(&phpExtensions).Error - return phpExtensions, err -} - -func (p *PHPExtensionsRepo) Save(extension *model.PHPExtensions) error { - return getDb().Save(&extension).Error -} - -func (p *PHPExtensionsRepo) Create(extension *model.PHPExtensions) error { - return getDb().Create(&extension).Error -} - -func (p *PHPExtensionsRepo) GetFirst(opts ...DBOption) (model.PHPExtensions, error) { - var extension model.PHPExtensions - db := getDb(opts...).Model(&model.PHPExtensions{}) - err := db.First(&extension).Error - return extension, err -} - -func (p *PHPExtensionsRepo) DeleteBy(opts ...DBOption) error { - return getDb(opts...).Delete(&model.PHPExtensions{}).Error -} diff --git a/backend/app/repo/runtime.go b/backend/app/repo/runtime.go deleted file mode 100644 index 489743c62..000000000 --- a/backend/app/repo/runtime.go +++ /dev/null @@ -1,107 +0,0 @@ -package repo - -import ( - "context" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm" -) - -type RuntimeRepo struct { -} - -type IRuntimeRepo interface { - WithName(name string) DBOption - WithImage(image string) DBOption - WithNotId(id uint) DBOption - WithStatus(status string) DBOption - WithDetailId(id uint) DBOption - WithPort(port int) DBOption - Page(page, size int, opts ...DBOption) (int64, []model.Runtime, error) - Create(ctx context.Context, runtime *model.Runtime) error - Save(runtime *model.Runtime) error - DeleteBy(opts ...DBOption) error - GetFirst(opts ...DBOption) (*model.Runtime, error) - List(opts ...DBOption) ([]model.Runtime, error) -} - -func NewIRunTimeRepo() IRuntimeRepo { - return &RuntimeRepo{} -} - -func (r *RuntimeRepo) WithName(name string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("name = ?", name) - } -} - -func (r *RuntimeRepo) WithStatus(status string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("status = ?", status) - } -} - -func (r *RuntimeRepo) WithImage(image string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("image = ?", image) - } -} - -func (r *RuntimeRepo) WithDetailId(id uint) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("app_detail_id = ?", id) - } -} - -func (r *RuntimeRepo) WithNotId(id uint) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("id != ?", id) - } -} - -func (r *RuntimeRepo) WithPort(port int) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("port = ?", port) - } -} - -func (r *RuntimeRepo) Page(page, size int, opts ...DBOption) (int64, []model.Runtime, error) { - var runtimes []model.Runtime - db := getDb(opts...).Model(&model.Runtime{}) - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&runtimes).Error - return count, runtimes, err -} - -func (r *RuntimeRepo) List(opts ...DBOption) ([]model.Runtime, error) { - var runtimes []model.Runtime - db := global.DB.Model(&model.Runtime{}) - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&runtimes).Error - return runtimes, err -} - -func (r *RuntimeRepo) Create(ctx context.Context, runtime *model.Runtime) error { - db := getTx(ctx).Model(&model.Runtime{}) - return db.Create(&runtime).Error -} - -func (r *RuntimeRepo) Save(runtime *model.Runtime) error { - return getDb().Save(&runtime).Error -} - -func (r *RuntimeRepo) DeleteBy(opts ...DBOption) error { - return getDb(opts...).Delete(&model.Runtime{}).Error -} - -func (r *RuntimeRepo) GetFirst(opts ...DBOption) (*model.Runtime, error) { - var runtime model.Runtime - if err := getDb(opts...).First(&runtime).Error; err != nil { - return nil, err - } - return &runtime, nil -} diff --git a/backend/app/repo/setting.go b/backend/app/repo/setting.go deleted file mode 100644 index c5453189f..000000000 --- a/backend/app/repo/setting.go +++ /dev/null @@ -1,87 +0,0 @@ -package repo - -import ( - "time" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm" -) - -type SettingRepo struct{} - -type ISettingRepo interface { - GetList(opts ...DBOption) ([]model.Setting, error) - Get(opts ...DBOption) (model.Setting, error) - Create(key, value string) error - Update(key, value string) error - WithByKey(key string) DBOption - - CreateMonitorBase(model model.MonitorBase) error - BatchCreateMonitorIO(ioList []model.MonitorIO) error - BatchCreateMonitorNet(ioList []model.MonitorNetwork) error - DelMonitorBase(timeForDelete time.Time) error - DelMonitorIO(timeForDelete time.Time) error - DelMonitorNet(timeForDelete time.Time) error -} - -func NewISettingRepo() ISettingRepo { - return &SettingRepo{} -} - -func (u *SettingRepo) GetList(opts ...DBOption) ([]model.Setting, error) { - var settings []model.Setting - db := global.DB.Model(&model.Setting{}) - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&settings).Error - return settings, err -} - -func (u *SettingRepo) Create(key, value string) error { - setting := &model.Setting{ - Key: key, - Value: value, - } - return global.DB.Create(setting).Error -} - -func (u *SettingRepo) Get(opts ...DBOption) (model.Setting, error) { - var settings model.Setting - db := global.DB.Model(&model.Setting{}) - for _, opt := range opts { - db = opt(db) - } - err := db.First(&settings).Error - return settings, err -} - -func (c *SettingRepo) WithByKey(key string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("key = ?", key) - } -} - -func (u *SettingRepo) Update(key, value string) error { - return global.DB.Model(&model.Setting{}).Where("key = ?", key).Updates(map[string]interface{}{"value": value}).Error -} - -func (u *SettingRepo) CreateMonitorBase(model model.MonitorBase) error { - return global.MonitorDB.Create(&model).Error -} -func (u *SettingRepo) BatchCreateMonitorIO(ioList []model.MonitorIO) error { - return global.MonitorDB.CreateInBatches(ioList, len(ioList)).Error -} -func (u *SettingRepo) BatchCreateMonitorNet(ioList []model.MonitorNetwork) error { - return global.MonitorDB.CreateInBatches(ioList, len(ioList)).Error -} -func (u *SettingRepo) DelMonitorBase(timeForDelete time.Time) error { - return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorBase{}).Error -} -func (u *SettingRepo) DelMonitorIO(timeForDelete time.Time) error { - return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorIO{}).Error -} -func (u *SettingRepo) DelMonitorNet(timeForDelete time.Time) error { - return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorNetwork{}).Error -} diff --git a/backend/app/repo/snapshot.go b/backend/app/repo/snapshot.go deleted file mode 100644 index 0b6eec6f8..000000000 --- a/backend/app/repo/snapshot.go +++ /dev/null @@ -1,105 +0,0 @@ -package repo - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" -) - -type ISnapshotRepo interface { - Get(opts ...DBOption) (model.Snapshot, error) - GetList(opts ...DBOption) ([]model.Snapshot, error) - Create(snap *model.Snapshot) error - Update(id uint, vars map[string]interface{}) error - Page(limit, offset int, opts ...DBOption) (int64, []model.Snapshot, error) - Delete(opts ...DBOption) error - - GetStatus(snapID uint) (model.SnapshotStatus, error) - GetStatusList(opts ...DBOption) ([]model.SnapshotStatus, error) - CreateStatus(snap *model.SnapshotStatus) error - DeleteStatus(snapID uint) error - UpdateStatus(id uint, vars map[string]interface{}) error -} - -func NewISnapshotRepo() ISnapshotRepo { - return &SnapshotRepo{} -} - -type SnapshotRepo struct{} - -func (u *SnapshotRepo) Get(opts ...DBOption) (model.Snapshot, error) { - var Snapshot model.Snapshot - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.First(&Snapshot).Error - return Snapshot, err -} - -func (u *SnapshotRepo) GetList(opts ...DBOption) ([]model.Snapshot, error) { - var snaps []model.Snapshot - db := global.DB.Model(&model.Snapshot{}) - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&snaps).Error - return snaps, err -} - -func (u *SnapshotRepo) Page(page, size int, opts ...DBOption) (int64, []model.Snapshot, error) { - var users []model.Snapshot - db := global.DB.Model(&model.Snapshot{}) - for _, opt := range opts { - db = opt(db) - } - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&users).Error - return count, users, err -} - -func (u *SnapshotRepo) Create(Snapshot *model.Snapshot) error { - return global.DB.Create(Snapshot).Error -} - -func (u *SnapshotRepo) Update(id uint, vars map[string]interface{}) error { - return global.DB.Model(&model.Snapshot{}).Where("id = ?", id).Updates(vars).Error -} - -func (u *SnapshotRepo) Delete(opts ...DBOption) error { - db := global.DB - for _, opt := range opts { - db = opt(db) - } - return db.Delete(&model.Snapshot{}).Error -} - -func (u *SnapshotRepo) GetStatus(snapID uint) (model.SnapshotStatus, error) { - var data model.SnapshotStatus - if err := global.DB.Where("snap_id = ?", snapID).First(&data).Error; err != nil { - return data, err - } - return data, nil -} - -func (u *SnapshotRepo) GetStatusList(opts ...DBOption) ([]model.SnapshotStatus, error) { - var status []model.SnapshotStatus - db := global.DB.Model(&model.SnapshotStatus{}) - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&status).Error - return status, err -} - -func (u *SnapshotRepo) CreateStatus(snap *model.SnapshotStatus) error { - return global.DB.Create(snap).Error -} - -func (u *SnapshotRepo) DeleteStatus(snapID uint) error { - return global.DB.Where("snap_id = ?", snapID).Delete(&model.SnapshotStatus{}).Error -} - -func (u *SnapshotRepo) UpdateStatus(id uint, vars map[string]interface{}) error { - return global.DB.Model(&model.SnapshotStatus{}).Where("id = ?", id).Updates(vars).Error -} diff --git a/backend/app/repo/tag.go b/backend/app/repo/tag.go deleted file mode 100644 index 122792c14..000000000 --- a/backend/app/repo/tag.go +++ /dev/null @@ -1,62 +0,0 @@ -package repo - -import ( - "context" - "github.com/1Panel-dev/1Panel/backend/app/model" -) - -type TagRepo struct { -} - -type ITagRepo interface { - BatchCreate(ctx context.Context, tags []*model.Tag) error - DeleteAll(ctx context.Context) error - All() ([]model.Tag, error) - GetByIds(ids []uint) ([]model.Tag, error) - GetByKeys(keys []string) ([]model.Tag, error) - GetByAppId(appId uint) ([]model.Tag, error) -} - -func NewITagRepo() ITagRepo { - return &TagRepo{} -} - -func (t TagRepo) BatchCreate(ctx context.Context, tags []*model.Tag) error { - return getTx(ctx).Create(&tags).Error -} - -func (t TagRepo) DeleteAll(ctx context.Context) error { - return getTx(ctx).Where("1 = 1 ").Delete(&model.Tag{}).Error -} - -func (t TagRepo) All() ([]model.Tag, error) { - var tags []model.Tag - if err := getDb().Where("1 = 1 ").Order("sort asc").Find(&tags).Error; err != nil { - return nil, err - } - return tags, nil -} - -func (t TagRepo) GetByIds(ids []uint) ([]model.Tag, error) { - var tags []model.Tag - if err := getDb().Where("id in (?)", ids).Find(&tags).Error; err != nil { - return nil, err - } - return tags, nil -} - -func (t TagRepo) GetByKeys(keys []string) ([]model.Tag, error) { - var tags []model.Tag - if err := getDb().Where("key in (?)", keys).Find(&tags).Error; err != nil { - return nil, err - } - return tags, nil -} - -func (t TagRepo) GetByAppId(appId uint) ([]model.Tag, error) { - var tags []model.Tag - if err := getDb().Where("id in (select tag_id from app_tags where app_id = ?)", appId).Find(&tags).Error; err != nil { - return nil, err - } - return tags, nil -} diff --git a/backend/app/repo/website.go b/backend/app/repo/website.go deleted file mode 100644 index 50f453ac1..000000000 --- a/backend/app/repo/website.go +++ /dev/null @@ -1,145 +0,0 @@ -package repo - -import ( - "context" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm" - "gorm.io/gorm/clause" -) - -type IWebsiteRepo interface { - WithAppInstallId(appInstallId uint) DBOption - WithDomain(domain string) DBOption - WithAlias(alias string) DBOption - WithWebsiteSSLID(sslId uint) DBOption - WithGroupID(groupId uint) DBOption - WithDefaultServer() DBOption - WithDomainLike(domain string) DBOption - WithRuntimeID(runtimeID uint) DBOption - WithIDs(ids []uint) DBOption - Page(page, size int, opts ...DBOption) (int64, []model.Website, error) - List(opts ...DBOption) ([]model.Website, error) - GetFirst(opts ...DBOption) (model.Website, error) - GetBy(opts ...DBOption) ([]model.Website, error) - Save(ctx context.Context, app *model.Website) error - SaveWithoutCtx(app *model.Website) error - DeleteBy(ctx context.Context, opts ...DBOption) error - Create(ctx context.Context, app *model.Website) error - DeleteAll(ctx context.Context) error -} - -func NewIWebsiteRepo() IWebsiteRepo { - return &WebsiteRepo{} -} - -type WebsiteRepo struct { -} - -func (w *WebsiteRepo) WithAppInstallId(appInstallID uint) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("app_install_id = ?", appInstallID) - } -} - -func (w *WebsiteRepo) WithIDs(ids []uint) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("id in (?)", ids) - } -} - -func (w *WebsiteRepo) WithRuntimeID(runtimeID uint) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("runtime_id = ?", runtimeID) - } -} - -func (w *WebsiteRepo) WithDomain(domain string) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("primary_domain = ?", domain) - } -} - -func (w *WebsiteRepo) WithDomainLike(domain string) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("primary_domain like ?", "%"+domain+"%") - } -} - -func (w *WebsiteRepo) WithAlias(alias string) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("alias = ?", alias) - } -} - -func (w *WebsiteRepo) WithWebsiteSSLID(sslId uint) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("website_ssl_id = ?", sslId) - } -} - -func (w *WebsiteRepo) WithGroupID(groupId uint) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("website_group_id = ?", groupId) - } -} - -func (w *WebsiteRepo) WithDefaultServer() DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("default_server = 1") - } -} - -func (w *WebsiteRepo) Page(page, size int, opts ...DBOption) (int64, []model.Website, error) { - var websites []model.Website - db := getDb(opts...).Model(&model.Website{}) - count := int64(0) - db = db.Count(&count) - err := db.Debug().Limit(size).Offset(size * (page - 1)).Preload("WebsiteSSL").Find(&websites).Error - return count, websites, err -} - -func (w *WebsiteRepo) List(opts ...DBOption) ([]model.Website, error) { - var websites []model.Website - err := getDb(opts...).Model(&model.Website{}).Preload("Domains").Preload("WebsiteSSL").Find(&websites).Error - return websites, err -} - -func (w *WebsiteRepo) GetFirst(opts ...DBOption) (model.Website, error) { - var website model.Website - db := getDb(opts...).Model(&model.Website{}) - if err := db.Preload("Domains").First(&website).Error; err != nil { - return website, err - } - return website, nil -} - -func (w *WebsiteRepo) GetBy(opts ...DBOption) ([]model.Website, error) { - var websites []model.Website - db := getDb(opts...).Model(&model.Website{}) - if err := db.Find(&websites).Error; err != nil { - return websites, err - } - return websites, nil -} - -func (w *WebsiteRepo) Create(ctx context.Context, app *model.Website) error { - return getTx(ctx).Omit(clause.Associations).Create(app).Error -} - -func (w *WebsiteRepo) Save(ctx context.Context, app *model.Website) error { - return getTx(ctx).Omit(clause.Associations).Save(app).Error -} - -func (w *WebsiteRepo) SaveWithoutCtx(website *model.Website) error { - return global.DB.Save(website).Error -} - -func (w *WebsiteRepo) DeleteBy(ctx context.Context, opts ...DBOption) error { - return getTx(ctx, opts...).Delete(&model.Website{}).Error -} - -func (w *WebsiteRepo) DeleteAll(ctx context.Context) error { - return getTx(ctx).Where("1 = 1 ").Delete(&model.Website{}).Error -} diff --git a/backend/app/repo/website_acme_account.go b/backend/app/repo/website_acme_account.go deleted file mode 100644 index c2ebee637..000000000 --- a/backend/app/repo/website_acme_account.go +++ /dev/null @@ -1,64 +0,0 @@ -package repo - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" - "gorm.io/gorm" -) - -type IAcmeAccountRepo interface { - Page(page, size int, opts ...DBOption) (int64, []model.WebsiteAcmeAccount, error) - GetFirst(opts ...DBOption) (*model.WebsiteAcmeAccount, error) - Create(account model.WebsiteAcmeAccount) error - Save(account model.WebsiteAcmeAccount) error - DeleteBy(opts ...DBOption) error - WithEmail(email string) DBOption - WithType(acType string) DBOption -} - -func NewIAcmeAccountRepo() IAcmeAccountRepo { - return &WebsiteAcmeAccountRepo{} -} - -type WebsiteAcmeAccountRepo struct { -} - -func (w *WebsiteAcmeAccountRepo) WithEmail(email string) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("email = ?", email) - } -} -func (w *WebsiteAcmeAccountRepo) WithType(acType string) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("type = ?", acType) - } -} - -func (w *WebsiteAcmeAccountRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebsiteAcmeAccount, error) { - var accounts []model.WebsiteAcmeAccount - db := getDb(opts...).Model(&model.WebsiteAcmeAccount{}) - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&accounts).Error - return count, accounts, err -} - -func (w *WebsiteAcmeAccountRepo) GetFirst(opts ...DBOption) (*model.WebsiteAcmeAccount, error) { - var account model.WebsiteAcmeAccount - db := getDb(opts...).Model(&model.WebsiteAcmeAccount{}) - if err := db.First(&account).Error; err != nil { - return nil, err - } - return &account, nil -} - -func (w *WebsiteAcmeAccountRepo) Create(account model.WebsiteAcmeAccount) error { - return getDb().Create(&account).Error -} - -func (w *WebsiteAcmeAccountRepo) Save(account model.WebsiteAcmeAccount) error { - return getDb().Save(&account).Error -} - -func (w *WebsiteAcmeAccountRepo) DeleteBy(opts ...DBOption) error { - return getDb(opts...).Debug().Delete(&model.WebsiteAcmeAccount{}).Error -} diff --git a/backend/app/repo/website_ca.go b/backend/app/repo/website_ca.go deleted file mode 100644 index d9c9ae5f1..000000000 --- a/backend/app/repo/website_ca.go +++ /dev/null @@ -1,54 +0,0 @@ -package repo - -import ( - "context" - "github.com/1Panel-dev/1Panel/backend/app/model" -) - -type WebsiteCARepo struct { -} - -func NewIWebsiteCARepo() IWebsiteCARepo { - return &WebsiteCARepo{} -} - -type IWebsiteCARepo interface { - Page(page, size int, opts ...DBOption) (int64, []model.WebsiteCA, error) - GetFirst(opts ...DBOption) (model.WebsiteCA, error) - List(opts ...DBOption) ([]model.WebsiteCA, error) - Create(ctx context.Context, ca *model.WebsiteCA) error - DeleteBy(opts ...DBOption) error -} - -func (w WebsiteCARepo) Page(page, size int, opts ...DBOption) (int64, []model.WebsiteCA, error) { - var caList []model.WebsiteCA - db := getDb(opts...).Model(&model.WebsiteCA{}) - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&caList).Error - return count, caList, err -} - -func (w WebsiteCARepo) GetFirst(opts ...DBOption) (model.WebsiteCA, error) { - var ca model.WebsiteCA - db := getDb(opts...).Model(&model.WebsiteCA{}) - if err := db.First(&ca).Error; err != nil { - return ca, err - } - return ca, nil -} - -func (w WebsiteCARepo) List(opts ...DBOption) ([]model.WebsiteCA, error) { - var caList []model.WebsiteCA - db := getDb(opts...).Model(&model.WebsiteCA{}) - err := db.Find(&caList).Error - return caList, err -} - -func (w WebsiteCARepo) Create(ctx context.Context, ca *model.WebsiteCA) error { - return getTx(ctx).Create(ca).Error -} - -func (w WebsiteCARepo) DeleteBy(opts ...DBOption) error { - return getDb(opts...).Delete(&model.WebsiteCA{}).Error -} diff --git a/backend/app/repo/website_dns_account.go b/backend/app/repo/website_dns_account.go deleted file mode 100644 index 56811b975..000000000 --- a/backend/app/repo/website_dns_account.go +++ /dev/null @@ -1,60 +0,0 @@ -package repo - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" -) - -type WebsiteDnsAccountRepo struct { -} - -type IWebsiteDnsAccountRepo interface { - Page(page, size int, opts ...DBOption) (int64, []model.WebsiteDnsAccount, error) - GetFirst(opts ...DBOption) (*model.WebsiteDnsAccount, error) - List(opts ...DBOption) ([]model.WebsiteDnsAccount, error) - Create(account model.WebsiteDnsAccount) error - Save(account model.WebsiteDnsAccount) error - DeleteBy(opts ...DBOption) error -} - -func NewIWebsiteDnsAccountRepo() IWebsiteDnsAccountRepo { - return &WebsiteDnsAccountRepo{} -} - -func (w WebsiteDnsAccountRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebsiteDnsAccount, error) { - var accounts []model.WebsiteDnsAccount - db := getDb(opts...).Model(&model.WebsiteDnsAccount{}) - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&accounts).Error - return count, accounts, err -} - -func (w WebsiteDnsAccountRepo) GetFirst(opts ...DBOption) (*model.WebsiteDnsAccount, error) { - var account model.WebsiteDnsAccount - db := getDb(opts...).Model(&model.WebsiteDnsAccount{}) - if err := db.First(&account).Error; err != nil { - return nil, err - } - return &account, nil -} - -func (w WebsiteDnsAccountRepo) List(opts ...DBOption) ([]model.WebsiteDnsAccount, error) { - var accounts []model.WebsiteDnsAccount - db := getDb(opts...).Model(&model.WebsiteDnsAccount{}) - if err := db.Find(&accounts).Error; err != nil { - return nil, err - } - return accounts, nil -} - -func (w WebsiteDnsAccountRepo) Create(account model.WebsiteDnsAccount) error { - return getDb().Create(&account).Error -} - -func (w WebsiteDnsAccountRepo) Save(account model.WebsiteDnsAccount) error { - return getDb().Save(&account).Error -} - -func (w WebsiteDnsAccountRepo) DeleteBy(opts ...DBOption) error { - return getDb(opts...).Delete(&model.WebsiteDnsAccount{}).Error -} diff --git a/backend/app/repo/website_domain.go b/backend/app/repo/website_domain.go deleted file mode 100644 index fa5c45560..000000000 --- a/backend/app/repo/website_domain.go +++ /dev/null @@ -1,98 +0,0 @@ -package repo - -import ( - "context" - "github.com/1Panel-dev/1Panel/backend/app/model" - "gorm.io/gorm" - "gorm.io/gorm/clause" -) - -type WebsiteDomainRepo struct { -} - -type IWebsiteDomainRepo interface { - WithWebsiteId(websiteId uint) DBOption - WithPort(port int) DBOption - WithDomain(domain string) DBOption - WithDomainLike(domain string) DBOption - Page(page, size int, opts ...DBOption) (int64, []model.WebsiteDomain, error) - GetFirst(opts ...DBOption) (model.WebsiteDomain, error) - GetBy(opts ...DBOption) ([]model.WebsiteDomain, error) - BatchCreate(ctx context.Context, domains []model.WebsiteDomain) error - Create(ctx context.Context, app *model.WebsiteDomain) error - Save(ctx context.Context, app *model.WebsiteDomain) error - DeleteBy(ctx context.Context, opts ...DBOption) error - DeleteAll(ctx context.Context) error -} - -func NewIWebsiteDomainRepo() IWebsiteDomainRepo { - return &WebsiteDomainRepo{} -} - -func (w WebsiteDomainRepo) WithWebsiteId(websiteId uint) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("website_id = ?", websiteId) - } -} - -func (w WebsiteDomainRepo) WithPort(port int) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("port = ?", port) - } -} -func (w WebsiteDomainRepo) WithDomain(domain string) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("domain = ?", domain) - } -} -func (w WebsiteDomainRepo) WithDomainLike(domain string) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("domain like ?", "%"+domain+"%") - } -} -func (w WebsiteDomainRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebsiteDomain, error) { - var domains []model.WebsiteDomain - db := getDb(opts...).Model(&model.WebsiteDomain{}) - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&domains).Error - return count, domains, err -} - -func (w WebsiteDomainRepo) GetFirst(opts ...DBOption) (model.WebsiteDomain, error) { - var domain model.WebsiteDomain - db := getDb(opts...).Model(&model.WebsiteDomain{}) - if err := db.First(&domain).Error; err != nil { - return domain, err - } - return domain, nil -} - -func (w WebsiteDomainRepo) GetBy(opts ...DBOption) ([]model.WebsiteDomain, error) { - var domains []model.WebsiteDomain - db := getDb(opts...).Model(&model.WebsiteDomain{}) - if err := db.Find(&domains).Error; err != nil { - return domains, err - } - return domains, nil -} - -func (w WebsiteDomainRepo) BatchCreate(ctx context.Context, domains []model.WebsiteDomain) error { - return getTx(ctx).Model(&model.WebsiteDomain{}).Create(&domains).Error -} - -func (w WebsiteDomainRepo) Create(ctx context.Context, app *model.WebsiteDomain) error { - return getTx(ctx).Omit(clause.Associations).Create(app).Error -} - -func (w WebsiteDomainRepo) Save(ctx context.Context, app *model.WebsiteDomain) error { - return getTx(ctx).Omit(clause.Associations).Save(app).Error -} - -func (w WebsiteDomainRepo) DeleteBy(ctx context.Context, opts ...DBOption) error { - return getTx(ctx, opts...).Delete(&model.WebsiteDomain{}).Error -} - -func (w WebsiteDomainRepo) DeleteAll(ctx context.Context) error { - return getTx(ctx).Where("1 = 1 ").Delete(&model.WebsiteDomain{}).Error -} diff --git a/backend/app/repo/website_ssl.go b/backend/app/repo/website_ssl.go deleted file mode 100644 index bac38543b..000000000 --- a/backend/app/repo/website_ssl.go +++ /dev/null @@ -1,99 +0,0 @@ -package repo - -import ( - "context" - "github.com/1Panel-dev/1Panel/backend/app/model" - "gorm.io/gorm" -) - -func NewISSLRepo() ISSLRepo { - return &WebsiteSSLRepo{} -} - -type ISSLRepo interface { - WithByAlias(alias string) DBOption - WithByAcmeAccountId(acmeAccountId uint) DBOption - WithByDnsAccountId(dnsAccountId uint) DBOption - WithByCAID(caID uint) DBOption - Page(page, size int, opts ...DBOption) (int64, []model.WebsiteSSL, error) - GetFirst(opts ...DBOption) (*model.WebsiteSSL, error) - List(opts ...DBOption) ([]model.WebsiteSSL, error) - Create(ctx context.Context, ssl *model.WebsiteSSL) error - Save(ssl *model.WebsiteSSL) error - DeleteBy(opts ...DBOption) error - SaveByMap(ssl *model.WebsiteSSL, params map[string]interface{}) error -} - -type WebsiteSSLRepo struct { -} - -func (w WebsiteSSLRepo) WithByAlias(alias string) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("alias = ?", alias) - } -} - -func (w WebsiteSSLRepo) WithByAcmeAccountId(acmeAccountId uint) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("acme_account_id = ?", acmeAccountId) - } -} - -func (w WebsiteSSLRepo) WithByDnsAccountId(dnsAccountId uint) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("dns_account_id = ?", dnsAccountId) - } -} - -func (w WebsiteSSLRepo) WithByCAID(caID uint) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("ca_id = ?", caID) - } -} - -func (w WebsiteSSLRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebsiteSSL, error) { - var sslList []model.WebsiteSSL - db := getDb(opts...).Model(&model.WebsiteSSL{}) - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Preload("AcmeAccount").Preload("DnsAccount").Preload("Websites").Find(&sslList).Error - return count, sslList, err -} - -func (w WebsiteSSLRepo) GetFirst(opts ...DBOption) (*model.WebsiteSSL, error) { - var website *model.WebsiteSSL - db := getDb(opts...).Model(&model.WebsiteSSL{}) - if err := db.Preload("AcmeAccount").Preload("DnsAccount").First(&website).Error; err != nil { - return website, err - } - return website, nil -} - -func (w WebsiteSSLRepo) List(opts ...DBOption) ([]model.WebsiteSSL, error) { - var websites []model.WebsiteSSL - db := getDb(opts...).Model(&model.WebsiteSSL{}) - if err := db.Preload("AcmeAccount").Preload("DnsAccount").Find(&websites).Error; err != nil { - return websites, err - } - return websites, nil -} - -func (w WebsiteSSLRepo) Create(ctx context.Context, ssl *model.WebsiteSSL) error { - return getTx(ctx).Create(ssl).Error -} - -func (w WebsiteSSLRepo) Save(ssl *model.WebsiteSSL) error { - return getDb().Model(&model.WebsiteSSL{BaseModel: model.BaseModel{ - ID: ssl.ID, - }}).Save(&ssl).Error -} - -func (w WebsiteSSLRepo) SaveByMap(ssl *model.WebsiteSSL, params map[string]interface{}) error { - return getDb().Model(&model.WebsiteSSL{BaseModel: model.BaseModel{ - ID: ssl.ID, - }}).Updates(params).Error -} - -func (w WebsiteSSLRepo) DeleteBy(opts ...DBOption) error { - return getDb(opts...).Delete(&model.WebsiteSSL{}).Error -} diff --git a/backend/app/service/app.go b/backend/app/service/app.go deleted file mode 100644 index 2f557060d..000000000 --- a/backend/app/service/app.go +++ /dev/null @@ -1,1028 +0,0 @@ -package service - -import ( - "context" - "encoding/base64" - "encoding/json" - "fmt" - "net/http" - "os" - "path/filepath" - "reflect" - "strconv" - "strings" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/app/repo" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/i18n" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/1Panel-dev/1Panel/backend/utils/files" - http2 "github.com/1Panel-dev/1Panel/backend/utils/http" - httpUtil "github.com/1Panel-dev/1Panel/backend/utils/http" - "github.com/1Panel-dev/1Panel/backend/utils/xpack" - "gopkg.in/yaml.v3" -) - -type AppService struct { -} - -type IAppService interface { - PageApp(req request.AppSearch) (interface{}, error) - GetAppTags() ([]response.TagDTO, error) - GetApp(key string) (*response.AppDTO, error) - GetAppDetail(appId uint, version, appType string) (response.AppDetailDTO, error) - Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error) - SyncAppListFromRemote() error - GetAppUpdate() (*response.AppUpdateRes, error) - GetAppDetailByID(id uint) (*response.AppDetailDTO, error) - SyncAppListFromLocal() - GetIgnoredApp() ([]response.IgnoredApp, error) -} - -func NewIAppService() IAppService { - return &AppService{} -} - -func (a AppService) PageApp(req request.AppSearch) (interface{}, error) { - var opts []repo.DBOption - opts = append(opts, appRepo.OrderByRecommend()) - if req.Name != "" { - opts = append(opts, appRepo.WithLikeName(req.Name)) - } - if req.Type != "" { - opts = append(opts, appRepo.WithType(req.Type)) - } - if req.Recommend { - opts = append(opts, appRepo.GetRecommend()) - } - if req.Resource != "" && req.Resource != "all" { - opts = append(opts, appRepo.WithResource(req.Resource)) - } - if len(req.Tags) != 0 { - tags, err := tagRepo.GetByKeys(req.Tags) - if err != nil { - return nil, err - } - var tagIds []uint - for _, t := range tags { - tagIds = append(tagIds, t.ID) - } - appTags, err := appTagRepo.GetByTagIds(tagIds) - if err != nil { - return nil, err - } - var appIds []uint - for _, t := range appTags { - appIds = append(appIds, t.AppId) - } - opts = append(opts, commonRepo.WithIdsIn(appIds)) - } - var res response.AppRes - total, apps, err := appRepo.Page(req.Page, req.PageSize, opts...) - if err != nil { - return nil, err - } - var appDTOs []*response.AppDto - for _, ap := range apps { - ap.ReadMe = "" - ap.Website = "" - ap.Document = "" - ap.Github = "" - appDTO := &response.AppDto{ - ID: ap.ID, - Name: ap.Name, - Key: ap.Key, - Type: ap.Type, - Icon: ap.Icon, - ShortDescZh: ap.ShortDescZh, - ShortDescEn: ap.ShortDescEn, - Resource: ap.Resource, - Limit: ap.Limit, - } - appDTOs = append(appDTOs, appDTO) - appTags, err := appTagRepo.GetByAppId(ap.ID) - if err != nil { - continue - } - var tagIds []uint - for _, at := range appTags { - tagIds = append(tagIds, at.TagId) - } - tags, err := tagRepo.GetByIds(tagIds) - if err != nil { - continue - } - appDTO.Tags = tags - installs, _ := appInstallRepo.ListBy(appInstallRepo.WithAppId(ap.ID)) - appDTO.Installed = len(installs) > 0 - } - res.Items = appDTOs - res.Total = total - - return res, nil -} - -func (a AppService) GetAppTags() ([]response.TagDTO, error) { - tags, err := tagRepo.All() - if err != nil { - return nil, err - } - var res []response.TagDTO - for _, tag := range tags { - res = append(res, response.TagDTO{ - Tag: tag, - }) - } - return res, nil -} - -func (a AppService) GetApp(key string) (*response.AppDTO, error) { - var appDTO response.AppDTO - app, err := appRepo.GetFirst(appRepo.WithKey(key)) - if err != nil { - return nil, err - } - appDTO.App = app - details, err := appDetailRepo.GetBy(appDetailRepo.WithAppId(app.ID)) - if err != nil { - return nil, err - } - var versionsRaw []string - for _, detail := range details { - versionsRaw = append(versionsRaw, detail.Version) - } - appDTO.Versions = common.GetSortedVersions(versionsRaw) - - return &appDTO, nil -} - -func (a AppService) GetAppDetail(appID uint, version, appType string) (response.AppDetailDTO, error) { - var ( - appDetailDTO response.AppDetailDTO - opts []repo.DBOption - ) - opts = append(opts, appDetailRepo.WithAppId(appID), appDetailRepo.WithVersion(version)) - detail, err := appDetailRepo.GetFirst(opts...) - if err != nil { - return appDetailDTO, err - } - appDetailDTO.AppDetail = detail - appDetailDTO.Enable = true - - if appType == "runtime" { - app, err := appRepo.GetFirst(commonRepo.WithByID(appID)) - if err != nil { - return appDetailDTO, err - } - fileOp := files.NewFileOp() - - versionPath := filepath.Join(app.GetAppResourcePath(), detail.Version) - if !fileOp.Stat(versionPath) || detail.Update { - if err = downloadApp(app, detail, nil); err != nil { - return appDetailDTO, err - } - } - switch app.Type { - case constant.RuntimePHP: - buildPath := filepath.Join(versionPath, "build") - paramsPath := filepath.Join(buildPath, "config.json") - if !fileOp.Stat(paramsPath) { - return appDetailDTO, buserr.New(constant.ErrFileNotExist) - } - param, err := fileOp.GetContent(paramsPath) - if err != nil { - return appDetailDTO, err - } - paramMap := make(map[string]interface{}) - if err := json.Unmarshal(param, ¶mMap); err != nil { - return appDetailDTO, err - } - appDetailDTO.Params = paramMap - composePath := filepath.Join(buildPath, "docker-compose.yml") - if !fileOp.Stat(composePath) { - return appDetailDTO, buserr.New(constant.ErrFileNotExist) - } - compose, err := fileOp.GetContent(composePath) - if err != nil { - return appDetailDTO, err - } - composeMap := make(map[string]interface{}) - if err := yaml.Unmarshal(compose, &composeMap); err != nil { - return appDetailDTO, err - } - if service, ok := composeMap["services"]; ok { - servicesMap := service.(map[string]interface{}) - for k := range servicesMap { - appDetailDTO.Image = k - } - } - } - } else { - paramMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(detail.Params), ¶mMap); err != nil { - return appDetailDTO, err - } - appDetailDTO.Params = paramMap - } - - if appDetailDTO.DockerCompose == "" { - filename := filepath.Base(appDetailDTO.DownloadUrl) - dockerComposeUrl := fmt.Sprintf("%s%s", strings.TrimSuffix(appDetailDTO.DownloadUrl, filename), "docker-compose.yml") - statusCode, composeRes, err := httpUtil.HandleGet(dockerComposeUrl, http.MethodGet, constant.TimeOut20s) - if err != nil { - return appDetailDTO, buserr.WithDetail("ErrGetCompose", err.Error(), err) - } - if statusCode > 200 { - return appDetailDTO, buserr.WithDetail("ErrGetCompose", string(composeRes), err) - } - detail.DockerCompose = string(composeRes) - _ = appDetailRepo.Update(context.Background(), detail) - appDetailDTO.DockerCompose = string(composeRes) - } - - appDetailDTO.HostMode = isHostModel(appDetailDTO.DockerCompose) - - app, err := appRepo.GetFirst(commonRepo.WithByID(detail.AppId)) - if err != nil { - return appDetailDTO, err - } - if err := checkLimit(app); err != nil { - appDetailDTO.Enable = false - } - return appDetailDTO, nil -} -func (a AppService) GetAppDetailByID(id uint) (*response.AppDetailDTO, error) { - res := &response.AppDetailDTO{} - appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(id)) - if err != nil { - return nil, err - } - res.AppDetail = appDetail - paramMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(appDetail.Params), ¶mMap); err != nil { - return nil, err - } - res.Params = paramMap - res.HostMode = isHostModel(appDetail.DockerCompose) - return res, nil -} - -func (a AppService) GetIgnoredApp() ([]response.IgnoredApp, error) { - var res []response.IgnoredApp - details, _ := appDetailRepo.GetBy(appDetailRepo.WithIgnored()) - if len(details) == 0 { - return res, nil - } - for _, detail := range details { - app, err := appRepo.GetFirst(commonRepo.WithByID(detail.AppId)) - if err != nil { - return nil, err - } - res = append(res, response.IgnoredApp{ - Name: app.Name, - Version: detail.Version, - DetailID: detail.ID, - Icon: app.Icon, - }) - } - return res, nil -} - -func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (appInstall *model.AppInstall, err error) { - if err = docker.CreateDefaultDockerNetwork(); err != nil { - err = buserr.WithDetail(constant.Err1PanelNetworkFailed, err.Error(), nil) - return - } - if list, _ := appInstallRepo.ListBy(commonRepo.WithByName(req.Name)); len(list) > 0 { - err = buserr.New(constant.ErrAppNameExist) - return - } - var ( - httpPort int - httpsPort int - appDetail model.AppDetail - app model.App - ) - appDetail, err = appDetailRepo.GetFirst(commonRepo.WithByID(req.AppDetailId)) - if err != nil { - return - } - app, err = appRepo.GetFirst(commonRepo.WithByID(appDetail.AppId)) - if err != nil { - return - } - if DatabaseKeys[app.Key] > 0 { - if existDatabases, _ := databaseRepo.GetList(commonRepo.WithByName(req.Name)); len(existDatabases) > 0 { - err = buserr.New(constant.ErrRemoteExist) - return - } - } - for key := range req.Params { - if !strings.Contains(key, "PANEL_APP_PORT") { - continue - } - var port int - if port, err = checkPort(key, req.Params); err == nil { - if key == "PANEL_APP_PORT_HTTP" { - httpPort = port - } - if key == "PANEL_APP_PORT_HTTPS" { - httpsPort = port - } - } else { - return - } - } - - if err = checkRequiredAndLimit(app); err != nil { - return - } - - appInstall = &model.AppInstall{ - Name: req.Name, - AppId: appDetail.AppId, - AppDetailId: appDetail.ID, - Version: appDetail.Version, - Status: constant.Installing, - HttpPort: httpPort, - HttpsPort: httpsPort, - App: app, - } - composeMap := make(map[string]interface{}) - if req.EditCompose { - if err = yaml.Unmarshal([]byte(req.DockerCompose), &composeMap); err != nil { - return - } - } else { - if err = yaml.Unmarshal([]byte(appDetail.DockerCompose), &composeMap); err != nil { - return - } - } - - value, ok := composeMap["services"] - if !ok || value == nil { - err = buserr.New(constant.ErrFileParse) - return - } - servicesMap := value.(map[string]interface{}) - containerName := constant.ContainerPrefix + app.Key + "-" + common.RandStr(4) - if req.Advanced && req.ContainerName != "" { - containerName = req.ContainerName - appInstalls, _ := appInstallRepo.ListBy(appInstallRepo.WithContainerName(containerName)) - if len(appInstalls) > 0 { - err = buserr.New(constant.ErrContainerName) - return - } - containerExist := false - containerExist, err = checkContainerNameIsExist(req.ContainerName, appInstall.GetPath()) - if err != nil { - return - } - if containerExist { - err = buserr.New(constant.ErrContainerName) - return - } - } - req.Params[constant.ContainerName] = containerName - appInstall.ContainerName = containerName - - index := 0 - serviceName := "" - for k := range servicesMap { - serviceName = k - if index > 0 { - continue - } - index++ - } - if app.Limit == 0 && appInstall.Name != serviceName && len(servicesMap) == 1 { - servicesMap[appInstall.Name] = servicesMap[serviceName] - delete(servicesMap, serviceName) - serviceName = appInstall.Name - } - appInstall.ServiceName = serviceName - - if err = addDockerComposeCommonParam(composeMap, appInstall.ServiceName, req.AppContainerConfig, req.Params); err != nil { - return - } - var ( - composeByte []byte - paramByte []byte - ) - - composeByte, err = yaml.Marshal(composeMap) - if err != nil { - return - } - appInstall.DockerCompose = string(composeByte) - - defer func() { - if err != nil { - hErr := handleAppInstallErr(ctx, appInstall) - if hErr != nil { - global.LOG.Errorf("delete app dir error %s", hErr.Error()) - } - } - }() - if hostName, ok := req.Params["PANEL_DB_HOST"]; ok { - database, _ := databaseRepo.Get(commonRepo.WithByName(hostName.(string))) - if !reflect.DeepEqual(database, model.Database{}) { - req.Params["PANEL_DB_HOST"] = database.Address - req.Params["PANEL_DB_PORT"] = database.Port - req.Params["PANEL_DB_HOST_NAME"] = hostName - } - } - paramByte, err = json.Marshal(req.Params) - if err != nil { - return - } - appInstall.Env = string(paramByte) - - if err = appInstallRepo.Create(ctx, appInstall); err != nil { - return - } - if err = createLink(ctx, app, appInstall, req.Params); err != nil { - return - } - go func() { - defer func() { - if err != nil { - appInstall.Status = constant.UpErr - appInstall.Message = err.Error() - _ = appInstallRepo.Save(context.Background(), appInstall) - } - }() - if err = copyData(app, appDetail, appInstall, req); err != nil { - return - } - if err = runScript(appInstall, "init"); err != nil { - return - } - upApp(appInstall, req.PullImage) - }() - go updateToolApp(appInstall) - return -} - -func (a AppService) SyncAppListFromLocal() { - fileOp := files.NewFileOp() - localAppDir := constant.LocalAppResourceDir - if !fileOp.Stat(localAppDir) { - return - } - var ( - err error - dirEntries []os.DirEntry - localApps []model.App - ) - - defer func() { - if err != nil { - global.LOG.Errorf("Sync local app failed %v", err) - } - }() - - global.LOG.Infof("Starting local application synchronization ...") - dirEntries, err = os.ReadDir(localAppDir) - if err != nil { - return - } - for _, dirEntry := range dirEntries { - if dirEntry.IsDir() { - appDir := filepath.Join(localAppDir, dirEntry.Name()) - appDirEntries, err := os.ReadDir(appDir) - if err != nil { - global.LOG.Errorf(i18n.GetMsgWithMap("ErrAppDirNull", map[string]interface{}{"name": dirEntry.Name(), "err": err.Error()})) - continue - } - app, err := handleLocalApp(appDir) - if err != nil { - global.LOG.Errorf(i18n.GetMsgWithMap("LocalAppErr", map[string]interface{}{"name": dirEntry.Name(), "err": err.Error()})) - continue - } - var appDetails []model.AppDetail - for _, appDirEntry := range appDirEntries { - if appDirEntry.IsDir() { - appDetail := model.AppDetail{ - Version: appDirEntry.Name(), - Status: constant.AppNormal, - } - versionDir := filepath.Join(appDir, appDirEntry.Name()) - if err = handleLocalAppDetail(versionDir, &appDetail); err != nil { - global.LOG.Errorf(i18n.GetMsgWithMap("LocalAppVersionErr", map[string]interface{}{"name": app.Name, "version": appDetail.Version, "err": err.Error()})) - continue - } - appDetails = append(appDetails, appDetail) - } - } - if len(appDetails) > 0 { - app.Details = appDetails - localApps = append(localApps, *app) - } else { - global.LOG.Errorf(i18n.GetMsgWithMap("LocalAppVersionNull", map[string]interface{}{"name": app.Name})) - } - } - } - - var ( - newApps []model.App - deleteApps []model.App - updateApps []model.App - oldAppIds []uint - - deleteAppIds []uint - deleteAppDetails []model.AppDetail - newAppDetails []model.AppDetail - updateDetails []model.AppDetail - - appTags []*model.AppTag - ) - - oldApps, _ := appRepo.GetBy(appRepo.WithResource(constant.AppResourceLocal)) - apps := make(map[string]model.App, len(oldApps)) - for _, old := range oldApps { - old.Status = constant.AppTakeDown - apps[old.Key] = old - } - for _, app := range localApps { - if oldApp, ok := apps[app.Key]; ok { - app.ID = oldApp.ID - appDetails := make(map[string]model.AppDetail, len(oldApp.Details)) - for _, old := range oldApp.Details { - old.Status = constant.AppTakeDown - appDetails[old.Version] = old - } - for i, newDetail := range app.Details { - version := newDetail.Version - newDetail.Status = constant.AppNormal - newDetail.AppId = app.ID - oldDetail, exist := appDetails[version] - if exist { - newDetail.ID = oldDetail.ID - delete(appDetails, version) - } - app.Details[i] = newDetail - } - for _, v := range appDetails { - app.Details = append(app.Details, v) - } - } - app.TagsKey = append(app.TagsKey, constant.AppResourceLocal) - apps[app.Key] = app - } - - for _, app := range apps { - if app.ID == 0 { - newApps = append(newApps, app) - } else { - oldAppIds = append(oldAppIds, app.ID) - if app.Status == constant.AppTakeDown { - installs, _ := appInstallRepo.ListBy(appInstallRepo.WithAppId(app.ID)) - if len(installs) > 0 { - updateApps = append(updateApps, app) - continue - } - deleteAppIds = append(deleteAppIds, app.ID) - deleteApps = append(deleteApps, app) - deleteAppDetails = append(deleteAppDetails, app.Details...) - } else { - updateApps = append(updateApps, app) - } - } - - } - - tags, _ := tagRepo.All() - tagMap := make(map[string]uint, len(tags)) - for _, tag := range tags { - tagMap[tag.Key] = tag.ID - } - - tx, ctx := getTxAndContext() - defer tx.Rollback() - if len(newApps) > 0 { - if err = appRepo.BatchCreate(ctx, newApps); err != nil { - return - } - } - for _, update := range updateApps { - if err = appRepo.Save(ctx, &update); err != nil { - return - } - } - if len(deleteApps) > 0 { - if err = appRepo.BatchDelete(ctx, deleteApps); err != nil { - return - } - if err = appDetailRepo.DeleteByAppIds(ctx, deleteAppIds); err != nil { - return - } - } - - if err = appTagRepo.DeleteByAppIds(ctx, oldAppIds); err != nil { - return - } - for _, newApp := range newApps { - if newApp.ID > 0 { - for _, detail := range newApp.Details { - detail.AppId = newApp.ID - newAppDetails = append(newAppDetails, detail) - } - } - } - for _, update := range updateApps { - for _, detail := range update.Details { - if detail.ID == 0 { - detail.AppId = update.ID - newAppDetails = append(newAppDetails, detail) - } else { - if detail.Status == constant.AppNormal { - updateDetails = append(updateDetails, detail) - } else { - deleteAppDetails = append(deleteAppDetails, detail) - } - } - } - } - - allApps := append(newApps, updateApps...) - for _, app := range allApps { - for _, t := range app.TagsKey { - tagId, ok := tagMap[t] - if ok { - appTags = append(appTags, &model.AppTag{ - AppId: app.ID, - TagId: tagId, - }) - } - } - } - - if len(newAppDetails) > 0 { - if err = appDetailRepo.BatchCreate(ctx, newAppDetails); err != nil { - return - } - } - - for _, updateAppDetail := range updateDetails { - if err = appDetailRepo.Update(ctx, updateAppDetail); err != nil { - return - } - } - - if len(deleteAppDetails) > 0 { - if err = appDetailRepo.BatchDelete(ctx, deleteAppDetails); err != nil { - return - } - } - - if len(oldAppIds) > 0 { - if err = appTagRepo.DeleteByAppIds(ctx, oldAppIds); err != nil { - return - } - } - - if len(appTags) > 0 { - if err = appTagRepo.BatchCreate(ctx, appTags); err != nil { - return - } - } - tx.Commit() - global.LOG.Infof("Synchronization of local applications completed") -} - -func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) { - res := &response.AppUpdateRes{ - CanUpdate: false, - } - - versionUrl := fmt.Sprintf("%s/%s/1panel.json.version.txt", global.CONF.System.AppRepo, global.CONF.System.Mode) - _, versionRes, err := http2.HandleGet(versionUrl, http.MethodGet, constant.TimeOut20s) - if err != nil { - return nil, err - } - lastModifiedStr := string(versionRes) - lastModified, err := strconv.Atoi(lastModifiedStr) - if err != nil { - return nil, err - } - setting, err := NewISettingService().GetSettingInfo() - if err != nil { - return nil, err - } - if setting.AppStoreSyncStatus == constant.Syncing { - res.IsSyncing = true - return res, nil - } - - appStoreLastModified, _ := strconv.Atoi(setting.AppStoreLastModified) - res.AppStoreLastModified = appStoreLastModified - if setting.AppStoreLastModified == "" || lastModified != appStoreLastModified { - res.CanUpdate = true - return res, err - } - apps, _ := appRepo.GetBy(appRepo.WithResource(constant.AppResourceRemote)) - for _, app := range apps { - if app.Icon == "" { - res.CanUpdate = true - return res, err - } - } - - list, err := getAppList() - if err != nil { - return res, err - } - if list.Extra.Version != "" && setting.SystemVersion != list.Extra.Version && !common.CompareVersion(setting.SystemVersion, list.Extra.Version) { - global.LOG.Errorf("The current version is too low to synchronize with the App Store. The minimum required version is %s", list.Extra.Version) - return nil, buserr.New("ErrVersionTooLow") - } - res.AppList = list - return res, nil -} - -func getAppFromRepo(downloadPath string) error { - downloadUrl := downloadPath - global.LOG.Infof("[AppStore] download file from %s", downloadUrl) - fileOp := files.NewFileOp() - packagePath := filepath.Join(constant.ResourceDir, filepath.Base(downloadUrl)) - if err := fileOp.DownloadFileWithProxy(downloadUrl, packagePath); err != nil { - return err - } - if err := fileOp.Decompress(packagePath, constant.ResourceDir, files.SdkZip, ""); err != nil { - return err - } - defer func() { - _ = fileOp.DeleteFile(packagePath) - }() - return nil -} - -func getAppList() (*dto.AppList, error) { - list := &dto.AppList{} - if err := getAppFromRepo(fmt.Sprintf("%s/%s/1panel.json.zip", global.CONF.System.AppRepo, global.CONF.System.Mode)); err != nil { - return nil, err - } - listFile := filepath.Join(constant.ResourceDir, "1panel.json") - content, err := os.ReadFile(listFile) - if err != nil { - return nil, err - } - if err = json.Unmarshal(content, list); err != nil { - return nil, err - } - return list, nil -} - -var InitTypes = map[string]struct{}{ - "runtime": {}, - "php": {}, - "node": {}, -} - -func (a AppService) SyncAppListFromRemote() (err error) { - global.LOG.Infof("Starting synchronization with App Store...") - updateRes, err := a.GetAppUpdate() - if err != nil { - return err - } - if !updateRes.CanUpdate { - if updateRes.IsSyncing { - global.LOG.Infof("AppStore is Syncing!") - return - } - global.LOG.Infof("The App Store is at the latest version") - return - } - - list := &dto.AppList{} - if updateRes.AppList == nil { - list, err = getAppList() - if err != nil { - return - } - } else { - list = updateRes.AppList - } - settingService := NewISettingService() - _ = settingService.Update("AppStoreSyncStatus", constant.Syncing) - - var ( - tags []*model.Tag - appTags []*model.AppTag - oldAppIds []uint - ) - for _, t := range list.Extra.Tags { - tags = append(tags, &model.Tag{ - Key: t.Key, - Name: t.Name, - Sort: t.Sort, - }) - } - oldApps, err := appRepo.GetBy(appRepo.WithResource(constant.AppResourceRemote)) - if err != nil { - return - } - for _, old := range oldApps { - oldAppIds = append(oldAppIds, old.ID) - } - - transport := xpack.LoadRequestTransport() - baseRemoteUrl := fmt.Sprintf("%s/%s/1panel", global.CONF.System.AppRepo, global.CONF.System.Mode) - appsMap := getApps(oldApps, list.Apps) - - global.LOG.Infof("Starting synchronization of application details...") - for _, l := range list.Apps { - app := appsMap[l.AppProperty.Key] - _, iconRes, err := httpUtil.HandleGetWithTransport(l.Icon, http.MethodGet, transport, constant.TimeOut20s) - if err != nil { - return err - } - iconStr := "" - if !strings.Contains(string(iconRes), "") { - iconStr = base64.StdEncoding.EncodeToString(iconRes) - } - - app.Icon = iconStr - app.TagsKey = l.AppProperty.Tags - if l.AppProperty.Recommend > 0 { - app.Recommend = l.AppProperty.Recommend - } else { - app.Recommend = 9999 - } - app.ReadMe = l.ReadMe - app.LastModified = l.LastModified - versions := l.Versions - detailsMap := getAppDetails(app.Details, versions) - for _, v := range versions { - version := v.Name - detail := detailsMap[version] - versionUrl := fmt.Sprintf("%s/%s/%s", baseRemoteUrl, app.Key, version) - - if _, ok := InitTypes[app.Type]; ok { - dockerComposeUrl := fmt.Sprintf("%s/%s", versionUrl, "docker-compose.yml") - _, composeRes, err := httpUtil.HandleGetWithTransport(dockerComposeUrl, http.MethodGet, transport, constant.TimeOut20s) - if err != nil { - return err - } - detail.DockerCompose = string(composeRes) - } else { - detail.DockerCompose = "" - } - - paramByte, _ := json.Marshal(v.AppForm) - detail.Params = string(paramByte) - detail.DownloadUrl = fmt.Sprintf("%s/%s", versionUrl, app.Key+"-"+version+".tar.gz") - detail.DownloadCallBackUrl = v.DownloadCallBackUrl - detail.Update = true - detail.LastModified = v.LastModified - detailsMap[version] = detail - } - var newDetails []model.AppDetail - for _, detail := range detailsMap { - newDetails = append(newDetails, detail) - } - app.Details = newDetails - appsMap[l.AppProperty.Key] = app - } - - global.LOG.Infof("Synchronization of application details Success") - - var ( - addAppArray []model.App - updateAppArray []model.App - deleteAppArray []model.App - deleteIds []uint - tagMap = make(map[string]uint, len(tags)) - ) - - for _, v := range appsMap { - if v.ID == 0 { - addAppArray = append(addAppArray, v) - } else { - if v.Status == constant.AppTakeDown { - installs, _ := appInstallRepo.ListBy(appInstallRepo.WithAppId(v.ID)) - if len(installs) > 0 { - updateAppArray = append(updateAppArray, v) - continue - } - deleteAppArray = append(deleteAppArray, v) - deleteIds = append(deleteIds, v.ID) - } else { - updateAppArray = append(updateAppArray, v) - } - } - } - tx, ctx := getTxAndContext() - defer tx.Rollback() - if len(addAppArray) > 0 { - if err = appRepo.BatchCreate(ctx, addAppArray); err != nil { - return - } - } - if len(deleteAppArray) > 0 { - if err = appRepo.BatchDelete(ctx, deleteAppArray); err != nil { - return - } - if err = appDetailRepo.DeleteByAppIds(ctx, deleteIds); err != nil { - return - } - } - if err = tagRepo.DeleteAll(ctx); err != nil { - return - } - if len(tags) > 0 { - if err = tagRepo.BatchCreate(ctx, tags); err != nil { - return - } - for _, t := range tags { - tagMap[t.Key] = t.ID - } - } - for _, update := range updateAppArray { - if err = appRepo.Save(ctx, &update); err != nil { - return - } - } - apps := append(addAppArray, updateAppArray...) - - var ( - addDetails []model.AppDetail - updateDetails []model.AppDetail - deleteDetails []model.AppDetail - ) - for _, app := range apps { - for _, t := range app.TagsKey { - tagId, ok := tagMap[t] - if ok { - appTags = append(appTags, &model.AppTag{ - AppId: app.ID, - TagId: tagId, - }) - } - } - for _, d := range app.Details { - d.AppId = app.ID - if d.ID == 0 { - addDetails = append(addDetails, d) - } else { - if d.Status == constant.AppTakeDown { - runtime, _ := runtimeRepo.GetFirst(runtimeRepo.WithDetailId(d.ID)) - if runtime != nil { - updateDetails = append(updateDetails, d) - continue - } - installs, _ := appInstallRepo.ListBy(appInstallRepo.WithDetailIdsIn([]uint{d.ID})) - if len(installs) > 0 { - updateDetails = append(updateDetails, d) - continue - } - deleteDetails = append(deleteDetails, d) - } else { - updateDetails = append(updateDetails, d) - } - } - } - } - if len(addDetails) > 0 { - if err = appDetailRepo.BatchCreate(ctx, addDetails); err != nil { - return - } - } - if len(deleteDetails) > 0 { - if err = appDetailRepo.BatchDelete(ctx, deleteDetails); err != nil { - return - } - } - for _, u := range updateDetails { - if err = appDetailRepo.Update(ctx, u); err != nil { - return - } - } - - if len(oldAppIds) > 0 { - if err = appTagRepo.DeleteByAppIds(ctx, oldAppIds); err != nil { - return - } - } - - if len(appTags) > 0 { - if err = appTagRepo.BatchCreate(ctx, appTags); err != nil { - return - } - } - tx.Commit() - - _ = settingService.Update("AppStoreSyncStatus", constant.SyncSuccess) - _ = settingService.Update("AppStoreLastModified", strconv.Itoa(list.LastModified)) - - global.LOG.Infof("Synchronization with the App Store was successful!") - return -} diff --git a/backend/app/service/app_install.go b/backend/app/service/app_install.go deleted file mode 100644 index 41fbfe9f1..000000000 --- a/backend/app/service/app_install.go +++ /dev/null @@ -1,848 +0,0 @@ -package service - -import ( - "context" - "encoding/json" - "fmt" - "math" - "net/http" - "os" - "path" - "path/filepath" - "reflect" - "sort" - "strconv" - "strings" - - "github.com/1Panel-dev/1Panel/backend/utils/files" - httpUtil "github.com/1Panel-dev/1Panel/backend/utils/http" - "github.com/docker/docker/api/types" - "gopkg.in/yaml.v3" - - "github.com/1Panel-dev/1Panel/backend/utils/env" - "github.com/1Panel-dev/1Panel/backend/utils/nginx" - "github.com/joho/godotenv" - - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/buserr" - - "github.com/1Panel-dev/1Panel/backend/app/repo" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/compose" - "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/pkg/errors" -) - -type AppInstallService struct { -} - -type IAppInstallService interface { - Page(req request.AppInstalledSearch) (int64, []response.AppInstallDTO, error) - CheckExist(req request.AppInstalledInfo) (*response.AppInstalledCheck, error) - LoadPort(req dto.OperationWithNameAndType) (int64, error) - LoadConnInfo(req dto.OperationWithNameAndType) (response.DatabaseConn, error) - SearchForWebsite(req request.AppInstalledSearch) ([]response.AppInstallDTO, error) - Operate(req request.AppInstalledOperate) error - Update(req request.AppInstalledUpdate) error - IgnoreUpgrade(req request.AppInstalledIgnoreUpgrade) error - SyncAll(systemInit bool) error - GetServices(key string) ([]response.AppService, error) - GetUpdateVersions(req request.AppUpdateVersion) ([]dto.AppVersion, error) - GetParams(id uint) (*response.AppConfig, error) - ChangeAppPort(req request.PortUpdate) error - GetDefaultConfigByKey(key, name string) (string, error) - DeleteCheck(installId uint) ([]dto.AppResource, error) - - GetInstallList() ([]dto.AppInstallInfo, error) -} - -func NewIAppInstalledService() IAppInstallService { - return &AppInstallService{} -} - -func (a *AppInstallService) GetInstallList() ([]dto.AppInstallInfo, error) { - var datas []dto.AppInstallInfo - appInstalls, err := appInstallRepo.ListBy() - if err != nil { - return nil, err - } - for _, install := range appInstalls { - datas = append(datas, dto.AppInstallInfo{ID: install.ID, Key: install.App.Key, Name: install.Name}) - } - return datas, nil -} - -func (a *AppInstallService) Page(req request.AppInstalledSearch) (int64, []response.AppInstallDTO, error) { - var ( - opts []repo.DBOption - total int64 - installs []model.AppInstall - err error - ) - - if req.Name != "" { - opts = append(opts, commonRepo.WithLikeName(req.Name)) - } - if len(req.Tags) != 0 { - tags, err := tagRepo.GetByKeys(req.Tags) - if err != nil { - return 0, nil, err - } - var tagIds []uint - for _, t := range tags { - tagIds = append(tagIds, t.ID) - } - appTags, err := appTagRepo.GetByTagIds(tagIds) - if err != nil { - return 0, nil, err - } - var appIds []uint - for _, t := range appTags { - appIds = append(appIds, t.AppId) - } - - opts = append(opts, appInstallRepo.WithAppIdsIn(appIds)) - } - - if req.Update { - installs, err = appInstallRepo.ListBy(opts...) - if err != nil { - return 0, nil, err - } - } else { - total, installs, err = appInstallRepo.Page(req.Page, req.PageSize, opts...) - if err != nil { - return 0, nil, err - } - } - - installDTOs, err := handleInstalled(installs, req.Update, req.Sync) - if err != nil { - return 0, nil, err - } - if req.Update { - total = int64(len(installDTOs)) - } - - return total, installDTOs, nil -} - -func (a *AppInstallService) CheckExist(req request.AppInstalledInfo) (*response.AppInstalledCheck, error) { - res := &response.AppInstalledCheck{ - IsExist: false, - } - - app, err := appRepo.GetFirst(appRepo.WithKey(req.Key)) - if err != nil { - return res, nil - } - res.App = app.Name - - var appInstall model.AppInstall - if len(req.Name) == 0 { - appInstall, _ = appInstallRepo.GetFirst(appInstallRepo.WithAppId(app.ID)) - } else { - appInstall, _ = appInstallRepo.GetFirst(appInstallRepo.WithAppId(app.ID), commonRepo.WithByName(req.Name)) - } - - if reflect.DeepEqual(appInstall, model.AppInstall{}) { - return res, nil - } - if err = syncAppInstallStatus(&appInstall, false); err != nil { - return nil, err - } - - res.ContainerName = appInstall.ContainerName - res.Name = appInstall.Name - res.Version = appInstall.Version - res.CreatedAt = appInstall.CreatedAt - res.Status = appInstall.Status - res.AppInstallID = appInstall.ID - res.IsExist = true - res.InstallPath = path.Join(constant.AppInstallDir, appInstall.App.Key, appInstall.Name) - res.HttpPort = appInstall.HttpPort - res.HttpsPort = appInstall.HttpsPort - - return res, nil -} - -func (a *AppInstallService) LoadPort(req dto.OperationWithNameAndType) (int64, error) { - app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name) - if err != nil { - return int64(0), nil - } - return app.Port, nil -} - -func (a *AppInstallService) LoadConnInfo(req dto.OperationWithNameAndType) (response.DatabaseConn, error) { - var data response.DatabaseConn - app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name) - if err != nil { - return data, nil - } - data.Status = app.Status - data.Username = app.UserName - data.Password = app.Password - data.ServiceName = app.ServiceName - data.Port = app.Port - data.ContainerName = app.ContainerName - return data, nil -} - -func (a *AppInstallService) SearchForWebsite(req request.AppInstalledSearch) ([]response.AppInstallDTO, error) { - var ( - installs []model.AppInstall - err error - opts []repo.DBOption - ) - if req.Type != "" { - apps, err := appRepo.GetBy(appRepo.WithType(req.Type)) - if err != nil { - return nil, err - } - var ids []uint - for _, app := range apps { - ids = append(ids, app.ID) - } - if req.Unused { - opts = append(opts, appInstallRepo.WithIdNotInWebsite()) - } - opts = append(opts, appInstallRepo.WithAppIdsIn(ids)) - installs, err = appInstallRepo.ListBy(opts...) - if err != nil { - return nil, err - } - } else { - installs, err = appInstallRepo.ListBy() - if err != nil { - return nil, err - } - } - - return handleInstalled(installs, false, true) -} - -func (a *AppInstallService) Operate(req request.AppInstalledOperate) error { - install, err := appInstallRepo.GetFirstByCtx(context.Background(), commonRepo.WithByID(req.InstallId)) - if err != nil { - return err - } - if !req.ForceDelete && !files.NewFileOp().Stat(install.GetPath()) { - return buserr.New(constant.ErrInstallDirNotFound) - } - dockerComposePath := install.GetComposePath() - switch req.Operate { - case constant.Rebuild: - return rebuildApp(install) - case constant.Start: - out, err := compose.Start(dockerComposePath) - if err != nil { - return handleErr(install, err, out) - } - return syncAppInstallStatus(&install, false) - case constant.Stop: - out, err := compose.Stop(dockerComposePath) - if err != nil { - return handleErr(install, err, out) - } - return syncAppInstallStatus(&install, false) - case constant.Restart: - out, err := compose.Restart(dockerComposePath) - if err != nil { - return handleErr(install, err, out) - } - return syncAppInstallStatus(&install, false) - case constant.Delete: - if err := deleteAppInstall(install, req.DeleteBackup, req.ForceDelete, req.DeleteDB); err != nil && !req.ForceDelete { - return err - } - return nil - case constant.Sync: - return syncAppInstallStatus(&install, true) - case constant.Upgrade: - upgradeReq := request.AppInstallUpgrade{ - InstallID: install.ID, - DetailID: req.DetailId, - Backup: req.Backup, - PullImage: req.PullImage, - DockerCompose: req.DockerCompose, - } - return upgradeInstall(upgradeReq) - case constant.Reload: - return opNginx(install.ContainerName, constant.NginxReload) - default: - return errors.New("operate not support") - } -} - -func (a *AppInstallService) Update(req request.AppInstalledUpdate) error { - installed, err := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallId)) - if err != nil { - return err - } - changePort := false - port, ok := req.Params["PANEL_APP_PORT_HTTP"] - if ok { - portN := int(math.Ceil(port.(float64))) - if portN != installed.HttpPort { - changePort = true - httpPort, err := checkPort("PANEL_APP_PORT_HTTP", req.Params) - if err != nil { - return err - } - installed.HttpPort = httpPort - } - } - ports, ok := req.Params["PANEL_APP_PORT_HTTPS"] - if ok { - portN := int(math.Ceil(ports.(float64))) - if portN != installed.HttpsPort { - httpsPort, err := checkPort("PANEL_APP_PORT_HTTPS", req.Params) - if err != nil { - return err - } - installed.HttpsPort = httpsPort - } - } - - backupDockerCompose := installed.DockerCompose - if req.Advanced { - composeMap := make(map[string]interface{}) - if req.EditCompose { - if err = yaml.Unmarshal([]byte(req.DockerCompose), &composeMap); err != nil { - return err - } - } else { - if err = yaml.Unmarshal([]byte(installed.DockerCompose), &composeMap); err != nil { - return err - } - } - if err = addDockerComposeCommonParam(composeMap, installed.ServiceName, req.AppContainerConfig, req.Params); err != nil { - return err - } - composeByte, err := yaml.Marshal(composeMap) - if err != nil { - return err - } - installed.DockerCompose = string(composeByte) - if req.ContainerName == "" { - req.Params[constant.ContainerName] = installed.ContainerName - } else { - req.Params[constant.ContainerName] = req.ContainerName - if installed.ContainerName != req.ContainerName { - exist, _ := appInstallRepo.GetFirst(appInstallRepo.WithContainerName(req.ContainerName), appInstallRepo.WithIDNotIs(installed.ID)) - if exist.ID > 0 { - return buserr.New(constant.ErrContainerName) - } - containerExist, err := checkContainerNameIsExist(req.ContainerName, installed.GetPath()) - if err != nil { - return err - } - if containerExist { - return buserr.New(constant.ErrContainerName) - } - installed.ContainerName = req.ContainerName - } - } - } - - envPath := path.Join(installed.GetPath(), ".env") - oldEnvMaps, err := godotenv.Read(envPath) - if err != nil { - return err - } - backupEnvMaps := oldEnvMaps - handleMap(req.Params, oldEnvMaps) - paramByte, err := json.Marshal(oldEnvMaps) - if err != nil { - return err - } - installed.Env = string(paramByte) - if err := env.Write(oldEnvMaps, envPath); err != nil { - return err - } - fileOp := files.NewFileOp() - _ = fileOp.WriteFile(installed.GetComposePath(), strings.NewReader(installed.DockerCompose), 0755) - if err := rebuildApp(installed); err != nil { - _ = env.Write(backupEnvMaps, envPath) - _ = fileOp.WriteFile(installed.GetComposePath(), strings.NewReader(backupDockerCompose), 0755) - return err - } - installed.Status = constant.Running - _ = appInstallRepo.Save(context.Background(), &installed) - - website, _ := websiteRepo.GetFirst(websiteRepo.WithAppInstallId(installed.ID)) - if changePort && website.ID != 0 && website.Status == constant.Running { - go func() { - nginxInstall, err := getNginxFull(&website) - if err != nil { - global.LOG.Errorf(buserr.WithErr(constant.ErrUpdateBuWebsite, err).Error()) - return - } - config := nginxInstall.SiteConfig.Config - servers := config.FindServers() - if len(servers) == 0 { - global.LOG.Errorf(buserr.WithErr(constant.ErrUpdateBuWebsite, errors.New("nginx config is not valid")).Error()) - return - } - server := servers[0] - proxy := fmt.Sprintf("http://127.0.0.1:%d", installed.HttpPort) - server.UpdateRootProxy([]string{proxy}) - - if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { - global.LOG.Errorf(buserr.WithErr(constant.ErrUpdateBuWebsite, err).Error()) - return - } - if err := nginxCheckAndReload(nginxInstall.SiteConfig.OldContent, config.FilePath, nginxInstall.Install.ContainerName); err != nil { - global.LOG.Errorf(buserr.WithErr(constant.ErrUpdateBuWebsite, err).Error()) - return - } - }() - } - return nil -} - -func (a *AppInstallService) IgnoreUpgrade(req request.AppInstalledIgnoreUpgrade) error { - appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(req.DetailID)) - if err != nil { - return err - } - appDetail.IgnoreUpgrade = req.Operate == "ignore" - return appDetailRepo.Update(context.Background(), appDetail) -} - -func (a *AppInstallService) SyncAll(systemInit bool) error { - allList, err := appInstallRepo.ListBy() - if err != nil { - return err - } - for _, i := range allList { - if i.Status == constant.Installing || i.Status == constant.Upgrading || i.Status == constant.Rebuilding { - if systemInit { - i.Status = constant.Error - i.Message = "1Panel restart causes the task to terminate" - _ = appInstallRepo.Save(context.Background(), &i) - } - continue - } - if !systemInit { - if err = syncAppInstallStatus(&i, false); err != nil { - global.LOG.Errorf("sync install app[%s] error,mgs: %s", i.Name, err.Error()) - } - } - } - return nil -} - -func (a *AppInstallService) GetServices(key string) ([]response.AppService, error) { - var res []response.AppService - if DatabaseKeys[key] > 0 { - if key == constant.AppPostgres { - key = constant.AppPostgresql - } - dbs, _ := databaseRepo.GetList(commonRepo.WithByType(key)) - if len(dbs) == 0 { - return res, nil - } - for _, db := range dbs { - service := response.AppService{ - Label: db.Name, - Value: db.Name, - } - if db.AppInstallID > 0 { - install, err := appInstallRepo.GetFirst(commonRepo.WithByID(db.AppInstallID)) - if err != nil { - return nil, err - } - paramMap := make(map[string]string) - if install.Param != "" { - _ = json.Unmarshal([]byte(install.Param), ¶mMap) - } - service.Config = paramMap - service.From = constant.AppResourceLocal - } else { - service.From = constant.AppResourceRemote - } - res = append(res, service) - } - } else { - app, err := appRepo.GetFirst(appRepo.WithKey(key)) - if err != nil { - return nil, err - } - installs, err := appInstallRepo.ListBy(appInstallRepo.WithAppId(app.ID), appInstallRepo.WithStatus(constant.Running)) - if err != nil { - return nil, err - } - for _, install := range installs { - paramMap := make(map[string]string) - if install.Param != "" { - _ = json.Unmarshal([]byte(install.Param), ¶mMap) - } - res = append(res, response.AppService{ - Label: install.Name, - Value: install.ServiceName, - Config: paramMap, - }) - } - } - return res, nil -} - -func (a *AppInstallService) GetUpdateVersions(req request.AppUpdateVersion) ([]dto.AppVersion, error) { - install, err := appInstallRepo.GetFirst(commonRepo.WithByID(req.AppInstallID)) - var versions []dto.AppVersion - if err != nil { - return versions, err - } - app, err := appRepo.GetFirst(commonRepo.WithByID(install.AppId)) - if err != nil { - return versions, err - } - details, err := appDetailRepo.GetBy(appDetailRepo.WithAppId(app.ID)) - if err != nil { - return versions, err - } - for _, detail := range details { - if detail.IgnoreUpgrade { - continue - } - if common.IsCrossVersion(install.Version, detail.Version) && !app.CrossVersionUpdate { - continue - } - if common.CompareVersion(detail.Version, install.Version) { - var newCompose string - if req.UpdateVersion != "" && req.UpdateVersion == detail.Version && detail.DockerCompose == "" && !app.IsLocalApp() { - filename := filepath.Base(detail.DownloadUrl) - dockerComposeUrl := fmt.Sprintf("%s%s", strings.TrimSuffix(detail.DownloadUrl, filename), "docker-compose.yml") - statusCode, composeRes, err := httpUtil.HandleGet(dockerComposeUrl, http.MethodGet, constant.TimeOut20s) - if err != nil { - return versions, err - } - if statusCode > 200 { - return versions, err - } - detail.DockerCompose = string(composeRes) - _ = appDetailRepo.Update(context.Background(), detail) - } - newCompose, err = getUpgradeCompose(install, detail) - if err != nil { - return versions, err - } - versions = append(versions, dto.AppVersion{ - Version: detail.Version, - DetailId: detail.ID, - DockerCompose: newCompose, - }) - } - } - sort.Slice(versions, func(i, j int) bool { - return common.CompareVersion(versions[i].Version, versions[j].Version) - }) - return versions, nil -} - -func (a *AppInstallService) ChangeAppPort(req request.PortUpdate) error { - if common.ScanPort(int(req.Port)) { - return buserr.WithDetail(constant.ErrPortInUsed, req.Port, nil) - } - - appInstall, err := appInstallRepo.LoadBaseInfo(req.Key, req.Name) - if err != nil { - return nil - } - - if err := updateInstallInfoInDB(req.Key, req.Name, "port", strconv.FormatInt(req.Port, 10)); err != nil { - return nil - } - - appRess, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithLinkId(appInstall.ID)) - for _, appRes := range appRess { - appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(appRes.AppInstallId)) - if err != nil { - return err - } - if _, err := compose.Restart(fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, appInstall.App.Key, appInstall.Name)); err != nil { - global.LOG.Errorf("docker-compose restart %s[%s] failed, err: %v", appInstall.App.Key, appInstall.Name, err) - } - } - - return nil -} - -func (a *AppInstallService) DeleteCheck(installID uint) ([]dto.AppResource, error) { - var res []dto.AppResource - appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(installID)) - if err != nil { - return nil, err - } - app, err := appRepo.GetFirst(commonRepo.WithByID(appInstall.AppId)) - if err != nil { - return nil, err - } - websites, _ := websiteRepo.GetBy(websiteRepo.WithAppInstallId(appInstall.ID)) - for _, website := range websites { - res = append(res, dto.AppResource{ - Type: "website", - Name: website.PrimaryDomain, - }) - } - if app.Key == constant.AppOpenresty { - websites, _ := websiteRepo.GetBy() - for _, website := range websites { - res = append(res, dto.AppResource{ - Type: "website", - Name: website.PrimaryDomain, - }) - } - } - if app.Type == constant.Runtime { - resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithLinkId(appInstall.ID), commonRepo.WithByFrom(constant.AppResourceLocal)) - for _, resource := range resources { - linkInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(resource.AppInstallId)) - res = append(res, dto.AppResource{ - Type: "app", - Name: linkInstall.Name, - }) - } - } - return res, nil -} - -func (a *AppInstallService) GetDefaultConfigByKey(key, name string) (string, error) { - baseInfo, err := appInstallRepo.LoadBaseInfo(key, name) - if err != nil { - return "", err - } - - fileOp := files.NewFileOp() - filePath := path.Join(constant.AppResourceDir, "remote", baseInfo.Key, baseInfo.Version, "conf") - if !fileOp.Stat(filePath) { - filePath = path.Join(constant.AppResourceDir, baseInfo.Key, "versions", baseInfo.Version, "conf") - } - if !fileOp.Stat(filePath) { - return "", buserr.New(constant.ErrPathNotFound) - } - - if key == constant.AppMysql || key == constant.AppMariaDB { - filePath = path.Join(filePath, "my.cnf") - } - if key == constant.AppRedis { - filePath = path.Join(filePath, "redis.conf") - } - if key == constant.AppOpenresty { - filePath = path.Join(filePath, "nginx.conf") - } - contentByte, err := os.ReadFile(filePath) - if err != nil { - return "", err - } - return string(contentByte), nil -} - -func (a *AppInstallService) GetParams(id uint) (*response.AppConfig, error) { - var ( - params []response.AppParam - appForm dto.AppForm - envs = make(map[string]interface{}) - res response.AppConfig - ) - install, err := appInstallRepo.GetFirst(commonRepo.WithByID(id)) - if err != nil { - return nil, err - } - detail, err := appDetailRepo.GetFirst(commonRepo.WithByID(install.AppDetailId)) - if err != nil { - return nil, err - } - if err = json.Unmarshal([]byte(detail.Params), &appForm); err != nil { - return nil, err - } - if err = json.Unmarshal([]byte(install.Env), &envs); err != nil { - return nil, err - } - for _, form := range appForm.FormFields { - if v, ok := envs[form.EnvKey]; ok { - appParam := response.AppParam{ - Edit: false, - Key: form.EnvKey, - Rule: form.Rule, - Type: form.Type, - Multiple: form.Multiple, - } - if form.Edit { - appParam.Edit = true - } - appParam.LabelZh = form.LabelZh - appParam.LabelEn = form.LabelEn - appParam.Value = v - if form.Type == "service" { - appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithServiceName(v.(string))) - appParam.ShowValue = appInstall.Name - } else if form.Type == "select" { - if form.Multiple { - if v == "" { - appParam.Value = []string{} - } else { - if str, ok := v.(string); ok { - appParam.Value = strings.Split(str, ",") - } - } - } else { - for _, fv := range form.Values { - if fv.Value == v { - appParam.ShowValue = fv.Label - break - } - } - } - appParam.Values = form.Values - } - params = append(params, appParam) - } else { - params = append(params, response.AppParam{ - Edit: form.Edit, - Key: form.EnvKey, - Rule: form.Rule, - Type: form.Type, - LabelZh: form.LabelZh, - LabelEn: form.LabelEn, - Value: form.Default, - Values: form.Values, - Multiple: form.Multiple, - }) - } - } - - config := getAppCommonConfig(envs) - config.DockerCompose = install.DockerCompose - res.Params = params - if config.ContainerName == "" { - config.ContainerName = install.ContainerName - } - res.AppContainerConfig = config - res.HostMode = isHostModel(install.DockerCompose) - return &res, nil -} - -func syncAppInstallStatus(appInstall *model.AppInstall, force bool) error { - if appInstall.Status == constant.Installing || appInstall.Status == constant.Rebuilding || appInstall.Status == constant.Upgrading { - return nil - } - cli, err := docker.NewClient() - if err != nil { - return err - } - defer cli.Close() - - var ( - containers []types.Container - containersMap map[string]types.Container - containerNames = strings.Split(appInstall.ContainerName, ",") - ) - containers, err = cli.ListContainersByName(containerNames) - if err != nil { - return err - } - containersMap = make(map[string]types.Container) - for _, con := range containers { - containersMap[con.Names[0]] = con - } - synAppInstall(containersMap, appInstall, force) - return nil -} - -func updateInstallInfoInDB(appKey, appName, param string, value interface{}) error { - if param != "password" && param != "port" && param != "user-password" { - return nil - } - appInstall, err := appInstallRepo.LoadBaseInfo(appKey, appName) - if err != nil { - return nil - } - envPath := fmt.Sprintf("%s/%s/.env", appInstall.AppPath, appInstall.Name) - lineBytes, err := os.ReadFile(envPath) - if err != nil { - return err - } - - envKey := "" - switch param { - case "password": - if appKey == "mysql" || appKey == "mariadb" || appKey == "postgresql" { - envKey = "PANEL_DB_ROOT_PASSWORD=" - } else { - envKey = "PANEL_REDIS_ROOT_PASSWORD=" - } - case "port": - envKey = "PANEL_APP_PORT_HTTP=" - default: - envKey = "PANEL_DB_USER_PASSWORD=" - } - files := strings.Split(string(lineBytes), "\n") - var newFiles []string - for _, line := range files { - if strings.HasPrefix(line, envKey) { - newFiles = append(newFiles, fmt.Sprintf("%s%v", envKey, value)) - } else { - newFiles = append(newFiles, line) - } - } - file, err := os.OpenFile(envPath, os.O_WRONLY|os.O_TRUNC, 0666) - if err != nil { - return err - } - defer file.Close() - _, err = file.WriteString(strings.Join(newFiles, "\n")) - if err != nil { - return err - } - - oldVal, newVal := "", "" - if param == "password" { - oldVal = fmt.Sprintf("\"PANEL_DB_ROOT_PASSWORD\":\"%v\"", appInstall.Password) - newVal = fmt.Sprintf("\"PANEL_DB_ROOT_PASSWORD\":\"%v\"", value) - if appKey == "redis" { - oldVal = fmt.Sprintf("\"PANEL_REDIS_ROOT_PASSWORD\":\"%v\"", appInstall.Password) - newVal = fmt.Sprintf("\"PANEL_REDIS_ROOT_PASSWORD\":\"%v\"", value) - } - _ = appInstallRepo.BatchUpdateBy(map[string]interface{}{ - "param": strings.ReplaceAll(appInstall.Param, oldVal, newVal), - "env": strings.ReplaceAll(appInstall.Env, oldVal, newVal), - }, commonRepo.WithByID(appInstall.ID)) - } - if param == "user-password" { - oldVal = fmt.Sprintf("\"PANEL_DB_USER_PASSWORD\":\"%v\"", appInstall.UserPassword) - newVal = fmt.Sprintf("\"PANEL_DB_USER_PASSWORD\":\"%v\"", value) - _ = appInstallRepo.BatchUpdateBy(map[string]interface{}{ - "param": strings.ReplaceAll(appInstall.Param, oldVal, newVal), - "env": strings.ReplaceAll(appInstall.Env, oldVal, newVal), - }, commonRepo.WithByID(appInstall.ID)) - } - if param == "port" { - oldVal = fmt.Sprintf("\"PANEL_APP_PORT_HTTP\":%v", appInstall.Port) - newVal = fmt.Sprintf("\"PANEL_APP_PORT_HTTP\":%v", value) - _ = appInstallRepo.BatchUpdateBy(map[string]interface{}{ - "param": strings.ReplaceAll(appInstall.Param, oldVal, newVal), - "env": strings.ReplaceAll(appInstall.Env, oldVal, newVal), - "http_port": value, - }, commonRepo.WithByID(appInstall.ID)) - } - - ComposeFile := fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, appKey, appInstall.Name) - stdout, err := compose.Down(ComposeFile) - if err != nil { - return errors.New(stdout) - } - stdout, err = compose.Up(ComposeFile) - if err != nil { - return errors.New(stdout) - } - return nil -} diff --git a/backend/app/service/app_utils.go b/backend/app/service/app_utils.go deleted file mode 100644 index 80c740109..000000000 --- a/backend/app/service/app_utils.go +++ /dev/null @@ -1,1521 +0,0 @@ -package service - -import ( - "context" - "encoding/base64" - "encoding/json" - "fmt" - "math" - "net/http" - "os" - "os/exec" - "path" - "reflect" - "regexp" - "strconv" - "strings" - "time" - - "github.com/docker/docker/api/types" - - httpUtil "github.com/1Panel-dev/1Panel/backend/utils/http" - "github.com/1Panel-dev/1Panel/backend/utils/xpack" - "github.com/docker/docker/api/types/container" - - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/i18n" - "github.com/subosito/gotenv" - "gopkg.in/yaml.v3" - - "github.com/1Panel-dev/1Panel/backend/app/repo" - "github.com/1Panel-dev/1Panel/backend/utils/env" - - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/buserr" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/compose" - "github.com/1Panel-dev/1Panel/backend/utils/docker" - composeV2 "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/pkg/errors" -) - -type DatabaseOp string - -var ( - Add DatabaseOp = "add" - Delete DatabaseOp = "delete" -) - -func checkPort(key string, params map[string]interface{}) (int, error) { - port, ok := params[key] - if ok { - portN := 0 - var err error - switch p := port.(type) { - case string: - portN, err = strconv.Atoi(p) - if err != nil { - return portN, nil - } - case float64: - portN = int(math.Ceil(p)) - case int: - portN = p - } - - oldInstalled, _ := appInstallRepo.ListBy(appInstallRepo.WithPort(portN)) - if len(oldInstalled) > 0 { - var apps []string - for _, install := range oldInstalled { - apps = append(apps, install.App.Name) - } - return portN, buserr.WithMap(constant.ErrPortInOtherApp, map[string]interface{}{"port": portN, "apps": apps}, nil) - } - if common.ScanPort(portN) { - return portN, buserr.WithDetail(constant.ErrPortInUsed, portN, nil) - } else { - return portN, nil - } - } - return 0, nil -} - -func checkPortExist(port int) error { - errMap := make(map[string]interface{}) - errMap["port"] = port - appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port)) - if appInstall.ID > 0 { - errMap["type"] = i18n.GetMsgByKey("TYPE_APP") - errMap["name"] = appInstall.Name - return buserr.WithMap("ErrPortExist", errMap, nil) - } - runtime, _ := runtimeRepo.GetFirst(runtimeRepo.WithPort(port)) - if runtime != nil { - errMap["type"] = i18n.GetMsgByKey("TYPE_RUNTIME") - errMap["name"] = runtime.Name - return buserr.WithMap("ErrPortExist", errMap, nil) - } - domain, _ := websiteDomainRepo.GetFirst(websiteDomainRepo.WithPort(port)) - if domain.ID > 0 { - errMap["type"] = i18n.GetMsgByKey("TYPE_DOMAIN") - errMap["name"] = domain.Domain - return buserr.WithMap("ErrPortExist", errMap, nil) - } - if common.ScanPort(port) { - return buserr.WithDetail(constant.ErrPortInUsed, port, nil) - } - return nil -} - -var DatabaseKeys = map[string]uint{ - constant.AppMysql: 3306, - constant.AppMariaDB: 3306, - constant.AppPostgresql: 5432, - constant.AppPostgres: 5432, - constant.AppMongodb: 27017, - constant.AppRedis: 6379, - constant.AppMemcached: 11211, -} - -var ToolKeys = map[string]uint{ - "minio": 9001, -} - -func createLink(ctx context.Context, app model.App, appInstall *model.AppInstall, params map[string]interface{}) error { - var dbConfig dto.AppDatabase - if DatabaseKeys[app.Key] > 0 { - database := &model.Database{ - AppInstallID: appInstall.ID, - Name: appInstall.Name, - Type: app.Key, - Version: appInstall.Version, - From: "local", - Address: appInstall.ServiceName, - Port: DatabaseKeys[app.Key], - } - detail, err := appDetailRepo.GetFirst(commonRepo.WithByID(appInstall.AppDetailId)) - if err != nil { - return err - } - - formFields := &dto.AppForm{} - if err := json.Unmarshal([]byte(detail.Params), formFields); err != nil { - return err - } - for _, form := range formFields.FormFields { - if form.EnvKey == "PANEL_APP_PORT_HTTP" { - portFloat, ok := form.Default.(float64) - if ok { - database.Port = uint(int(portFloat)) - } - break - } - } - - switch app.Key { - case constant.AppMysql, constant.AppMariaDB, constant.AppPostgresql, constant.AppMongodb: - if password, ok := params["PANEL_DB_ROOT_PASSWORD"]; ok { - if password != "" { - database.Password = password.(string) - if app.Key == "mysql" || app.Key == "mariadb" { - database.Username = "root" - } - if rootUser, ok := params["PANEL_DB_ROOT_USER"]; ok { - database.Username = rootUser.(string) - } - authParam := dto.AuthParam{ - RootPassword: password.(string), - RootUser: database.Username, - } - authByte, err := json.Marshal(authParam) - if err != nil { - return err - } - appInstall.Param = string(authByte) - - } - } - case constant.AppRedis: - if password, ok := params["PANEL_REDIS_ROOT_PASSWORD"]; ok { - if password != "" { - authParam := dto.RedisAuthParam{ - RootPassword: password.(string), - } - authByte, err := json.Marshal(authParam) - if err != nil { - return err - } - appInstall.Param = string(authByte) - } - database.Password = password.(string) - } - } - if err := databaseRepo.Create(ctx, database); err != nil { - return err - } - } - if ToolKeys[app.Key] > 0 { - if app.Key == "minio" { - authParam := dto.MinioAuthParam{} - if password, ok := params["PANEL_MINIO_ROOT_PASSWORD"]; ok { - authParam.RootPassword = password.(string) - } - if rootUser, ok := params["PANEL_MINIO_ROOT_USER"]; ok { - authParam.RootUser = rootUser.(string) - } - authByte, err := json.Marshal(authParam) - if err != nil { - return err - } - appInstall.Param = string(authByte) - } - } - - if app.Type == "website" || app.Type == "tool" { - paramByte, err := json.Marshal(params) - if err != nil { - return err - } - if err = json.Unmarshal(paramByte, &dbConfig); err != nil { - return err - } - } - - if !reflect.DeepEqual(dbConfig, dto.AppDatabase{}) && dbConfig.ServiceName != "" { - hostName := params["PANEL_DB_HOST_NAME"] - if hostName == nil || hostName.(string) == "" { - return nil - } - database, _ := databaseRepo.Get(commonRepo.WithByName(hostName.(string))) - if database.ID == 0 { - return nil - } - var resourceId uint - if dbConfig.DbName != "" && dbConfig.DbUser != "" && dbConfig.Password != "" { - switch database.Type { - case constant.AppPostgresql, constant.AppPostgres: - iPostgresqlRepo := repo.NewIPostgresqlRepo() - oldPostgresqlDb, _ := iPostgresqlRepo.Get(commonRepo.WithByName(dbConfig.DbName), iPostgresqlRepo.WithByFrom(constant.ResourceLocal)) - resourceId = oldPostgresqlDb.ID - if oldPostgresqlDb.ID > 0 { - if oldPostgresqlDb.Username != dbConfig.DbUser || oldPostgresqlDb.Password != dbConfig.Password { - return buserr.New(constant.ErrDbUserNotValid) - } - } else { - var createPostgresql dto.PostgresqlDBCreate - createPostgresql.Name = dbConfig.DbName - createPostgresql.Username = dbConfig.DbUser - createPostgresql.Database = database.Name - createPostgresql.Format = "UTF8" - createPostgresql.Password = dbConfig.Password - createPostgresql.From = database.From - createPostgresql.SuperUser = true - pgdb, err := NewIPostgresqlService().Create(ctx, createPostgresql) - if err != nil { - return err - } - resourceId = pgdb.ID - } - case constant.AppMysql, constant.AppMariaDB: - iMysqlRepo := repo.NewIMysqlRepo() - oldMysqlDb, _ := iMysqlRepo.Get(commonRepo.WithByName(dbConfig.DbName), iMysqlRepo.WithByFrom(constant.ResourceLocal)) - resourceId = oldMysqlDb.ID - if oldMysqlDb.ID > 0 { - if oldMysqlDb.Username != dbConfig.DbUser || oldMysqlDb.Password != dbConfig.Password { - return buserr.New(constant.ErrDbUserNotValid) - } - } else { - var createMysql dto.MysqlDBCreate - createMysql.Name = dbConfig.DbName - createMysql.Username = dbConfig.DbUser - createMysql.Database = database.Name - createMysql.Format = "utf8mb4" - createMysql.Permission = "%" - createMysql.Password = dbConfig.Password - createMysql.From = database.From - mysqldb, err := NewIMysqlService().Create(ctx, createMysql) - if err != nil { - return err - } - resourceId = mysqldb.ID - } - } - - } - var installResource model.AppInstallResource - installResource.ResourceId = resourceId - installResource.AppInstallId = appInstall.ID - if database.AppInstallID > 0 { - installResource.LinkId = database.AppInstallID - } else { - installResource.LinkId = database.ID - } - installResource.Key = database.Type - installResource.From = database.From - if err := appInstallResourceRepo.Create(ctx, &installResource); err != nil { - return err - } - } - return nil -} - -func handleAppInstallErr(ctx context.Context, install *model.AppInstall) error { - op := files.NewFileOp() - appDir := install.GetPath() - dir, _ := os.Stat(appDir) - if dir != nil { - _, _ = compose.Down(install.GetComposePath()) - if err := op.DeleteDir(appDir); err != nil { - return err - } - } - if err := deleteLink(ctx, install, true, true, true); err != nil { - return err - } - return nil -} - -func deleteAppInstall(install model.AppInstall, deleteBackup bool, forceDelete bool, deleteDB bool) error { - op := files.NewFileOp() - appDir := install.GetPath() - dir, _ := os.Stat(appDir) - if dir != nil { - out, err := compose.Down(install.GetComposePath()) - if err != nil && !forceDelete { - return handleErr(install, err, out) - } - if err = runScript(&install, "uninstall"); err != nil { - _, _ = compose.Up(install.GetComposePath()) - return err - } - } - tx, ctx := helper.GetTxAndContext() - defer tx.Rollback() - if err := appInstallRepo.Delete(ctx, install); err != nil { - return err - } - if err := deleteLink(ctx, &install, deleteDB, forceDelete, deleteBackup); err != nil && !forceDelete { - return err - } - - if DatabaseKeys[install.App.Key] > 0 { - _ = databaseRepo.Delete(ctx, databaseRepo.WithAppInstallID(install.ID)) - } - - switch install.App.Key { - case constant.AppOpenresty: - websites, _ := websiteRepo.List() - for _, website := range websites { - if website.AppInstallID > 0 { - websiteAppInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) - if websiteAppInstall.AppId > 0 { - websiteApp, _ := appRepo.GetFirst(commonRepo.WithByID(websiteAppInstall.AppId)) - if websiteApp.Type == constant.RuntimePHP { - go func() { - _, _ = compose.Down(websiteAppInstall.GetComposePath()) - _ = op.DeleteDir(websiteAppInstall.GetPath()) - }() - _ = appInstallRepo.Delete(ctx, websiteAppInstall) - } - } - } - } - _ = websiteRepo.DeleteAll(ctx) - _ = websiteDomainRepo.DeleteAll(ctx) - xpack.RemoveTamper("") - case constant.AppMysql, constant.AppMariaDB: - _ = mysqlRepo.Delete(ctx, mysqlRepo.WithByMysqlName(install.Name)) - case constant.AppPostgresql: - _ = postgresqlRepo.Delete(ctx, postgresqlRepo.WithByPostgresqlName(install.Name)) - } - - _ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType("app"), commonRepo.WithByName(install.App.Key), backupRepo.WithByDetailName(install.Name)) - uploadDir := path.Join(global.CONF.System.BaseDir, fmt.Sprintf("1panel/uploads/app/%s/%s", install.App.Key, install.Name)) - if _, err := os.Stat(uploadDir); err == nil { - _ = os.RemoveAll(uploadDir) - } - if deleteBackup { - localDir, _ := loadLocalDir() - backupDir := path.Join(localDir, fmt.Sprintf("app/%s/%s", install.App.Key, install.Name)) - if _, err := os.Stat(backupDir); err == nil { - _ = os.RemoveAll(backupDir) - } - global.LOG.Infof("delete app %s-%s backups successful", install.App.Key, install.Name) - } - _ = op.DeleteDir(appDir) - tx.Commit() - return nil -} - -func deleteLink(ctx context.Context, install *model.AppInstall, deleteDB bool, forceDelete bool, deleteBackup bool) error { - resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID)) - if len(resources) == 0 { - return nil - } - for _, re := range resources { - if deleteDB { - switch re.Key { - case constant.AppMysql, constant.AppMariaDB: - mysqlService := NewIMysqlService() - database, _ := mysqlRepo.Get(commonRepo.WithByID(re.ResourceId)) - if reflect.DeepEqual(database, model.DatabaseMysql{}) { - continue - } - if err := mysqlService.Delete(ctx, dto.MysqlDBDelete{ - ID: database.ID, - ForceDelete: forceDelete, - DeleteBackup: deleteBackup, - Type: re.Key, - Database: database.MysqlName, - }); err != nil && !forceDelete { - return err - } - case constant.AppPostgresql: - pgsqlService := NewIPostgresqlService() - database, _ := postgresqlRepo.Get(commonRepo.WithByID(re.ResourceId)) - if reflect.DeepEqual(database, model.DatabasePostgresql{}) { - continue - } - if err := pgsqlService.Delete(ctx, dto.PostgresqlDBDelete{ - ID: database.ID, - ForceDelete: forceDelete, - DeleteBackup: deleteBackup, - Type: re.Key, - Database: database.PostgresqlName, - }); err != nil { - return err - } - } - } - - } - return appInstallResourceRepo.DeleteBy(ctx, appInstallResourceRepo.WithAppInstallId(install.ID)) -} - -func getUpgradeCompose(install model.AppInstall, detail model.AppDetail) (string, error) { - if detail.DockerCompose == "" { - return "", nil - } - composeMap := make(map[string]interface{}) - if err := yaml.Unmarshal([]byte(detail.DockerCompose), &composeMap); err != nil { - return "", err - } - value, ok := composeMap["services"] - if !ok || value == nil { - return "", buserr.New(constant.ErrFileParse) - } - servicesMap := value.(map[string]interface{}) - if len(servicesMap) == 1 { - index := 0 - oldServiceName := "" - for k := range servicesMap { - oldServiceName = k - index++ - if index > 0 { - break - } - } - servicesMap[install.ServiceName] = servicesMap[oldServiceName] - if install.ServiceName != oldServiceName { - delete(servicesMap, oldServiceName) - } - } - envs := make(map[string]interface{}) - if err := json.Unmarshal([]byte(install.Env), &envs); err != nil { - return "", err - } - config := getAppCommonConfig(envs) - if config.ContainerName == "" { - config.ContainerName = install.ContainerName - envs[constant.ContainerName] = install.ContainerName - } - config.Advanced = true - if err := addDockerComposeCommonParam(composeMap, install.ServiceName, config, envs); err != nil { - return "", err - } - paramByte, err := json.Marshal(envs) - if err != nil { - return "", err - } - install.Env = string(paramByte) - composeByte, err := yaml.Marshal(composeMap) - if err != nil { - return "", err - } - return string(composeByte), nil -} - -func upgradeInstall(req request.AppInstallUpgrade) error { - install, err := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallID)) - if err != nil { - return err - } - detail, err := appDetailRepo.GetFirst(commonRepo.WithByID(req.DetailID)) - if err != nil { - return err - } - if install.Version == detail.Version { - return errors.New("two version is same") - } - install.Status = constant.Upgrading - - go func() { - var ( - upErr error - backupFile string - preErr error - ) - global.LOG.Infof(i18n.GetMsgWithName("UpgradeAppStart", install.Name, nil)) - if req.Backup { - backupRecord, err := NewIBackupService().AppBackup(dto.CommonBackup{Name: install.App.Key, DetailName: install.Name}) - if err == nil { - localDir, err := loadLocalDir() - if err == nil { - backupFile = path.Join(localDir, backupRecord.FileDir, backupRecord.FileName) - } else { - global.LOG.Errorf(i18n.GetMsgWithName("ErrAppBackup", install.Name, err)) - } - } else { - global.LOG.Errorf(i18n.GetMsgWithName("ErrAppBackup", install.Name, err)) - } - } - - defer func() { - if upErr != nil { - global.LOG.Infof(i18n.GetMsgWithName("ErrAppUpgrade", install.Name, upErr)) - if req.Backup { - global.LOG.Infof(i18n.GetMsgWithName("AppRecover", install.Name, nil)) - if err := NewIBackupService().AppRecover(dto.CommonRecover{Name: install.App.Key, DetailName: install.Name, Type: "app", Source: constant.ResourceLocal, File: backupFile}); err != nil { - global.LOG.Errorf("recover app [%s] [%s] failed %v", install.App.Key, install.Name, err) - } - } - existInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallID)) - if existInstall.ID > 0 { - existInstall.Status = constant.UpgradeErr - existInstall.Message = upErr.Error() - _ = appInstallRepo.Save(context.Background(), &existInstall) - } - } - if preErr != nil { - global.LOG.Infof(i18n.GetMsgWithName("ErrAppUpgrade", install.Name, preErr)) - existInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallID)) - if existInstall.ID > 0 { - existInstall.Status = constant.UpgradeErr - existInstall.Message = preErr.Error() - _ = appInstallRepo.Save(context.Background(), &existInstall) - } - } - }() - - fileOp := files.NewFileOp() - detailDir := path.Join(constant.ResourceDir, "apps", install.App.Resource, install.App.Key, detail.Version) - if install.App.Resource == constant.AppResourceRemote { - if preErr = downloadApp(install.App, detail, &install); preErr != nil { - return - } - if detail.DockerCompose == "" { - composeDetail, err := fileOp.GetContent(path.Join(detailDir, "docker-compose.yml")) - if err != nil { - preErr = err - return - } - detail.DockerCompose = string(composeDetail) - _ = appDetailRepo.Update(context.Background(), detail) - } - go func() { - _, _, _ = httpUtil.HandleGet(detail.DownloadCallBackUrl, http.MethodGet, constant.TimeOut5s) - }() - } - - if install.App.Resource == constant.AppResourceLocal { - detailDir = path.Join(constant.ResourceDir, "apps", "local", strings.TrimPrefix(install.App.Key, "local"), detail.Version) - } - - content, err := fileOp.GetContent(install.GetEnvPath()) - if err != nil { - preErr = err - return - } - if req.PullImage { - projectName := strings.ToLower(install.Name) - images, err := composeV2.GetDockerComposeImages(projectName, content, []byte(detail.DockerCompose)) - if err != nil { - preErr = err - return - } - for _, image := range images { - global.LOG.Infof(i18n.GetMsgWithName("PullImageStart", image, nil)) - if out, err := cmd.ExecWithTimeOut("docker pull "+image, 20*time.Minute); err != nil { - if out != "" { - err = errors.New(out) - } - preErr = buserr.WithNameAndErr("ErrDockerPullImage", "", err) - return - } else { - global.LOG.Infof(i18n.GetMsgByKey("PullImageSuccess")) - } - } - } - - command := exec.Command("/bin/bash", "-c", fmt.Sprintf("cp -rn %s/* %s || true", detailDir, install.GetPath())) - stdout, _ := command.CombinedOutput() - if stdout != nil { - global.LOG.Infof("upgrade app [%s] [%s] cp file log : %s ", install.App.Key, install.Name, string(stdout)) - } - sourceScripts := path.Join(detailDir, "scripts") - if fileOp.Stat(sourceScripts) { - dstScripts := path.Join(install.GetPath(), "scripts") - _ = fileOp.DeleteDir(dstScripts) - _ = fileOp.CreateDir(dstScripts, 0755) - scriptCmd := exec.Command("cp", "-rf", sourceScripts+"/.", dstScripts+"/") - _, _ = scriptCmd.CombinedOutput() - } - - var newCompose string - if req.DockerCompose == "" { - newCompose, upErr = getUpgradeCompose(install, detail) - if upErr != nil { - return - } - } else { - newCompose = req.DockerCompose - } - - install.DockerCompose = newCompose - install.Version = detail.Version - install.AppDetailId = req.DetailID - - if out, err := compose.Down(install.GetComposePath()); err != nil { - if out != "" { - upErr = errors.New(out) - return - } - upErr = err - return - } - envs := make(map[string]interface{}) - if upErr = json.Unmarshal([]byte(install.Env), &envs); upErr != nil { - return - } - envParams := make(map[string]string, len(envs)) - handleMap(envs, envParams) - if upErr = env.Write(envParams, install.GetEnvPath()); upErr != nil { - return - } - - if upErr = runScript(&install, "upgrade"); upErr != nil { - return - } - - if upErr = fileOp.WriteFile(install.GetComposePath(), strings.NewReader(install.DockerCompose), 0775); upErr != nil { - return - } - if out, err := compose.Up(install.GetComposePath()); err != nil { - if out != "" { - upErr = errors.New(out) - return - } - upErr = err - return - } - install.Status = constant.Running - _ = appInstallRepo.Save(context.Background(), &install) - global.LOG.Infof(i18n.GetMsgWithName("UpgradeAppSuccess", install.Name, nil)) - }() - - return appInstallRepo.Save(context.Background(), &install) -} - -func getContainerNames(install model.AppInstall) ([]string, error) { - envStr, err := coverEnvJsonToStr(install.Env) - if err != nil { - return nil, err - } - project, err := composeV2.GetComposeProject(install.Name, install.GetPath(), []byte(install.DockerCompose), []byte(envStr), true) - if err != nil { - return nil, err - } - containerMap := make(map[string]struct{}) - for _, service := range project.AllServices() { - if service.ContainerName == "${CONTAINER_NAME}" || service.ContainerName == "" { - continue - } - containerMap[service.ContainerName] = struct{}{} - } - var containerNames []string - for k := range containerMap { - containerNames = append(containerNames, k) - } - if len(containerNames) == 0 { - containerNames = append(containerNames, install.ContainerName) - } - return containerNames, nil -} - -func coverEnvJsonToStr(envJson string) (string, error) { - envMap := make(map[string]interface{}) - _ = json.Unmarshal([]byte(envJson), &envMap) - newEnvMap := make(map[string]string, len(envMap)) - handleMap(envMap, newEnvMap) - envStr, err := gotenv.Marshal(newEnvMap) - if err != nil { - return "", err - } - return envStr, nil -} - -func checkLimit(app model.App) error { - if app.Limit > 0 { - installs, err := appInstallRepo.ListBy(appInstallRepo.WithAppId(app.ID)) - if err != nil { - return err - } - if len(installs) >= app.Limit { - return buserr.New(constant.ErrAppLimit) - } - } - return nil -} - -func checkRequiredAndLimit(app model.App) error { - if err := checkLimit(app); err != nil { - return err - } - return nil -} - -func handleMap(params map[string]interface{}, envParams map[string]string) { - for k, v := range params { - switch t := v.(type) { - case string: - envParams[k] = t - case float64: - envParams[k] = strconv.FormatFloat(t, 'f', -1, 32) - case uint: - envParams[k] = strconv.Itoa(int(t)) - case int: - envParams[k] = strconv.Itoa(t) - case []interface{}: - strArray := make([]string, len(t)) - for i := range t { - strArray[i] = strings.ToLower(fmt.Sprintf("%v", t[i])) - } - envParams[k] = strings.Join(strArray, ",") - case map[string]interface{}: - handleMap(t, envParams) - } - } -} - -func downloadApp(app model.App, appDetail model.AppDetail, appInstall *model.AppInstall) (err error) { - if app.IsLocalApp() { - //本地应用,不去官网下载 - return nil - } - appResourceDir := path.Join(constant.AppResourceDir, app.Resource) - appDownloadDir := app.GetAppResourcePath() - appVersionDir := path.Join(appDownloadDir, appDetail.Version) - fileOp := files.NewFileOp() - if !appDetail.Update && fileOp.Stat(appVersionDir) { - return - } - if !fileOp.Stat(appDownloadDir) { - _ = fileOp.CreateDir(appDownloadDir, 0755) - } - if !fileOp.Stat(appVersionDir) { - _ = fileOp.CreateDir(appVersionDir, 0755) - } - global.LOG.Infof("download app[%s] from %s", app.Name, appDetail.DownloadUrl) - filePath := path.Join(appVersionDir, app.Key+"-"+appDetail.Version+".tar.gz") - - defer func() { - if err != nil { - if appInstall != nil { - appInstall.Status = constant.DownloadErr - appInstall.Message = err.Error() - } - } - }() - - if err = fileOp.DownloadFileWithProxy(appDetail.DownloadUrl, filePath); err != nil { - global.LOG.Errorf("download app[%s] error %v", app.Name, err) - return - } - if err = fileOp.Decompress(filePath, appResourceDir, files.SdkTarGz, ""); err != nil { - global.LOG.Errorf("decompress app[%s] error %v", app.Name, err) - return - } - _ = fileOp.DeleteFile(filePath) - appDetail.Update = false - _ = appDetailRepo.Update(context.Background(), appDetail) - return -} - -func copyData(app model.App, appDetail model.AppDetail, appInstall *model.AppInstall, req request.AppInstallCreate) (err error) { - fileOp := files.NewFileOp() - appResourceDir := path.Join(constant.AppResourceDir, app.Resource) - - if app.Resource == constant.AppResourceRemote { - err = downloadApp(app, appDetail, appInstall) - if err != nil { - return - } - go func() { - _, _, _ = httpUtil.HandleGet(appDetail.DownloadCallBackUrl, http.MethodGet, constant.TimeOut5s) - }() - } - appKey := app.Key - installAppDir := path.Join(constant.AppInstallDir, app.Key) - if app.Resource == constant.AppResourceLocal { - appResourceDir = constant.LocalAppResourceDir - appKey = strings.TrimPrefix(app.Key, "local") - installAppDir = path.Join(constant.LocalAppInstallDir, appKey) - } - resourceDir := path.Join(appResourceDir, appKey, appDetail.Version) - - if !fileOp.Stat(installAppDir) { - if err = fileOp.CreateDir(installAppDir, 0755); err != nil { - return - } - } - appDir := path.Join(installAppDir, req.Name) - if fileOp.Stat(appDir) { - if err = fileOp.DeleteDir(appDir); err != nil { - return - } - } - if err = fileOp.Copy(resourceDir, installAppDir); err != nil { - return - } - versionDir := path.Join(installAppDir, appDetail.Version) - if err = fileOp.Rename(versionDir, appDir); err != nil { - return - } - envPath := path.Join(appDir, ".env") - - envParams := make(map[string]string, len(req.Params)) - handleMap(req.Params, envParams) - if err = env.Write(envParams, envPath); err != nil { - return - } - if err := fileOp.WriteFile(appInstall.GetComposePath(), strings.NewReader(appInstall.DockerCompose), 0755); err != nil { - return err - } - return -} - -func runScript(appInstall *model.AppInstall, operate string) error { - workDir := appInstall.GetPath() - scriptPath := "" - switch operate { - case "init": - scriptPath = path.Join(workDir, "scripts", "init.sh") - case "upgrade": - scriptPath = path.Join(workDir, "scripts", "upgrade.sh") - case "uninstall": - scriptPath = path.Join(workDir, "scripts", "uninstall.sh") - } - if !files.NewFileOp().Stat(scriptPath) { - return nil - } - out, err := cmd.ExecScript(scriptPath, workDir) - if err != nil { - if out != "" { - errMsg := fmt.Sprintf("run script %s error %s", scriptPath, out) - global.LOG.Error(errMsg) - return errors.New(errMsg) - } - return err - } - return nil -} - -func checkContainerNameIsExist(containerName, appDir string) (bool, error) { - client, err := composeV2.NewDockerClient() - if err != nil { - return false, err - } - defer client.Close() - var options container.ListOptions - list, err := client.ContainerList(context.Background(), options) - if err != nil { - return false, err - } - for _, container := range list { - if containerName == container.Names[0][1:] { - if workDir, ok := container.Labels[composeWorkdirLabel]; ok { - if workDir != appDir { - return true, nil - } - } else { - return true, nil - } - } - - } - return false, nil -} - -func upApp(appInstall *model.AppInstall, pullImages bool) { - upProject := func(appInstall *model.AppInstall) (err error) { - var ( - out string - errMsg string - ) - if pullImages && appInstall.App.Type != "php" { - out, err = compose.Pull(appInstall.GetComposePath()) - if err != nil { - if out != "" { - if strings.Contains(out, "no such host") { - errMsg = i18n.GetMsgByKey("ErrNoSuchHost") + ":" - } - if strings.Contains(out, "timeout") { - errMsg = i18n.GetMsgByKey("ErrImagePullTimeOut") + ":" - } - appInstall.Message = errMsg + out - } - return err - } - } - - out, err = compose.Up(appInstall.GetComposePath()) - if err != nil { - if out != "" { - appInstall.Message = errMsg + out - } - return err - } - return - } - if err := upProject(appInstall); err != nil { - appInstall.Status = constant.UpErr - } else { - appInstall.Status = constant.Running - } - exist, _ := appInstallRepo.GetFirst(commonRepo.WithByID(appInstall.ID)) - if exist.ID > 0 { - containerNames, err := getContainerNames(*appInstall) - if err != nil { - return - } - if len(containerNames) > 0 { - appInstall.ContainerName = strings.Join(containerNames, ",") - } - _ = appInstallRepo.Save(context.Background(), appInstall) - } -} - -func rebuildApp(appInstall model.AppInstall) error { - appInstall.Status = constant.Rebuilding - _ = appInstallRepo.Save(context.Background(), &appInstall) - go func() { - dockerComposePath := appInstall.GetComposePath() - out, err := compose.Down(dockerComposePath) - if err != nil { - _ = handleErr(appInstall, err, out) - return - } - out, err = compose.Up(appInstall.GetComposePath()) - if err != nil { - _ = handleErr(appInstall, err, out) - return - } - containerNames, err := getContainerNames(appInstall) - if err != nil { - _ = handleErr(appInstall, err, out) - return - } - appInstall.ContainerName = strings.Join(containerNames, ",") - - appInstall.Status = constant.Running - _ = appInstallRepo.Save(context.Background(), &appInstall) - }() - return nil -} - -func getAppDetails(details []model.AppDetail, versions []dto.AppConfigVersion) map[string]model.AppDetail { - appDetails := make(map[string]model.AppDetail, len(details)) - for _, old := range details { - old.Status = constant.AppTakeDown - appDetails[old.Version] = old - } - for _, v := range versions { - version := v.Name - detail, ok := appDetails[version] - if ok { - detail.Status = constant.AppNormal - appDetails[version] = detail - } else { - appDetails[version] = model.AppDetail{ - Version: version, - Status: constant.AppNormal, - } - } - } - return appDetails -} - -func getApps(oldApps []model.App, items []dto.AppDefine) map[string]model.App { - apps := make(map[string]model.App, len(oldApps)) - for _, old := range oldApps { - old.Status = constant.AppTakeDown - apps[old.Key] = old - } - for _, item := range items { - config := item.AppProperty - key := config.Key - app, ok := apps[key] - if !ok { - app = model.App{} - } - app.Resource = constant.AppResourceRemote - app.Name = item.Name - app.Limit = config.Limit - app.Key = key - app.ShortDescZh = config.ShortDescZh - app.ShortDescEn = config.ShortDescEn - app.Website = config.Website - app.Document = config.Document - app.Github = config.Github - app.Type = config.Type - app.CrossVersionUpdate = config.CrossVersionUpdate - app.Status = constant.AppNormal - app.LastModified = item.LastModified - app.ReadMe = item.ReadMe - apps[key] = app - } - return apps -} - -func handleLocalAppDetail(versionDir string, appDetail *model.AppDetail) error { - fileOp := files.NewFileOp() - dockerComposePath := path.Join(versionDir, "docker-compose.yml") - if !fileOp.Stat(dockerComposePath) { - return buserr.WithName(constant.ErrFileNotFound, "docker-compose.yml") - } - dockerComposeByte, _ := fileOp.GetContent(dockerComposePath) - if dockerComposeByte == nil { - return buserr.WithName(constant.ErrFileParseApp, "docker-compose.yml") - } - appDetail.DockerCompose = string(dockerComposeByte) - paramPath := path.Join(versionDir, "data.yml") - if !fileOp.Stat(paramPath) { - return buserr.WithName(constant.ErrFileNotFound, "data.yml") - } - paramByte, _ := fileOp.GetContent(paramPath) - if paramByte == nil { - return buserr.WithName(constant.ErrFileNotFound, "data.yml") - } - appParamConfig := dto.LocalAppParam{} - if err := yaml.Unmarshal(paramByte, &appParamConfig); err != nil { - return buserr.WithMap(constant.ErrFileParseApp, map[string]interface{}{"name": "data.yml", "err": err.Error()}, err) - } - dataJson, err := json.Marshal(appParamConfig.AppParams) - if err != nil { - return buserr.WithMap(constant.ErrFileParseApp, map[string]interface{}{"name": "data.yml", "err": err.Error()}, err) - } - var appParam dto.AppForm - if err = json.Unmarshal(dataJson, &appParam); err != nil { - return buserr.WithMap(constant.ErrFileParseApp, map[string]interface{}{"name": "data.yml", "err": err.Error()}, err) - } - for _, formField := range appParam.FormFields { - if strings.Contains(formField.EnvKey, " ") { - return buserr.WithName(constant.ErrAppParamKey, formField.EnvKey) - } - } - - var dataMap map[string]interface{} - err = yaml.Unmarshal(paramByte, &dataMap) - if err != nil { - return buserr.WithMap(constant.ErrFileParseApp, map[string]interface{}{"name": "data.yml", "err": err.Error()}, err) - } - - additionalProperties, ok := dataMap["additionalProperties"].(map[string]interface{}) - if !ok { - return buserr.WithName(constant.ErrAppParamKey, "additionalProperties") - } - - formFieldsInterface, ok := additionalProperties["formFields"] - if ok { - formFields, ok := formFieldsInterface.([]interface{}) - if !ok { - return buserr.WithName(constant.ErrAppParamKey, "formFields") - } - for _, item := range formFields { - field := item.(map[string]interface{}) - for key, value := range field { - if value == nil { - return buserr.WithName(constant.ErrAppParamKey, key) - } - } - } - } - - appDetail.Params = string(dataJson) - return nil -} - -func handleLocalApp(appDir string) (app *model.App, err error) { - fileOp := files.NewFileOp() - configYamlPath := path.Join(appDir, "data.yml") - if !fileOp.Stat(configYamlPath) { - err = buserr.WithName(constant.ErrFileNotFound, "data.yml") - return - } - iconPath := path.Join(appDir, "logo.png") - if !fileOp.Stat(iconPath) { - err = buserr.WithName(constant.ErrFileNotFound, "logo.png") - return - } - configYamlByte, err := fileOp.GetContent(configYamlPath) - if err != nil { - err = buserr.WithMap(constant.ErrFileParseApp, map[string]interface{}{"name": "data.yml", "err": err.Error()}, err) - return - } - localAppDefine := dto.LocalAppAppDefine{} - if err = yaml.Unmarshal(configYamlByte, &localAppDefine); err != nil { - err = buserr.WithMap(constant.ErrFileParseApp, map[string]interface{}{"name": "data.yml", "err": err.Error()}, err) - return - } - app = &localAppDefine.AppProperty - app.Resource = constant.AppResourceLocal - app.Status = constant.AppNormal - app.Recommend = 9999 - app.TagsKey = append(app.TagsKey, "Local") - app.Key = "local" + app.Key - readMePath := path.Join(appDir, "README.md") - readMeByte, err := fileOp.GetContent(readMePath) - if err == nil { - app.ReadMe = string(readMeByte) - } - iconByte, _ := fileOp.GetContent(iconPath) - if iconByte != nil { - iconStr := base64.StdEncoding.EncodeToString(iconByte) - app.Icon = iconStr - } - return -} - -func handleErr(install model.AppInstall, err error, out string) error { - reErr := err - install.Message = err.Error() - if out != "" { - install.Message = out - reErr = errors.New(out) - } - install.Status = constant.UpErr - _ = appInstallRepo.Save(context.Background(), &install) - return reErr -} - -func doNotNeedSync(installed model.AppInstall) bool { - return installed.Status == constant.Installing || installed.Status == constant.Rebuilding || installed.Status == constant.Upgrading || - installed.Status == constant.Syncing -} - -func synAppInstall(containers map[string]types.Container, appInstall *model.AppInstall, force bool) { - containerNames := strings.Split(appInstall.ContainerName, ",") - if len(containers) == 0 { - if appInstall.Status == constant.UpErr && !force { - return - } - appInstall.Status = constant.Error - appInstall.Message = buserr.WithName("ErrContainerNotFound", strings.Join(containerNames, ",")).Error() - _ = appInstallRepo.Save(context.Background(), appInstall) - return - } - notFoundNames := make([]string, 0) - exitNames := make([]string, 0) - exitedCount := 0 - pausedCount := 0 - runningCount := 0 - total := len(containerNames) - for _, name := range containerNames { - if con, ok := containers["/"+name]; ok { - switch con.State { - case "exited": - exitedCount++ - exitNames = append(exitNames, name) - case "running": - runningCount++ - case "paused": - pausedCount++ - } - } else { - notFoundNames = append(notFoundNames, name) - } - } - switch { - case exitedCount == total: - appInstall.Status = constant.Stopped - case runningCount == total: - appInstall.Status = constant.Running - case pausedCount == total: - appInstall.Status = constant.Paused - case len(notFoundNames) == total: - if appInstall.Status == constant.UpErr && !force { - return - } - appInstall.Status = constant.Error - appInstall.Message = buserr.WithName("ErrContainerNotFound", strings.Join(notFoundNames, ",")).Error() - default: - var msg string - if exitedCount > 0 { - msg = buserr.WithName("ErrContainerMsg", strings.Join(exitNames, ",")).Error() - } - if len(notFoundNames) > 0 { - msg += buserr.WithName("ErrContainerNotFound", strings.Join(notFoundNames, ",")).Error() - } - if msg == "" { - msg = buserr.New("ErrAppWarn").Error() - } - appInstall.Message = msg - appInstall.Status = constant.UnHealthy - } - _ = appInstallRepo.Save(context.Background(), appInstall) -} - -func handleInstalled(appInstallList []model.AppInstall, updated bool, sync bool) ([]response.AppInstallDTO, error) { - var ( - res []response.AppInstallDTO - containersMap map[string]types.Container - ) - if sync { - cli, err := docker.NewClient() - if err != nil { - return nil, err - } - defer cli.Close() - containers, err := cli.ListAllContainers() - if err != nil { - return nil, err - } - containersMap = make(map[string]types.Container, len(containers)) - for _, contain := range containers { - containersMap[contain.Names[0]] = contain - } - } - - for _, installed := range appInstallList { - if updated && (installed.App.Type == "php" || installed.Status == constant.Installing || (installed.App.Key == constant.AppMysql && installed.Version == "5.6.51")) { - continue - } - if sync && !doNotNeedSync(installed) { - synAppInstall(containersMap, &installed, false) - } - - installDTO := response.AppInstallDTO{ - ID: installed.ID, - Name: installed.Name, - AppID: installed.AppId, - AppDetailID: installed.AppDetailId, - Version: installed.Version, - Status: installed.Status, - Message: installed.Message, - HttpPort: installed.HttpPort, - HttpsPort: installed.HttpsPort, - Icon: installed.App.Icon, - AppName: installed.App.Name, - AppKey: installed.App.Key, - AppType: installed.App.Type, - Path: installed.GetPath(), - CreatedAt: installed.CreatedAt, - App: response.AppDetail{ - Github: installed.App.Github, - Website: installed.App.Website, - Document: installed.App.Document, - }, - } - if updated { - installDTO.DockerCompose = installed.DockerCompose - } - app, err := appRepo.GetFirst(commonRepo.WithByID(installed.AppId)) - if err != nil { - return nil, err - } - details, err := appDetailRepo.GetBy(appDetailRepo.WithAppId(app.ID)) - if err != nil { - return nil, err - } - var versions []string - for _, detail := range details { - if detail.IgnoreUpgrade || installed.Version == "latest" { - continue - } - if common.IsCrossVersion(installed.Version, detail.Version) && !app.CrossVersionUpdate { - continue - } - versions = append(versions, detail.Version) - } - versions = common.GetSortedVersions(versions) - if len(versions) == 0 { - if !updated { - installDTO.CanUpdate = false - res = append(res, installDTO) - } - continue - } - lastVersion := versions[0] - if common.IsCrossVersion(installed.Version, lastVersion) { - installDTO.CanUpdate = app.CrossVersionUpdate - } else { - installDTO.CanUpdate = common.CompareVersion(lastVersion, installed.Version) - } - if updated { - if installDTO.CanUpdate { - res = append(res, installDTO) - } - } else { - res = append(res, installDTO) - } - } - return res, nil -} - -func getAppInstallByKey(key string) (model.AppInstall, error) { - app, err := appRepo.GetFirst(appRepo.WithKey(key)) - if err != nil { - return model.AppInstall{}, err - } - appInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithAppId(app.ID)) - if err != nil { - return model.AppInstall{}, err - } - return appInstall, nil -} - -func getAppInstallPort(key string) (httpPort, httpsPort int, err error) { - install, err := getAppInstallByKey(key) - if err != nil { - return - } - httpPort = install.HttpPort - httpsPort = install.HttpsPort - return -} - -func updateToolApp(installed *model.AppInstall) { - tooKey, ok := dto.AppToolMap[installed.App.Key] - if !ok { - return - } - toolInstall, _ := getAppInstallByKey(tooKey) - if reflect.DeepEqual(toolInstall, model.AppInstall{}) { - return - } - paramMap := make(map[string]string) - _ = json.Unmarshal([]byte(installed.Param), ¶mMap) - envMap := make(map[string]interface{}) - _ = json.Unmarshal([]byte(toolInstall.Env), &envMap) - if password, ok := paramMap["PANEL_DB_ROOT_PASSWORD"]; ok { - envMap["PANEL_DB_ROOT_PASSWORD"] = password - } - if _, ok := envMap["PANEL_REDIS_HOST"]; ok { - envMap["PANEL_REDIS_HOST"] = installed.ServiceName - } - if _, ok := envMap["PANEL_DB_HOST"]; ok { - envMap["PANEL_DB_HOST"] = installed.ServiceName - } - - envPath := path.Join(toolInstall.GetPath(), ".env") - contentByte, err := json.Marshal(envMap) - if err != nil { - global.LOG.Errorf("update tool app [%s] error : %s", toolInstall.Name, err.Error()) - return - } - envFileMap := make(map[string]string) - handleMap(envMap, envFileMap) - if err = env.Write(envFileMap, envPath); err != nil { - global.LOG.Errorf("update tool app [%s] error : %s", toolInstall.Name, err.Error()) - return - } - toolInstall.Env = string(contentByte) - if err := appInstallRepo.Save(context.Background(), &toolInstall); err != nil { - global.LOG.Errorf("update tool app [%s] error : %s", toolInstall.Name, err.Error()) - return - } - if out, err := compose.Down(toolInstall.GetComposePath()); err != nil { - global.LOG.Errorf("update tool app [%s] error : %s", toolInstall.Name, out) - return - } - if out, err := compose.Up(toolInstall.GetComposePath()); err != nil { - global.LOG.Errorf("update tool app [%s] error : %s", toolInstall.Name, out) - return - } -} - -func addDockerComposeCommonParam(composeMap map[string]interface{}, serviceName string, req request.AppContainerConfig, params map[string]interface{}) error { - services, serviceValid := composeMap["services"].(map[string]interface{}) - if !serviceValid { - return buserr.New(constant.ErrFileParse) - } - service, serviceExist := services[serviceName] - if !serviceExist { - return buserr.New(constant.ErrFileParse) - } - serviceValue := service.(map[string]interface{}) - - deploy := map[string]interface{}{} - if de, ok := serviceValue["deploy"]; ok { - deploy = de.(map[string]interface{}) - } - resource := map[string]interface{}{} - if res, ok := deploy["resources"]; ok { - resource = res.(map[string]interface{}) - } - resource["limits"] = map[string]interface{}{ - "cpus": "${CPUS}", - "memory": "${MEMORY_LIMIT}", - } - deploy["resources"] = resource - serviceValue["deploy"] = deploy - - ports, ok := serviceValue["ports"].([]interface{}) - if ok { - for i, port := range ports { - portStr, portOK := port.(string) - if !portOK { - continue - } - portArray := strings.Split(portStr, ":") - if len(portArray) == 2 { - portArray = append([]string{"${HOST_IP}"}, portArray...) - } - ports[i] = strings.Join(portArray, ":") - } - serviceValue["ports"] = ports - } - - params[constant.CPUS] = "0" - params[constant.MemoryLimit] = "0" - if req.Advanced { - if req.CpuQuota > 0 { - params[constant.CPUS] = req.CpuQuota - } - if req.MemoryLimit > 0 { - params[constant.MemoryLimit] = strconv.FormatFloat(req.MemoryLimit, 'f', -1, 32) + req.MemoryUnit - } - } - _, portExist := serviceValue["ports"].([]interface{}) - if portExist { - allowHost := "127.0.0.1" - if req.Advanced && req.AllowPort { - allowHost = "" - } - params[constant.HostIP] = allowHost - } - services[serviceName] = serviceValue - return nil -} - -func getAppCommonConfig(envs map[string]interface{}) request.AppContainerConfig { - config := request.AppContainerConfig{} - - if hostIp, ok := envs[constant.HostIP]; ok { - config.AllowPort = hostIp.(string) != "127.0.0.1" - } else { - config.AllowPort = true - } - if cpuCore, ok := envs[constant.CPUS]; ok { - numStr, ok := cpuCore.(string) - if ok { - num, err := strconv.ParseFloat(numStr, 64) - if err == nil { - config.CpuQuota = num - } - } else { - num64, flOk := cpuCore.(float64) - if flOk { - config.CpuQuota = num64 - } - } - } else { - config.CpuQuota = 0 - } - if memLimit, ok := envs[constant.MemoryLimit]; ok { - re := regexp.MustCompile(`(\d+)([A-Za-z]+)`) - matches := re.FindStringSubmatch(memLimit.(string)) - if len(matches) == 3 { - num, err := strconv.ParseFloat(matches[1], 64) - if err == nil { - unit := matches[2] - config.MemoryLimit = num - config.MemoryUnit = unit - } - } - } else { - config.MemoryLimit = 0 - config.MemoryUnit = "M" - } - - if containerName, ok := envs[constant.ContainerName]; ok { - config.ContainerName = containerName.(string) - } - - return config -} - -func isHostModel(dockerCompose string) bool { - composeMap := make(map[string]interface{}) - _ = yaml.Unmarshal([]byte(dockerCompose), &composeMap) - services, serviceValid := composeMap["services"].(map[string]interface{}) - if !serviceValid { - return false - } - for _, service := range services { - serviceValue := service.(map[string]interface{}) - if value, ok := serviceValue["network_mode"]; ok && value == "host" { - return true - } - } - return false -} diff --git a/backend/app/service/backup.go b/backend/app/service/backup.go deleted file mode 100644 index f355430e1..000000000 --- a/backend/app/service/backup.go +++ /dev/null @@ -1,637 +0,0 @@ -package service - -import ( - "bufio" - "context" - "encoding/base64" - "encoding/json" - "fmt" - "os" - "path" - "sort" - "strings" - "sync" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cloud_storage" - "github.com/1Panel-dev/1Panel/backend/utils/cloud_storage/client" - fileUtils "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/jinzhu/copier" - "github.com/pkg/errors" -) - -type BackupService struct{} - -type IBackupService interface { - List() ([]dto.BackupInfo, error) - SearchRecordsWithPage(search dto.RecordSearch) (int64, []dto.BackupRecords, error) - SearchRecordsByCronjobWithPage(search dto.RecordSearchByCronjob) (int64, []dto.BackupRecords, error) - LoadOneDriveInfo() (dto.OneDriveInfo, error) - DownloadRecord(info dto.DownloadRecord) (string, error) - Create(backupDto dto.BackupOperate) error - GetBuckets(backupDto dto.ForBuckets) ([]interface{}, error) - Update(ireq dto.BackupOperate) error - Delete(id uint) error - DeleteRecordByName(backupType, name, detailName string, withDeleteFile bool) error - BatchDeleteRecord(ids []uint) error - NewClient(backup *model.BackupAccount) (cloud_storage.CloudStorageClient, error) - - ListFiles(req dto.BackupSearchFile) []string - - MysqlBackup(db dto.CommonBackup) error - PostgresqlBackup(db dto.CommonBackup) error - MysqlRecover(db dto.CommonRecover) error - PostgresqlRecover(db dto.CommonRecover) error - MysqlRecoverByUpload(req dto.CommonRecover) error - PostgresqlRecoverByUpload(req dto.CommonRecover) error - - RedisBackup(db dto.CommonBackup) error - RedisRecover(db dto.CommonRecover) error - - WebsiteBackup(db dto.CommonBackup) error - WebsiteRecover(req dto.CommonRecover) error - - AppBackup(db dto.CommonBackup) (*model.BackupRecord, error) - AppRecover(req dto.CommonRecover) error - - Run() -} - -func NewIBackupService() IBackupService { - return &BackupService{} -} - -func (u *BackupService) List() ([]dto.BackupInfo, error) { - ops, err := backupRepo.List(commonRepo.WithOrderBy("created_at desc")) - var dtobas []dto.BackupInfo - dtobas = append(dtobas, u.loadByType("LOCAL", ops)) - dtobas = append(dtobas, u.loadByType("OSS", ops)) - dtobas = append(dtobas, u.loadByType("S3", ops)) - dtobas = append(dtobas, u.loadByType("SFTP", ops)) - dtobas = append(dtobas, u.loadByType("MINIO", ops)) - dtobas = append(dtobas, u.loadByType("COS", ops)) - dtobas = append(dtobas, u.loadByType("KODO", ops)) - dtobas = append(dtobas, u.loadByType("OneDrive", ops)) - dtobas = append(dtobas, u.loadByType("WebDAV", ops)) - return dtobas, err -} - -func (u *BackupService) SearchRecordsWithPage(search dto.RecordSearch) (int64, []dto.BackupRecords, error) { - total, records, err := backupRepo.PageRecord( - search.Page, search.PageSize, - commonRepo.WithOrderBy("created_at desc"), - commonRepo.WithByName(search.Name), - commonRepo.WithByType(search.Type), - backupRepo.WithByDetailName(search.DetailName), - ) - if err != nil { - return 0, nil, err - } - - datas, err := u.loadRecordSize(records) - sort.Slice(datas, func(i, j int) bool { - return datas[i].CreatedAt.After(datas[j].CreatedAt) - }) - return total, datas, err -} - -func (u *BackupService) SearchRecordsByCronjobWithPage(search dto.RecordSearchByCronjob) (int64, []dto.BackupRecords, error) { - total, records, err := backupRepo.PageRecord( - search.Page, search.PageSize, - commonRepo.WithOrderBy("created_at desc"), - backupRepo.WithByCronID(search.CronjobID), - ) - if err != nil { - return 0, nil, err - } - - datas, err := u.loadRecordSize(records) - sort.Slice(datas, func(i, j int) bool { - return datas[i].CreatedAt.After(datas[j].CreatedAt) - }) - return total, datas, err -} - -type loadSizeHelper struct { - isOk bool - backupPath string - client cloud_storage.CloudStorageClient -} - -func (u *BackupService) LoadOneDriveInfo() (dto.OneDriveInfo, error) { - var data dto.OneDriveInfo - data.RedirectUri = constant.OneDriveRedirectURI - clientID, err := settingRepo.Get(settingRepo.WithByKey("OneDriveID")) - if err != nil { - return data, err - } - idItem, err := base64.StdEncoding.DecodeString(clientID.Value) - if err != nil { - return data, err - } - data.ClientID = string(idItem) - clientSecret, err := settingRepo.Get(settingRepo.WithByKey("OneDriveSc")) - if err != nil { - return data, err - } - secretItem, err := base64.StdEncoding.DecodeString(clientSecret.Value) - if err != nil { - return data, err - } - data.ClientSecret = string(secretItem) - - return data, err -} - -func (u *BackupService) DownloadRecord(info dto.DownloadRecord) (string, error) { - if info.Source == "LOCAL" { - localDir, err := loadLocalDir() - if err != nil { - return "", err - } - return path.Join(localDir, info.FileDir, info.FileName), nil - } - backup, _ := backupRepo.Get(commonRepo.WithByType(info.Source)) - if backup.ID == 0 { - return "", constant.ErrRecordNotFound - } - varMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil { - return "", err - } - varMap["bucket"] = backup.Bucket - switch backup.Type { - case constant.Sftp, constant.WebDAV: - varMap["username"] = backup.AccessKey - varMap["password"] = backup.Credential - case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo: - varMap["accessKey"] = backup.AccessKey - varMap["secretKey"] = backup.Credential - case constant.OneDrive: - varMap["accessToken"] = backup.Credential - } - backClient, err := cloud_storage.NewCloudStorageClient(backup.Type, varMap) - if err != nil { - return "", fmt.Errorf("new cloud storage client failed, err: %v", err) - } - targetPath := fmt.Sprintf("%s/download/%s/%s", constant.DataDir, info.FileDir, info.FileName) - if _, err := os.Stat(path.Dir(targetPath)); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(path.Dir(targetPath), os.ModePerm); err != nil { - global.LOG.Errorf("mkdir %s failed, err: %v", path.Dir(targetPath), err) - } - } - srcPath := fmt.Sprintf("%s/%s", info.FileDir, info.FileName) - if len(backup.BackupPath) != 0 { - srcPath = path.Join(strings.TrimPrefix(backup.BackupPath, "/"), srcPath) - } - if exist, _ := backClient.Exist(srcPath); exist { - isOK, err := backClient.Download(srcPath, targetPath) - if !isOK { - return "", fmt.Errorf("cloud storage download failed, err: %v", err) - } - } - return targetPath, nil -} - -func (u *BackupService) Create(req dto.BackupOperate) error { - backup, _ := backupRepo.Get(commonRepo.WithByType(req.Type)) - if backup.ID != 0 { - return constant.ErrRecordExist - } - if err := copier.Copy(&backup, &req); err != nil { - return errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - - if req.Type == constant.OneDrive { - if err := u.loadAccessToken(&backup); err != nil { - return err - } - } - if req.Type != "LOCAL" { - if _, err := u.checkBackupConn(&backup); err != nil { - return buserr.WithMap("ErrBackupCheck", map[string]interface{}{"err": err.Error()}, err) - } - } - if backup.Type == constant.OneDrive { - StartRefreshOneDriveToken() - } - if err := backupRepo.Create(&backup); err != nil { - return err - } - return nil -} - -func (u *BackupService) GetBuckets(backupDto dto.ForBuckets) ([]interface{}, error) { - varMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(backupDto.Vars), &varMap); err != nil { - return nil, err - } - switch backupDto.Type { - case constant.Sftp, constant.WebDAV: - varMap["username"] = backupDto.AccessKey - varMap["password"] = backupDto.Credential - case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo: - varMap["accessKey"] = backupDto.AccessKey - varMap["secretKey"] = backupDto.Credential - } - client, err := cloud_storage.NewCloudStorageClient(backupDto.Type, varMap) - if err != nil { - return nil, err - } - return client.ListBuckets() -} - -func (u *BackupService) Delete(id uint) error { - backup, _ := backupRepo.Get(commonRepo.WithByID(id)) - if backup.ID == 0 { - return constant.ErrRecordNotFound - } - if backup.Type == constant.OneDrive { - global.Cron.Remove(global.OneDriveCronID) - } - cronjobs, _ := cronjobRepo.List(cronjobRepo.WithByDefaultDownload(backup.Type)) - if len(cronjobs) != 0 { - return buserr.New(constant.ErrBackupInUsed) - } - return backupRepo.Delete(commonRepo.WithByID(id)) -} - -func (u *BackupService) DeleteRecordByName(backupType, name, detailName string, withDeleteFile bool) error { - if !withDeleteFile { - return backupRepo.DeleteRecord(context.Background(), commonRepo.WithByType(backupType), commonRepo.WithByName(name), backupRepo.WithByDetailName(detailName)) - } - - records, err := backupRepo.ListRecord(commonRepo.WithByType(backupType), commonRepo.WithByName(name), backupRepo.WithByDetailName(detailName)) - if err != nil { - return err - } - - for _, record := range records { - backupAccount, err := backupRepo.Get(commonRepo.WithByType(record.Source)) - if err != nil { - global.LOG.Errorf("load backup account %s info from db failed, err: %v", record.Source, err) - continue - } - client, err := u.NewClient(&backupAccount) - if err != nil { - global.LOG.Errorf("new client for backup account %s failed, err: %v", record.Source, err) - continue - } - if _, err = client.Delete(path.Join(record.FileDir, record.FileName)); err != nil { - global.LOG.Errorf("remove file %s from %s failed, err: %v", path.Join(record.FileDir, record.FileName), record.Source, err) - } - _ = backupRepo.DeleteRecord(context.Background(), commonRepo.WithByID(record.ID)) - } - return nil -} - -func (u *BackupService) BatchDeleteRecord(ids []uint) error { - records, err := backupRepo.ListRecord(commonRepo.WithIdsIn(ids)) - if err != nil { - return err - } - for _, record := range records { - backupAccount, err := backupRepo.Get(commonRepo.WithByType(record.Source)) - if err != nil { - global.LOG.Errorf("load backup account %s info from db failed, err: %v", record.Source, err) - continue - } - client, err := u.NewClient(&backupAccount) - if err != nil { - global.LOG.Errorf("new client for backup account %s failed, err: %v", record.Source, err) - continue - } - if _, err = client.Delete(path.Join(record.FileDir, record.FileName)); err != nil { - global.LOG.Errorf("remove file %s from %s failed, err: %v", path.Join(record.FileDir, record.FileName), record.Source, err) - } - } - return backupRepo.DeleteRecord(context.Background(), commonRepo.WithIdsIn(ids)) -} - -func (u *BackupService) Update(req dto.BackupOperate) error { - backup, err := backupRepo.Get(commonRepo.WithByID(req.ID)) - if err != nil { - return constant.ErrRecordNotFound - } - varMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(req.Vars), &varMap); err != nil { - return err - } - - oldVars := backup.Vars - oldDir, err := loadLocalDir() - if err != nil { - return err - } - upMap := make(map[string]interface{}) - upMap["bucket"] = req.Bucket - upMap["access_key"] = req.AccessKey - upMap["credential"] = req.Credential - upMap["backup_path"] = req.BackupPath - upMap["vars"] = req.Vars - backup.Bucket = req.Bucket - backup.Vars = req.Vars - backup.Credential = req.Credential - backup.AccessKey = req.AccessKey - backup.BackupPath = req.BackupPath - - if req.Type == constant.OneDrive { - if err := u.loadAccessToken(&backup); err != nil { - return err - } - upMap["credential"] = backup.Credential - upMap["vars"] = backup.Vars - } - if backup.Type != "LOCAL" { - isOk, err := u.checkBackupConn(&backup) - if err != nil || !isOk { - return buserr.WithMap("ErrBackupCheck", map[string]interface{}{"err": err.Error()}, err) - } - } - - if err := backupRepo.Update(req.ID, upMap); err != nil { - return err - } - if backup.Type == "LOCAL" { - if dir, ok := varMap["dir"]; ok { - if dirStr, isStr := dir.(string); isStr { - if strings.HasSuffix(dirStr, "/") && dirStr != "/" { - dirStr = dirStr[:strings.LastIndex(dirStr, "/")] - } - if err := copyDir(oldDir, dirStr); err != nil { - _ = backupRepo.Update(req.ID, map[string]interface{}{"vars": oldVars}) - return err - } - global.CONF.System.Backup = dirStr - } - } - } - return nil -} - -func (u *BackupService) ListFiles(req dto.BackupSearchFile) []string { - var datas []string - backup, err := backupRepo.Get(backupRepo.WithByType(req.Type)) - if err != nil { - return datas - } - client, err := u.NewClient(&backup) - if err != nil { - return datas - } - prefix := "system_snapshot" - if len(backup.BackupPath) != 0 { - prefix = path.Join(strings.TrimPrefix(backup.BackupPath, "/"), prefix) - } - files, err := client.ListObjects(prefix) - if err != nil { - global.LOG.Debugf("load files from %s failed, err: %v", req.Type, err) - return datas - } - for _, file := range files { - if len(file) != 0 { - datas = append(datas, path.Base(file)) - } - } - return datas -} - -func (u *BackupService) NewClient(backup *model.BackupAccount) (cloud_storage.CloudStorageClient, error) { - varMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil { - return nil, err - } - varMap["bucket"] = backup.Bucket - switch backup.Type { - case constant.Sftp, constant.WebDAV: - varMap["username"] = backup.AccessKey - varMap["password"] = backup.Credential - case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo: - varMap["accessKey"] = backup.AccessKey - varMap["secretKey"] = backup.Credential - } - - backClient, err := cloud_storage.NewCloudStorageClient(backup.Type, varMap) - if err != nil { - return nil, err - } - - return backClient, nil -} - -func (u *BackupService) loadByType(accountType string, accounts []model.BackupAccount) dto.BackupInfo { - for _, account := range accounts { - if account.Type == accountType { - var item dto.BackupInfo - if err := copier.Copy(&item, &account); err != nil { - global.LOG.Errorf("copy backup account to dto backup info failed, err: %v", err) - } - if account.Type == constant.OneDrive { - varMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(item.Vars), &varMap); err != nil { - return dto.BackupInfo{Type: accountType} - } - delete(varMap, "refresh_token") - itemVars, _ := json.Marshal(varMap) - item.Vars = string(itemVars) - } - return item - } - } - return dto.BackupInfo{Type: accountType} -} - -func (u *BackupService) loadAccessToken(backup *model.BackupAccount) error { - varMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil { - return fmt.Errorf("unmarshal backup vars failed, err: %v", err) - } - refreshToken, err := client.RefreshToken("authorization_code", "refreshToken", varMap) - if err != nil { - return err - } - delete(varMap, "code") - varMap["refresh_status"] = constant.StatusSuccess - varMap["refresh_time"] = time.Now().Format(constant.DateTimeLayout) - varMap["refresh_token"] = refreshToken - itemVars, err := json.Marshal(varMap) - if err != nil { - return fmt.Errorf("json marshal var map failed, err: %v", err) - } - backup.Vars = string(itemVars) - return nil -} - -func (u *BackupService) loadRecordSize(records []model.BackupRecord) ([]dto.BackupRecords, error) { - var datas []dto.BackupRecords - clientMap := make(map[string]loadSizeHelper) - var wg sync.WaitGroup - for i := 0; i < len(records); i++ { - var item dto.BackupRecords - if err := copier.Copy(&item, &records[i]); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - itemPath := path.Join(records[i].FileDir, records[i].FileName) - if _, ok := clientMap[records[i].Source]; !ok { - backup, err := backupRepo.Get(commonRepo.WithByType(records[i].Source)) - if err != nil { - global.LOG.Errorf("load backup model %s from db failed, err: %v", records[i].Source, err) - clientMap[records[i].Source] = loadSizeHelper{} - datas = append(datas, item) - continue - } - client, err := u.NewClient(&backup) - if err != nil { - global.LOG.Errorf("load backup client %s from db failed, err: %v", records[i].Source, err) - clientMap[records[i].Source] = loadSizeHelper{} - datas = append(datas, item) - continue - } - item.Size, _ = client.Size(path.Join(strings.TrimLeft(backup.BackupPath, "/"), itemPath)) - datas = append(datas, item) - clientMap[records[i].Source] = loadSizeHelper{backupPath: strings.TrimLeft(backup.BackupPath, "/"), client: client, isOk: true} - continue - } - if clientMap[records[i].Source].isOk { - wg.Add(1) - go func(index int) { - item.Size, _ = clientMap[records[index].Source].client.Size(path.Join(clientMap[records[index].Source].backupPath, itemPath)) - datas = append(datas, item) - wg.Done() - }(i) - } else { - datas = append(datas, item) - } - } - wg.Wait() - return datas, nil -} - -func loadLocalDir() (string, error) { - backup, err := backupRepo.Get(commonRepo.WithByType("LOCAL")) - if err != nil { - return "", err - } - varMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil { - return "", err - } - if _, ok := varMap["dir"]; !ok { - return "", errors.New("load local backup dir failed") - } - baseDir, ok := varMap["dir"].(string) - if ok { - if _, err := os.Stat(baseDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(baseDir, os.ModePerm); err != nil { - return "", fmt.Errorf("mkdir %s failed, err: %v", baseDir, err) - } - } - return baseDir, nil - } - return "", fmt.Errorf("error type dir: %T", varMap["dir"]) -} - -func copyDir(src, dst string) error { - srcInfo, err := os.Stat(src) - if err != nil { - return err - } - if err = os.MkdirAll(dst, srcInfo.Mode()); err != nil { - return err - } - files, err := os.ReadDir(src) - if err != nil { - return err - } - - fileOP := fileUtils.NewFileOp() - for _, file := range files { - srcPath := fmt.Sprintf("%s/%s", src, file.Name()) - dstPath := fmt.Sprintf("%s/%s", dst, file.Name()) - if file.IsDir() { - if err = copyDir(srcPath, dstPath); err != nil { - global.LOG.Errorf("copy dir %s to %s failed, err: %v", srcPath, dstPath, err) - } - } else { - if err := fileOP.CopyFile(srcPath, dst); err != nil { - global.LOG.Errorf("copy file %s to %s failed, err: %v", srcPath, dstPath, err) - } - } - } - - return nil -} - -func (u *BackupService) checkBackupConn(backup *model.BackupAccount) (bool, error) { - client, err := u.NewClient(backup) - if err != nil { - return false, err - } - fileItem := path.Join(global.CONF.System.TmpDir, "test", "1panel") - if _, err := os.Stat(path.Dir(fileItem)); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(path.Dir(fileItem), os.ModePerm); err != nil { - return false, err - } - } - file, err := os.OpenFile(fileItem, os.O_WRONLY|os.O_CREATE, 0666) - if err != nil { - return false, err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString("1Panel 备份账号测试文件。\n") - _, _ = write.WriteString("1Panel 備份賬號測試文件。\n") - _, _ = write.WriteString("1Panel Backs up account test files.\n") - _, _ = write.WriteString("1Panelアカウントのテストファイルをバックアップします。\n") - write.Flush() - - targetPath := strings.TrimPrefix(path.Join(backup.BackupPath, "test/1panel"), "/") - return client.Upload(fileItem, targetPath) -} - -func StartRefreshOneDriveToken() { - service := NewIBackupService() - oneDriveCronID, err := global.Cron.AddJob("0 3 */31 * *", service) - if err != nil { - global.LOG.Errorf("can not add OneDrive corn job: %s", err.Error()) - return - } - global.OneDriveCronID = oneDriveCronID -} - -func (u *BackupService) Run() { - var backupItem model.BackupAccount - _ = global.DB.Where("`type` = ?", "OneDrive").First(&backupItem) - if backupItem.ID == 0 { - return - } - global.LOG.Info("start to refresh token of OneDrive ...") - varMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(backupItem.Vars), &varMap); err != nil { - global.LOG.Errorf("Failed to refresh OneDrive token, please retry, err: %v", err) - return - } - refreshToken, err := client.RefreshToken("refresh_token", "refreshToken", varMap) - varMap["refresh_status"] = constant.StatusSuccess - varMap["refresh_time"] = time.Now().Format(constant.DateTimeLayout) - if err != nil { - varMap["refresh_status"] = constant.StatusFailed - varMap["refresh_msg"] = err.Error() - global.LOG.Errorf("Failed to refresh OneDrive token, please retry, err: %v", err) - return - } - varMap["refresh_token"] = refreshToken - - varsItem, _ := json.Marshal(varMap) - _ = global.DB.Model(&model.BackupAccount{}). - Where("id = ?", backupItem.ID). - Updates(map[string]interface{}{ - "vars": varsItem, - }).Error - global.LOG.Info("Successfully refreshed OneDrive token.") -} diff --git a/backend/app/service/backup_app.go b/backend/app/service/backup_app.go deleted file mode 100644 index 2a1e0ccaf..000000000 --- a/backend/app/service/backup_app.go +++ /dev/null @@ -1,315 +0,0 @@ -package service - -import ( - "context" - "encoding/json" - "fmt" - "io/fs" - "os" - "path" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/buserr" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/compose" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/pkg/errors" -) - -func (u *BackupService) AppBackup(req dto.CommonBackup) (*model.BackupRecord, error) { - localDir, err := loadLocalDir() - if err != nil { - return nil, err - } - app, err := appRepo.GetFirst(appRepo.WithKey(req.Name)) - if err != nil { - return nil, err - } - install, err := appInstallRepo.GetFirst(commonRepo.WithByName(req.DetailName), appInstallRepo.WithAppId(app.ID)) - if err != nil { - return nil, err - } - timeNow := time.Now().Format(constant.DateTimeSlimLayout) - itemDir := fmt.Sprintf("app/%s/%s", req.Name, req.DetailName) - backupDir := path.Join(localDir, itemDir) - - fileName := fmt.Sprintf("%s_%s.tar.gz", req.DetailName, timeNow+common.RandStrAndNum(5)) - if err := handleAppBackup(&install, backupDir, fileName, "", req.Secret); err != nil { - return nil, err - } - - record := &model.BackupRecord{ - Type: "app", - Name: req.Name, - DetailName: req.DetailName, - Source: "LOCAL", - BackupType: "LOCAL", - FileDir: itemDir, - FileName: fileName, - } - - if err := backupRepo.CreateRecord(record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) - return nil, err - } - return record, nil -} - -func (u *BackupService) AppRecover(req dto.CommonRecover) error { - app, err := appRepo.GetFirst(appRepo.WithKey(req.Name)) - if err != nil { - return err - } - install, err := appInstallRepo.GetFirst(commonRepo.WithByName(req.DetailName), appInstallRepo.WithAppId(app.ID)) - if err != nil { - return err - } - - fileOp := files.NewFileOp() - if !fileOp.Stat(req.File) { - return buserr.WithName("ErrFileNotFound", req.File) - } - if _, err := compose.Down(install.GetComposePath()); err != nil { - return err - } - if err := handleAppRecover(&install, req.File, false, req.Secret); err != nil { - return err - } - return nil -} - -func handleAppBackup(install *model.AppInstall, backupDir, fileName string, excludes string, secret string) error { - fileOp := files.NewFileOp() - tmpDir := fmt.Sprintf("%s/%s", backupDir, strings.ReplaceAll(fileName, ".tar.gz", "")) - if !fileOp.Stat(tmpDir) { - if err := os.MkdirAll(tmpDir, os.ModePerm); err != nil { - return fmt.Errorf("mkdir %s failed, err: %v", backupDir, err) - } - } - defer func() { - _ = os.RemoveAll(tmpDir) - }() - - remarkInfo, _ := json.Marshal(install) - remarkInfoPath := fmt.Sprintf("%s/app.json", tmpDir) - if err := fileOp.SaveFile(remarkInfoPath, string(remarkInfo), fs.ModePerm); err != nil { - return err - } - - appPath := install.GetPath() - if err := handleTar(appPath, tmpDir, "app.tar.gz", excludes, ""); err != nil { - return err - } - - resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID)) - for _, resource := range resources { - switch resource.Key { - case constant.AppMysql, constant.AppMariaDB: - db, err := mysqlRepo.Get(commonRepo.WithByID(resource.ResourceId)) - if err != nil { - return err - } - if err := handleMysqlBackup(db.MysqlName, resource.Key, db.Name, tmpDir, fmt.Sprintf("%s.sql.gz", install.Name)); err != nil { - return err - } - case constant.AppPostgresql: - db, err := postgresqlRepo.Get(commonRepo.WithByID(resource.ResourceId)) - if err != nil { - return err - } - if err := handlePostgresqlBackup(db.PostgresqlName, db.Name, tmpDir, fmt.Sprintf("%s.sql.gz", install.Name)); err != nil { - return err - } - } - } - - if err := handleTar(tmpDir, backupDir, fileName, "", secret); err != nil { - return err - } - return nil -} - -func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback bool, secret string) error { - isOk := false - fileOp := files.NewFileOp() - if err := handleUnTar(recoverFile, path.Dir(recoverFile), secret); err != nil { - return err - } - tmpPath := strings.ReplaceAll(recoverFile, ".tar.gz", "") - defer func() { - _, _ = compose.Up(install.GetComposePath()) - _ = os.RemoveAll(strings.ReplaceAll(recoverFile, ".tar.gz", "")) - }() - - if !fileOp.Stat(tmpPath+"/app.json") || !fileOp.Stat(tmpPath+"/app.tar.gz") { - return errors.New("the wrong recovery package does not have app.json or app.tar.gz files") - } - var oldInstall model.AppInstall - appjson, err := os.ReadFile(tmpPath + "/app.json") - if err != nil { - return err - } - if err := json.Unmarshal(appjson, &oldInstall); err != nil { - return fmt.Errorf("unmarshal app.json failed, err: %v", err) - } - if oldInstall.App.Key != install.App.Key || oldInstall.Name != install.Name { - return errors.New("the current backup file does not match the application") - } - - if !isRollback { - rollbackFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("app/%s_%s.tar.gz", install.Name, time.Now().Format(constant.DateTimeSlimLayout))) - if err := handleAppBackup(install, path.Dir(rollbackFile), path.Base(rollbackFile), "", ""); err != nil { - return fmt.Errorf("backup app %s for rollback before recover failed, err: %v", install.Name, err) - } - defer func() { - if !isOk { - global.LOG.Info("recover failed, start to rollback now") - if err := handleAppRecover(install, rollbackFile, true, secret); err != nil { - global.LOG.Errorf("rollback app %s from %s failed, err: %v", install.Name, rollbackFile, err) - return - } - global.LOG.Infof("rollback app %s from %s successful", install.Name, rollbackFile) - _ = os.RemoveAll(rollbackFile) - } else { - _ = os.RemoveAll(rollbackFile) - } - }() - } - - newEnvFile := "" - resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID)) - for _, resource := range resources { - var database model.Database - switch resource.From { - case constant.AppResourceRemote: - database, err = databaseRepo.Get(commonRepo.WithByID(resource.LinkId)) - if err != nil { - return err - } - case constant.AppResourceLocal: - resourceApp, err := appInstallRepo.GetFirst(commonRepo.WithByID(resource.LinkId)) - if err != nil { - return err - } - database, err = databaseRepo.Get(databaseRepo.WithAppInstallID(resourceApp.ID), commonRepo.WithByType(resource.Key), databaseRepo.WithByFrom(constant.AppResourceLocal), commonRepo.WithByName(resourceApp.Name)) - if err != nil { - return err - } - } - switch database.Type { - case constant.AppPostgresql: - db, err := postgresqlRepo.Get(commonRepo.WithByID(resource.ResourceId)) - if err != nil { - return err - } - if err := handlePostgresqlRecover(dto.CommonRecover{ - Name: database.Name, - DetailName: db.Name, - File: fmt.Sprintf("%s/%s.sql.gz", tmpPath, install.Name), - }, true); err != nil { - global.LOG.Errorf("handle recover from sql.gz failed, err: %v", err) - return err - } - case constant.AppMysql, constant.AppMariaDB: - db, err := mysqlRepo.Get(commonRepo.WithByID(resource.ResourceId)) - if err != nil { - return err - } - newDB, envMap, err := reCreateDB(db.ID, database, oldInstall.Env) - if err != nil { - return err - } - oldHost := fmt.Sprintf("\"PANEL_DB_HOST\":\"%v\"", envMap["PANEL_DB_HOST"].(string)) - newHost := fmt.Sprintf("\"PANEL_DB_HOST\":\"%v\"", database.Address) - oldInstall.Env = strings.ReplaceAll(oldInstall.Env, oldHost, newHost) - envMap["PANEL_DB_HOST"] = database.Address - newEnvFile, err = coverEnvJsonToStr(oldInstall.Env) - if err != nil { - return err - } - _ = appInstallResourceRepo.BatchUpdateBy(map[string]interface{}{"resource_id": newDB.ID}, commonRepo.WithByID(resource.ID)) - - if err := handleMysqlRecover(dto.CommonRecover{ - Name: newDB.MysqlName, - DetailName: newDB.Name, - File: fmt.Sprintf("%s/%s.sql.gz", tmpPath, install.Name), - }, true); err != nil { - global.LOG.Errorf("handle recover from sql.gz failed, err: %v", err) - return err - } - } - } - - appDir := install.GetPath() - backPath := fmt.Sprintf("%s_bak", appDir) - _ = fileOp.Rename(appDir, backPath) - _ = fileOp.CreateDir(appDir, 0755) - - if err := handleUnTar(tmpPath+"/app.tar.gz", install.GetAppPath(), ""); err != nil { - global.LOG.Errorf("handle recover from app.tar.gz failed, err: %v", err) - _ = fileOp.DeleteDir(appDir) - _ = fileOp.Rename(backPath, appDir) - return err - } - _ = fileOp.DeleteDir(backPath) - - if len(newEnvFile) != 0 { - envPath := fmt.Sprintf("%s/%s/.env", install.GetAppPath(), install.Name) - file, err := os.OpenFile(envPath, os.O_WRONLY|os.O_TRUNC, 0640) - if err != nil { - return err - } - defer file.Close() - _, _ = file.WriteString(newEnvFile) - } - - oldInstall.ID = install.ID - oldInstall.Status = constant.StatusRunning - oldInstall.AppId = install.AppId - oldInstall.AppDetailId = install.AppDetailId - oldInstall.App.ID = install.AppId - if err := appInstallRepo.Save(context.Background(), &oldInstall); err != nil { - global.LOG.Errorf("save db app install failed, err: %v", err) - return err - } - isOk = true - - return nil -} - -func reCreateDB(dbID uint, database model.Database, oldEnv string) (*model.DatabaseMysql, map[string]interface{}, error) { - mysqlService := NewIMysqlService() - ctx := context.Background() - _ = mysqlService.Delete(ctx, dto.MysqlDBDelete{ID: dbID, Database: database.Name, Type: database.Type, DeleteBackup: false, ForceDelete: true}) - - envMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(oldEnv), &envMap); err != nil { - return nil, envMap, err - } - oldName, _ := envMap["PANEL_DB_NAME"].(string) - oldUser, _ := envMap["PANEL_DB_USER"].(string) - oldPassword, _ := envMap["PANEL_DB_USER_PASSWORD"].(string) - createDB, err := mysqlService.Create(context.Background(), dto.MysqlDBCreate{ - Name: oldName, - From: database.From, - Database: database.Name, - Format: "utf8mb4", - Username: oldUser, - Password: oldPassword, - Permission: "%", - }) - cronjobs, _ := cronjobRepo.List(cronjobRepo.WithByDbName(fmt.Sprintf("%v", dbID))) - for _, job := range cronjobs { - _ = cronjobRepo.Update(job.ID, map[string]interface{}{"db_name": fmt.Sprintf("%v", createDB.ID)}) - } - if err != nil { - return nil, envMap, err - } - return createDB, envMap, nil -} diff --git a/backend/app/service/backup_mysql.go b/backend/app/service/backup_mysql.go deleted file mode 100644 index 40a1d90ce..000000000 --- a/backend/app/service/backup_mysql.go +++ /dev/null @@ -1,193 +0,0 @@ -package service - -import ( - "fmt" - "github.com/1Panel-dev/1Panel/backend/constant" - "os" - "path" - "path/filepath" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/buserr" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/1Panel-dev/1Panel/backend/utils/mysql/client" -) - -func (u *BackupService) MysqlBackup(req dto.CommonBackup) error { - localDir, err := loadLocalDir() - if err != nil { - return err - } - - timeNow := time.Now().Format(constant.DateTimeSlimLayout) - itemDir := fmt.Sprintf("database/%s/%s/%s", req.Type, req.Name, req.DetailName) - targetDir := path.Join(localDir, itemDir) - fileName := fmt.Sprintf("%s_%s.sql.gz", req.DetailName, timeNow+common.RandStrAndNum(5)) - - if err := handleMysqlBackup(req.Name, req.Type, req.DetailName, targetDir, fileName); err != nil { - return err - } - - record := &model.BackupRecord{ - Type: req.Type, - Name: req.Name, - DetailName: req.DetailName, - Source: "LOCAL", - BackupType: "LOCAL", - FileDir: itemDir, - FileName: fileName, - } - if err := backupRepo.CreateRecord(record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) - } - return nil -} - -func (u *BackupService) MysqlRecover(req dto.CommonRecover) error { - if err := handleMysqlRecover(req, false); err != nil { - return err - } - return nil -} - -func (u *BackupService) MysqlRecoverByUpload(req dto.CommonRecover) error { - file := req.File - fileName := path.Base(req.File) - if strings.HasSuffix(fileName, ".tar.gz") { - fileNameItem := time.Now().Format(constant.DateTimeSlimLayout) - dstDir := fmt.Sprintf("%s/%s", path.Dir(req.File), fileNameItem) - if _, err := os.Stat(dstDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(dstDir, os.ModePerm); err != nil { - return fmt.Errorf("mkdir %s failed, err: %v", dstDir, err) - } - } - if err := handleUnTar(req.File, dstDir, ""); err != nil { - _ = os.RemoveAll(dstDir) - return err - } - global.LOG.Infof("decompress file %s successful, now start to check test.sql is exist", req.File) - hasTestSql := false - _ = filepath.Walk(dstDir, func(path string, info os.FileInfo, err error) error { - if err != nil { - return nil - } - if !info.IsDir() && info.Name() == "test.sql" { - hasTestSql = true - file = path - fileName = "test.sql" - } - return nil - }) - if !hasTestSql { - _ = os.RemoveAll(dstDir) - return fmt.Errorf("no such file named test.sql in %s", fileName) - } - defer func() { - _ = os.RemoveAll(dstDir) - }() - } - - req.File = path.Dir(file) + "/" + fileName - if err := handleMysqlRecover(req, false); err != nil { - return err - } - global.LOG.Info("recover from uploads successful!") - return nil -} - -func handleMysqlBackup(database, dbType, dbName, targetDir, fileName string) error { - dbInfo, err := mysqlRepo.Get(commonRepo.WithByName(dbName), mysqlRepo.WithByMysqlName(database)) - if err != nil { - return err - } - cli, version, err := LoadMysqlClientByFrom(database) - if err != nil { - return err - } - - backupInfo := client.BackupInfo{ - Name: dbName, - Type: dbType, - Version: version, - Format: dbInfo.Format, - TargetDir: targetDir, - FileName: fileName, - - Timeout: 300, - } - if err := cli.Backup(backupInfo); err != nil { - return err - } - return nil -} - -func handleMysqlRecover(req dto.CommonRecover, isRollback bool) error { - isOk := false - fileOp := files.NewFileOp() - if !fileOp.Stat(req.File) { - return buserr.WithName("ErrFileNotFound", req.File) - } - dbInfo, err := mysqlRepo.Get(commonRepo.WithByName(req.DetailName), mysqlRepo.WithByMysqlName(req.Name)) - if err != nil { - return err - } - cli, version, err := LoadMysqlClientByFrom(req.Name) - if err != nil { - return err - } - - if !isRollback { - rollbackFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("database/%s/%s_%s.sql.gz", req.Type, req.DetailName, time.Now().Format(constant.DateTimeSlimLayout))) - if err := cli.Backup(client.BackupInfo{ - Name: req.DetailName, - Type: req.Type, - Version: version, - Format: dbInfo.Format, - TargetDir: path.Dir(rollbackFile), - FileName: path.Base(rollbackFile), - - Timeout: 300, - }); err != nil { - return fmt.Errorf("backup mysql db %s for rollback before recover failed, err: %v", req.DetailName, err) - } - defer func() { - if !isOk { - global.LOG.Info("recover failed, start to rollback now") - if err := cli.Recover(client.RecoverInfo{ - Name: req.DetailName, - Type: req.Type, - Version: version, - Format: dbInfo.Format, - SourceFile: rollbackFile, - - Timeout: 300, - }); err != nil { - global.LOG.Errorf("rollback mysql db %s from %s failed, err: %v", req.DetailName, rollbackFile, err) - } - global.LOG.Infof("rollback mysql db %s from %s successful", req.DetailName, rollbackFile) - _ = os.RemoveAll(rollbackFile) - } else { - _ = os.RemoveAll(rollbackFile) - } - }() - } - if err := cli.Recover(client.RecoverInfo{ - Name: req.DetailName, - Type: req.Type, - Version: version, - Format: dbInfo.Format, - SourceFile: req.File, - - Timeout: 300, - }); err != nil { - return err - } - isOk = true - return nil -} diff --git a/backend/app/service/backup_postgresql.go b/backend/app/service/backup_postgresql.go deleted file mode 100644 index ee2d7852f..000000000 --- a/backend/app/service/backup_postgresql.go +++ /dev/null @@ -1,178 +0,0 @@ -package service - -import ( - "fmt" - "github.com/1Panel-dev/1Panel/backend/constant" - "os" - "path" - "path/filepath" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/utils/common" - pgclient "github.com/1Panel-dev/1Panel/backend/utils/postgresql/client" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/1Panel-dev/1Panel/backend/utils/postgresql/client" -) - -func (u *BackupService) PostgresqlBackup(req dto.CommonBackup) error { - localDir, err := loadLocalDir() - if err != nil { - return err - } - - timeNow := time.Now().Format(constant.DateTimeSlimLayout) - itemDir := fmt.Sprintf("database/%s/%s/%s", req.Type, req.Name, req.DetailName) - targetDir := path.Join(localDir, itemDir) - fileName := fmt.Sprintf("%s_%s.sql.gz", req.DetailName, timeNow+common.RandStrAndNum(5)) - - if err := handlePostgresqlBackup(req.Name, req.DetailName, targetDir, fileName); err != nil { - return err - } - - record := &model.BackupRecord{ - Type: req.Type, - Name: req.Name, - DetailName: req.DetailName, - Source: "LOCAL", - BackupType: "LOCAL", - FileDir: itemDir, - FileName: fileName, - } - if err := backupRepo.CreateRecord(record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) - } - return nil -} -func (u *BackupService) PostgresqlRecover(req dto.CommonRecover) error { - if err := handlePostgresqlRecover(req, false); err != nil { - return err - } - return nil -} - -func (u *BackupService) PostgresqlRecoverByUpload(req dto.CommonRecover) error { - file := req.File - fileName := path.Base(req.File) - if strings.HasSuffix(fileName, ".tar.gz") { - fileNameItem := time.Now().Format(constant.DateTimeSlimLayout) - dstDir := fmt.Sprintf("%s/%s", path.Dir(req.File), fileNameItem) - if _, err := os.Stat(dstDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(dstDir, os.ModePerm); err != nil { - return fmt.Errorf("mkdir %s failed, err: %v", dstDir, err) - } - } - if err := handleUnTar(req.File, dstDir, ""); err != nil { - _ = os.RemoveAll(dstDir) - return err - } - global.LOG.Infof("decompress file %s successful, now start to check test.sql is exist", req.File) - hasTestSql := false - _ = filepath.Walk(dstDir, func(path string, info os.FileInfo, err error) error { - if err != nil { - return nil - } - if !info.IsDir() && info.Name() == "test.sql" { - hasTestSql = true - file = path - fileName = "test.sql" - } - return nil - }) - if !hasTestSql { - _ = os.RemoveAll(dstDir) - return fmt.Errorf("no such file named test.sql in %s", fileName) - } - defer func() { - _ = os.RemoveAll(dstDir) - }() - } - - req.File = path.Dir(file) + "/" + fileName - if err := handlePostgresqlRecover(req, false); err != nil { - return err - } - global.LOG.Info("recover from uploads successful!") - return nil -} -func handlePostgresqlBackup(database, dbName, targetDir, fileName string) error { - cli, err := LoadPostgresqlClientByFrom(database) - if err != nil { - return err - } - defer cli.Close() - - backupInfo := pgclient.BackupInfo{ - Name: dbName, - TargetDir: targetDir, - FileName: fileName, - - Timeout: 300, - } - if err := cli.Backup(backupInfo); err != nil { - return err - } - return nil -} - -func handlePostgresqlRecover(req dto.CommonRecover, isRollback bool) error { - isOk := false - fileOp := files.NewFileOp() - if !fileOp.Stat(req.File) { - return buserr.WithName("ErrFileNotFound", req.File) - } - dbInfo, err := postgresqlRepo.Get(commonRepo.WithByName(req.DetailName), postgresqlRepo.WithByPostgresqlName(req.Name)) - if err != nil { - return err - } - cli, err := LoadPostgresqlClientByFrom(req.Name) - if err != nil { - return err - } - defer cli.Close() - - if !isRollback { - rollbackFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("database/%s/%s_%s.sql.gz", req.Type, req.DetailName, time.Now().Format(constant.DateTimeSlimLayout))) - if err := cli.Backup(client.BackupInfo{ - Name: req.DetailName, - TargetDir: path.Dir(rollbackFile), - FileName: path.Base(rollbackFile), - - Timeout: 300, - }); err != nil { - return fmt.Errorf("backup postgresql db %s for rollback before recover failed, err: %v", req.DetailName, err) - } - defer func() { - if !isOk { - global.LOG.Info("recover failed, start to rollback now") - if err := cli.Recover(client.RecoverInfo{ - Name: req.DetailName, - SourceFile: rollbackFile, - - Timeout: 300, - }); err != nil { - global.LOG.Errorf("rollback postgresql db %s from %s failed, err: %v", req.DetailName, rollbackFile, err) - } - global.LOG.Infof("rollback postgresql db %s from %s successful", req.DetailName, rollbackFile) - _ = os.RemoveAll(rollbackFile) - } else { - _ = os.RemoveAll(rollbackFile) - } - }() - } - if err := cli.Recover(client.RecoverInfo{ - Name: req.DetailName, - SourceFile: req.File, - Username: dbInfo.Username, - Timeout: 300, - }); err != nil { - return err - } - isOk = true - return nil -} diff --git a/backend/app/service/backup_redis.go b/backend/app/service/backup_redis.go deleted file mode 100644 index ddec5303a..000000000 --- a/backend/app/service/backup_redis.go +++ /dev/null @@ -1,194 +0,0 @@ -package service - -import ( - "fmt" - "os" - "path" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/app/repo" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/compose" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/pkg/errors" -) - -func (u *BackupService) RedisBackup(db dto.CommonBackup) error { - localDir, err := loadLocalDir() - if err != nil { - return err - } - redisInfo, err := appInstallRepo.LoadBaseInfo("redis", db.Name) - if err != nil { - return err - } - appendonly, err := configGetStr(redisInfo.ContainerName, redisInfo.Password, "appendonly") - if err != nil { - return err - } - global.LOG.Infof("appendonly in redis conf is %s", appendonly) - - timeNow := time.Now().Format(constant.DateTimeSlimLayout) + common.RandStrAndNum(5) - fileName := fmt.Sprintf("%s.rdb", timeNow) - if appendonly == "yes" { - if strings.HasPrefix(redisInfo.Version, "6.") { - fileName = fmt.Sprintf("%s.aof", timeNow) - } else { - fileName = fmt.Sprintf("%s.tar.gz", timeNow) - } - } - itemDir := fmt.Sprintf("database/redis/%s", redisInfo.Name) - backupDir := path.Join(localDir, itemDir) - if err := handleRedisBackup(redisInfo, backupDir, fileName, db.Secret); err != nil { - return err - } - record := &model.BackupRecord{ - Type: "redis", - Name: db.Name, - Source: "LOCAL", - BackupType: "LOCAL", - FileDir: itemDir, - FileName: fileName, - } - if err := backupRepo.CreateRecord(record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) - } - - return nil -} - -func (u *BackupService) RedisRecover(req dto.CommonRecover) error { - redisInfo, err := appInstallRepo.LoadBaseInfo("redis", req.Name) - if err != nil { - return err - } - global.LOG.Infof("recover redis from backup file %s", req.File) - if err := handleRedisRecover(redisInfo, req.File, false, req.Secret); err != nil { - return err - } - return nil -} - -func handleRedisBackup(redisInfo *repo.RootInfo, backupDir, fileName string, secret string) error { - fileOp := files.NewFileOp() - if !fileOp.Stat(backupDir) { - if err := os.MkdirAll(backupDir, os.ModePerm); err != nil { - return fmt.Errorf("mkdir %s failed, err: %v", backupDir, err) - } - } - - stdout, err := cmd.Execf("docker exec %s redis-cli -a %s --no-auth-warning save", redisInfo.ContainerName, redisInfo.Password) - if err != nil { - return errors.New(string(stdout)) - } - - if strings.HasSuffix(fileName, ".tar.gz") { - redisDataDir := fmt.Sprintf("%s/%s/%s/data/appendonlydir", constant.AppInstallDir, "redis", redisInfo.Name) - if err := handleTar(redisDataDir, backupDir, fileName, "", secret); err != nil { - return err - } - return nil - } - if strings.HasSuffix(fileName, ".aof") { - stdout1, err := cmd.Execf("docker cp %s:/data/appendonly.aof %s/%s", redisInfo.ContainerName, backupDir, fileName) - if err != nil { - return errors.New(string(stdout1)) - } - return nil - } - - stdout1, err1 := cmd.Execf("docker cp %s:/data/dump.rdb %s/%s", redisInfo.ContainerName, backupDir, fileName) - if err1 != nil { - return errors.New(string(stdout1)) - } - return nil -} - -func handleRedisRecover(redisInfo *repo.RootInfo, recoverFile string, isRollback bool, secret string) error { - fileOp := files.NewFileOp() - if !fileOp.Stat(recoverFile) { - return buserr.WithName("ErrFileNotFound", recoverFile) - } - - appendonly, err := configGetStr(redisInfo.ContainerName, redisInfo.Password, "appendonly") - if err != nil { - return err - } - - if appendonly == "yes" { - if strings.HasPrefix(redisInfo.Version, "6.") && !strings.HasSuffix(recoverFile, ".aof") { - return buserr.New(constant.ErrTypeOfRedis) - } - if strings.HasPrefix(redisInfo.Version, "7.") && !strings.HasSuffix(recoverFile, ".tar.gz") { - return buserr.New(constant.ErrTypeOfRedis) - } - } else { - if !strings.HasSuffix(recoverFile, ".rdb") { - return buserr.New(constant.ErrTypeOfRedis) - } - } - - global.LOG.Infof("appendonly in redis conf is %s", appendonly) - isOk := false - if !isRollback { - suffix := "rdb" - if appendonly == "yes" { - if strings.HasPrefix(redisInfo.Version, "6.") { - suffix = "aof" - } else { - suffix = "tar.gz" - } - } - rollbackFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("database/redis/%s_%s.%s", redisInfo.Name, time.Now().Format(constant.DateTimeSlimLayout), suffix)) - if err := handleRedisBackup(redisInfo, path.Dir(rollbackFile), path.Base(rollbackFile), secret); err != nil { - return fmt.Errorf("backup database %s for rollback before recover failed, err: %v", redisInfo.Name, err) - } - defer func() { - if !isOk { - global.LOG.Info("recover failed, start to rollback now") - if err := handleRedisRecover(redisInfo, rollbackFile, true, secret); err != nil { - global.LOG.Errorf("rollback redis from %s failed, err: %v", rollbackFile, err) - return - } - global.LOG.Infof("rollback redis from %s successful", rollbackFile) - _ = os.RemoveAll(rollbackFile) - } else { - _ = os.RemoveAll(rollbackFile) - } - }() - } - composeDir := fmt.Sprintf("%s/redis/%s", constant.AppInstallDir, redisInfo.Name) - if _, err := compose.Down(composeDir + "/docker-compose.yml"); err != nil { - return err - } - if appendonly == "yes" && strings.HasPrefix(redisInfo.Version, "7.") { - redisDataDir := fmt.Sprintf("%s/%s/%s/data", constant.AppInstallDir, "redis", redisInfo.Name) - if err := handleUnTar(recoverFile, redisDataDir, secret); err != nil { - return err - } - } else { - itemName := "dump.rdb" - if appendonly == "yes" && strings.HasPrefix(redisInfo.Version, "6.") { - itemName = "appendonly.aof" - } - input, err := os.ReadFile(recoverFile) - if err != nil { - return err - } - if err = os.WriteFile(composeDir+"/data/"+itemName, input, 0640); err != nil { - return err - } - } - if _, err := compose.Up(composeDir + "/docker-compose.yml"); err != nil { - return err - } - isOk = true - return nil -} diff --git a/backend/app/service/backup_runtime.go b/backend/app/service/backup_runtime.go deleted file mode 100644 index cf0fd510b..000000000 --- a/backend/app/service/backup_runtime.go +++ /dev/null @@ -1,129 +0,0 @@ -package service - -import ( - "encoding/json" - "errors" - "fmt" - "io/fs" - "os" - "path" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/files" -) - -func handleRuntimeBackup(runtime *model.Runtime, backupDir, fileName string, excludes string, secret string) error { - fileOp := files.NewFileOp() - tmpDir := fmt.Sprintf("%s/%s", backupDir, strings.ReplaceAll(fileName, ".tar.gz", "")) - if !fileOp.Stat(tmpDir) { - if err := os.MkdirAll(tmpDir, os.ModePerm); err != nil { - return fmt.Errorf("mkdir %s failed, err: %v", backupDir, err) - } - } - defer func() { - _ = os.RemoveAll(tmpDir) - }() - - remarkInfo, _ := json.Marshal(runtime) - remarkInfoPath := fmt.Sprintf("%s/runtime.json", tmpDir) - if err := fileOp.SaveFile(remarkInfoPath, string(remarkInfo), fs.ModePerm); err != nil { - return err - } - - appPath := runtime.GetPath() - if err := handleTar(appPath, tmpDir, "runtime.tar.gz", excludes, secret); err != nil { - return err - } - if err := handleTar(tmpDir, backupDir, fileName, "", secret); err != nil { - return err - } - return nil -} - -func handleRuntimeRecover(runtime *model.Runtime, recoverFile string, isRollback bool, secret string) error { - isOk := false - fileOp := files.NewFileOp() - if err := handleUnTar(recoverFile, path.Dir(recoverFile), secret); err != nil { - return err - } - tmpPath := strings.ReplaceAll(recoverFile, ".tar.gz", "") - defer func() { - go startRuntime(runtime) - _ = os.RemoveAll(strings.ReplaceAll(recoverFile, ".tar.gz", "")) - }() - - if !fileOp.Stat(tmpPath+"/runtime.json") || !fileOp.Stat(tmpPath+"/runtime.tar.gz") { - return errors.New("the wrong recovery package does not have runtime.json or runtime.tar.gz files") - } - var oldRuntime model.Runtime - runtimeJson, err := os.ReadFile(tmpPath + "/runtime.json") - if err != nil { - return err - } - if err := json.Unmarshal(runtimeJson, &oldRuntime); err != nil { - return fmt.Errorf("unmarshal runtime.json failed, err: %v", err) - } - if oldRuntime.Type != runtime.Type || oldRuntime.Name != runtime.Name { - return errors.New("the current backup file does not match the application") - } - - if !isRollback { - rollbackFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("runtime/%s_%s.tar.gz", runtime.Name, time.Now().Format(constant.DateTimeSlimLayout))) - if err := handleRuntimeBackup(runtime, path.Dir(rollbackFile), path.Base(rollbackFile), "", secret); err != nil { - return fmt.Errorf("backup runtime %s for rollback before recover failed, err: %v", runtime.Name, err) - } - defer func() { - if !isOk { - global.LOG.Info("recover failed, start to rollback now") - if err := handleRuntimeRecover(runtime, rollbackFile, true, secret); err != nil { - global.LOG.Errorf("rollback runtime %s from %s failed, err: %v", runtime.Name, rollbackFile, err) - return - } - global.LOG.Infof("rollback runtime %s from %s successful", runtime.Name, rollbackFile) - _ = os.RemoveAll(rollbackFile) - } else { - _ = os.RemoveAll(rollbackFile) - } - }() - } - - newEnvFile, err := coverEnvJsonToStr(runtime.Env) - if err != nil { - return err - } - runtimeDir := runtime.GetPath() - backPath := fmt.Sprintf("%s_bak", runtimeDir) - _ = fileOp.Rename(runtimeDir, backPath) - _ = fileOp.CreateDir(runtimeDir, 0755) - - if err := handleUnTar(tmpPath+"/runtime.tar.gz", fmt.Sprintf("%s/%s", constant.RuntimeDir, runtime.Type), secret); err != nil { - global.LOG.Errorf("handle recover from runtime.tar.gz failed, err: %v", err) - _ = fileOp.DeleteDir(runtimeDir) - _ = fileOp.Rename(backPath, runtimeDir) - return err - } - _ = fileOp.DeleteDir(backPath) - - if len(newEnvFile) != 0 { - envPath := fmt.Sprintf("%s/%s/%s/.env", constant.RuntimeDir, runtime.Type, runtime.Name) - file, err := os.OpenFile(envPath, os.O_WRONLY|os.O_TRUNC, 0640) - if err != nil { - return err - } - defer file.Close() - _, _ = file.WriteString(newEnvFile) - } - - oldRuntime.ID = runtime.ID - oldRuntime.Status = constant.RuntimeStarting - if err := runtimeRepo.Save(&oldRuntime); err != nil { - global.LOG.Errorf("save db app install failed, err: %v", err) - return err - } - isOk = true - return nil -} diff --git a/backend/app/service/backup_website.go b/backend/app/service/backup_website.go deleted file mode 100644 index e7e7c3da1..000000000 --- a/backend/app/service/backup_website.go +++ /dev/null @@ -1,269 +0,0 @@ -package service - -import ( - "encoding/json" - "fmt" - "io/fs" - "os" - "path" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/compose" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/pkg/errors" -) - -func (u *BackupService) WebsiteBackup(req dto.CommonBackup) error { - localDir, err := loadLocalDir() - if err != nil { - return err - } - website, err := websiteRepo.GetFirst(websiteRepo.WithAlias(req.DetailName)) - if err != nil { - return err - } - - timeNow := time.Now().Format(constant.DateTimeSlimLayout) - itemDir := fmt.Sprintf("website/%s", req.Name) - backupDir := path.Join(localDir, itemDir) - fileName := fmt.Sprintf("%s_%s.tar.gz", website.PrimaryDomain, timeNow+common.RandStrAndNum(5)) - if err := handleWebsiteBackup(&website, backupDir, fileName, "", req.Secret); err != nil { - return err - } - - record := &model.BackupRecord{ - Type: "website", - Name: website.PrimaryDomain, - DetailName: req.DetailName, - Source: "LOCAL", - BackupType: "LOCAL", - FileDir: itemDir, - FileName: fileName, - } - if err := backupRepo.CreateRecord(record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) - return err - } - return nil -} - -func (u *BackupService) WebsiteRecover(req dto.CommonRecover) error { - fileOp := files.NewFileOp() - if !fileOp.Stat(req.File) { - return buserr.WithName("ErrFileNotFound", req.File) - } - website, err := websiteRepo.GetFirst(websiteRepo.WithAlias(req.DetailName)) - if err != nil { - return err - } - global.LOG.Infof("recover website %s from backup file %s", req.Name, req.File) - if err := handleWebsiteRecover(&website, req.File, false, req.Secret); err != nil { - return err - } - return nil -} - -func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback bool, secret string) error { - fileOp := files.NewFileOp() - tmpPath := strings.ReplaceAll(recoverFile, ".tar.gz", "") - if err := handleUnTar(recoverFile, path.Dir(recoverFile), secret); err != nil { - return err - } - defer func() { - _ = os.RemoveAll(tmpPath) - }() - - var oldWebsite model.Website - websiteJson, err := os.ReadFile(tmpPath + "/website.json") - if err != nil { - return err - } - if err := json.Unmarshal(websiteJson, &oldWebsite); err != nil { - return fmt.Errorf("unmarshal app.json failed, err: %v", err) - } - - if err := checkValidOfWebsite(&oldWebsite, website); err != nil { - return err - } - - temPathWithName := tmpPath + "/" + website.Alias - if !fileOp.Stat(tmpPath+"/website.json") || !fileOp.Stat(temPathWithName+".conf") || !fileOp.Stat(temPathWithName+".web.tar.gz") { - return buserr.WithDetail(constant.ErrBackupExist, ".conf or .web.tar.gz", nil) - } - if website.Type == constant.Deployment { - if !fileOp.Stat(temPathWithName + ".app.tar.gz") { - return buserr.WithDetail(constant.ErrBackupExist, ".app.tar.gz", nil) - } - } - - isOk := false - if !isRollback { - rollbackFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("website/%s_%s.tar.gz", website.Alias, time.Now().Format(constant.DateTimeSlimLayout))) - if err := handleWebsiteBackup(website, path.Dir(rollbackFile), path.Base(rollbackFile), "", ""); err != nil { - return fmt.Errorf("backup website %s for rollback before recover failed, err: %v", website.Alias, err) - } - defer func() { - if !isOk { - global.LOG.Info("recover failed, start to rollback now") - if err := handleWebsiteRecover(website, rollbackFile, true, ""); err != nil { - global.LOG.Errorf("rollback website %s from %s failed, err: %v", website.Alias, rollbackFile, err) - return - } - global.LOG.Infof("rollback website %s from %s successful", website.Alias, rollbackFile) - _ = os.RemoveAll(rollbackFile) - } else { - _ = os.RemoveAll(rollbackFile) - } - }() - } - - nginxInfo, err := appInstallRepo.LoadBaseInfo(constant.AppOpenresty, "") - if err != nil { - return err - } - nginxConfPath := fmt.Sprintf("%s/openresty/%s/conf/conf.d", constant.AppInstallDir, nginxInfo.Name) - if err := fileOp.CopyFile(fmt.Sprintf("%s/%s.conf", tmpPath, website.Alias), nginxConfPath); err != nil { - global.LOG.Errorf("handle recover from conf.d failed, err: %v", err) - return err - } - - switch website.Type { - case constant.Deployment: - app, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) - if err != nil { - return err - } - if err := handleAppRecover(&app, fmt.Sprintf("%s/%s.app.tar.gz", tmpPath, website.Alias), true, ""); err != nil { - global.LOG.Errorf("handle recover from app.tar.gz failed, err: %v", err) - return err - } - if _, err := compose.Restart(fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, app.App.Key, app.Name)); err != nil { - global.LOG.Errorf("docker-compose restart failed, err: %v", err) - return err - } - case constant.Runtime: - runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID)) - if err != nil { - return err - } - if runtime.Type == constant.RuntimeNode || runtime.Type == constant.RuntimeJava || runtime.Type == constant.RuntimeGo { - if err := handleRuntimeRecover(runtime, fmt.Sprintf("%s/%s.runtime.tar.gz", tmpPath, website.Alias), true, ""); err != nil { - return err - } - global.LOG.Info("put runtime.tar.gz into tmp dir successful") - } - } - - siteDir := fmt.Sprintf("%s/openresty/%s/www/sites", constant.AppInstallDir, nginxInfo.Name) - if err := handleUnTar(fmt.Sprintf("%s/%s.web.tar.gz", tmpPath, website.Alias), siteDir, ""); err != nil { - global.LOG.Errorf("handle recover from web.tar.gz failed, err: %v", err) - return err - } - stdout, err := cmd.Execf("docker exec -i %s nginx -s reload", nginxInfo.ContainerName) - if err != nil { - global.LOG.Errorf("nginx -s reload failed, err: %s", stdout) - return errors.New(string(stdout)) - } - - oldWebsite.ID = website.ID - if err := websiteRepo.SaveWithoutCtx(&oldWebsite); err != nil { - global.LOG.Errorf("handle save website data failed, err: %v", err) - return err - } - isOk = true - return nil -} - -func handleWebsiteBackup(website *model.Website, backupDir, fileName string, excludes string, secret string) error { - fileOp := files.NewFileOp() - tmpDir := fmt.Sprintf("%s/%s", backupDir, strings.ReplaceAll(fileName, ".tar.gz", "")) - if !fileOp.Stat(tmpDir) { - if err := os.MkdirAll(tmpDir, os.ModePerm); err != nil { - return fmt.Errorf("mkdir %s failed, err: %v", backupDir, err) - } - } - defer func() { - _ = os.RemoveAll(tmpDir) - }() - - remarkInfo, _ := json.Marshal(website) - if err := fileOp.SaveFile(tmpDir+"/website.json", string(remarkInfo), fs.ModePerm); err != nil { - return err - } - global.LOG.Info("put website.json into tmp dir successful") - - nginxInfo, err := appInstallRepo.LoadBaseInfo(constant.AppOpenresty, "") - if err != nil { - return err - } - nginxConfFile := fmt.Sprintf("%s/openresty/%s/conf/conf.d/%s.conf", constant.AppInstallDir, nginxInfo.Name, website.Alias) - if err := fileOp.CopyFile(nginxConfFile, tmpDir); err != nil { - return err - } - global.LOG.Info("put openresty conf into tmp dir successful") - - switch website.Type { - case constant.Deployment: - app, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) - if err != nil { - return err - } - if err := handleAppBackup(&app, tmpDir, fmt.Sprintf("%s.app.tar.gz", website.Alias), excludes, ""); err != nil { - return err - } - global.LOG.Info("put app.tar.gz into tmp dir successful") - case constant.Runtime: - runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID)) - if err != nil { - return err - } - if runtime.Type == constant.RuntimeNode || runtime.Type == constant.RuntimeJava || runtime.Type == constant.RuntimeGo { - if err := handleRuntimeBackup(runtime, tmpDir, fmt.Sprintf("%s.runtime.tar.gz", website.Alias), excludes, ""); err != nil { - return err - } - global.LOG.Info("put runtime.tar.gz into tmp dir successful") - } - } - - websiteDir := fmt.Sprintf("%s/openresty/%s/www/sites/%s", constant.AppInstallDir, nginxInfo.Name, website.Alias) - if err := handleTar(websiteDir, tmpDir, fmt.Sprintf("%s.web.tar.gz", website.Alias), excludes, ""); err != nil { - return err - } - global.LOG.Info("put web.tar.gz into tmp dir successful, now start to tar tmp dir") - if err := handleTar(tmpDir, backupDir, fileName, "", secret); err != nil { - return err - } - - return nil -} - -func checkValidOfWebsite(oldWebsite, website *model.Website) error { - if oldWebsite.Alias != website.Alias || oldWebsite.Type != website.Type { - return buserr.WithDetail(constant.ErrBackupMatch, fmt.Sprintf("oldName: %s, oldType: %v", oldWebsite.Alias, oldWebsite.Type), nil) - } - if oldWebsite.AppInstallID != 0 { - _, err := appInstallRepo.GetFirst(commonRepo.WithByID(oldWebsite.AppInstallID)) - if err != nil { - return buserr.WithDetail(constant.ErrBackupMatch, "app", nil) - } - } - if oldWebsite.RuntimeID != 0 { - if _, err := runtimeRepo.GetFirst(commonRepo.WithByID(oldWebsite.RuntimeID)); err != nil { - return buserr.WithDetail(constant.ErrBackupMatch, "runtime", nil) - } - } - if oldWebsite.WebsiteSSLID != 0 { - if _, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(oldWebsite.WebsiteSSLID)); err != nil { - return buserr.WithDetail(constant.ErrBackupMatch, "ssl", nil) - } - } - return nil -} diff --git a/backend/app/service/clam.go b/backend/app/service/clam.go deleted file mode 100644 index 75c3371e4..000000000 --- a/backend/app/service/clam.go +++ /dev/null @@ -1,562 +0,0 @@ -package service - -import ( - "bufio" - "fmt" - "os" - "os/exec" - "path" - "path/filepath" - "sort" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/systemctl" - "github.com/1Panel-dev/1Panel/backend/utils/xpack" - "github.com/jinzhu/copier" - "github.com/robfig/cron/v3" - - "github.com/pkg/errors" -) - -const ( - clamServiceNameCentOs = "clamd@scan.service" - clamServiceNameUbuntu = "clamav-daemon.service" - freshClamService = "clamav-freshclam.service" - resultDir = "clamav" -) - -type ClamService struct { - serviceName string -} - -type IClamService interface { - LoadBaseInfo() (dto.ClamBaseInfo, error) - Operate(operate string) error - SearchWithPage(search dto.SearchClamWithPage) (int64, interface{}, error) - Create(req dto.ClamCreate) error - Update(req dto.ClamUpdate) error - UpdateStatus(id uint, status string) error - Delete(req dto.ClamDelete) error - HandleOnce(req dto.OperateByID) error - LoadFile(req dto.ClamFileReq) (string, error) - UpdateFile(req dto.UpdateByNameAndFile) error - LoadRecords(req dto.ClamLogSearch) (int64, interface{}, error) - CleanRecord(req dto.OperateByID) error - - LoadRecordLog(req dto.ClamLogReq) (string, error) -} - -func NewIClamService() IClamService { - return &ClamService{} -} - -func (c *ClamService) LoadBaseInfo() (dto.ClamBaseInfo, error) { - var baseInfo dto.ClamBaseInfo - baseInfo.Version = "-" - baseInfo.FreshVersion = "-" - exist1, _ := systemctl.IsExist(clamServiceNameCentOs) - if exist1 { - c.serviceName = clamServiceNameCentOs - baseInfo.IsExist = true - baseInfo.IsActive, _ = systemctl.IsActive(clamServiceNameCentOs) - } - exist2, _ := systemctl.IsExist(clamServiceNameUbuntu) - if exist2 { - c.serviceName = clamServiceNameUbuntu - baseInfo.IsExist = true - baseInfo.IsActive, _ = systemctl.IsActive(clamServiceNameUbuntu) - } - freshExist, _ := systemctl.IsExist(freshClamService) - if freshExist { - baseInfo.FreshIsExist = true - baseInfo.FreshIsActive, _ = systemctl.IsActive(freshClamService) - } - if !cmd.Which("clamdscan") { - baseInfo.IsActive = false - } - - if baseInfo.IsActive { - version, err := cmd.Exec("clamdscan --version") - if err == nil { - if strings.Contains(version, "/") { - baseInfo.Version = strings.TrimPrefix(strings.Split(version, "/")[0], "ClamAV ") - } else { - baseInfo.Version = strings.TrimPrefix(version, "ClamAV ") - } - } - } - if baseInfo.FreshIsActive { - version, err := cmd.Exec("freshclam --version") - if err == nil { - if strings.Contains(version, "/") { - baseInfo.FreshVersion = strings.TrimPrefix(strings.Split(version, "/")[0], "ClamAV ") - } else { - baseInfo.FreshVersion = strings.TrimPrefix(version, "ClamAV ") - } - } - } - return baseInfo, nil -} - -func (c *ClamService) Operate(operate string) error { - switch operate { - case "start", "restart", "stop": - stdout, err := cmd.Execf("systemctl %s %s", operate, c.serviceName) - if err != nil { - return fmt.Errorf("%s the %s failed, err: %s", operate, c.serviceName, stdout) - } - return nil - case "fresh-start", "fresh-restart", "fresh-stop": - stdout, err := cmd.Execf("systemctl %s %s", strings.TrimPrefix(operate, "fresh-"), freshClamService) - if err != nil { - return fmt.Errorf("%s the %s failed, err: %s", operate, c.serviceName, stdout) - } - return nil - default: - return fmt.Errorf("not support such operation: %v", operate) - } -} - -func (c *ClamService) SearchWithPage(req dto.SearchClamWithPage) (int64, interface{}, error) { - total, commands, err := clamRepo.Page(req.Page, req.PageSize, commonRepo.WithLikeName(req.Info), commonRepo.WithOrderRuleBy(req.OrderBy, req.Order)) - if err != nil { - return 0, nil, err - } - var datas []dto.ClamInfo - for _, command := range commands { - var item dto.ClamInfo - if err := copier.Copy(&item, &command); err != nil { - return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - item.LastHandleDate = "-" - datas = append(datas, item) - } - nyc, _ := time.LoadLocation(common.LoadTimeZone()) - for i := 0; i < len(datas); i++ { - logPaths := loadFileByName(datas[i].Name) - sort.Slice(logPaths, func(i, j int) bool { - return logPaths[i] > logPaths[j] - }) - if len(logPaths) != 0 { - t1, err := time.ParseInLocation(constant.DateTimeSlimLayout, logPaths[0], nyc) - if err != nil { - continue - } - datas[i].LastHandleDate = t1.Format(constant.DateTimeLayout) - } - } - return total, datas, err -} - -func (c *ClamService) Create(req dto.ClamCreate) error { - clam, _ := clamRepo.Get(commonRepo.WithByName(req.Name)) - if clam.ID != 0 { - return constant.ErrRecordExist - } - if err := copier.Copy(&clam, &req); err != nil { - return errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - if clam.InfectedStrategy == "none" || clam.InfectedStrategy == "remove" { - clam.InfectedDir = "" - } - if len(req.Spec) != 0 { - entryID, err := xpack.StartClam(clam, false) - if err != nil { - return err - } - clam.EntryID = entryID - clam.Status = constant.StatusEnable - } - if err := clamRepo.Create(&clam); err != nil { - return err - } - return nil -} - -func (c *ClamService) Update(req dto.ClamUpdate) error { - clam, _ := clamRepo.Get(commonRepo.WithByName(req.Name)) - if clam.ID == 0 { - return constant.ErrRecordNotFound - } - if req.InfectedStrategy == "none" || req.InfectedStrategy == "remove" { - req.InfectedDir = "" - } - var clamItem model.Clam - if err := copier.Copy(&clamItem, &req); err != nil { - return errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - clamItem.EntryID = clam.EntryID - upMap := map[string]interface{}{} - if len(clam.Spec) != 0 && clam.EntryID != 0 { - global.Cron.Remove(cron.EntryID(clamItem.EntryID)) - upMap["entry_id"] = 0 - } - if len(req.Spec) == 0 { - upMap["status"] = "" - upMap["entry_id"] = 0 - } - if len(req.Spec) != 0 && clam.Status != constant.StatusDisable { - newEntryID, err := xpack.StartClam(clamItem, true) - if err != nil { - return err - } - upMap["entry_id"] = newEntryID - } - if len(clam.Spec) == 0 && len(req.Spec) != 0 { - upMap["status"] = constant.StatusEnable - } - - upMap["name"] = req.Name - upMap["path"] = req.Path - upMap["infected_dir"] = req.InfectedDir - upMap["infected_strategy"] = req.InfectedStrategy - upMap["spec"] = req.Spec - upMap["description"] = req.Description - if err := clamRepo.Update(req.ID, upMap); err != nil { - return err - } - return nil -} - -func (c *ClamService) UpdateStatus(id uint, status string) error { - clam, _ := clamRepo.Get(commonRepo.WithByID(id)) - if clam.ID == 0 { - return constant.ErrRecordNotFound - } - var ( - entryID int - err error - ) - if status == constant.StatusEnable { - entryID, err = xpack.StartClam(clam, true) - if err != nil { - return err - } - } else { - global.Cron.Remove(cron.EntryID(clam.EntryID)) - global.LOG.Infof("stop cronjob entryID: %v", clam.EntryID) - } - - return clamRepo.Update(clam.ID, map[string]interface{}{"status": status, "entry_id": entryID}) -} - -func (c *ClamService) Delete(req dto.ClamDelete) error { - for _, id := range req.Ids { - clam, _ := clamRepo.Get(commonRepo.WithByID(id)) - if clam.ID == 0 { - continue - } - if req.RemoveRecord { - _ = os.RemoveAll(path.Join(global.CONF.System.DataDir, resultDir, clam.Name)) - } - if req.RemoveInfected { - _ = os.RemoveAll(path.Join(clam.InfectedDir, "1panel-infected", clam.Name)) - } - if err := clamRepo.Delete(commonRepo.WithByID(id)); err != nil { - return err - } - } - return nil -} - -func (c *ClamService) HandleOnce(req dto.OperateByID) error { - if !cmd.Which("clamdscan") { - return buserr.New("ErrClamdscanNotFound") - } - clam, _ := clamRepo.Get(commonRepo.WithByID(req.ID)) - if clam.ID == 0 { - return constant.ErrRecordNotFound - } - if cmd.CheckIllegal(clam.Path) { - return buserr.New(constant.ErrCmdIllegal) - } - timeNow := time.Now().Format(constant.DateTimeSlimLayout) - logFile := path.Join(global.CONF.System.DataDir, resultDir, clam.Name, timeNow) - if _, err := os.Stat(path.Dir(logFile)); err != nil { - _ = os.MkdirAll(path.Dir(logFile), os.ModePerm) - } - go func() { - strategy := "" - switch clam.InfectedStrategy { - case "remove": - strategy = "--remove" - case "move": - dir := path.Join(clam.InfectedDir, "1panel-infected", clam.Name, timeNow) - strategy = "--move=" + dir - if _, err := os.Stat(dir); err != nil { - _ = os.MkdirAll(dir, os.ModePerm) - } - case "copy": - dir := path.Join(clam.InfectedDir, "1panel-infected", clam.Name, timeNow) - strategy = "--copy=" + dir - if _, err := os.Stat(dir); err != nil { - _ = os.MkdirAll(dir, os.ModePerm) - } - } - global.LOG.Debugf("clamdscan --fdpass %s %s -l %s", strategy, clam.Path, logFile) - stdout, err := cmd.Execf("clamdscan --fdpass %s %s -l %s", strategy, clam.Path, logFile) - if err != nil { - global.LOG.Errorf("clamdscan failed, stdout: %v, err: %v", stdout, err) - } - }() - return nil -} - -func (c *ClamService) LoadRecords(req dto.ClamLogSearch) (int64, interface{}, error) { - clam, _ := clamRepo.Get(commonRepo.WithByID(req.ClamID)) - if clam.ID == 0 { - return 0, nil, constant.ErrRecordNotFound - } - logPaths := loadFileByName(clam.Name) - if len(logPaths) == 0 { - return 0, nil, nil - } - - var filterFiles []string - nyc, _ := time.LoadLocation(common.LoadTimeZone()) - for _, item := range logPaths { - t1, err := time.ParseInLocation(constant.DateTimeSlimLayout, item, nyc) - if err != nil { - continue - } - if t1.After(req.StartTime) && t1.Before(req.EndTime) { - filterFiles = append(filterFiles, item) - } - } - if len(filterFiles) == 0 { - return 0, nil, nil - } - - sort.Slice(filterFiles, func(i, j int) bool { - return filterFiles[i] > filterFiles[j] - }) - - var records []string - total, start, end := len(filterFiles), (req.Page-1)*req.PageSize, req.Page*req.PageSize - if start > total { - records = make([]string, 0) - } else { - if end >= total { - end = total - } - records = filterFiles[start:end] - } - - var datas []dto.ClamLog - for i := 0; i < len(records); i++ { - item := loadResultFromLog(path.Join(global.CONF.System.DataDir, resultDir, clam.Name, records[i])) - datas = append(datas, item) - } - return int64(total), datas, nil -} -func (c *ClamService) LoadRecordLog(req dto.ClamLogReq) (string, error) { - logPath := path.Join(global.CONF.System.DataDir, resultDir, req.ClamName, req.RecordName) - var tail string - if req.Tail != "0" { - tail = req.Tail - } else { - tail = "+1" - } - cmd := exec.Command("tail", "-n", tail, logPath) - stdout, err := cmd.CombinedOutput() - if err != nil { - return "", fmt.Errorf("tail -n %v failed, err: %v", req.Tail, err) - } - return string(stdout), nil -} - -func (c *ClamService) CleanRecord(req dto.OperateByID) error { - clam, _ := clamRepo.Get(commonRepo.WithByID(req.ID)) - if clam.ID == 0 { - return constant.ErrRecordNotFound - } - pathItem := path.Join(global.CONF.System.DataDir, resultDir, clam.Name) - _ = os.RemoveAll(pathItem) - return nil -} - -func (c *ClamService) LoadFile(req dto.ClamFileReq) (string, error) { - filePath := "" - switch req.Name { - case "clamd": - if c.serviceName == clamServiceNameUbuntu { - filePath = "/etc/clamav/clamd.conf" - } else { - filePath = "/etc/clamd.d/scan.conf" - } - case "clamd-log": - filePath = c.loadLogPath("clamd-log") - if len(filePath) != 0 { - break - } - if c.serviceName == clamServiceNameUbuntu { - filePath = "/var/log/clamav/clamav.log" - } else { - filePath = "/var/log/clamd.scan" - } - case "freshclam": - if c.serviceName == clamServiceNameUbuntu { - filePath = "/etc/clamav/freshclam.conf" - } else { - filePath = "/etc/freshclam.conf" - } - case "freshclam-log": - filePath = c.loadLogPath("freshclam-log") - if len(filePath) != 0 { - break - } - if c.serviceName == clamServiceNameUbuntu { - filePath = "/var/log/clamav/freshclam.log" - } else { - filePath = "/var/log/freshclam.log" - } - default: - return "", fmt.Errorf("not support such type") - } - if _, err := os.Stat(filePath); err != nil { - return "", buserr.New("ErrHttpReqNotFound") - } - var tail string - if req.Tail != "0" { - tail = req.Tail - } else { - tail = "+1" - } - cmd := exec.Command("tail", "-n", tail, filePath) - stdout, err := cmd.CombinedOutput() - if err != nil { - return "", fmt.Errorf("tail -n %v failed, err: %v", req.Tail, err) - } - return string(stdout), nil -} - -func (c *ClamService) UpdateFile(req dto.UpdateByNameAndFile) error { - filePath := "" - service := "" - switch req.Name { - case "clamd": - if c.serviceName == clamServiceNameUbuntu { - service = clamServiceNameUbuntu - filePath = "/etc/clamav/clamd.conf" - } else { - service = clamServiceNameCentOs - filePath = "/etc/clamd.d/scan.conf" - } - case "freshclam": - if c.serviceName == clamServiceNameUbuntu { - filePath = "/etc/clamav/freshclam.conf" - } else { - filePath = "/etc/freshclam.conf" - } - service = "clamav-freshclam.service" - default: - return fmt.Errorf("not support such type") - } - file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_TRUNC, 0640) - if err != nil { - return err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(req.File) - write.Flush() - - _ = systemctl.Restart(service) - return nil -} - -func loadFileByName(name string) []string { - var logPaths []string - pathItem := path.Join(global.CONF.System.DataDir, resultDir, name) - _ = filepath.Walk(pathItem, func(path string, info os.FileInfo, err error) error { - if err != nil { - return nil - } - if info.IsDir() || info.Name() == name { - return nil - } - logPaths = append(logPaths, info.Name()) - return nil - }) - return logPaths -} -func loadResultFromLog(pathItem string) dto.ClamLog { - var data dto.ClamLog - data.Name = path.Base(pathItem) - data.Status = constant.StatusWaiting - file, err := os.ReadFile(pathItem) - if err != nil { - return data - } - lines := strings.Split(string(file), "\n") - for _, line := range lines { - if strings.Contains(line, "- SCAN SUMMARY -") { - data.Status = constant.StatusDone - } - if data.Status != constant.StatusDone { - continue - } - switch { - case strings.HasPrefix(line, "Infected files:"): - data.InfectedFiles = strings.TrimPrefix(line, "Infected files:") - case strings.HasPrefix(line, "Total errors:"): - data.TotalError = strings.TrimPrefix(line, "Total errors:") - case strings.HasPrefix(line, "Time:"): - if strings.Contains(line, "(") { - data.ScanTime = strings.ReplaceAll(strings.Split(line, "(")[1], ")", "") - continue - } - data.ScanTime = strings.TrimPrefix(line, "Time:") - case strings.HasPrefix(line, "Start Date:"): - data.ScanDate = strings.TrimPrefix(line, "Start Date:") - } - } - return data -} -func (c *ClamService) loadLogPath(name string) string { - confPath := "" - if name == "clamd-log" { - if c.serviceName == clamServiceNameUbuntu { - confPath = "/etc/clamav/clamd.conf" - } else { - confPath = "/etc/clamd.d/scan.conf" - } - } else { - if c.serviceName == clamServiceNameUbuntu { - confPath = "/etc/clamav/freshclam.conf" - } else { - confPath = "/etc/freshclam.conf" - } - } - if _, err := os.Stat(confPath); err != nil { - return "" - } - content, err := os.ReadFile(confPath) - if err != nil { - return "" - } - lines := strings.Split(string(content), "\n") - if name == "clamd-log" { - for _, line := range lines { - if strings.HasPrefix(line, "LogFile ") { - return strings.Trim(strings.ReplaceAll(line, "LogFile ", ""), " ") - } - } - } else { - for _, line := range lines { - if strings.HasPrefix(line, "UpdateLogFile ") { - return strings.Trim(strings.ReplaceAll(line, "UpdateLogFile ", ""), " ") - } - } - } - - return "" -} diff --git a/backend/app/service/command.go b/backend/app/service/command.go deleted file mode 100644 index d32e8f2c8..000000000 --- a/backend/app/service/command.go +++ /dev/null @@ -1,183 +0,0 @@ -package service - -import ( - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/jinzhu/copier" - "github.com/pkg/errors" -) - -type CommandService struct{} - -type ICommandService interface { - List() ([]dto.CommandInfo, error) - SearchForTree() ([]dto.CommandTree, error) - SearchWithPage(search dto.SearchCommandWithPage) (int64, interface{}, error) - Create(commandDto dto.CommandOperate) error - Update(id uint, upMap map[string]interface{}) error - Delete(ids []uint) error - - SearchRedisCommandWithPage(search dto.SearchWithPage) (int64, interface{}, error) - ListRedisCommand() ([]dto.RedisCommand, error) - SaveRedisCommand(commandDto dto.RedisCommand) error - DeleteRedisCommand(ids []uint) error -} - -func NewICommandService() ICommandService { - return &CommandService{} -} - -func (u *CommandService) List() ([]dto.CommandInfo, error) { - commands, err := commandRepo.GetList(commonRepo.WithOrderBy("name")) - if err != nil { - return nil, constant.ErrRecordNotFound - } - var dtoCommands []dto.CommandInfo - for _, command := range commands { - var item dto.CommandInfo - if err := copier.Copy(&item, &command); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - dtoCommands = append(dtoCommands, item) - } - return dtoCommands, err -} - -func (u *CommandService) SearchForTree() ([]dto.CommandTree, error) { - cmdList, err := commandRepo.GetList(commonRepo.WithOrderBy("name")) - if err != nil { - return nil, err - } - groups, err := groupRepo.GetList(commonRepo.WithByType("command")) - if err != nil { - return nil, err - } - var lists []dto.CommandTree - for _, group := range groups { - var data dto.CommandTree - data.ID = group.ID + 10000 - data.Label = group.Name - for _, cmd := range cmdList { - if cmd.GroupID == group.ID { - data.Children = append(data.Children, dto.CommandInfo{ID: cmd.ID, Name: cmd.Name, Command: cmd.Command}) - } - } - if len(data.Children) != 0 { - lists = append(lists, data) - } - } - return lists, err -} - -func (u *CommandService) SearchWithPage(search dto.SearchCommandWithPage) (int64, interface{}, error) { - total, commands, err := commandRepo.Page(search.Page, search.PageSize, commandRepo.WithLikeName(search.Name), commonRepo.WithLikeName(search.Info), commonRepo.WithByGroupID(search.GroupID), commonRepo.WithOrderRuleBy(search.OrderBy, search.Order)) - if err != nil { - return 0, nil, err - } - groups, _ := groupRepo.GetList(commonRepo.WithByType("command"), commonRepo.WithOrderBy("name")) - var dtoCommands []dto.CommandInfo - for _, command := range commands { - var item dto.CommandInfo - if err := copier.Copy(&item, &command); err != nil { - return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - for _, group := range groups { - if command.GroupID == group.ID { - item.GroupBelong = group.Name - item.GroupID = group.ID - } - } - dtoCommands = append(dtoCommands, item) - } - return total, dtoCommands, err -} - -func (u *CommandService) Create(commandDto dto.CommandOperate) error { - command, _ := commandRepo.Get(commonRepo.WithByName(commandDto.Name)) - if command.ID != 0 { - return constant.ErrRecordExist - } - if err := copier.Copy(&command, &commandDto); err != nil { - return errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - if err := commandRepo.Create(&command); err != nil { - return err - } - return nil -} - -func (u *CommandService) Delete(ids []uint) error { - if len(ids) == 1 { - command, _ := commandRepo.Get(commonRepo.WithByID(ids[0])) - if command.ID == 0 { - return constant.ErrRecordNotFound - } - return commandRepo.Delete(commonRepo.WithByID(ids[0])) - } - return commandRepo.Delete(commonRepo.WithIdsIn(ids)) -} - -func (u *CommandService) Update(id uint, upMap map[string]interface{}) error { - return commandRepo.Update(id, upMap) -} - -func (u *CommandService) SearchRedisCommandWithPage(search dto.SearchWithPage) (int64, interface{}, error) { - total, commands, err := commandRepo.PageRedis(search.Page, search.PageSize, commandRepo.WithLikeName(search.Info)) - if err != nil { - return 0, nil, err - } - var dtoCommands []dto.RedisCommand - for _, command := range commands { - var item dto.RedisCommand - if err := copier.Copy(&item, &command); err != nil { - return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - dtoCommands = append(dtoCommands, item) - } - return total, dtoCommands, err -} - -func (u *CommandService) ListRedisCommand() ([]dto.RedisCommand, error) { - commands, err := commandRepo.GetRedisList() - if err != nil { - return nil, constant.ErrRecordNotFound - } - var dtoCommands []dto.RedisCommand - for _, command := range commands { - var item dto.RedisCommand - if err := copier.Copy(&item, &command); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - dtoCommands = append(dtoCommands, item) - } - return dtoCommands, err -} - -func (u *CommandService) SaveRedisCommand(req dto.RedisCommand) error { - if req.ID == 0 { - command, _ := commandRepo.GetRedis(commonRepo.WithByName(req.Name)) - if command.ID != 0 { - return constant.ErrRecordExist - } - } - var command model.RedisCommand - if err := copier.Copy(&command, &req); err != nil { - return errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - if err := commandRepo.SaveRedis(&command); err != nil { - return err - } - return nil -} - -func (u *CommandService) DeleteRedisCommand(ids []uint) error { - if len(ids) == 1 { - command, _ := commandRepo.GetRedis(commonRepo.WithByID(ids[0])) - if command.ID == 0 { - return constant.ErrRecordNotFound - } - return commandRepo.DeleteRedis(commonRepo.WithByID(ids[0])) - } - return commandRepo.DeleteRedis(commonRepo.WithIdsIn(ids)) -} diff --git a/backend/app/service/compose_template.go b/backend/app/service/compose_template.go deleted file mode 100644 index e3bcb7a65..000000000 --- a/backend/app/service/compose_template.go +++ /dev/null @@ -1,80 +0,0 @@ -package service - -import ( - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/jinzhu/copier" - "github.com/pkg/errors" -) - -type ComposeTemplateService struct{} - -type IComposeTemplateService interface { - List() ([]dto.ComposeTemplateInfo, error) - SearchWithPage(search dto.SearchWithPage) (int64, interface{}, error) - Create(composeDto dto.ComposeTemplateCreate) error - Update(id uint, upMap map[string]interface{}) error - Delete(ids []uint) error -} - -func NewIComposeTemplateService() IComposeTemplateService { - return &ComposeTemplateService{} -} - -func (u *ComposeTemplateService) List() ([]dto.ComposeTemplateInfo, error) { - composes, err := composeRepo.List() - if err != nil { - return nil, constant.ErrRecordNotFound - } - var dtoLists []dto.ComposeTemplateInfo - for _, compose := range composes { - var item dto.ComposeTemplateInfo - if err := copier.Copy(&item, &compose); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - dtoLists = append(dtoLists, item) - } - return dtoLists, err -} - -func (u *ComposeTemplateService) SearchWithPage(req dto.SearchWithPage) (int64, interface{}, error) { - total, composes, err := composeRepo.Page(req.Page, req.PageSize, commonRepo.WithLikeName(req.Info)) - var dtoComposeTemplates []dto.ComposeTemplateInfo - for _, compose := range composes { - var item dto.ComposeTemplateInfo - if err := copier.Copy(&item, &compose); err != nil { - return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - dtoComposeTemplates = append(dtoComposeTemplates, item) - } - return total, dtoComposeTemplates, err -} - -func (u *ComposeTemplateService) Create(composeDto dto.ComposeTemplateCreate) error { - compose, _ := composeRepo.Get(commonRepo.WithByName(composeDto.Name)) - if compose.ID != 0 { - return constant.ErrRecordExist - } - if err := copier.Copy(&compose, &composeDto); err != nil { - return errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - if err := composeRepo.Create(&compose); err != nil { - return err - } - return nil -} - -func (u *ComposeTemplateService) Delete(ids []uint) error { - if len(ids) == 1 { - compose, _ := composeRepo.Get(commonRepo.WithByID(ids[0])) - if compose.ID == 0 { - return constant.ErrRecordNotFound - } - return composeRepo.Delete(commonRepo.WithByID(ids[0])) - } - return composeRepo.Delete(commonRepo.WithIdsIn(ids)) -} - -func (u *ComposeTemplateService) Update(id uint, upMap map[string]interface{}) error { - return composeRepo.Update(id, upMap) -} diff --git a/backend/app/service/container.go b/backend/app/service/container.go deleted file mode 100644 index 08ea98e5d..000000000 --- a/backend/app/service/container.go +++ /dev/null @@ -1,1312 +0,0 @@ -package service - -import ( - "bufio" - "context" - "encoding/base64" - "encoding/json" - "fmt" - "io" - "net/http" - "net/url" - "os" - "os/exec" - "path/filepath" - "sort" - "strconv" - "strings" - "sync" - "syscall" - "time" - "unicode/utf8" - - "github.com/gin-gonic/gin" - - "github.com/pkg/errors" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/api/types/mount" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/client" - "github.com/docker/go-connections/nat" - "github.com/gorilla/websocket" - v1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/shirou/gopsutil/v3/cpu" - "github.com/shirou/gopsutil/v3/mem" -) - -type ContainerService struct{} - -type IContainerService interface { - Page(req dto.PageContainer) (int64, interface{}, error) - List() ([]string, error) - PageNetwork(req dto.SearchWithPage) (int64, interface{}, error) - ListNetwork() ([]dto.Options, error) - PageVolume(req dto.SearchWithPage) (int64, interface{}, error) - ListVolume() ([]dto.Options, error) - PageCompose(req dto.SearchWithPage) (int64, interface{}, error) - CreateCompose(req dto.ComposeCreate) (string, error) - ComposeOperation(req dto.ComposeOperation) error - ContainerCreate(req dto.ContainerOperate) error - ContainerUpdate(req dto.ContainerOperate) error - ContainerUpgrade(req dto.ContainerUpgrade) error - ContainerInfo(req dto.OperationWithName) (*dto.ContainerOperate, error) - ContainerListStats() ([]dto.ContainerListStats, error) - LoadResourceLimit() (*dto.ResourceLimit, error) - ContainerRename(req dto.ContainerRename) error - ContainerCommit(req dto.ContainerCommit) error - ContainerLogClean(req dto.OperationWithName) error - ContainerOperation(req dto.ContainerOperation) error - ContainerLogs(wsConn *websocket.Conn, containerType, container, since, tail string, follow bool) error - DownloadContainerLogs(containerType, container, since, tail string, c *gin.Context) error - ContainerStats(id string) (*dto.ContainerStats, error) - Inspect(req dto.InspectReq) (string, error) - DeleteNetwork(req dto.BatchDelete) error - CreateNetwork(req dto.NetworkCreate) error - DeleteVolume(req dto.BatchDelete) error - CreateVolume(req dto.VolumeCreate) error - TestCompose(req dto.ComposeCreate) (bool, error) - ComposeUpdate(req dto.ComposeUpdate) error - Prune(req dto.ContainerPrune) (dto.ContainerPruneReport, error) - - LoadContainerLogs(req dto.OperationWithNameAndType) string -} - -func NewIContainerService() IContainerService { - return &ContainerService{} -} - -func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, error) { - var ( - records []types.Container - list []types.Container - ) - client, err := docker.NewDockerClient() - if err != nil { - return 0, nil, err - } - defer client.Close() - options := container.ListOptions{ - All: true, - } - if len(req.Filters) != 0 { - options.Filters = filters.NewArgs() - options.Filters.Add("label", req.Filters) - } - containers, err := client.ContainerList(context.Background(), options) - if err != nil { - return 0, nil, err - } - if req.ExcludeAppStore { - for _, item := range containers { - if created, ok := item.Labels[composeCreatedBy]; ok && created == "Apps" { - continue - } - list = append(list, item) - } - } else { - list = containers - } - - if len(req.Name) != 0 { - length, count := len(list), 0 - for count < length { - if !strings.Contains(list[count].Names[0][1:], req.Name) { - list = append(list[:count], list[(count+1):]...) - length-- - } else { - count++ - } - } - } - if req.State != "all" { - length, count := len(list), 0 - for count < length { - if list[count].State != req.State { - list = append(list[:count], list[(count+1):]...) - length-- - } else { - count++ - } - } - } - switch req.OrderBy { - case "name": - sort.Slice(list, func(i, j int) bool { - if req.Order == constant.OrderAsc { - return list[i].Names[0][1:] < list[j].Names[0][1:] - } - return list[i].Names[0][1:] > list[j].Names[0][1:] - }) - case "state": - sort.Slice(list, func(i, j int) bool { - if req.Order == constant.OrderAsc { - return list[i].State < list[j].State - } - return list[i].State > list[j].State - }) - default: - sort.Slice(list, func(i, j int) bool { - if req.Order == constant.OrderAsc { - return list[i].Created < list[j].Created - } - return list[i].Created > list[j].Created - }) - } - - total, start, end := len(list), (req.Page-1)*req.PageSize, req.Page*req.PageSize - if start > total { - records = make([]types.Container, 0) - } else { - if end >= total { - end = total - } - records = list[start:end] - } - - backDatas := make([]dto.ContainerInfo, len(records)) - for i := 0; i < len(records); i++ { - item := records[i] - IsFromCompose := false - if _, ok := item.Labels[composeProjectLabel]; ok { - IsFromCompose = true - } - IsFromApp := false - if created, ok := item.Labels[composeCreatedBy]; ok && created == "Apps" { - IsFromApp = true - } - - ports := loadContainerPort(item.Ports) - info := dto.ContainerInfo{ - ContainerID: item.ID, - CreateTime: time.Unix(item.Created, 0).Format(constant.DateTimeLayout), - Name: item.Names[0][1:], - ImageId: strings.Split(item.ImageID, ":")[1], - ImageName: item.Image, - State: item.State, - RunTime: item.Status, - Ports: ports, - IsFromApp: IsFromApp, - IsFromCompose: IsFromCompose, - } - install, _ := appInstallRepo.GetFirst(appInstallRepo.WithContainerName(info.Name)) - if install.ID > 0 { - info.AppInstallName = install.Name - info.AppName = install.App.Name - websites, _ := websiteRepo.GetBy(websiteRepo.WithAppInstallId(install.ID)) - for _, website := range websites { - info.Websites = append(info.Websites, website.PrimaryDomain) - } - } - backDatas[i] = info - if item.NetworkSettings != nil && len(item.NetworkSettings.Networks) > 0 { - networks := make([]string, 0, len(item.NetworkSettings.Networks)) - for key := range item.NetworkSettings.Networks { - networks = append(networks, item.NetworkSettings.Networks[key].IPAddress) - } - sort.Strings(networks) - backDatas[i].Network = networks - } - } - - return int64(total), backDatas, nil -} - -func (u *ContainerService) List() ([]string, error) { - client, err := docker.NewDockerClient() - if err != nil { - return nil, err - } - defer client.Close() - containers, err := client.ContainerList(context.Background(), container.ListOptions{All: true}) - if err != nil { - return nil, err - } - var datas []string - for _, container := range containers { - for _, name := range container.Names { - if len(name) != 0 { - datas = append(datas, strings.TrimPrefix(name, "/")) - } - } - } - - return datas, nil -} - -func (u *ContainerService) ContainerListStats() ([]dto.ContainerListStats, error) { - client, err := docker.NewDockerClient() - if err != nil { - return nil, err - } - defer client.Close() - list, err := client.ContainerList(context.Background(), container.ListOptions{All: true}) - if err != nil { - return nil, err - } - var datas []dto.ContainerListStats - var wg sync.WaitGroup - wg.Add(len(list)) - for i := 0; i < len(list); i++ { - go func(item types.Container) { - datas = append(datas, loadCpuAndMem(client, item.ID)) - wg.Done() - }(list[i]) - } - wg.Wait() - return datas, nil -} - -func (u *ContainerService) Inspect(req dto.InspectReq) (string, error) { - client, err := docker.NewDockerClient() - if err != nil { - return "", err - } - defer client.Close() - var inspectInfo interface{} - switch req.Type { - case "container": - inspectInfo, err = client.ContainerInspect(context.Background(), req.ID) - case "image": - inspectInfo, _, err = client.ImageInspectWithRaw(context.Background(), req.ID) - case "network": - inspectInfo, err = client.NetworkInspect(context.TODO(), req.ID, types.NetworkInspectOptions{}) - case "volume": - inspectInfo, err = client.VolumeInspect(context.TODO(), req.ID) - } - if err != nil { - return "", err - } - bytes, err := json.Marshal(inspectInfo) - if err != nil { - return "", err - } - return string(bytes), nil -} - -func (u *ContainerService) Prune(req dto.ContainerPrune) (dto.ContainerPruneReport, error) { - report := dto.ContainerPruneReport{} - client, err := docker.NewDockerClient() - if err != nil { - return report, err - } - defer client.Close() - pruneFilters := filters.NewArgs() - if req.WithTagAll { - pruneFilters.Add("dangling", "false") - if req.PruneType != "image" { - pruneFilters.Add("until", "24h") - } - } - switch req.PruneType { - case "container": - rep, err := client.ContainersPrune(context.Background(), pruneFilters) - if err != nil { - return report, err - } - report.DeletedNumber = len(rep.ContainersDeleted) - report.SpaceReclaimed = int(rep.SpaceReclaimed) - case "image": - rep, err := client.ImagesPrune(context.Background(), pruneFilters) - if err != nil { - return report, err - } - report.DeletedNumber = len(rep.ImagesDeleted) - report.SpaceReclaimed = int(rep.SpaceReclaimed) - case "network": - rep, err := client.NetworksPrune(context.Background(), pruneFilters) - if err != nil { - return report, err - } - report.DeletedNumber = len(rep.NetworksDeleted) - case "volume": - versions, err := client.ServerVersion(context.Background()) - if err != nil { - return report, err - } - if common.ComparePanelVersion(versions.APIVersion, "1.42") { - pruneFilters.Add("all", "true") - } - rep, err := client.VolumesPrune(context.Background(), pruneFilters) - if err != nil { - return report, err - } - report.DeletedNumber = len(rep.VolumesDeleted) - report.SpaceReclaimed = int(rep.SpaceReclaimed) - case "buildcache": - opts := types.BuildCachePruneOptions{} - opts.All = true - rep, err := client.BuildCachePrune(context.Background(), opts) - if err != nil { - return report, err - } - report.DeletedNumber = len(rep.CachesDeleted) - report.SpaceReclaimed = int(rep.SpaceReclaimed) - } - return report, nil -} - -func (u *ContainerService) LoadResourceLimit() (*dto.ResourceLimit, error) { - cpuCounts, err := cpu.Counts(true) - if err != nil { - return nil, fmt.Errorf("load cpu limit failed, err: %v", err) - } - memoryInfo, err := mem.VirtualMemory() - if err != nil { - return nil, fmt.Errorf("load memory limit failed, err: %v", err) - } - - data := dto.ResourceLimit{ - CPU: cpuCounts, - Memory: memoryInfo.Total, - } - return &data, nil -} - -func (u *ContainerService) ContainerCreate(req dto.ContainerOperate) error { - client, err := docker.NewDockerClient() - if err != nil { - return err - } - defer client.Close() - ctx := context.Background() - newContainer, _ := client.ContainerInspect(ctx, req.Name) - if newContainer.ContainerJSONBase != nil { - return buserr.New(constant.ErrContainerName) - } - - if !checkImageExist(client, req.Image) || req.ForcePull { - if err := pullImages(ctx, client, req.Image); err != nil { - if !req.ForcePull { - return err - } - global.LOG.Errorf("force pull image %s failed, err: %v", req.Image, err) - } - } - imageInfo, _, err := client.ImageInspectWithRaw(ctx, req.Image) - if err != nil { - return err - } - if len(req.Entrypoint) == 0 { - req.Entrypoint = imageInfo.Config.Entrypoint - } - if len(req.Cmd) == 0 { - req.Cmd = imageInfo.Config.Cmd - } - config, hostConf, networkConf, err := loadConfigInfo(true, req, nil) - if err != nil { - return err - } - global.LOG.Infof("new container info %s has been made, now start to create", req.Name) - con, err := client.ContainerCreate(ctx, config, hostConf, networkConf, &v1.Platform{}, req.Name) - if err != nil { - _ = client.ContainerRemove(ctx, req.Name, container.RemoveOptions{RemoveVolumes: true, Force: true}) - return err - } - global.LOG.Infof("create container %s successful! now check if the container is started and delete the container information if it is not.", req.Name) - if err := client.ContainerStart(ctx, con.ID, container.StartOptions{}); err != nil { - _ = client.ContainerRemove(ctx, req.Name, container.RemoveOptions{RemoveVolumes: true, Force: true}) - return fmt.Errorf("create successful but start failed, err: %v", err) - } - return nil -} - -func (u *ContainerService) ContainerInfo(req dto.OperationWithName) (*dto.ContainerOperate, error) { - client, err := docker.NewDockerClient() - if err != nil { - return nil, err - } - defer client.Close() - ctx := context.Background() - oldContainer, err := client.ContainerInspect(ctx, req.Name) - if err != nil { - return nil, err - } - - var data dto.ContainerOperate - data.ContainerID = oldContainer.ID - data.Name = strings.ReplaceAll(oldContainer.Name, "/", "") - data.Image = oldContainer.Config.Image - if oldContainer.NetworkSettings != nil { - for network := range oldContainer.NetworkSettings.Networks { - data.Network = network - break - } - } - - networkSettings := oldContainer.NetworkSettings - bridgeNetworkSettings := networkSettings.Networks[data.Network] - if bridgeNetworkSettings.IPAMConfig != nil { - ipv4Address := bridgeNetworkSettings.IPAMConfig.IPv4Address - data.Ipv4 = ipv4Address - ipv6Address := bridgeNetworkSettings.IPAMConfig.IPv6Address - data.Ipv6 = ipv6Address - } else { - data.Ipv4 = bridgeNetworkSettings.IPAddress - } - - data.Cmd = oldContainer.Config.Cmd - data.OpenStdin = oldContainer.Config.OpenStdin - data.Tty = oldContainer.Config.Tty - data.Entrypoint = oldContainer.Config.Entrypoint - data.Env = oldContainer.Config.Env - data.CPUShares = oldContainer.HostConfig.CPUShares - for key, val := range oldContainer.Config.Labels { - data.Labels = append(data.Labels, fmt.Sprintf("%s=%s", key, val)) - } - for key, val := range oldContainer.HostConfig.PortBindings { - var itemPort dto.PortHelper - if !strings.Contains(string(key), "/") { - continue - } - itemPort.ContainerPort = strings.Split(string(key), "/")[0] - itemPort.Protocol = strings.Split(string(key), "/")[1] - for _, binds := range val { - itemPort.HostIP = binds.HostIP - itemPort.HostPort = binds.HostPort - data.ExposedPorts = append(data.ExposedPorts, itemPort) - } - } - data.AutoRemove = oldContainer.HostConfig.AutoRemove - data.Privileged = oldContainer.HostConfig.Privileged - data.PublishAllPorts = oldContainer.HostConfig.PublishAllPorts - data.RestartPolicy = string(oldContainer.HostConfig.RestartPolicy.Name) - if oldContainer.HostConfig.NanoCPUs != 0 { - data.NanoCPUs = float64(oldContainer.HostConfig.NanoCPUs) / 1000000000 - } - if oldContainer.HostConfig.Memory != 0 { - data.Memory = float64(oldContainer.HostConfig.Memory) / 1024 / 1024 - } - data.Volumes = loadVolumeBinds(oldContainer.Mounts) - - return &data, nil -} - -func (u *ContainerService) ContainerUpdate(req dto.ContainerOperate) error { - client, err := docker.NewDockerClient() - if err != nil { - return err - } - defer client.Close() - ctx := context.Background() - newContainer, _ := client.ContainerInspect(ctx, req.Name) - if newContainer.ContainerJSONBase != nil && newContainer.ID != req.ContainerID { - return buserr.New(constant.ErrContainerName) - } - - oldContainer, err := client.ContainerInspect(ctx, req.ContainerID) - if err != nil { - return err - } - if !checkImageExist(client, req.Image) || req.ForcePull { - if err := pullImages(ctx, client, req.Image); err != nil { - if !req.ForcePull { - return err - } - return fmt.Errorf("pull image %s failed, err: %v", req.Image, err) - } - } - - if err := client.ContainerRemove(ctx, req.ContainerID, container.RemoveOptions{Force: true}); err != nil { - return err - } - - config, hostConf, networkConf, err := loadConfigInfo(false, req, &oldContainer) - if err != nil { - reCreateAfterUpdate(req.Name, client, oldContainer.Config, oldContainer.HostConfig, oldContainer.NetworkSettings) - return err - } - - global.LOG.Infof("new container info %s has been update, now start to recreate", req.Name) - con, err := client.ContainerCreate(ctx, config, hostConf, networkConf, &v1.Platform{}, req.Name) - if err != nil { - reCreateAfterUpdate(req.Name, client, oldContainer.Config, oldContainer.HostConfig, oldContainer.NetworkSettings) - return fmt.Errorf("update container failed, err: %v", err) - } - global.LOG.Infof("update container %s successful! now check if the container is started.", req.Name) - if err := client.ContainerStart(ctx, con.ID, container.StartOptions{}); err != nil { - return fmt.Errorf("update successful but start failed, err: %v", err) - } - - return nil -} - -func (u *ContainerService) ContainerUpgrade(req dto.ContainerUpgrade) error { - client, err := docker.NewDockerClient() - if err != nil { - return err - } - defer client.Close() - ctx := context.Background() - oldContainer, err := client.ContainerInspect(ctx, req.Name) - if err != nil { - return err - } - if !checkImageExist(client, req.Image) || req.ForcePull { - if err := pullImages(ctx, client, req.Image); err != nil { - if !req.ForcePull { - return err - } - return fmt.Errorf("pull image %s failed, err: %v", req.Image, err) - } - } - config := oldContainer.Config - config.Image = req.Image - hostConf := oldContainer.HostConfig - var networkConf network.NetworkingConfig - if oldContainer.NetworkSettings != nil { - for networkKey := range oldContainer.NetworkSettings.Networks { - networkConf.EndpointsConfig = map[string]*network.EndpointSettings{networkKey: {}} - break - } - } - if err := client.ContainerRemove(ctx, req.Name, container.RemoveOptions{Force: true}); err != nil { - return err - } - - global.LOG.Infof("new container info %s has been update, now start to recreate", req.Name) - con, err := client.ContainerCreate(ctx, config, hostConf, &networkConf, &v1.Platform{}, req.Name) - if err != nil { - reCreateAfterUpdate(req.Name, client, oldContainer.Config, oldContainer.HostConfig, oldContainer.NetworkSettings) - return fmt.Errorf("upgrade container failed, err: %v", err) - } - global.LOG.Infof("upgrade container %s successful! now check if the container is started.", req.Name) - if err := client.ContainerStart(ctx, con.ID, container.StartOptions{}); err != nil { - return fmt.Errorf("upgrade successful but start failed, err: %v", err) - } - - return nil -} - -func (u *ContainerService) ContainerRename(req dto.ContainerRename) error { - ctx := context.Background() - client, err := docker.NewDockerClient() - if err != nil { - return err - } - defer client.Close() - - newContainer, _ := client.ContainerInspect(ctx, req.NewName) - if newContainer.ContainerJSONBase != nil { - return buserr.New(constant.ErrContainerName) - } - return client.ContainerRename(ctx, req.Name, req.NewName) -} - -func (u *ContainerService) ContainerCommit(req dto.ContainerCommit) error { - ctx := context.Background() - client, err := docker.NewDockerClient() - if err != nil { - return err - } - defer client.Close() - options := container.CommitOptions{ - Reference: req.NewImageName, - Comment: req.Comment, - Author: req.Author, - Changes: nil, - Pause: req.Pause, - Config: nil, - } - _, err = client.ContainerCommit(ctx, req.ContainerId, options) - if err != nil { - return fmt.Errorf("failed to commit container, err: %v", err) - } - return nil -} - -func (u *ContainerService) ContainerOperation(req dto.ContainerOperation) error { - var err error - ctx := context.Background() - client, err := docker.NewDockerClient() - if err != nil { - return err - } - defer client.Close() - for _, item := range req.Names { - global.LOG.Infof("start container %s operation %s", item, req.Operation) - switch req.Operation { - case constant.ContainerOpStart: - err = client.ContainerStart(ctx, item, container.StartOptions{}) - case constant.ContainerOpStop: - err = client.ContainerStop(ctx, item, container.StopOptions{}) - case constant.ContainerOpRestart: - err = client.ContainerRestart(ctx, item, container.StopOptions{}) - case constant.ContainerOpKill: - err = client.ContainerKill(ctx, item, "SIGKILL") - case constant.ContainerOpPause: - err = client.ContainerPause(ctx, item) - case constant.ContainerOpUnpause: - err = client.ContainerUnpause(ctx, item) - case constant.ContainerOpRemove: - err = client.ContainerRemove(ctx, item, container.RemoveOptions{RemoveVolumes: true, Force: true}) - } - } - return err -} - -func (u *ContainerService) ContainerLogClean(req dto.OperationWithName) error { - client, err := docker.NewDockerClient() - if err != nil { - return err - } - defer client.Close() - ctx := context.Background() - containerItem, err := client.ContainerInspect(ctx, req.Name) - if err != nil { - return err - } - if err := client.ContainerStop(ctx, containerItem.ID, container.StopOptions{}); err != nil { - return err - } - file, err := os.OpenFile(containerItem.LogPath, os.O_RDWR|os.O_CREATE, 0666) - if err != nil { - return err - } - defer file.Close() - if err = file.Truncate(0); err != nil { - return err - } - _, _ = file.Seek(0, 0) - - files, _ := filepath.Glob(fmt.Sprintf("%s.*", containerItem.LogPath)) - for _, file := range files { - _ = os.Remove(file) - } - - if err := client.ContainerStart(ctx, containerItem.ID, container.StartOptions{}); err != nil { - return err - } - return nil -} - -func (u *ContainerService) ContainerLogs(wsConn *websocket.Conn, containerType, container, since, tail string, follow bool) error { - defer func() { wsConn.Close() }() - if cmd.CheckIllegal(container, since, tail) { - return buserr.New(constant.ErrCmdIllegal) - } - commandName := "docker" - commandArg := []string{"logs", container} - if containerType == "compose" { - commandName = "docker-compose" - commandArg = []string{"-f", container, "logs"} - } - if tail != "0" { - commandArg = append(commandArg, "--tail") - commandArg = append(commandArg, tail) - } - if since != "all" { - commandArg = append(commandArg, "--since") - commandArg = append(commandArg, since) - } - if follow { - commandArg = append(commandArg, "-f") - } - if !follow { - cmd := exec.Command(commandName, commandArg...) - cmd.Stderr = cmd.Stdout - stdout, _ := cmd.CombinedOutput() - if !utf8.Valid(stdout) { - return errors.New("invalid utf8") - } - if err := wsConn.WriteMessage(websocket.TextMessage, stdout); err != nil { - global.LOG.Errorf("send message with log to ws failed, err: %v", err) - } - return nil - } - - cmd := exec.Command(commandName, commandArg...) - stdout, err := cmd.StdoutPipe() - if err != nil { - _ = cmd.Process.Signal(syscall.SIGTERM) - return err - } - cmd.Stderr = cmd.Stdout - if err := cmd.Start(); err != nil { - _ = cmd.Process.Signal(syscall.SIGTERM) - return err - } - exitCh := make(chan struct{}) - go func() { - _, wsData, _ := wsConn.ReadMessage() - if string(wsData) == "close conn" { - _ = cmd.Process.Signal(syscall.SIGTERM) - exitCh <- struct{}{} - } - }() - - go func() { - buffer := make([]byte, 1024) - for { - select { - case <-exitCh: - return - default: - n, err := stdout.Read(buffer) - if err != nil { - if err == io.EOF { - return - } - global.LOG.Errorf("read bytes from log failed, err: %v", err) - return - } - if !utf8.Valid(buffer[:n]) { - continue - } - if err = wsConn.WriteMessage(websocket.TextMessage, buffer[:n]); err != nil { - global.LOG.Errorf("send message with log to ws failed, err: %v", err) - return - } - } - } - }() - _ = cmd.Wait() - return nil -} - -func (u *ContainerService) DownloadContainerLogs(containerType, container, since, tail string, c *gin.Context) error { - if cmd.CheckIllegal(container, since, tail) { - return buserr.New(constant.ErrCmdIllegal) - } - commandName := "docker" - commandArg := []string{"logs", container} - if containerType == "compose" { - commandName = "docker-compose" - commandArg = []string{"-f", container, "logs"} - } - if tail != "0" { - commandArg = append(commandArg, "--tail") - commandArg = append(commandArg, tail) - } - if since != "all" { - commandArg = append(commandArg, "--since") - commandArg = append(commandArg, since) - } - - cmd := exec.Command(commandName, commandArg...) - stdout, err := cmd.StdoutPipe() - if err != nil { - _ = cmd.Process.Signal(syscall.SIGTERM) - return err - } - cmd.Stderr = cmd.Stdout - if err := cmd.Start(); err != nil { - _ = cmd.Process.Signal(syscall.SIGTERM) - return err - } - - tempFile, err := os.CreateTemp("", "cmd_output_*.txt") - if err != nil { - return err - } - defer tempFile.Close() - defer func() { - if err := os.Remove(tempFile.Name()); err != nil { - global.LOG.Errorf("os.Remove() failed: %v", err) - } - }() - errCh := make(chan error) - go func() { - scanner := bufio.NewScanner(stdout) - for scanner.Scan() { - line := scanner.Text() - if _, err := tempFile.WriteString(line + "\n"); err != nil { - errCh <- err - return - } - } - if err := scanner.Err(); err != nil { - errCh <- err - return - } - errCh <- nil - }() - select { - case err := <-errCh: - if err != nil { - global.LOG.Errorf("Error: %v", err) - } - case <-time.After(3 * time.Second): - global.LOG.Errorf("Timeout reached") - } - info, _ := tempFile.Stat() - - c.Header("Content-Length", strconv.FormatInt(info.Size(), 10)) - c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(info.Name())) - http.ServeContent(c.Writer, c.Request, info.Name(), info.ModTime(), tempFile) - return nil -} - -func (u *ContainerService) ContainerStats(id string) (*dto.ContainerStats, error) { - client, err := docker.NewDockerClient() - if err != nil { - return nil, err - } - defer client.Close() - res, err := client.ContainerStats(context.TODO(), id, false) - if err != nil { - return nil, err - } - defer res.Body.Close() - - body, err := io.ReadAll(res.Body) - if err != nil { - res.Body.Close() - return nil, err - } - res.Body.Close() - var stats *types.StatsJSON - if err := json.Unmarshal(body, &stats); err != nil { - return nil, err - } - var data dto.ContainerStats - data.CPUPercent = calculateCPUPercentUnix(stats) - data.IORead, data.IOWrite = calculateBlockIO(stats.BlkioStats) - data.Memory = float64(stats.MemoryStats.Usage) / 1024 / 1024 - if cache, ok := stats.MemoryStats.Stats["cache"]; ok { - data.Cache = float64(cache) / 1024 / 1024 - } - data.NetworkRX, data.NetworkTX = calculateNetwork(stats.Networks) - data.ShotTime = stats.Read - return &data, nil -} - -func (u *ContainerService) LoadContainerLogs(req dto.OperationWithNameAndType) string { - filePath := "" - if req.Type == "compose-detail" { - cli, err := docker.NewDockerClient() - if err != nil { - return "" - } - defer cli.Close() - options := container.ListOptions{All: true} - options.Filters = filters.NewArgs() - options.Filters.Add("label", fmt.Sprintf("%s=%s", composeProjectLabel, req.Name)) - containers, err := cli.ContainerList(context.Background(), options) - if err != nil { - return "" - } - for _, container := range containers { - config := container.Labels[composeConfigLabel] - workdir := container.Labels[composeWorkdirLabel] - if len(config) != 0 && len(workdir) != 0 && strings.Contains(config, workdir) { - filePath = config - break - } else { - filePath = workdir - break - } - } - } - if _, err := os.Stat(filePath); err != nil { - return "" - } - content, err := os.ReadFile(filePath) - if err != nil { - return "" - } - return string(content) -} - -func stringsToMap(list []string) map[string]string { - var labelMap = make(map[string]string) - for _, label := range list { - if strings.Contains(label, "=") { - sps := strings.SplitN(label, "=", 2) - labelMap[sps[0]] = sps[1] - } - } - return labelMap -} - -func calculateCPUPercentUnix(stats *types.StatsJSON) float64 { - cpuPercent := 0.0 - cpuDelta := float64(stats.CPUStats.CPUUsage.TotalUsage) - float64(stats.PreCPUStats.CPUUsage.TotalUsage) - systemDelta := float64(stats.CPUStats.SystemUsage) - float64(stats.PreCPUStats.SystemUsage) - - if systemDelta > 0.0 && cpuDelta > 0.0 { - cpuPercent = (cpuDelta / systemDelta) * 100.0 - if len(stats.CPUStats.CPUUsage.PercpuUsage) != 0 { - cpuPercent = cpuPercent * float64(len(stats.CPUStats.CPUUsage.PercpuUsage)) - } - } - return cpuPercent -} -func calculateMemPercentUnix(memStats types.MemoryStats) float64 { - memPercent := 0.0 - memUsage := float64(memStats.Usage) - memLimit := float64(memStats.Limit) - if memUsage > 0.0 && memLimit > 0.0 { - memPercent = (memUsage / memLimit) * 100.0 - } - return memPercent -} -func calculateBlockIO(blkio types.BlkioStats) (blkRead float64, blkWrite float64) { - for _, bioEntry := range blkio.IoServiceBytesRecursive { - switch strings.ToLower(bioEntry.Op) { - case "read": - blkRead = (blkRead + float64(bioEntry.Value)) / 1024 / 1024 - case "write": - blkWrite = (blkWrite + float64(bioEntry.Value)) / 1024 / 1024 - } - } - return -} -func calculateNetwork(network map[string]types.NetworkStats) (float64, float64) { - var rx, tx float64 - - for _, v := range network { - rx += float64(v.RxBytes) / 1024 - tx += float64(v.TxBytes) / 1024 - } - return rx, tx -} - -func checkImageExist(client *client.Client, imageItem string) bool { - images, err := client.ImageList(context.Background(), image.ListOptions{}) - if err != nil { - return false - } - - for _, img := range images { - for _, tag := range img.RepoTags { - if tag == imageItem || tag == imageItem+":latest" { - return true - } - } - } - return false -} - -func pullImages(ctx context.Context, client *client.Client, imageName string) error { - options := image.PullOptions{} - repos, _ := imageRepoRepo.List() - if len(repos) != 0 { - for _, repo := range repos { - if strings.HasPrefix(imageName, repo.DownloadUrl) && repo.Auth { - authConfig := registry.AuthConfig{ - Username: repo.Username, - Password: repo.Password, - } - encodedJSON, err := json.Marshal(authConfig) - if err != nil { - return err - } - authStr := base64.URLEncoding.EncodeToString(encodedJSON) - options.RegistryAuth = authStr - } - } - } else { - hasAuth, authStr := loadAuthInfo(imageName) - if hasAuth { - options.RegistryAuth = authStr - } - } - out, err := client.ImagePull(ctx, imageName, options) - if err != nil { - return err - } - defer out.Close() - _, err = io.Copy(io.Discard, out) - if err != nil { - return err - } - return nil -} - -func loadCpuAndMem(client *client.Client, container string) dto.ContainerListStats { - data := dto.ContainerListStats{ - ContainerID: container, - } - res, err := client.ContainerStats(context.Background(), container, false) - if err != nil { - return data - } - - defer res.Body.Close() - body, err := io.ReadAll(res.Body) - if err != nil { - return data - } - var stats *types.StatsJSON - if err := json.Unmarshal(body, &stats); err != nil { - return data - } - - data.CPUTotalUsage = stats.CPUStats.CPUUsage.TotalUsage - stats.PreCPUStats.CPUUsage.TotalUsage - data.SystemUsage = stats.CPUStats.SystemUsage - stats.PreCPUStats.SystemUsage - data.CPUPercent = calculateCPUPercentUnix(stats) - data.PercpuUsage = len(stats.CPUStats.CPUUsage.PercpuUsage) - - data.MemoryCache = stats.MemoryStats.Stats["cache"] - data.MemoryUsage = stats.MemoryStats.Usage - data.MemoryLimit = stats.MemoryStats.Limit - - data.MemoryPercent = calculateMemPercentUnix(stats.MemoryStats) - return data -} - -func checkPortStats(ports []dto.PortHelper) (nat.PortMap, error) { - portMap := make(nat.PortMap) - if len(ports) == 0 { - return portMap, nil - } - for _, port := range ports { - if strings.Contains(port.ContainerPort, "-") { - if !strings.Contains(port.HostPort, "-") { - return portMap, buserr.New(constant.ErrPortRules) - } - hostStart, _ := strconv.Atoi(strings.Split(port.HostPort, "-")[0]) - hostEnd, _ := strconv.Atoi(strings.Split(port.HostPort, "-")[1]) - containerStart, _ := strconv.Atoi(strings.Split(port.ContainerPort, "-")[0]) - containerEnd, _ := strconv.Atoi(strings.Split(port.ContainerPort, "-")[1]) - if (hostEnd-hostStart) <= 0 || (containerEnd-containerStart) <= 0 { - return portMap, buserr.New(constant.ErrPortRules) - } - if (containerEnd - containerStart) != (hostEnd - hostStart) { - return portMap, buserr.New(constant.ErrPortRules) - } - for i := 0; i <= hostEnd-hostStart; i++ { - bindItem := nat.PortBinding{HostPort: strconv.Itoa(hostStart + i), HostIP: port.HostIP} - portMap[nat.Port(fmt.Sprintf("%d/%s", containerStart+i, port.Protocol))] = []nat.PortBinding{bindItem} - } - for i := hostStart; i <= hostEnd; i++ { - if common.ScanPort(i) { - return portMap, buserr.WithDetail(constant.ErrPortInUsed, i, nil) - } - } - } else { - portItem := 0 - if strings.Contains(port.HostPort, "-") { - portItem, _ = strconv.Atoi(strings.Split(port.HostPort, "-")[0]) - } else { - portItem, _ = strconv.Atoi(port.HostPort) - } - if common.ScanPort(portItem) { - return portMap, buserr.WithDetail(constant.ErrPortInUsed, portItem, nil) - } - bindItem := nat.PortBinding{HostPort: strconv.Itoa(portItem), HostIP: port.HostIP} - portMap[nat.Port(fmt.Sprintf("%s/%s", port.ContainerPort, port.Protocol))] = []nat.PortBinding{bindItem} - } - } - return portMap, nil -} - -func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *types.ContainerJSON) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) { - var config container.Config - var hostConf container.HostConfig - if !isCreate { - config = *oldContainer.Config - hostConf = *oldContainer.HostConfig - } - var networkConf network.NetworkingConfig - - portMap, err := checkPortStats(req.ExposedPorts) - if err != nil { - return nil, nil, nil, err - } - exposed := make(nat.PortSet) - for port := range portMap { - exposed[port] = struct{}{} - } - config.Image = req.Image - config.Cmd = req.Cmd - config.Entrypoint = req.Entrypoint - config.Env = req.Env - config.Labels = stringsToMap(req.Labels) - config.ExposedPorts = exposed - config.OpenStdin = req.OpenStdin - config.Tty = req.Tty - - if len(req.Network) != 0 { - switch req.Network { - case "host", "none", "bridge": - hostConf.NetworkMode = container.NetworkMode(req.Network) - } - if req.Ipv4 != "" || req.Ipv6 != "" { - networkConf.EndpointsConfig = map[string]*network.EndpointSettings{ - req.Network: { - IPAMConfig: &network.EndpointIPAMConfig{ - IPv4Address: req.Ipv4, - IPv6Address: req.Ipv6, - }, - }} - } else { - networkConf.EndpointsConfig = map[string]*network.EndpointSettings{req.Network: {}} - } - } else { - if req.Ipv4 != "" || req.Ipv6 != "" { - return nil, nil, nil, fmt.Errorf("please set up the network") - } - networkConf = network.NetworkingConfig{} - } - - hostConf.Privileged = req.Privileged - hostConf.AutoRemove = req.AutoRemove - hostConf.CPUShares = req.CPUShares - hostConf.PublishAllPorts = req.PublishAllPorts - hostConf.RestartPolicy = container.RestartPolicy{Name: container.RestartPolicyMode(req.RestartPolicy)} - if req.RestartPolicy == "on-failure" { - hostConf.RestartPolicy.MaximumRetryCount = 5 - } - hostConf.NanoCPUs = int64(req.NanoCPUs * 1000000000) - hostConf.Memory = int64(req.Memory * 1024 * 1024) - hostConf.MemorySwap = 0 - hostConf.PortBindings = portMap - hostConf.Binds = []string{} - hostConf.Mounts = []mount.Mount{} - config.Volumes = make(map[string]struct{}) - for _, volume := range req.Volumes { - if volume.Type == "volume" { - hostConf.Mounts = append(hostConf.Mounts, mount.Mount{ - Type: mount.Type(volume.Type), - Source: volume.SourceDir, - Target: volume.ContainerDir, - }) - config.Volumes[volume.ContainerDir] = struct{}{} - } else { - hostConf.Binds = append(hostConf.Binds, fmt.Sprintf("%s:%s:%s", volume.SourceDir, volume.ContainerDir, volume.Mode)) - } - } - return &config, &hostConf, &networkConf, nil -} - -func reCreateAfterUpdate(name string, client *client.Client, config *container.Config, hostConf *container.HostConfig, networkConf *types.NetworkSettings) { - ctx := context.Background() - - var oldNetworkConf network.NetworkingConfig - if networkConf != nil { - for networkKey := range networkConf.Networks { - oldNetworkConf.EndpointsConfig = map[string]*network.EndpointSettings{networkKey: {}} - break - } - } - - oldContainer, err := client.ContainerCreate(ctx, config, hostConf, &oldNetworkConf, &v1.Platform{}, name) - if err != nil { - global.LOG.Errorf("recreate after container update failed, err: %v", err) - return - } - if err := client.ContainerStart(ctx, oldContainer.ID, container.StartOptions{}); err != nil { - global.LOG.Errorf("restart after container update failed, err: %v", err) - } - global.LOG.Errorf("recreate after container update successful") -} - -func loadVolumeBinds(binds []types.MountPoint) []dto.VolumeHelper { - var datas []dto.VolumeHelper - for _, bind := range binds { - var volumeItem dto.VolumeHelper - volumeItem.Type = string(bind.Type) - if bind.Type == "volume" { - volumeItem.SourceDir = bind.Name - } else { - volumeItem.SourceDir = bind.Source - } - volumeItem.ContainerDir = bind.Destination - volumeItem.Mode = "ro" - if bind.RW { - volumeItem.Mode = "rw" - } - datas = append(datas, volumeItem) - } - return datas -} - -func loadContainerPort(ports []types.Port) []string { - var ( - ipv4Ports []types.Port - ipv6Ports []types.Port - ) - for _, port := range ports { - if strings.Contains(port.IP, ":") { - ipv6Ports = append(ipv6Ports, port) - } else { - ipv4Ports = append(ipv4Ports, port) - } - } - list1 := simplifyPort(ipv4Ports) - list2 := simplifyPort(ipv6Ports) - return append(list1, list2...) -} -func simplifyPort(ports []types.Port) []string { - var datas []string - if len(ports) == 0 { - return datas - } - if len(ports) == 1 { - ip := "" - if len(ports[0].IP) != 0 { - ip = ports[0].IP + ":" - } - itemPortStr := fmt.Sprintf("%s%v/%s", ip, ports[0].PrivatePort, ports[0].Type) - if ports[0].PublicPort != 0 { - itemPortStr = fmt.Sprintf("%s%v->%v/%s", ip, ports[0].PublicPort, ports[0].PrivatePort, ports[0].Type) - } - datas = append(datas, itemPortStr) - return datas - } - - sort.Slice(ports, func(i, j int) bool { - return ports[i].PrivatePort < ports[j].PrivatePort - }) - start := ports[0] - - for i := 1; i < len(ports); i++ { - if ports[i].PrivatePort != ports[i-1].PrivatePort+1 || ports[i].IP != ports[i-1].IP || ports[i].PublicPort != ports[i-1].PublicPort+1 || ports[i].Type != ports[i-1].Type { - if ports[i-1].PrivatePort == start.PrivatePort { - itemPortStr := fmt.Sprintf("%s:%v/%s", start.IP, start.PrivatePort, start.Type) - if start.PublicPort != 0 { - itemPortStr = fmt.Sprintf("%s:%v->%v/%s", start.IP, start.PublicPort, start.PrivatePort, start.Type) - } - if len(start.IP) == 0 { - itemPortStr = strings.TrimPrefix(itemPortStr, ":") - } - datas = append(datas, itemPortStr) - } else { - itemPortStr := fmt.Sprintf("%s:%v-%v/%s", start.IP, start.PrivatePort, ports[i-1].PrivatePort, start.Type) - if start.PublicPort != 0 { - itemPortStr = fmt.Sprintf("%s:%v-%v->%v-%v/%s", start.IP, start.PublicPort, ports[i-1].PublicPort, start.PrivatePort, ports[i-1].PrivatePort, start.Type) - } - if len(start.IP) == 0 { - itemPortStr = strings.TrimPrefix(itemPortStr, ":") - } - datas = append(datas, itemPortStr) - } - start = ports[i] - } - if i == len(ports)-1 { - if ports[i].PrivatePort == start.PrivatePort { - itemPortStr := fmt.Sprintf("%s:%v/%s", start.IP, start.PrivatePort, start.Type) - if start.PublicPort != 0 { - itemPortStr = fmt.Sprintf("%s:%v->%v/%s", start.IP, start.PublicPort, start.PrivatePort, start.Type) - } - if len(start.IP) == 0 { - itemPortStr = strings.TrimPrefix(itemPortStr, ":") - } - datas = append(datas, itemPortStr) - } else { - itemPortStr := fmt.Sprintf("%s:%v-%v/%s", start.IP, start.PrivatePort, ports[i].PrivatePort, start.Type) - if start.PublicPort != 0 { - itemPortStr = fmt.Sprintf("%s:%v-%v->%v-%v/%s", start.IP, start.PublicPort, ports[i].PublicPort, start.PrivatePort, ports[i].PrivatePort, start.Type) - } - if len(start.IP) == 0 { - itemPortStr = strings.TrimPrefix(itemPortStr, ":") - } - datas = append(datas, itemPortStr) - } - } - } - return datas -} diff --git a/backend/app/service/container_compose.go b/backend/app/service/container_compose.go deleted file mode 100644 index 565abf292..000000000 --- a/backend/app/service/container_compose.go +++ /dev/null @@ -1,282 +0,0 @@ -package service - -import ( - "bufio" - "errors" - "fmt" - "io" - "os" - "os/exec" - "path" - "sort" - "strings" - "time" - - "github.com/docker/docker/api/types/container" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/compose" - "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/docker/docker/api/types/filters" - "golang.org/x/net/context" -) - -const composeProjectLabel = "com.docker.compose.project" -const composeConfigLabel = "com.docker.compose.project.config_files" -const composeWorkdirLabel = "com.docker.compose.project.working_dir" -const composeCreatedBy = "createdBy" - -func (u *ContainerService) PageCompose(req dto.SearchWithPage) (int64, interface{}, error) { - var ( - records []dto.ComposeInfo - BackDatas []dto.ComposeInfo - ) - client, err := docker.NewDockerClient() - if err != nil { - return 0, nil, err - } - defer client.Close() - - options := container.ListOptions{All: true} - options.Filters = filters.NewArgs() - options.Filters.Add("label", composeProjectLabel) - - list, err := client.ContainerList(context.Background(), options) - if err != nil { - return 0, nil, err - } - - composeCreatedByLocal, _ := composeRepo.ListRecord() - composeMap := make(map[string]dto.ComposeInfo) - for _, container := range list { - if name, ok := container.Labels[composeProjectLabel]; ok { - containerItem := dto.ComposeContainer{ - ContainerID: container.ID, - Name: container.Names[0][1:], - State: container.State, - CreateTime: time.Unix(container.Created, 0).Format(constant.DateTimeLayout), - } - if compose, has := composeMap[name]; has { - compose.ContainerNumber++ - compose.Containers = append(compose.Containers, containerItem) - composeMap[name] = compose - } else { - config := container.Labels[composeConfigLabel] - workdir := container.Labels[composeWorkdirLabel] - composeItem := dto.ComposeInfo{ - ContainerNumber: 1, - CreatedAt: time.Unix(container.Created, 0).Format(constant.DateTimeLayout), - ConfigFile: config, - Workdir: workdir, - Containers: []dto.ComposeContainer{containerItem}, - } - createdBy, ok := container.Labels[composeCreatedBy] - if ok { - composeItem.CreatedBy = createdBy - } - if len(config) != 0 && len(workdir) != 0 && strings.Contains(config, workdir) { - composeItem.Path = config - } else { - composeItem.Path = workdir - } - for i := 0; i < len(composeCreatedByLocal); i++ { - if composeCreatedByLocal[i].Name == name { - composeItem.CreatedBy = "1Panel" - composeCreatedByLocal = append(composeCreatedByLocal[:i], composeCreatedByLocal[i+1:]...) - break - } - } - composeMap[name] = composeItem - } - } - } - for _, item := range composeCreatedByLocal { - if err := composeRepo.DeleteRecord(commonRepo.WithByID(item.ID)); err != nil { - global.LOG.Error(err) - } - } - for key, value := range composeMap { - value.Name = key - records = append(records, value) - } - if len(req.Info) != 0 { - length, count := len(records), 0 - for count < length { - if !strings.Contains(records[count].Name, req.Info) { - records = append(records[:count], records[(count+1):]...) - length-- - } else { - count++ - } - } - } - sort.Slice(records, func(i, j int) bool { - return records[i].CreatedAt > records[j].CreatedAt - }) - total, start, end := len(records), (req.Page-1)*req.PageSize, req.Page*req.PageSize - if start > total { - BackDatas = make([]dto.ComposeInfo, 0) - } else { - if end >= total { - end = total - } - BackDatas = records[start:end] - } - return int64(total), BackDatas, nil -} - -func (u *ContainerService) TestCompose(req dto.ComposeCreate) (bool, error) { - if cmd.CheckIllegal(req.Path) { - return false, buserr.New(constant.ErrCmdIllegal) - } - composeItem, _ := composeRepo.GetRecord(commonRepo.WithByName(req.Name)) - if composeItem.ID != 0 { - return false, constant.ErrRecordExist - } - if err := u.loadPath(&req); err != nil { - return false, err - } - cmd := exec.Command("docker-compose", "-f", req.Path, "config") - stdout, err := cmd.CombinedOutput() - if err != nil { - return false, errors.New(string(stdout)) - } - return true, nil -} - -func (u *ContainerService) CreateCompose(req dto.ComposeCreate) (string, error) { - if cmd.CheckIllegal(req.Name, req.Path) { - return "", buserr.New(constant.ErrCmdIllegal) - } - if err := u.loadPath(&req); err != nil { - return "", err - } - global.LOG.Infof("docker-compose.yml %s create successful, start to docker-compose up", req.Name) - - if req.From == "path" { - req.Name = path.Base(path.Dir(req.Path)) - } - - dockerLogDir := path.Join(global.CONF.System.TmpDir, "docker_logs") - if _, err := os.Stat(dockerLogDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(dockerLogDir, os.ModePerm); err != nil { - return "", err - } - } - logItem := fmt.Sprintf("%s/compose_create_%s_%s.log", dockerLogDir, req.Name, time.Now().Format(constant.DateTimeSlimLayout)) - file, err := os.OpenFile(logItem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) - if err != nil { - return "", err - } - go func() { - defer file.Close() - cmd := exec.Command("docker-compose", "-f", req.Path, "up", "-d") - multiWriter := io.MultiWriter(os.Stdout, file) - cmd.Stdout = multiWriter - cmd.Stderr = multiWriter - if err := cmd.Run(); err != nil { - global.LOG.Errorf("docker-compose up %s failed, err: %v", req.Name, err) - _, _ = compose.Down(req.Path) - _, _ = file.WriteString("docker-compose up failed!") - return - } - global.LOG.Infof("docker-compose up %s successful!", req.Name) - _ = composeRepo.CreateRecord(&model.Compose{Name: req.Name}) - _, _ = file.WriteString("docker-compose up successful!") - }() - - return path.Base(logItem), nil -} - -func (u *ContainerService) ComposeOperation(req dto.ComposeOperation) error { - if cmd.CheckIllegal(req.Path, req.Operation) { - return buserr.New(constant.ErrCmdIllegal) - } - if _, err := os.Stat(req.Path); err != nil { - return fmt.Errorf("load file with path %s failed, %v", req.Path, err) - } - if stdout, err := compose.Operate(req.Path, req.Operation); err != nil { - return errors.New(string(stdout)) - } - global.LOG.Infof("docker-compose %s %s successful", req.Operation, req.Name) - if req.Operation == "down" { - _ = composeRepo.DeleteRecord(commonRepo.WithByName(req.Name)) - if req.WithFile { - _ = os.RemoveAll(path.Dir(req.Path)) - } - } - - return nil -} - -func (u *ContainerService) ComposeUpdate(req dto.ComposeUpdate) error { - if cmd.CheckIllegal(req.Name, req.Path) { - return buserr.New(constant.ErrCmdIllegal) - } - oldFile, err := os.ReadFile(req.Path) - if err != nil { - return fmt.Errorf("load file with path %s failed, %v", req.Path, err) - } - file, err := os.OpenFile(req.Path, os.O_WRONLY|os.O_TRUNC, 0640) - if err != nil { - return err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(req.Content) - write.Flush() - - global.LOG.Infof("docker-compose.yml %s has been replaced, now start to docker-compose restart", req.Path) - if stdout, err := compose.Up(req.Path); err != nil { - if err := recreateCompose(string(oldFile), req.Path); err != nil { - return fmt.Errorf("update failed when handle compose up, err: %s, recreate failed: %v", string(stdout), err) - } - return fmt.Errorf("update failed when handle compose up, err: %s", string(stdout)) - } - - return nil -} - -func (u *ContainerService) loadPath(req *dto.ComposeCreate) error { - if req.From == "template" || req.From == "edit" { - dir := fmt.Sprintf("%s/docker/compose/%s", constant.DataDir, req.Name) - if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(dir, os.ModePerm); err != nil { - return err - } - } - - path := fmt.Sprintf("%s/docker-compose.yml", dir) - file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) - if err != nil { - return err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(string(req.File)) - write.Flush() - req.Path = path - } - return nil -} - -func recreateCompose(content, path string) error { - file, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0640) - if err != nil { - return err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(content) - write.Flush() - - if stdout, err := compose.Up(path); err != nil { - return errors.New(string(stdout)) - } - return nil -} diff --git a/backend/app/service/container_network.go b/backend/app/service/container_network.go deleted file mode 100644 index 44424e914..000000000 --- a/backend/app/service/container_network.go +++ /dev/null @@ -1,179 +0,0 @@ -package service - -import ( - "context" - "fmt" - "sort" - "strings" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/network" -) - -func (u *ContainerService) PageNetwork(req dto.SearchWithPage) (int64, interface{}, error) { - client, err := docker.NewDockerClient() - if err != nil { - return 0, nil, err - } - defer client.Close() - list, err := client.NetworkList(context.TODO(), types.NetworkListOptions{}) - if err != nil { - return 0, nil, err - } - if len(req.Info) != 0 { - length, count := len(list), 0 - for count < length { - if !strings.Contains(list[count].Name, req.Info) { - list = append(list[:count], list[(count+1):]...) - length-- - } else { - count++ - } - } - } - var ( - data []dto.Network - records []types.NetworkResource - ) - sort.Slice(list, func(i, j int) bool { - return list[i].Created.Before(list[j].Created) - }) - total, start, end := len(list), (req.Page-1)*req.PageSize, req.Page*req.PageSize - if start > total { - records = make([]types.NetworkResource, 0) - } else { - if end >= total { - end = total - } - records = list[start:end] - } - - for _, item := range records { - tag := make([]string, 0) - for key, val := range item.Labels { - tag = append(tag, fmt.Sprintf("%s=%s", key, val)) - } - var ipam network.IPAMConfig - if len(item.IPAM.Config) > 0 { - ipam = item.IPAM.Config[0] - } - data = append(data, dto.Network{ - ID: item.ID, - CreatedAt: item.Created, - Name: item.Name, - Driver: item.Driver, - IPAMDriver: item.IPAM.Driver, - Subnet: ipam.Subnet, - Gateway: ipam.Gateway, - Attachable: item.Attachable, - Labels: tag, - }) - } - - return int64(total), data, nil -} - -func (u *ContainerService) ListNetwork() ([]dto.Options, error) { - client, err := docker.NewDockerClient() - if err != nil { - return nil, err - } - defer client.Close() - list, err := client.NetworkList(context.TODO(), types.NetworkListOptions{}) - if err != nil { - return nil, err - } - var datas []dto.Options - for _, item := range list { - datas = append(datas, dto.Options{Option: item.Name}) - } - sort.Slice(datas, func(i, j int) bool { - return datas[i].Option < datas[j].Option - }) - return datas, nil -} - -func (u *ContainerService) DeleteNetwork(req dto.BatchDelete) error { - client, err := docker.NewDockerClient() - if err != nil { - return err - } - defer client.Close() - for _, id := range req.Names { - if err := client.NetworkRemove(context.TODO(), id); err != nil { - if strings.Contains(err.Error(), "has active endpoints") { - return buserr.WithDetail(constant.ErrInUsed, id, nil) - } - return err - } - } - return nil -} -func (u *ContainerService) CreateNetwork(req dto.NetworkCreate) error { - client, err := docker.NewDockerClient() - if err != nil { - return err - } - defer client.Close() - var ( - ipams []network.IPAMConfig - enableV6 bool - ) - if req.Ipv4 { - var itemIpam network.IPAMConfig - if len(req.AuxAddress) != 0 { - itemIpam.AuxAddress = make(map[string]string) - } - if len(req.Subnet) != 0 { - itemIpam.Subnet = req.Subnet - } - if len(req.Gateway) != 0 { - itemIpam.Gateway = req.Gateway - } - if len(req.IPRange) != 0 { - itemIpam.IPRange = req.IPRange - } - for _, addr := range req.AuxAddress { - itemIpam.AuxAddress[addr.Key] = addr.Value - } - ipams = append(ipams, itemIpam) - } - if req.Ipv6 { - enableV6 = true - var itemIpam network.IPAMConfig - if len(req.AuxAddress) != 0 { - itemIpam.AuxAddress = make(map[string]string) - } - if len(req.SubnetV6) != 0 { - itemIpam.Subnet = req.SubnetV6 - } - if len(req.GatewayV6) != 0 { - itemIpam.Gateway = req.GatewayV6 - } - if len(req.IPRangeV6) != 0 { - itemIpam.IPRange = req.IPRangeV6 - } - for _, addr := range req.AuxAddressV6 { - itemIpam.AuxAddress[addr.Key] = addr.Value - } - ipams = append(ipams, itemIpam) - } - - options := types.NetworkCreate{ - EnableIPv6: enableV6, - Driver: req.Driver, - Options: stringsToMap(req.Options), - Labels: stringsToMap(req.Labels), - } - if len(ipams) != 0 { - options.IPAM = &network.IPAM{Config: ipams} - } - if _, err := client.NetworkCreate(context.TODO(), req.Name, options); err != nil { - return err - } - return nil -} diff --git a/backend/app/service/container_volume.go b/backend/app/service/container_volume.go deleted file mode 100644 index daaa49b4c..000000000 --- a/backend/app/service/container_volume.go +++ /dev/null @@ -1,143 +0,0 @@ -package service - -import ( - "context" - "sort" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/volume" -) - -func (u *ContainerService) PageVolume(req dto.SearchWithPage) (int64, interface{}, error) { - client, err := docker.NewDockerClient() - if err != nil { - return 0, nil, err - } - list, err := client.VolumeList(context.TODO(), volume.ListOptions{}) - if err != nil { - return 0, nil, err - } - if len(req.Info) != 0 { - length, count := len(list.Volumes), 0 - for count < length { - if !strings.Contains(list.Volumes[count].Name, req.Info) { - list.Volumes = append(list.Volumes[:count], list.Volumes[(count+1):]...) - length-- - } else { - count++ - } - } - } - var ( - data []dto.Volume - records []*volume.Volume - ) - sort.Slice(list.Volumes, func(i, j int) bool { - return list.Volumes[i].CreatedAt > list.Volumes[j].CreatedAt - }) - total, start, end := len(list.Volumes), (req.Page-1)*req.PageSize, req.Page*req.PageSize - if start > total { - records = make([]*volume.Volume, 0) - } else { - if end >= total { - end = total - } - records = list.Volumes[start:end] - } - - nyc, _ := time.LoadLocation(common.LoadTimeZone()) - for _, item := range records { - tag := make([]string, 0) - for _, val := range item.Labels { - tag = append(tag, val) - } - var createTime time.Time - if strings.Contains(item.CreatedAt, "Z") { - createTime, _ = time.ParseInLocation("2006-01-02T15:04:05Z", item.CreatedAt, nyc) - } else if strings.Contains(item.CreatedAt, "+") { - createTime, _ = time.ParseInLocation("2006-01-02T15:04:05+08:00", item.CreatedAt, nyc) - } else { - createTime, _ = time.ParseInLocation("2006-01-02T15:04:05", item.CreatedAt, nyc) - } - data = append(data, dto.Volume{ - CreatedAt: createTime, - Name: item.Name, - Driver: item.Driver, - Mountpoint: item.Mountpoint, - Labels: tag, - }) - } - - return int64(total), data, nil -} -func (u *ContainerService) ListVolume() ([]dto.Options, error) { - client, err := docker.NewDockerClient() - if err != nil { - return nil, err - } - defer client.Close() - list, err := client.VolumeList(context.TODO(), volume.ListOptions{}) - if err != nil { - return nil, err - } - var datas []dto.Options - for _, item := range list.Volumes { - datas = append(datas, dto.Options{ - Option: item.Name, - }) - } - sort.Slice(datas, func(i, j int) bool { - return datas[i].Option < datas[j].Option - }) - return datas, nil -} -func (u *ContainerService) DeleteVolume(req dto.BatchDelete) error { - client, err := docker.NewDockerClient() - if err != nil { - return err - } - defer client.Close() - for _, id := range req.Names { - if err := client.VolumeRemove(context.TODO(), id, true); err != nil { - if strings.Contains(err.Error(), "volume is in use") { - return buserr.WithDetail(constant.ErrInUsed, id, nil) - } - return err - } - } - return nil -} -func (u *ContainerService) CreateVolume(req dto.VolumeCreate) error { - client, err := docker.NewDockerClient() - if err != nil { - return err - } - defer client.Close() - arg := filters.NewArgs() - arg.Add("name", req.Name) - vos, _ := client.VolumeList(context.TODO(), volume.ListOptions{Filters: arg}) - if len(vos.Volumes) != 0 { - for _, v := range vos.Volumes { - if v.Name == req.Name { - return constant.ErrRecordExist - } - } - } - options := volume.CreateOptions{ - Name: req.Name, - Driver: req.Driver, - DriverOpts: stringsToMap(req.Options), - Labels: stringsToMap(req.Labels), - } - if _, err := client.VolumeCreate(context.TODO(), options); err != nil { - return err - } - return nil -} diff --git a/backend/app/service/cronjob.go b/backend/app/service/cronjob.go deleted file mode 100644 index 41accecf4..000000000 --- a/backend/app/service/cronjob.go +++ /dev/null @@ -1,344 +0,0 @@ -package service - -import ( - "bufio" - "fmt" - "os" - "path" - "strconv" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/jinzhu/copier" - "github.com/pkg/errors" - "github.com/robfig/cron/v3" -) - -type CronjobService struct{} - -type ICronjobService interface { - SearchWithPage(search dto.PageCronjob) (int64, interface{}, error) - SearchRecords(search dto.SearchRecord) (int64, interface{}, error) - Create(cronjobDto dto.CronjobCreate) error - HandleOnce(id uint) error - Update(id uint, req dto.CronjobUpdate) error - UpdateStatus(id uint, status string) error - Delete(req dto.CronjobBatchDelete) error - Download(down dto.CronjobDownload) (string, error) - StartJob(cronjob *model.Cronjob, isUpdate bool) (string, error) - CleanRecord(req dto.CronjobClean) error - - LoadRecordLog(req dto.OperateByID) string -} - -func NewICronjobService() ICronjobService { - return &CronjobService{} -} - -func (u *CronjobService) SearchWithPage(search dto.PageCronjob) (int64, interface{}, error) { - total, cronjobs, err := cronjobRepo.Page(search.Page, search.PageSize, commonRepo.WithLikeName(search.Info), commonRepo.WithOrderRuleBy(search.OrderBy, search.Order)) - var dtoCronjobs []dto.CronjobInfo - for _, cronjob := range cronjobs { - var item dto.CronjobInfo - if err := copier.Copy(&item, &cronjob); err != nil { - return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - record, _ := cronjobRepo.RecordFirst(cronjob.ID) - if record.ID != 0 { - item.LastRecordTime = record.StartTime.Format(constant.DateTimeLayout) - } else { - item.LastRecordTime = "-" - } - dtoCronjobs = append(dtoCronjobs, item) - } - return total, dtoCronjobs, err -} - -func (u *CronjobService) SearchRecords(search dto.SearchRecord) (int64, interface{}, error) { - total, records, err := cronjobRepo.PageRecords( - search.Page, - search.PageSize, - commonRepo.WithByStatus(search.Status), - cronjobRepo.WithByJobID(search.CronjobID), - commonRepo.WithByDate(search.StartTime, search.EndTime)) - var dtoCronjobs []dto.Record - for _, record := range records { - var item dto.Record - if err := copier.Copy(&item, &record); err != nil { - return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - item.StartTime = record.StartTime.Format(constant.DateTimeLayout) - dtoCronjobs = append(dtoCronjobs, item) - } - return total, dtoCronjobs, err -} - -func (u *CronjobService) LoadRecordLog(req dto.OperateByID) string { - record, err := cronjobRepo.GetRecord(commonRepo.WithByID(req.ID)) - if err != nil { - return "" - } - if _, err := os.Stat(record.Records); err != nil { - return "" - } - content, err := os.ReadFile(record.Records) - if err != nil { - return "" - } - return string(content) -} - -func (u *CronjobService) CleanRecord(req dto.CronjobClean) error { - cronjob, err := cronjobRepo.Get(commonRepo.WithByID(req.CronjobID)) - if err != nil { - return err - } - if req.CleanData { - if hasBackup(cronjob.Type) { - accountMap, err := loadClientMap(cronjob.BackupAccounts) - if err != nil { - return err - } - cronjob.RetainCopies = 0 - u.removeExpiredBackup(cronjob, accountMap, model.BackupRecord{}) - } else { - u.removeExpiredLog(cronjob) - } - } - if req.IsDelete { - records, _ := backupRepo.ListRecord(backupRepo.WithByCronID(cronjob.ID)) - for _, records := range records { - records.CronjobID = 0 - _ = backupRepo.UpdateRecord(&records) - } - } - delRecords, err := cronjobRepo.ListRecord(cronjobRepo.WithByJobID(int(req.CronjobID))) - if err != nil { - return err - } - for _, del := range delRecords { - _ = os.RemoveAll(del.Records) - } - if err := cronjobRepo.DeleteRecord(cronjobRepo.WithByJobID(int(req.CronjobID))); err != nil { - return err - } - return nil -} - -func (u *CronjobService) Download(down dto.CronjobDownload) (string, error) { - record, _ := cronjobRepo.GetRecord(commonRepo.WithByID(down.RecordID)) - if record.ID == 0 { - return "", constant.ErrRecordNotFound - } - backup, _ := backupRepo.Get(commonRepo.WithByID(down.BackupAccountID)) - if backup.ID == 0 { - return "", constant.ErrRecordNotFound - } - if backup.Type == "LOCAL" || record.FromLocal { - if _, err := os.Stat(record.File); err != nil && os.IsNotExist(err) { - return "", err - } - return record.File, nil - } - tempPath := fmt.Sprintf("%s/download/%s", constant.DataDir, record.File) - if _, err := os.Stat(tempPath); err != nil && os.IsNotExist(err) { - client, err := NewIBackupService().NewClient(&backup) - if err != nil { - return "", err - } - _ = os.MkdirAll(path.Dir(tempPath), os.ModePerm) - isOK, err := client.Download(record.File, tempPath) - if !isOK || err != nil { - return "", err - } - } - return tempPath, nil -} - -func (u *CronjobService) HandleOnce(id uint) error { - cronjob, _ := cronjobRepo.Get(commonRepo.WithByID(id)) - if cronjob.ID == 0 { - return constant.ErrRecordNotFound - } - u.HandleJob(&cronjob) - return nil -} - -func (u *CronjobService) Create(cronjobDto dto.CronjobCreate) error { - cronjob, _ := cronjobRepo.Get(commonRepo.WithByName(cronjobDto.Name)) - if cronjob.ID != 0 { - return constant.ErrRecordExist - } - cronjob.Secret = cronjobDto.Secret - if err := copier.Copy(&cronjob, &cronjobDto); err != nil { - return errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - cronjob.Status = constant.StatusEnable - - global.LOG.Infof("create cronjob %s successful, spec: %s", cronjob.Name, cronjob.Spec) - spec := cronjob.Spec - entryIDs, err := u.StartJob(&cronjob, false) - if err != nil { - return err - } - cronjob.Spec = spec - cronjob.EntryIDs = entryIDs - if err := cronjobRepo.Create(&cronjob); err != nil { - return err - } - return nil -} - -func (u *CronjobService) StartJob(cronjob *model.Cronjob, isUpdate bool) (string, error) { - if len(cronjob.EntryIDs) != 0 && isUpdate { - ids := strings.Split(cronjob.EntryIDs, ",") - for _, id := range ids { - idItem, _ := strconv.Atoi(id) - global.Cron.Remove(cron.EntryID(idItem)) - } - } - specs := strings.Split(cronjob.Spec, ",") - var ids []string - for _, spec := range specs { - cronjob.Spec = spec - entryID, err := u.AddCronJob(cronjob) - if err != nil { - return "", err - } - ids = append(ids, fmt.Sprintf("%v", entryID)) - } - return strings.Join(ids, ","), nil -} - -func (u *CronjobService) Delete(req dto.CronjobBatchDelete) error { - for _, id := range req.IDs { - cronjob, _ := cronjobRepo.Get(commonRepo.WithByID(id)) - if cronjob.ID == 0 { - return errors.New("find cronjob in db failed") - } - ids := strings.Split(cronjob.EntryIDs, ",") - for _, id := range ids { - idItem, _ := strconv.Atoi(id) - global.Cron.Remove(cron.EntryID(idItem)) - } - global.LOG.Infof("stop cronjob entryID: %s", cronjob.EntryIDs) - if err := u.CleanRecord(dto.CronjobClean{CronjobID: id, CleanData: req.CleanData, IsDelete: true}); err != nil { - return err - } - if err := cronjobRepo.Delete(commonRepo.WithByID(id)); err != nil { - return err - } - } - - return nil -} - -func (u *CronjobService) Update(id uint, req dto.CronjobUpdate) error { - var cronjob model.Cronjob - if err := copier.Copy(&cronjob, &req); err != nil { - return errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - cronModel, err := cronjobRepo.Get(commonRepo.WithByID(id)) - if err != nil { - return constant.ErrRecordNotFound - } - upMap := make(map[string]interface{}) - cronjob.EntryIDs = cronModel.EntryIDs - cronjob.Type = cronModel.Type - spec := cronjob.Spec - if cronModel.Status == constant.StatusEnable { - newEntryIDs, err := u.StartJob(&cronjob, true) - if err != nil { - return err - } - upMap["entry_ids"] = newEntryIDs - } else { - ids := strings.Split(cronjob.EntryIDs, ",") - for _, id := range ids { - idItem, _ := strconv.Atoi(id) - global.Cron.Remove(cron.EntryID(idItem)) - } - } - - upMap["name"] = req.Name - upMap["spec"] = spec - upMap["script"] = req.Script - upMap["command"] = req.Command - upMap["container_name"] = req.ContainerName - upMap["app_id"] = req.AppID - upMap["website"] = req.Website - upMap["exclusion_rules"] = req.ExclusionRules - upMap["db_type"] = req.DBType - upMap["db_name"] = req.DBName - upMap["url"] = req.URL - upMap["source_dir"] = req.SourceDir - - upMap["backup_accounts"] = req.BackupAccounts - upMap["default_download"] = req.DefaultDownload - upMap["retain_copies"] = req.RetainCopies - upMap["secret"] = req.Secret - return cronjobRepo.Update(id, upMap) -} - -func (u *CronjobService) UpdateStatus(id uint, status string) error { - cronjob, _ := cronjobRepo.Get(commonRepo.WithByID(id)) - if cronjob.ID == 0 { - return errors.WithMessage(constant.ErrRecordNotFound, "record not found") - } - var ( - entryIDs string - err error - ) - if status == constant.StatusEnable { - entryIDs, err = u.StartJob(&cronjob, false) - if err != nil { - return err - } - } else { - ids := strings.Split(cronjob.EntryIDs, ",") - for _, id := range ids { - idItem, _ := strconv.Atoi(id) - global.Cron.Remove(cron.EntryID(idItem)) - } - global.LOG.Infof("stop cronjob entryID: %s", cronjob.EntryIDs) - } - return cronjobRepo.Update(cronjob.ID, map[string]interface{}{"status": status, "entry_ids": entryIDs}) -} - -func (u *CronjobService) AddCronJob(cronjob *model.Cronjob) (int, error) { - addFunc := func() { - u.HandleJob(cronjob) - } - global.LOG.Infof("add %s job %s successful", cronjob.Type, cronjob.Name) - entryID, err := global.Cron.AddFunc(cronjob.Spec, addFunc) - if err != nil { - return 0, err - } - global.LOG.Infof("start cronjob entryID: %d", entryID) - return int(entryID), nil -} - -func mkdirAndWriteFile(cronjob *model.Cronjob, startTime time.Time, msg []byte) (string, error) { - dir := fmt.Sprintf("%s/task/%s/%s", constant.DataDir, cronjob.Type, cronjob.Name) - if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(dir, os.ModePerm); err != nil { - return "", err - } - } - - path := fmt.Sprintf("%s/%s.log", dir, startTime.Format(constant.DateTimeSlimLayout)) - global.LOG.Infof("cronjob %s has generated some logs %s", cronjob.Name, path) - file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0666) - if err != nil { - return "", err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(string(msg)) - write.Flush() - return path, nil -} diff --git a/backend/app/service/cronjob_backup.go b/backend/app/service/cronjob_backup.go deleted file mode 100644 index e77f94075..000000000 --- a/backend/app/service/cronjob_backup.go +++ /dev/null @@ -1,386 +0,0 @@ -package service - -import ( - "fmt" - "os" - "path" - "strconv" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/common" -) - -func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time) error { - var apps []model.AppInstall - if cronjob.AppID == "all" { - apps, _ = appInstallRepo.ListBy() - } else { - itemID, _ := strconv.Atoi(cronjob.AppID) - app, err := appInstallRepo.GetFirst(commonRepo.WithByID(uint(itemID))) - if err != nil { - return err - } - apps = append(apps, app) - } - accountMap, err := loadClientMap(cronjob.BackupAccounts) - if err != nil { - return err - } - for _, app := range apps { - var record model.BackupRecord - record.From = "cronjob" - record.Type = "app" - record.CronjobID = cronjob.ID - record.Name = app.App.Key - record.DetailName = app.Name - record.Source, record.BackupType = loadRecordPath(cronjob, accountMap) - backupDir := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("app/%s/%s", app.App.Key, app.Name)) - record.FileName = fmt.Sprintf("app_%s_%s.tar.gz", app.Name, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)) - if err := handleAppBackup(&app, backupDir, record.FileName, cronjob.ExclusionRules, cronjob.Secret); err != nil { - return err - } - downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(backupDir, record.FileName)) - if err != nil { - return err - } - record.FileDir = path.Dir(downloadPath) - if err := backupRepo.CreateRecord(&record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) - return err - } - u.removeExpiredBackup(cronjob, accountMap, record) - } - return nil -} - -func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Time) error { - webs := loadWebsForJob(cronjob) - accountMap, err := loadClientMap(cronjob.BackupAccounts) - if err != nil { - return err - } - for _, web := range webs { - var record model.BackupRecord - record.From = "cronjob" - record.Type = "website" - record.CronjobID = cronjob.ID - record.Name = web.PrimaryDomain - record.DetailName = web.Alias - record.Source, record.BackupType = loadRecordPath(cronjob, accountMap) - backupDir := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("website/%s", web.PrimaryDomain)) - record.FileName = fmt.Sprintf("website_%s_%s.tar.gz", web.PrimaryDomain, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)) - if err := handleWebsiteBackup(&web, backupDir, record.FileName, cronjob.ExclusionRules, cronjob.Secret); err != nil { - return err - } - downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(backupDir, record.FileName)) - if err != nil { - return err - } - record.FileDir = path.Dir(downloadPath) - if err := backupRepo.CreateRecord(&record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) - return err - } - u.removeExpiredBackup(cronjob, accountMap, record) - } - return nil -} - -func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Time) error { - dbs := loadDbsForJob(cronjob) - accountMap, err := loadClientMap(cronjob.BackupAccounts) - if err != nil { - return err - } - for _, dbInfo := range dbs { - var record model.BackupRecord - record.From = "cronjob" - record.Type = dbInfo.DBType - record.CronjobID = cronjob.ID - record.Name = dbInfo.Database - record.DetailName = dbInfo.Name - record.Source, record.BackupType = loadRecordPath(cronjob, accountMap) - - backupDir := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("database/%s/%s/%s", dbInfo.DBType, record.Name, dbInfo.Name)) - record.FileName = fmt.Sprintf("db_%s_%s.sql.gz", dbInfo.Name, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)) - if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" { - if err := handleMysqlBackup(dbInfo.Database, dbInfo.DBType, dbInfo.Name, backupDir, record.FileName); err != nil { - return err - } - } else { - if err := handlePostgresqlBackup(dbInfo.Database, dbInfo.Name, backupDir, record.FileName); err != nil { - return err - } - } - downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(backupDir, record.FileName)) - if err != nil { - return err - } - record.FileDir = path.Dir(downloadPath) - if err := backupRepo.CreateRecord(&record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) - return err - } - u.removeExpiredBackup(cronjob, accountMap, record) - } - return nil -} - -func (u *CronjobService) handleDirectory(cronjob model.Cronjob, startTime time.Time) error { - accountMap, err := loadClientMap(cronjob.BackupAccounts) - if err != nil { - return err - } - fileName := fmt.Sprintf("directory%s_%s.tar.gz", strings.ReplaceAll(cronjob.SourceDir, "/", "_"), startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)) - backupDir := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("%s/%s", cronjob.Type, cronjob.Name)) - if err := handleTar(cronjob.SourceDir, backupDir, fileName, cronjob.ExclusionRules, cronjob.Secret); err != nil { - return err - } - var record model.BackupRecord - record.From = "cronjob" - record.Type = "directory" - record.CronjobID = cronjob.ID - record.Name = cronjob.Name - record.Source, record.BackupType = loadRecordPath(cronjob, accountMap) - downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(backupDir, fileName)) - if err != nil { - return err - } - record.FileDir = path.Dir(downloadPath) - record.FileName = fileName - if err := backupRepo.CreateRecord(&record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) - return err - } - u.removeExpiredBackup(cronjob, accountMap, record) - return nil -} - -func (u *CronjobService) handleSystemLog(cronjob model.Cronjob, startTime time.Time) error { - accountMap, err := loadClientMap(cronjob.BackupAccounts) - if err != nil { - return err - } - nameItem := startTime.Format(constant.DateTimeSlimLayout) + common.RandStrAndNum(5) - fileName := fmt.Sprintf("system_log_%s.tar.gz", nameItem) - backupDir := path.Join(global.CONF.System.TmpDir, "log", nameItem) - if err := handleBackupLogs(backupDir, fileName, cronjob.Secret); err != nil { - return err - } - var record model.BackupRecord - record.From = "cronjob" - record.Type = "log" - record.CronjobID = cronjob.ID - record.Name = cronjob.Name - record.Source, record.BackupType = loadRecordPath(cronjob, accountMap) - downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(path.Dir(backupDir), fileName)) - if err != nil { - return err - } - record.FileDir = path.Dir(downloadPath) - record.FileName = fileName - if err := backupRepo.CreateRecord(&record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) - return err - } - u.removeExpiredBackup(cronjob, accountMap, record) - return nil -} - -func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, startTime time.Time, logPath string) error { - accountMap, err := loadClientMap(cronjob.BackupAccounts) - if err != nil { - return err - } - - var record model.BackupRecord - record.From = "cronjob" - record.Type = "directory" - record.CronjobID = cronjob.ID - record.Name = cronjob.Name - record.Source, record.BackupType = loadRecordPath(cronjob, accountMap) - record.FileDir = "system_snapshot" - - req := dto.SnapshotCreate{ - From: record.BackupType, - DefaultDownload: cronjob.DefaultDownload, - } - name, err := NewISnapshotService().HandleSnapshot(true, logPath, req, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5), cronjob.Secret) - if err != nil { - return err - } - record.FileName = name + ".tar.gz" - - if err := backupRepo.CreateRecord(&record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) - return err - } - u.removeExpiredBackup(cronjob, accountMap, record) - return nil -} - -type databaseHelper struct { - DBType string - Database string - Name string -} - -func loadDbsForJob(cronjob model.Cronjob) []databaseHelper { - var dbs []databaseHelper - if cronjob.DBName == "all" { - if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" { - mysqlItems, _ := mysqlRepo.List() - for _, mysql := range mysqlItems { - dbs = append(dbs, databaseHelper{ - DBType: cronjob.DBType, - Database: mysql.MysqlName, - Name: mysql.Name, - }) - } - } else { - pgItems, _ := postgresqlRepo.List() - for _, pg := range pgItems { - dbs = append(dbs, databaseHelper{ - DBType: cronjob.DBType, - Database: pg.PostgresqlName, - Name: pg.Name, - }) - } - } - return dbs - } - itemID, _ := strconv.Atoi(cronjob.DBName) - if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" { - mysqlItem, _ := mysqlRepo.Get(commonRepo.WithByID(uint(itemID))) - dbs = append(dbs, databaseHelper{ - DBType: cronjob.DBType, - Database: mysqlItem.MysqlName, - Name: mysqlItem.Name, - }) - } else { - pgItem, _ := postgresqlRepo.Get(commonRepo.WithByID(uint(itemID))) - dbs = append(dbs, databaseHelper{ - DBType: cronjob.DBType, - Database: pgItem.PostgresqlName, - Name: pgItem.Name, - }) - } - return dbs -} - -func loadWebsForJob(cronjob model.Cronjob) []model.Website { - var weblist []model.Website - if cronjob.Website == "all" { - weblist, _ = websiteRepo.List() - return weblist - } - itemID, _ := strconv.Atoi(cronjob.Website) - webItem, _ := websiteRepo.GetFirst(commonRepo.WithByID(uint(itemID))) - if webItem.ID != 0 { - weblist = append(weblist, webItem) - } - return weblist -} - -func loadRecordPath(cronjob model.Cronjob, accountMap map[string]cronjobUploadHelper) (string, string) { - source := accountMap[fmt.Sprintf("%v", cronjob.DefaultDownload)].backType - targets := strings.Split(cronjob.BackupAccounts, ",") - var itemAccounts []string - for _, target := range targets { - if len(target) == 0 { - continue - } - if len(accountMap[target].backType) != 0 { - itemAccounts = append(itemAccounts, accountMap[target].backType) - } - } - backupType := strings.Join(itemAccounts, ",") - return source, backupType -} - -func handleBackupLogs(targetDir, fileName string, secret string) error { - websites, err := websiteRepo.List() - if err != nil { - return err - } - if len(websites) != 0 { - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return err - } - webItem := path.Join(nginxInstall.GetPath(), "www/sites") - for _, website := range websites { - dirItem := path.Join(targetDir, "website", website.Alias) - if _, err := os.Stat(dirItem); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(dirItem, os.ModePerm); err != nil { - return err - } - } - itemDir := path.Join(webItem, website.Alias, "log") - logFiles, _ := os.ReadDir(itemDir) - if len(logFiles) != 0 { - for i := 0; i < len(logFiles); i++ { - if !logFiles[i].IsDir() { - _ = common.CopyFile(path.Join(itemDir, logFiles[i].Name()), dirItem) - } - } - } - itemDir2 := path.Join(global.CONF.System.Backup, "log/website", website.Alias) - logFiles2, _ := os.ReadDir(itemDir2) - if len(logFiles2) != 0 { - for i := 0; i < len(logFiles2); i++ { - if !logFiles2[i].IsDir() { - _ = common.CopyFile(path.Join(itemDir2, logFiles2[i].Name()), dirItem) - } - } - } - } - global.LOG.Debug("backup website log successful!") - } - - systemLogDir := path.Join(global.CONF.System.BaseDir, "1panel/log") - systemDir := path.Join(targetDir, "system") - if _, err := os.Stat(systemDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(systemDir, os.ModePerm); err != nil { - return err - } - } - systemLogFiles, _ := os.ReadDir(systemLogDir) - if len(systemLogFiles) != 0 { - for i := 0; i < len(systemLogFiles); i++ { - if !systemLogFiles[i].IsDir() { - _ = common.CopyFile(path.Join(systemLogDir, systemLogFiles[i].Name()), systemDir) - } - } - } - global.LOG.Debug("backup system log successful!") - - loginLogFiles, _ := os.ReadDir("/var/log") - loginDir := path.Join(targetDir, "login") - if _, err := os.Stat(loginDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(loginDir, os.ModePerm); err != nil { - return err - } - } - if len(loginLogFiles) != 0 { - for i := 0; i < len(loginLogFiles); i++ { - if !loginLogFiles[i].IsDir() && (strings.HasPrefix(loginLogFiles[i].Name(), "secure") || strings.HasPrefix(loginLogFiles[i].Name(), "auth.log")) { - _ = common.CopyFile(path.Join("/var/log", loginLogFiles[i].Name()), loginDir) - } - } - } - global.LOG.Debug("backup ssh log successful!") - - if err := handleTar(targetDir, path.Dir(targetDir), fileName, "", secret); err != nil { - return err - } - defer func() { - _ = os.RemoveAll(targetDir) - }() - return nil -} diff --git a/backend/app/service/cronjob_helper.go b/backend/app/service/cronjob_helper.go deleted file mode 100644 index aca743370..000000000 --- a/backend/app/service/cronjob_helper.go +++ /dev/null @@ -1,393 +0,0 @@ -package service - -import ( - "context" - "fmt" - "os" - "path" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/i18n" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/app/repo" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cloud_storage" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/1Panel-dev/1Panel/backend/utils/ntp" - "github.com/pkg/errors" -) - -func (u *CronjobService) HandleJob(cronjob *model.Cronjob) { - var ( - message []byte - err error - ) - record := cronjobRepo.StartRecords(cronjob.ID, cronjob.KeepLocal, "") - go func() { - switch cronjob.Type { - case "shell": - if len(cronjob.Script) == 0 { - return - } - record.Records = u.generateLogsPath(*cronjob, record.StartTime) - _ = cronjobRepo.UpdateRecords(record.ID, map[string]interface{}{"records": record.Records}) - script := cronjob.Script - if len(cronjob.ContainerName) != 0 { - command := "sh" - if len(cronjob.Command) != 0 { - command = cronjob.Command - } - script = fmt.Sprintf("docker exec %s %s -c \"%s\"", cronjob.ContainerName, command, strings.ReplaceAll(cronjob.Script, "\"", "\\\"")) - } - err = u.handleShell(cronjob.Type, cronjob.Name, script, record.Records) - u.removeExpiredLog(*cronjob) - case "curl": - if len(cronjob.URL) == 0 { - return - } - record.Records = u.generateLogsPath(*cronjob, record.StartTime) - _ = cronjobRepo.UpdateRecords(record.ID, map[string]interface{}{"records": record.Records}) - err = u.handleShell(cronjob.Type, cronjob.Name, fmt.Sprintf("curl '%s'", cronjob.URL), record.Records) - u.removeExpiredLog(*cronjob) - case "ntp": - err = u.handleNtpSync() - u.removeExpiredLog(*cronjob) - case "cutWebsiteLog": - var messageItem []string - messageItem, record.File, err = u.handleCutWebsiteLog(cronjob, record.StartTime) - message = []byte(strings.Join(messageItem, "\n")) - case "clean": - messageItem := "" - messageItem, err = u.handleSystemClean() - message = []byte(messageItem) - u.removeExpiredLog(*cronjob) - case "website": - err = u.handleWebsite(*cronjob, record.StartTime) - case "app": - err = u.handleApp(*cronjob, record.StartTime) - case "database": - err = u.handleDatabase(*cronjob, record.StartTime) - case "directory": - if len(cronjob.SourceDir) == 0 { - return - } - err = u.handleDirectory(*cronjob, record.StartTime) - case "log": - err = u.handleSystemLog(*cronjob, record.StartTime) - case "snapshot": - record.Records = u.generateLogsPath(*cronjob, record.StartTime) - _ = cronjobRepo.UpdateRecords(record.ID, map[string]interface{}{"records": record.Records}) - err = u.handleSnapshot(*cronjob, record.StartTime, record.Records) - } - - if err != nil { - if len(message) != 0 { - record.Records, _ = mkdirAndWriteFile(cronjob, record.StartTime, message) - } - cronjobRepo.EndRecords(record, constant.StatusFailed, err.Error(), record.Records) - return - } - if len(message) != 0 { - record.Records, err = mkdirAndWriteFile(cronjob, record.StartTime, message) - if err != nil { - global.LOG.Errorf("save file %s failed, err: %v", record.Records, err) - } - } - cronjobRepo.EndRecords(record, constant.StatusSuccess, "", record.Records) - }() -} - -func (u *CronjobService) handleShell(cronType, cornName, script, logPath string) error { - handleDir := fmt.Sprintf("%s/task/%s/%s", constant.DataDir, cronType, cornName) - if _, err := os.Stat(handleDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(handleDir, os.ModePerm); err != nil { - return err - } - } - if err := cmd.ExecCronjobWithTimeOut(script, handleDir, logPath, 24*time.Hour); err != nil { - return err - } - return nil -} - -func (u *CronjobService) handleNtpSync() error { - ntpServer, err := settingRepo.Get(settingRepo.WithByKey("NtpSite")) - if err != nil { - return err - } - ntime, err := ntp.GetRemoteTime(ntpServer.Value) - if err != nil { - return err - } - if err := ntp.UpdateSystemTime(ntime.Format(constant.DateTimeLayout)); err != nil { - return err - } - return nil -} - -func handleTar(sourceDir, targetDir, name, exclusionRules string, secret string) error { - if _, err := os.Stat(targetDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(targetDir, os.ModePerm); err != nil { - return err - } - } - - excludes := strings.Split(exclusionRules, ",") - excludeRules := "" - excludes = append(excludes, "*.sock") - for _, exclude := range excludes { - if len(exclude) == 0 { - continue - } - excludeRules += " --exclude " + exclude - } - path := "" - if strings.Contains(sourceDir, "/") { - itemDir := strings.ReplaceAll(sourceDir[strings.LastIndex(sourceDir, "/"):], "/", "") - aheadDir := sourceDir[:strings.LastIndex(sourceDir, "/")] - if len(aheadDir) == 0 { - aheadDir = "/" - } - path += fmt.Sprintf("-C %s %s", aheadDir, itemDir) - } else { - path = sourceDir - } - - commands := "" - - if len(secret) != 0 { - extraCmd := "| openssl enc -aes-256-cbc -salt -k '" + secret + "' -out" - commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read -zcf %s %s %s %s", " -"+excludeRules, path, extraCmd, targetDir+"/"+name) - global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" %s ", secret), "******")) - } else { - commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read -zcf %s %s %s", targetDir+"/"+name, excludeRules, path) - global.LOG.Debug(commands) - } - stdout, err := cmd.ExecWithTimeOut(commands, 24*time.Hour) - if err != nil { - if len(stdout) != 0 { - global.LOG.Errorf("do handle tar failed, stdout: %s, err: %v", stdout, err) - return fmt.Errorf("do handle tar failed, stdout: %s, err: %v", stdout, err) - } - } - return nil -} - -func handleUnTar(sourceFile, targetDir string, secret string) error { - if _, err := os.Stat(targetDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(targetDir, os.ModePerm); err != nil { - return err - } - } - commands := "" - if len(secret) != 0 { - extraCmd := "openssl enc -d -aes-256-cbc -k '" + secret + "' -in " + sourceFile + " | " - commands = fmt.Sprintf("%s tar -zxvf - -C %s", extraCmd, targetDir+" > /dev/null 2>&1") - global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" %s ", secret), "******")) - } else { - commands = fmt.Sprintf("tar zxvfC %s %s", sourceFile, targetDir) - global.LOG.Debug(commands) - } - - stdout, err := cmd.ExecWithTimeOut(commands, 24*time.Hour) - if err != nil { - global.LOG.Errorf("do handle untar failed, stdout: %s, err: %v", stdout, err) - return errors.New(stdout) - } - return nil -} - -func (u *CronjobService) handleCutWebsiteLog(cronjob *model.Cronjob, startTime time.Time) ([]string, string, error) { - var ( - err error - filePaths []string - msgs []string - ) - websites := loadWebsForJob(*cronjob) - nginx, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return msgs, "", nil - } - baseDir := path.Join(nginx.GetPath(), "www", "sites") - fileOp := files.NewFileOp() - for _, website := range websites { - websiteLogDir := path.Join(baseDir, website.Alias, "log") - srcAccessLogPath := path.Join(websiteLogDir, "access.log") - srcErrorLogPath := path.Join(websiteLogDir, "error.log") - dstLogDir := path.Join(global.CONF.System.Backup, "log", "website", website.Alias) - if !fileOp.Stat(dstLogDir) { - _ = os.MkdirAll(dstLogDir, 0755) - } - - dstName := fmt.Sprintf("%s_log_%s.gz", website.PrimaryDomain, startTime.Format(constant.DateTimeSlimLayout)) - dstFilePath := path.Join(dstLogDir, dstName) - filePaths = append(filePaths, dstFilePath) - - if err = backupLogFile(dstFilePath, websiteLogDir, fileOp); err != nil { - websiteErr := buserr.WithNameAndErr("ErrCutWebsiteLog", website.PrimaryDomain, err) - err = websiteErr - msgs = append(msgs, websiteErr.Error()) - global.LOG.Error(websiteErr.Error()) - continue - } else { - _ = fileOp.WriteFile(srcAccessLogPath, strings.NewReader(""), 0755) - _ = fileOp.WriteFile(srcErrorLogPath, strings.NewReader(""), 0755) - } - msg := i18n.GetMsgWithMap("CutWebsiteLogSuccess", map[string]interface{}{"name": website.PrimaryDomain, "path": dstFilePath}) - global.LOG.Infof(msg) - msgs = append(msgs, msg) - } - u.removeExpiredLog(*cronjob) - return msgs, strings.Join(filePaths, ","), err -} - -func backupLogFile(dstFilePath, websiteLogDir string, fileOp files.FileOp) error { - if err := cmd.ExecCmd(fmt.Sprintf("tar -czf %s -C %s %s", dstFilePath, websiteLogDir, strings.Join([]string{"access.log", "error.log"}, " "))); err != nil { - dstDir := path.Dir(dstFilePath) - if err = fileOp.Copy(path.Join(websiteLogDir, "access.log"), dstDir); err != nil { - return err - } - if err = fileOp.Copy(path.Join(websiteLogDir, "error.log"), dstDir); err != nil { - return err - } - if err = cmd.ExecCmd(fmt.Sprintf("tar -czf %s -C %s %s", dstFilePath, dstDir, strings.Join([]string{"access.log", "error.log"}, " "))); err != nil { - return err - } - _ = fileOp.DeleteFile(path.Join(dstDir, "access.log")) - _ = fileOp.DeleteFile(path.Join(dstDir, "error.log")) - return nil - } - return nil -} - -func (u *CronjobService) handleSystemClean() (string, error) { - return NewIDeviceService().CleanForCronjob() -} - -func loadClientMap(backupAccounts string) (map[string]cronjobUploadHelper, error) { - clients := make(map[string]cronjobUploadHelper) - accounts, err := backupRepo.List() - if err != nil { - return nil, err - } - targets := strings.Split(backupAccounts, ",") - for _, target := range targets { - if len(target) == 0 { - continue - } - for _, account := range accounts { - if target == account.Type { - client, err := NewIBackupService().NewClient(&account) - if err != nil { - return nil, err - } - pathItem := account.BackupPath - if account.BackupPath != "/" { - pathItem = strings.TrimPrefix(account.BackupPath, "/") - } - clients[target] = cronjobUploadHelper{ - client: client, - backupPath: pathItem, - backType: account.Type, - } - } - } - } - return clients, nil -} - -type cronjobUploadHelper struct { - backupPath string - backType string - client cloud_storage.CloudStorageClient -} - -func (u *CronjobService) uploadCronjobBackFile(cronjob model.Cronjob, accountMap map[string]cronjobUploadHelper, file string) (string, error) { - defer func() { - _ = os.Remove(file) - }() - accounts := strings.Split(cronjob.BackupAccounts, ",") - cloudSrc := strings.TrimPrefix(file, global.CONF.System.TmpDir+"/") - for _, account := range accounts { - if len(account) != 0 { - global.LOG.Debugf("start upload file to %s, dir: %s", account, path.Join(accountMap[account].backupPath, cloudSrc)) - if _, err := accountMap[account].client.Upload(file, path.Join(accountMap[account].backupPath, cloudSrc)); err != nil { - return "", err - } - global.LOG.Debugf("upload successful!") - } - } - return cloudSrc, nil -} - -func (u *CronjobService) removeExpiredBackup(cronjob model.Cronjob, accountMap map[string]cronjobUploadHelper, record model.BackupRecord) { - global.LOG.Infof("start to handle remove expired, retain copies: %d", cronjob.RetainCopies) - var opts []repo.DBOption - opts = append(opts, commonRepo.WithByFrom("cronjob")) - opts = append(opts, backupRepo.WithByCronID(cronjob.ID)) - opts = append(opts, commonRepo.WithOrderBy("created_at desc")) - if record.ID != 0 { - opts = append(opts, backupRepo.WithByType(record.Type)) - opts = append(opts, commonRepo.WithByName(record.Name)) - opts = append(opts, backupRepo.WithByDetailName(record.DetailName)) - } - records, _ := backupRepo.ListRecord(opts...) - if len(records) <= int(cronjob.RetainCopies) { - return - } - for i := int(cronjob.RetainCopies); i < len(records); i++ { - accounts := strings.Split(cronjob.BackupAccounts, ",") - if cronjob.Type == "snapshot" { - for _, account := range accounts { - if len(account) != 0 { - _, _ = accountMap[account].client.Delete(path.Join(accountMap[account].backupPath, "system_snapshot", records[i].FileName)) - } - } - _ = snapshotRepo.Delete(commonRepo.WithByName(strings.TrimSuffix(records[i].FileName, ".tar.gz"))) - } else { - for _, account := range accounts { - if len(account) != 0 { - _, _ = accountMap[account].client.Delete(path.Join(accountMap[account].backupPath, records[i].FileDir, records[i].FileName)) - } - } - } - _ = backupRepo.DeleteRecord(context.Background(), commonRepo.WithByID(records[i].ID)) - } -} - -func (u *CronjobService) removeExpiredLog(cronjob model.Cronjob) { - global.LOG.Infof("start to handle remove expired, retain copies: %d", cronjob.RetainCopies) - records, _ := cronjobRepo.ListRecord(cronjobRepo.WithByJobID(int(cronjob.ID)), commonRepo.WithOrderBy("created_at desc")) - if len(records) <= int(cronjob.RetainCopies) { - return - } - for i := int(cronjob.RetainCopies); i < len(records); i++ { - if len(records[i].File) != 0 { - files := strings.Split(records[i].File, ",") - for _, file := range files { - _ = os.Remove(file) - } - } - _ = cronjobRepo.DeleteRecord(commonRepo.WithByID(uint(records[i].ID))) - _ = os.Remove(records[i].Records) - } -} - -func (u *CronjobService) generateLogsPath(cronjob model.Cronjob, startTime time.Time) string { - dir := fmt.Sprintf("%s/task/%s/%s", constant.DataDir, cronjob.Type, cronjob.Name) - if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { - _ = os.MkdirAll(dir, os.ModePerm) - } - - path := fmt.Sprintf("%s/%s.log", dir, startTime.Format(constant.DateTimeSlimLayout)) - return path -} - -func hasBackup(cronjobType string) bool { - return cronjobType == "app" || cronjobType == "database" || cronjobType == "website" || cronjobType == "directory" || cronjobType == "snapshot" || cronjobType == "log" -} diff --git a/backend/app/service/dashboard.go b/backend/app/service/dashboard.go deleted file mode 100644 index 0ac4af844..000000000 --- a/backend/app/service/dashboard.go +++ /dev/null @@ -1,325 +0,0 @@ -package service - -import ( - "encoding/json" - "fmt" - "sort" - "strings" - "sync" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/copier" - "github.com/1Panel-dev/1Panel/backend/utils/xpack" - "github.com/shirou/gopsutil/v3/cpu" - "github.com/shirou/gopsutil/v3/disk" - "github.com/shirou/gopsutil/v3/host" - "github.com/shirou/gopsutil/v3/load" - "github.com/shirou/gopsutil/v3/mem" - "github.com/shirou/gopsutil/v3/net" -) - -type DashboardService struct{} - -type IDashboardService interface { - LoadOsInfo() (*dto.OsInfo, error) - LoadBaseInfo(ioOption string, netOption string) (*dto.DashboardBase, error) - LoadCurrentInfo(ioOption string, netOption string) *dto.DashboardCurrent - - Restart(operation string) error -} - -func NewIDashboardService() IDashboardService { - return &DashboardService{} -} - -func (u *DashboardService) Restart(operation string) error { - if operation != "1panel" && operation != "system" { - return fmt.Errorf("handle restart operation %s failed, err: nonsupport such operation", operation) - } - itemCmd := fmt.Sprintf("%s 1pctl restart", cmd.SudoHandleCmd()) - if operation == "system" { - itemCmd = fmt.Sprintf("%s reboot", cmd.SudoHandleCmd()) - } - go func() { - stdout, err := cmd.Exec(itemCmd) - if err != nil { - global.LOG.Errorf("handle %s failed, err: %v", itemCmd, stdout) - } - }() - return nil -} - -func (u *DashboardService) LoadOsInfo() (*dto.OsInfo, error) { - var baseInfo dto.OsInfo - hostInfo, err := host.Info() - if err != nil { - return nil, err - } - baseInfo.OS = hostInfo.OS - baseInfo.Platform = hostInfo.Platform - baseInfo.PlatformFamily = hostInfo.PlatformFamily - baseInfo.KernelArch = hostInfo.KernelArch - baseInfo.KernelVersion = hostInfo.KernelVersion - - diskInfo, err := disk.Usage(global.CONF.System.BaseDir) - if err == nil { - baseInfo.DiskSize = int64(diskInfo.Free) - } - - if baseInfo.KernelArch == "armv7l" { - baseInfo.KernelArch = "armv7" - } - if baseInfo.KernelArch == "x86_64" { - baseInfo.KernelArch = "amd64" - } - return &baseInfo, nil -} - -func (u *DashboardService) LoadBaseInfo(ioOption string, netOption string) (*dto.DashboardBase, error) { - var baseInfo dto.DashboardBase - hostInfo, err := host.Info() - if err != nil { - return nil, err - } - baseInfo.Hostname = hostInfo.Hostname - baseInfo.OS = hostInfo.OS - baseInfo.Platform = hostInfo.Platform - baseInfo.PlatformFamily = hostInfo.PlatformFamily - baseInfo.PlatformVersion = hostInfo.PlatformVersion - baseInfo.KernelArch = hostInfo.KernelArch - baseInfo.KernelVersion = hostInfo.KernelVersion - ss, _ := json.Marshal(hostInfo) - baseInfo.VirtualizationSystem = string(ss) - - appInstall, err := appInstallRepo.ListBy() - if err != nil { - return nil, err - } - baseInfo.AppInstalledNumber = len(appInstall) - postgresqlDbs, err := postgresqlRepo.List() - if err != nil { - return nil, err - } - mysqlDbs, err := mysqlRepo.List() - if err != nil { - return nil, err - } - baseInfo.DatabaseNumber = len(mysqlDbs) + len(postgresqlDbs) - website, err := websiteRepo.GetBy() - if err != nil { - return nil, err - } - baseInfo.WebsiteNumber = len(website) - cronjobs, err := cronjobRepo.List() - if err != nil { - return nil, err - } - baseInfo.CronjobNumber = len(cronjobs) - - cpuInfo, err := cpu.Info() - if err == nil { - baseInfo.CPUModelName = cpuInfo[0].ModelName - } - - baseInfo.CPUCores, _ = cpu.Counts(false) - baseInfo.CPULogicalCores, _ = cpu.Counts(true) - - baseInfo.CurrentInfo = *u.LoadCurrentInfo(ioOption, netOption) - return &baseInfo, nil -} - -func (u *DashboardService) LoadCurrentInfo(ioOption string, netOption string) *dto.DashboardCurrent { - var currentInfo dto.DashboardCurrent - hostInfo, _ := host.Info() - currentInfo.Uptime = hostInfo.Uptime - currentInfo.TimeSinceUptime = time.Now().Add(-time.Duration(hostInfo.Uptime) * time.Second).Format(constant.DateTimeLayout) - currentInfo.Procs = hostInfo.Procs - - currentInfo.CPUTotal, _ = cpu.Counts(true) - totalPercent, _ := cpu.Percent(0, false) - if len(totalPercent) == 1 { - currentInfo.CPUUsedPercent = totalPercent[0] - currentInfo.CPUUsed = currentInfo.CPUUsedPercent * 0.01 * float64(currentInfo.CPUTotal) - } - currentInfo.CPUPercent, _ = cpu.Percent(0, true) - - loadInfo, _ := load.Avg() - currentInfo.Load1 = loadInfo.Load1 - currentInfo.Load5 = loadInfo.Load5 - currentInfo.Load15 = loadInfo.Load15 - currentInfo.LoadUsagePercent = loadInfo.Load1 / (float64(currentInfo.CPUTotal*2) * 0.75) * 100 - - memoryInfo, _ := mem.VirtualMemory() - currentInfo.MemoryTotal = memoryInfo.Total - currentInfo.MemoryAvailable = memoryInfo.Available - currentInfo.MemoryUsed = memoryInfo.Used - currentInfo.MemoryUsedPercent = memoryInfo.UsedPercent - - swapInfo, _ := mem.SwapMemory() - currentInfo.SwapMemoryTotal = swapInfo.Total - currentInfo.SwapMemoryAvailable = swapInfo.Free - currentInfo.SwapMemoryUsed = swapInfo.Used - currentInfo.SwapMemoryUsedPercent = swapInfo.UsedPercent - - currentInfo.DiskData = loadDiskInfo() - currentInfo.GPUData = loadGPUInfo() - - if ioOption == "all" { - diskInfo, _ := disk.IOCounters() - for _, state := range diskInfo { - currentInfo.IOReadBytes += state.ReadBytes - currentInfo.IOWriteBytes += state.WriteBytes - currentInfo.IOCount += (state.ReadCount + state.WriteCount) - currentInfo.IOReadTime += state.ReadTime - currentInfo.IOWriteTime += state.WriteTime - } - } else { - diskInfo, _ := disk.IOCounters(ioOption) - for _, state := range diskInfo { - currentInfo.IOReadBytes += state.ReadBytes - currentInfo.IOWriteBytes += state.WriteBytes - currentInfo.IOCount += (state.ReadCount + state.WriteCount) - currentInfo.IOReadTime += state.ReadTime - currentInfo.IOWriteTime += state.WriteTime - } - } - - if netOption == "all" { - netInfo, _ := net.IOCounters(false) - if len(netInfo) != 0 { - currentInfo.NetBytesSent = netInfo[0].BytesSent - currentInfo.NetBytesRecv = netInfo[0].BytesRecv - } - } else { - netInfo, _ := net.IOCounters(true) - for _, state := range netInfo { - if state.Name == netOption { - currentInfo.NetBytesSent = state.BytesSent - currentInfo.NetBytesRecv = state.BytesRecv - } - } - } - - currentInfo.ShotTime = time.Now() - return ¤tInfo -} - -type diskInfo struct { - Type string - Mount string - Device string -} - -func loadDiskInfo() []dto.DiskInfo { - var datas []dto.DiskInfo - stdout, err := cmd.ExecWithTimeOut("df -hT -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev", 2*time.Second) - if err != nil { - stdout, err = cmd.ExecWithTimeOut("df -lhT -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev", 1*time.Second) - if err != nil { - return datas - } - } - lines := strings.Split(stdout, "\n") - - var mounts []diskInfo - var excludes = []string{"/mnt/cdrom", "/boot", "/boot/efi", "/dev", "/dev/shm", "/run/lock", "/run", "/run/shm", "/run/user"} - for _, line := range lines { - fields := strings.Fields(line) - if len(fields) < 7 { - continue - } - if strings.HasPrefix(fields[6], "/snap") || len(strings.Split(fields[6], "/")) > 10 { - continue - } - if strings.TrimSpace(fields[1]) == "tmpfs" { - continue - } - if strings.Contains(fields[2], "K") { - continue - } - if strings.Contains(fields[6], "docker") { - continue - } - isExclude := false - for _, exclude := range excludes { - if exclude == fields[6] { - isExclude = true - } - } - if isExclude { - continue - } - mounts = append(mounts, diskInfo{Type: fields[1], Device: fields[0], Mount: strings.Join(fields[6:], " ")}) - } - - var ( - wg sync.WaitGroup - mu sync.Mutex - ) - wg.Add(len(mounts)) - for i := 0; i < len(mounts); i++ { - go func(timeoutCh <-chan time.Time, mount diskInfo) { - defer wg.Done() - - var itemData dto.DiskInfo - itemData.Path = mount.Mount - itemData.Type = mount.Type - itemData.Device = mount.Device - select { - case <-timeoutCh: - mu.Lock() - datas = append(datas, itemData) - mu.Unlock() - global.LOG.Errorf("load disk info from %s failed, err: timeout", mount.Mount) - default: - state, err := disk.Usage(mount.Mount) - if err != nil { - mu.Lock() - datas = append(datas, itemData) - mu.Unlock() - global.LOG.Errorf("load disk info from %s failed, err: %v", mount.Mount, err) - return - } - itemData.Total = state.Total - itemData.Free = state.Free - itemData.Used = state.Used - itemData.UsedPercent = state.UsedPercent - itemData.InodesTotal = state.InodesTotal - itemData.InodesUsed = state.InodesUsed - itemData.InodesFree = state.InodesFree - itemData.InodesUsedPercent = state.InodesUsedPercent - mu.Lock() - datas = append(datas, itemData) - mu.Unlock() - } - }(time.After(5*time.Second), mounts[i]) - } - wg.Wait() - - sort.Slice(datas, func(i, j int) bool { - return datas[i].Path < datas[j].Path - }) - return datas -} - -func loadGPUInfo() []dto.GPUInfo { - list := xpack.LoadGpuInfo() - if len(list) == 0 { - return nil - } - var data []dto.GPUInfo - for _, gpu := range list { - var dataItem dto.GPUInfo - if err := copier.Copy(&dataItem, &gpu); err != nil { - continue - } - dataItem.PowerUsage = dataItem.PowerDraw + " / " + dataItem.MaxPowerLimit - dataItem.MemoryUsage = dataItem.MemUsed + " / " + dataItem.MemTotal - data = append(data, dataItem) - } - return data -} diff --git a/backend/app/service/database.go b/backend/app/service/database.go deleted file mode 100644 index 6804d4c71..000000000 --- a/backend/app/service/database.go +++ /dev/null @@ -1,330 +0,0 @@ -package service - -import ( - "context" - "fmt" - "os" - "path" - - "github.com/1Panel-dev/1Panel/backend/utils/postgresql" - pgclient "github.com/1Panel-dev/1Panel/backend/utils/postgresql/client" - redisclient "github.com/1Panel-dev/1Panel/backend/utils/redis" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/encrypt" - "github.com/1Panel-dev/1Panel/backend/utils/mysql" - "github.com/1Panel-dev/1Panel/backend/utils/mysql/client" - "github.com/jinzhu/copier" - "github.com/pkg/errors" -) - -type DatabaseService struct{} - -type IDatabaseService interface { - Get(name string) (dto.DatabaseInfo, error) - SearchWithPage(search dto.DatabaseSearch) (int64, interface{}, error) - CheckDatabase(req dto.DatabaseCreate) bool - Create(req dto.DatabaseCreate) error - Update(req dto.DatabaseUpdate) error - DeleteCheck(id uint) ([]string, error) - Delete(req dto.DatabaseDelete) error - List(dbType string) ([]dto.DatabaseOption, error) - LoadItems(dbType string) ([]dto.DatabaseItem, error) -} - -func NewIDatabaseService() IDatabaseService { - return &DatabaseService{} -} - -func (u *DatabaseService) SearchWithPage(search dto.DatabaseSearch) (int64, interface{}, error) { - total, dbs, err := databaseRepo.Page(search.Page, search.PageSize, - databaseRepo.WithTypeList(search.Type), - commonRepo.WithLikeName(search.Info), - commonRepo.WithOrderRuleBy(search.OrderBy, search.Order), - databaseRepo.WithoutByFrom("local"), - ) - var datas []dto.DatabaseInfo - for _, db := range dbs { - var item dto.DatabaseInfo - if err := copier.Copy(&item, &db); err != nil { - return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - datas = append(datas, item) - } - return total, datas, err -} - -func (u *DatabaseService) Get(name string) (dto.DatabaseInfo, error) { - var data dto.DatabaseInfo - remote, err := databaseRepo.Get(commonRepo.WithByName(name)) - if err != nil { - return data, err - } - if err := copier.Copy(&data, &remote); err != nil { - return data, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - return data, nil -} - -func (u *DatabaseService) List(dbType string) ([]dto.DatabaseOption, error) { - dbs, err := databaseRepo.GetList(databaseRepo.WithTypeList(dbType)) - if err != nil { - return nil, err - } - var datas []dto.DatabaseOption - for _, db := range dbs { - var item dto.DatabaseOption - if err := copier.Copy(&item, &db); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - item.Database = db.Name - datas = append(datas, item) - } - return datas, err -} - -func (u *DatabaseService) LoadItems(dbType string) ([]dto.DatabaseItem, error) { - dbs, err := databaseRepo.GetList(databaseRepo.WithTypeList(dbType)) - var datas []dto.DatabaseItem - for _, db := range dbs { - if dbType == "postgresql" { - items, _ := postgresqlRepo.List(postgresqlRepo.WithByPostgresqlName(db.Name)) - for _, item := range items { - var dItem dto.DatabaseItem - if err := copier.Copy(&dItem, &item); err != nil { - continue - } - dItem.Database = db.Name - datas = append(datas, dItem) - } - } else { - items, _ := mysqlRepo.List(mysqlRepo.WithByMysqlName(db.Name)) - for _, item := range items { - var dItem dto.DatabaseItem - if err := copier.Copy(&dItem, &item); err != nil { - continue - } - dItem.Database = db.Name - datas = append(datas, dItem) - } - } - } - return datas, err -} - -func (u *DatabaseService) CheckDatabase(req dto.DatabaseCreate) bool { - switch req.Type { - case constant.AppPostgresql: - _, err := postgresql.NewPostgresqlClient(pgclient.DBInfo{ - From: "remote", - Address: req.Address, - Port: req.Port, - Username: req.Username, - Password: req.Password, - Timeout: 6, - }) - return err == nil - case constant.AppRedis: - _, err := redisclient.NewRedisClient(redisclient.DBInfo{ - Address: req.Address, - Port: req.Port, - Password: req.Password, - }) - return err == nil - case "mysql", "mariadb": - _, err := mysql.NewMysqlClient(client.DBInfo{ - From: "remote", - Address: req.Address, - Port: req.Port, - Username: req.Username, - Password: req.Password, - - SSL: req.SSL, - RootCert: req.RootCert, - ClientKey: req.ClientKey, - ClientCert: req.ClientCert, - SkipVerify: req.SkipVerify, - Timeout: 6, - }) - return err == nil - } - - return false -} - -func (u *DatabaseService) Create(req dto.DatabaseCreate) error { - db, _ := databaseRepo.Get(commonRepo.WithByName(req.Name)) - if db.ID != 0 { - if db.From == "local" { - return buserr.New(constant.ErrLocalExist) - } - return constant.ErrRecordExist - } - switch req.Type { - case constant.AppPostgresql: - if _, err := postgresql.NewPostgresqlClient(pgclient.DBInfo{ - From: "remote", - Address: req.Address, - Port: req.Port, - Username: req.Username, - Password: req.Password, - Timeout: 6, - }); err != nil { - return err - } - case constant.AppRedis: - if _, err := redisclient.NewRedisClient(redisclient.DBInfo{ - Address: req.Address, - Port: req.Port, - Password: req.Password, - }); err != nil { - return err - } - case "mysql", "mariadb": - if _, err := mysql.NewMysqlClient(client.DBInfo{ - From: "remote", - Address: req.Address, - Port: req.Port, - Username: req.Username, - Password: req.Password, - - SSL: req.SSL, - RootCert: req.RootCert, - ClientKey: req.ClientKey, - ClientCert: req.ClientCert, - SkipVerify: req.SkipVerify, - Timeout: 6, - }); err != nil { - return err - } - default: - return errors.New("database type not supported") - } - - if err := copier.Copy(&db, &req); err != nil { - return errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - if err := databaseRepo.Create(context.Background(), &db); err != nil { - return err - } - return nil -} - -func (u *DatabaseService) DeleteCheck(id uint) ([]string, error) { - var appInUsed []string - apps, _ := appInstallResourceRepo.GetBy(databaseRepo.WithByFrom("remote"), appInstallResourceRepo.WithLinkId(id)) - for _, app := range apps { - appInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(app.AppInstallId)) - if appInstall.ID != 0 { - appInUsed = append(appInUsed, appInstall.Name) - } - } - - return appInUsed, nil -} - -func (u *DatabaseService) Delete(req dto.DatabaseDelete) error { - db, _ := databaseRepo.Get(commonRepo.WithByID(req.ID)) - if db.ID == 0 { - return constant.ErrRecordNotFound - } - - if req.DeleteBackup { - uploadDir := path.Join(global.CONF.System.BaseDir, fmt.Sprintf("1panel/uploads/database/%s/%s", db.Type, db.Name)) - if _, err := os.Stat(uploadDir); err == nil { - _ = os.RemoveAll(uploadDir) - } - localDir, err := loadLocalDir() - if err != nil && !req.ForceDelete { - return err - } - backupDir := path.Join(localDir, fmt.Sprintf("database/%s/%s", db.Type, db.Name)) - if _, err := os.Stat(backupDir); err == nil { - _ = os.RemoveAll(backupDir) - } - _ = backupRepo.DeleteRecord(context.Background(), commonRepo.WithByType(db.Type), commonRepo.WithByName(db.Name)) - global.LOG.Infof("delete database %s-%s backups successful", db.Type, db.Name) - } - - if err := databaseRepo.Delete(context.Background(), commonRepo.WithByID(req.ID)); err != nil && !req.ForceDelete { - return err - } - if db.From != "local" { - if db.Type == "mysql" || db.Type == "mariadb" { - if err := mysqlRepo.Delete(context.Background(), mysqlRepo.WithByMysqlName(db.Name)); err != nil && !req.ForceDelete { - return err - } - } else { - if err := postgresqlRepo.Delete(context.Background(), postgresqlRepo.WithByPostgresqlName(db.Name)); err != nil && !req.ForceDelete { - return err - } - } - } - return nil -} - -func (u *DatabaseService) Update(req dto.DatabaseUpdate) error { - switch req.Type { - case constant.AppPostgresql: - if _, err := postgresql.NewPostgresqlClient(pgclient.DBInfo{ - From: "remote", - Address: req.Address, - Port: req.Port, - Username: req.Username, - Password: req.Password, - Timeout: 300, - }); err != nil { - return err - } - case constant.AppRedis: - if _, err := redisclient.NewRedisClient(redisclient.DBInfo{ - Address: req.Address, - Port: req.Port, - Password: req.Password, - }); err != nil { - return err - } - case "mysql", "mariadb": - if _, err := mysql.NewMysqlClient(client.DBInfo{ - From: "remote", - Address: req.Address, - Port: req.Port, - Username: req.Username, - Password: req.Password, - - SSL: req.SSL, - RootCert: req.RootCert, - ClientKey: req.ClientKey, - ClientCert: req.ClientCert, - SkipVerify: req.SkipVerify, - Timeout: 300, - }); err != nil { - return err - } - default: - return errors.New("database type not supported") - } - - pass, err := encrypt.StringEncrypt(req.Password) - if err != nil { - return fmt.Errorf("decrypt database password failed, err: %v", err) - } - - upMap := make(map[string]interface{}) - upMap["type"] = req.Type - upMap["version"] = req.Version - upMap["address"] = req.Address - upMap["port"] = req.Port - upMap["username"] = req.Username - upMap["password"] = pass - upMap["description"] = req.Description - upMap["ssl"] = req.SSL - upMap["client_key"] = req.ClientKey - upMap["client_cert"] = req.ClientCert - upMap["root_cert"] = req.RootCert - upMap["skip_verify"] = req.SkipVerify - return databaseRepo.Update(req.ID, upMap) -} diff --git a/backend/app/service/database_common.go b/backend/app/service/database_common.go deleted file mode 100644 index 75d6973e6..000000000 --- a/backend/app/service/database_common.go +++ /dev/null @@ -1,94 +0,0 @@ -package service - -import ( - "bufio" - "fmt" - "os" - "path" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/compose" -) - -type DBCommonService struct{} - -type IDBCommonService interface { - LoadBaseInfo(req dto.OperationWithNameAndType) (*dto.DBBaseInfo, error) - LoadDatabaseFile(req dto.OperationWithNameAndType) (string, error) - - UpdateConfByFile(req dto.DBConfUpdateByFile) error -} - -func NewIDBCommonService() IDBCommonService { - return &DBCommonService{} -} - -func (u *DBCommonService) LoadBaseInfo(req dto.OperationWithNameAndType) (*dto.DBBaseInfo, error) { - var data dto.DBBaseInfo - app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name) - if err != nil { - return nil, err - } - data.ContainerName = app.ContainerName - data.Name = app.Name - data.Port = int64(app.Port) - - return &data, nil -} - -func (u *DBCommonService) LoadDatabaseFile(req dto.OperationWithNameAndType) (string, error) { - filePath := "" - switch req.Type { - case "mysql-conf": - filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mysql/%s/conf/my.cnf", req.Name)) - case "mariadb-conf": - filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mariadb/%s/conf/my.cnf", req.Name)) - case "postgresql-conf": - filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/postgresql/%s/data/postgresql.conf", req.Name)) - case "redis-conf": - filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/redis/%s/conf/redis.conf", req.Name)) - case "mysql-slow-logs": - filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mysql/%s/data/1Panel-slow.log", req.Name)) - case "mariadb-slow-logs": - filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mariadb/%s/db/data/1Panel-slow.log", req.Name)) - } - if _, err := os.Stat(filePath); err != nil { - return "", buserr.New("ErrHttpReqNotFound") - } - content, err := os.ReadFile(filePath) - if err != nil { - return "", err - } - return string(content), nil -} - -func (u *DBCommonService) UpdateConfByFile(req dto.DBConfUpdateByFile) error { - app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database) - if err != nil { - return err - } - path := "" - switch req.Type { - case constant.AppMariaDB, constant.AppMysql: - path = fmt.Sprintf("%s/%s/%s/conf/my.cnf", constant.AppInstallDir, req.Type, app.Name) - case constant.AppPostgresql: - path = fmt.Sprintf("%s/%s/%s/data/postgresql.conf", constant.AppInstallDir, req.Type, app.Name) - case constant.AppRedis: - path = fmt.Sprintf("%s/%s/%s/conf/redis.conf", constant.AppInstallDir, req.Type, app.Name) - } - file, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0640) - if err != nil { - return err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(req.File) - write.Flush() - if _, err := compose.Restart(fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, req.Type, app.Name)); err != nil { - return err - } - return nil -} diff --git a/backend/app/service/database_mysql.go b/backend/app/service/database_mysql.go deleted file mode 100644 index 07b39b50e..000000000 --- a/backend/app/service/database_mysql.go +++ /dev/null @@ -1,662 +0,0 @@ -package service - -import ( - "context" - "encoding/json" - "fmt" - "os" - "os/exec" - "path" - "regexp" - "strconv" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/compose" - "github.com/1Panel-dev/1Panel/backend/utils/encrypt" - "github.com/1Panel-dev/1Panel/backend/utils/mysql" - "github.com/1Panel-dev/1Panel/backend/utils/mysql/client" - _ "github.com/go-sql-driver/mysql" - "github.com/jinzhu/copier" - "github.com/pkg/errors" -) - -type MysqlService struct{} - -type IMysqlService interface { - SearchWithPage(search dto.MysqlDBSearch) (int64, interface{}, error) - ListDBOption() ([]dto.MysqlOption, error) - Create(ctx context.Context, req dto.MysqlDBCreate) (*model.DatabaseMysql, error) - BindUser(req dto.BindUser) error - LoadFromRemote(req dto.MysqlLoadDB) error - ChangeAccess(info dto.ChangeDBInfo) error - ChangePassword(info dto.ChangeDBInfo) error - UpdateVariables(req dto.MysqlVariablesUpdate) error - UpdateDescription(req dto.UpdateDescription) error - DeleteCheck(req dto.MysqlDBDeleteCheck) ([]string, error) - Delete(ctx context.Context, req dto.MysqlDBDelete) error - - LoadStatus(req dto.OperationWithNameAndType) (*dto.MysqlStatus, error) - LoadVariables(req dto.OperationWithNameAndType) (*dto.MysqlVariables, error) - LoadRemoteAccess(req dto.OperationWithNameAndType) (bool, error) -} - -func NewIMysqlService() IMysqlService { - return &MysqlService{} -} - -func (u *MysqlService) SearchWithPage(search dto.MysqlDBSearch) (int64, interface{}, error) { - total, mysqls, err := mysqlRepo.Page(search.Page, search.PageSize, - mysqlRepo.WithByMysqlName(search.Database), - commonRepo.WithLikeName(search.Info), - commonRepo.WithOrderRuleBy(search.OrderBy, search.Order), - ) - var dtoMysqls []dto.MysqlDBInfo - for _, mysql := range mysqls { - var item dto.MysqlDBInfo - if err := copier.Copy(&item, &mysql); err != nil { - return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - dtoMysqls = append(dtoMysqls, item) - } - return total, dtoMysqls, err -} - -func (u *MysqlService) ListDBOption() ([]dto.MysqlOption, error) { - mysqls, err := mysqlRepo.List() - if err != nil { - return nil, err - } - - databases, err := databaseRepo.GetList(databaseRepo.WithTypeList("mysql,mariadb")) - if err != nil { - return nil, err - } - var dbs []dto.MysqlOption - for _, mysql := range mysqls { - var item dto.MysqlOption - if err := copier.Copy(&item, &mysql); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - item.Database = mysql.MysqlName - for _, database := range databases { - if database.Name == item.Database { - item.Type = database.Type - } - } - dbs = append(dbs, item) - } - return dbs, err -} - -func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*model.DatabaseMysql, error) { - if cmd.CheckIllegal(req.Name, req.Username, req.Password, req.Format, req.Permission) { - return nil, buserr.New(constant.ErrCmdIllegal) - } - - mysql, _ := mysqlRepo.Get(commonRepo.WithByName(req.Name), mysqlRepo.WithByMysqlName(req.Database), databaseRepo.WithByFrom(req.From)) - if mysql.ID != 0 { - return nil, constant.ErrRecordExist - } - - var createItem model.DatabaseMysql - if err := copier.Copy(&createItem, &req); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - - if req.From == "local" && req.Username == "root" { - return nil, errors.New("Cannot set root as user name") - } - - cli, version, err := LoadMysqlClientByFrom(req.Database) - if err != nil { - return nil, err - } - createItem.MysqlName = req.Database - defer cli.Close() - if err := cli.Create(client.CreateInfo{ - Name: req.Name, - Format: req.Format, - Username: req.Username, - Password: req.Password, - Permission: req.Permission, - Version: version, - Timeout: 300, - }); err != nil { - return nil, err - } - - global.LOG.Infof("create database %s successful!", req.Name) - if err := mysqlRepo.Create(ctx, &createItem); err != nil { - return nil, err - } - return &createItem, nil -} - -func (u *MysqlService) BindUser(req dto.BindUser) error { - dbItem, err := mysqlRepo.Get(mysqlRepo.WithByMysqlName(req.Database), commonRepo.WithByName(req.DB)) - if err != nil { - return err - } - cli, version, err := LoadMysqlClientByFrom(req.Database) - if err != nil { - return err - } - defer cli.Close() - - if err := cli.CreateUser(client.CreateInfo{ - Name: dbItem.Name, - Format: dbItem.Format, - Username: req.Username, - Password: req.Password, - Permission: req.Permission, - Version: version, - Timeout: 300, - }, false); err != nil { - return err - } - pass, err := encrypt.StringEncrypt(req.Password) - if err != nil { - return fmt.Errorf("decrypt database db password failed, err: %v", err) - } - if err := mysqlRepo.Update(dbItem.ID, map[string]interface{}{ - "username": req.Username, - "password": pass, - "permission": req.Permission, - }); err != nil { - return err - } - return nil -} - -func (u *MysqlService) LoadFromRemote(req dto.MysqlLoadDB) error { - client, version, err := LoadMysqlClientByFrom(req.Database) - if err != nil { - return err - } - - databases, err := mysqlRepo.List(mysqlRepo.WithByMysqlName(req.Database)) - if err != nil { - return err - } - datas, err := client.SyncDB(version) - if err != nil { - return err - } - deleteList := databases - for _, data := range datas { - hasOld := false - for i := 0; i < len(databases); i++ { - if strings.EqualFold(databases[i].Name, data.Name) && strings.EqualFold(databases[i].MysqlName, data.MysqlName) { - hasOld = true - if databases[i].IsDelete { - _ = mysqlRepo.Update(databases[i].ID, map[string]interface{}{"is_delete": false}) - } - deleteList = append(deleteList[:i], deleteList[i+1:]...) - break - } - } - if !hasOld { - var createItem model.DatabaseMysql - if err := copier.Copy(&createItem, &data); err != nil { - return errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - if err := mysqlRepo.Create(context.Background(), &createItem); err != nil { - return err - } - } - } - for _, delItem := range deleteList { - _ = mysqlRepo.Update(delItem.ID, map[string]interface{}{"is_delete": true}) - } - return nil -} - -func (u *MysqlService) UpdateDescription(req dto.UpdateDescription) error { - return mysqlRepo.Update(req.ID, map[string]interface{}{"description": req.Description}) -} - -func (u *MysqlService) DeleteCheck(req dto.MysqlDBDeleteCheck) ([]string, error) { - var appInUsed []string - db, err := mysqlRepo.Get(commonRepo.WithByID(req.ID)) - if err != nil { - return appInUsed, err - } - - if db.From == "local" { - app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database) - if err != nil { - return appInUsed, err - } - apps, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithLinkId(app.ID), appInstallResourceRepo.WithResourceId(db.ID)) - for _, app := range apps { - appInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(app.AppInstallId)) - if appInstall.ID != 0 { - appInUsed = append(appInUsed, appInstall.Name) - } - } - } else { - apps, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithResourceId(db.ID), appRepo.WithKey(req.Type)) - for _, app := range apps { - appInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(app.AppInstallId)) - if appInstall.ID != 0 { - appInUsed = append(appInUsed, appInstall.Name) - } - } - } - - return appInUsed, nil -} - -func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error { - db, err := mysqlRepo.Get(commonRepo.WithByID(req.ID)) - if err != nil && !req.ForceDelete { - return err - } - cli, version, err := LoadMysqlClientByFrom(req.Database) - if err != nil { - return err - } - defer cli.Close() - if err := cli.Delete(client.DeleteInfo{ - Name: db.Name, - Version: version, - Username: db.Username, - Permission: db.Permission, - Timeout: 300, - }); err != nil && !req.ForceDelete { - return err - } - - if req.DeleteBackup { - uploadDir := path.Join(global.CONF.System.BaseDir, fmt.Sprintf("1panel/uploads/database/%s/%s/%s", req.Type, req.Database, db.Name)) - if _, err := os.Stat(uploadDir); err == nil { - _ = os.RemoveAll(uploadDir) - } - localDir, err := loadLocalDir() - if err != nil && !req.ForceDelete { - return err - } - backupDir := path.Join(localDir, fmt.Sprintf("database/%s/%s/%s", req.Type, db.MysqlName, db.Name)) - if _, err := os.Stat(backupDir); err == nil { - _ = os.RemoveAll(backupDir) - } - _ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType(req.Type), commonRepo.WithByName(req.Database), backupRepo.WithByDetailName(db.Name)) - global.LOG.Infof("delete database %s-%s backups successful", req.Database, db.Name) - } - - _ = mysqlRepo.Delete(ctx, commonRepo.WithByID(db.ID)) - return nil -} - -func (u *MysqlService) ChangePassword(req dto.ChangeDBInfo) error { - if cmd.CheckIllegal(req.Value) { - return buserr.New(constant.ErrCmdIllegal) - } - cli, version, err := LoadMysqlClientByFrom(req.Database) - if err != nil { - return err - } - defer cli.Close() - var ( - mysqlData model.DatabaseMysql - passwordInfo client.PasswordChangeInfo - ) - passwordInfo.Password = req.Value - passwordInfo.Timeout = 300 - passwordInfo.Version = version - - if req.ID != 0 { - mysqlData, err = mysqlRepo.Get(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - passwordInfo.Name = mysqlData.Name - passwordInfo.Username = mysqlData.Username - passwordInfo.Permission = mysqlData.Permission - } else { - passwordInfo.Username = "root" - } - if err := cli.ChangePassword(passwordInfo); err != nil { - return err - } - - if req.ID != 0 { - var appRess []model.AppInstallResource - if req.From == "local" { - app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database) - if err != nil { - return err - } - appRess, _ = appInstallResourceRepo.GetBy(appInstallResourceRepo.WithLinkId(app.ID), appInstallResourceRepo.WithResourceId(mysqlData.ID)) - } else { - appRess, _ = appInstallResourceRepo.GetBy(appInstallResourceRepo.WithResourceId(mysqlData.ID)) - } - for _, appRes := range appRess { - appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(appRes.AppInstallId)) - if err != nil { - return err - } - appModel, err := appRepo.GetFirst(commonRepo.WithByID(appInstall.AppId)) - if err != nil { - return err - } - - global.LOG.Infof("start to update mysql password used by app %s-%s", appModel.Key, appInstall.Name) - if err := updateInstallInfoInDB(appModel.Key, appInstall.Name, "user-password", req.Value); err != nil { - return err - } - } - global.LOG.Info("execute password change sql successful") - pass, err := encrypt.StringEncrypt(req.Value) - if err != nil { - return fmt.Errorf("decrypt database db password failed, err: %v", err) - } - _ = mysqlRepo.Update(mysqlData.ID, map[string]interface{}{"password": pass}) - return nil - } - - if err := updateInstallInfoInDB(req.Type, req.Database, "password", req.Value); err != nil { - return err - } - if req.From == "local" { - remote, err := databaseRepo.Get(commonRepo.WithByName(req.Database)) - if err != nil { - return err - } - pass, err := encrypt.StringEncrypt(req.Value) - if err != nil { - return fmt.Errorf("decrypt database password failed, err: %v", err) - } - _ = databaseRepo.Update(remote.ID, map[string]interface{}{"password": pass}) - } - return nil -} - -func (u *MysqlService) ChangeAccess(req dto.ChangeDBInfo) error { - if cmd.CheckIllegal(req.Value) { - return buserr.New(constant.ErrCmdIllegal) - } - cli, version, err := LoadMysqlClientByFrom(req.Database) - if err != nil { - return err - } - defer cli.Close() - var ( - mysqlData model.DatabaseMysql - accessInfo client.AccessChangeInfo - ) - accessInfo.Permission = req.Value - accessInfo.Timeout = 300 - accessInfo.Version = version - - if req.ID != 0 { - mysqlData, err = mysqlRepo.Get(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - accessInfo.Name = mysqlData.Name - accessInfo.Username = mysqlData.Username - accessInfo.Password = mysqlData.Password - accessInfo.OldPermission = mysqlData.Permission - } else { - accessInfo.Username = "root" - } - if err := cli.ChangeAccess(accessInfo); err != nil { - return err - } - - if mysqlData.ID != 0 { - _ = mysqlRepo.Update(mysqlData.ID, map[string]interface{}{"permission": req.Value}) - } - - return nil -} - -func (u *MysqlService) UpdateVariables(req dto.MysqlVariablesUpdate) error { - app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database) - if err != nil { - return err - } - var files []string - - path := fmt.Sprintf("%s/%s/%s/conf/my.cnf", constant.AppInstallDir, req.Type, app.Name) - lineBytes, err := os.ReadFile(path) - if err != nil { - return err - } - files = strings.Split(string(lineBytes), "\n") - - group := "[mysqld]" - for _, info := range req.Variables { - if !strings.HasPrefix(app.Version, "5.7") && !strings.HasPrefix(app.Version, "5.6") { - if info.Param == "query_cache_size" { - continue - } - } - - if _, ok := info.Value.(float64); ok { - files = updateMyCnf(files, group, info.Param, common.LoadSizeUnit(info.Value.(float64))) - } else { - files = updateMyCnf(files, group, info.Param, info.Value) - } - } - file, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0666) - if err != nil { - return err - } - defer file.Close() - _, err = file.WriteString(strings.Join(files, "\n")) - if err != nil { - return err - } - - if _, err := compose.Restart(fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, req.Type, app.Name)); err != nil { - return err - } - - return nil -} - -func (u *MysqlService) LoadRemoteAccess(req dto.OperationWithNameAndType) (bool, error) { - app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name) - if err != nil { - return false, err - } - hosts, err := executeSqlForRows(app.ContainerName, app.Key, app.Password, "select host from mysql.user where user='root';") - if err != nil { - return false, err - } - for _, host := range hosts { - if host == "%" { - return true, nil - } - } - - return false, nil -} - -func (u *MysqlService) LoadVariables(req dto.OperationWithNameAndType) (*dto.MysqlVariables, error) { - app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name) - if err != nil { - return nil, err - } - variableMap, err := executeSqlForMaps(app.ContainerName, app.Key, app.Password, "show global variables;") - if err != nil { - return nil, err - } - var info dto.MysqlVariables - arr, err := json.Marshal(variableMap) - if err != nil { - return nil, err - } - _ = json.Unmarshal(arr, &info) - return &info, nil -} - -func (u *MysqlService) LoadStatus(req dto.OperationWithNameAndType) (*dto.MysqlStatus, error) { - app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name) - if err != nil { - return nil, err - } - - statusMap, err := executeSqlForMaps(app.ContainerName, app.Key, app.Password, "show global status;") - if err != nil { - return nil, err - } - - var info dto.MysqlStatus - arr, err := json.Marshal(statusMap) - if err != nil { - return nil, err - } - _ = json.Unmarshal(arr, &info) - - if value, ok := statusMap["Run"]; ok { - uptime, _ := strconv.Atoi(value) - info.Run = time.Unix(time.Now().Unix()-int64(uptime), 0).Format(constant.DateTimeLayout) - } else { - if value, ok := statusMap["Uptime"]; ok { - uptime, _ := strconv.Atoi(value) - info.Run = time.Unix(time.Now().Unix()-int64(uptime), 0).Format(constant.DateTimeLayout) - } - } - - info.File = "OFF" - info.Position = "OFF" - rows, err := executeSqlForRows(app.ContainerName, app.Key, app.Password, "show master status;") - if err != nil { - return nil, err - } - if len(rows) > 2 { - itemValue := strings.Split(rows[1], "\t") - if len(itemValue) > 2 { - info.File = itemValue[0] - info.Position = itemValue[1] - } - } - - return &info, nil -} - -func executeSqlForMaps(containerName, dbType, password, command string) (map[string]string, error) { - cmd := exec.Command("docker", "exec", containerName, dbType, "-uroot", "-p"+password, "-e", command) - stdout, err := cmd.CombinedOutput() - stdStr := strings.ReplaceAll(string(stdout), "mysql: [Warning] Using a password on the command line interface can be insecure.\n", "") - if err != nil || strings.HasPrefix(string(stdStr), "ERROR ") { - return nil, errors.New(stdStr) - } - - rows := strings.Split(stdStr, "\n") - rowMap := make(map[string]string) - for _, v := range rows { - itemRow := strings.Split(v, "\t") - if len(itemRow) == 2 { - rowMap[itemRow[0]] = itemRow[1] - } - } - return rowMap, nil -} - -func executeSqlForRows(containerName, dbType, password, command string) ([]string, error) { - cmd := exec.Command("docker", "exec", containerName, dbType, "-uroot", "-p"+password, "-e", command) - stdout, err := cmd.CombinedOutput() - stdStr := strings.ReplaceAll(string(stdout), "mysql: [Warning] Using a password on the command line interface can be insecure.\n", "") - if err != nil || strings.HasPrefix(string(stdStr), "ERROR ") { - return nil, errors.New(stdStr) - } - return strings.Split(stdStr, "\n"), nil -} - -func updateMyCnf(oldFiles []string, group string, param string, value interface{}) []string { - isOn := false - hasGroup := false - hasKey := false - regItem, _ := regexp.Compile(`\[*\]`) - var newFiles []string - i := 0 - for _, line := range oldFiles { - i++ - if strings.HasPrefix(line, group) { - isOn = true - hasGroup = true - newFiles = append(newFiles, line) - continue - } - if !isOn { - newFiles = append(newFiles, line) - continue - } - if strings.HasPrefix(line, param+"=") || strings.HasPrefix(line, "# "+param+"=") { - newFiles = append(newFiles, fmt.Sprintf("%s=%v", param, value)) - hasKey = true - continue - } - if regItem.Match([]byte(line)) || i == len(oldFiles) { - isOn = false - if !hasKey { - newFiles = append(newFiles, fmt.Sprintf("%s=%v", param, value)) - } - newFiles = append(newFiles, line) - continue - } - newFiles = append(newFiles, line) - } - if !hasGroup { - newFiles = append(newFiles, group+"\n") - newFiles = append(newFiles, fmt.Sprintf("%s=%v\n", param, value)) - } - return newFiles -} - -func LoadMysqlClientByFrom(database string) (mysql.MysqlClient, string, error) { - var ( - dbInfo client.DBInfo - version string - err error - ) - - dbInfo.Timeout = 300 - databaseItem, err := databaseRepo.Get(commonRepo.WithByName(database)) - if err != nil { - return nil, "", err - } - dbInfo.Type = databaseItem.Type - dbInfo.From = databaseItem.From - dbInfo.Database = database - if dbInfo.From != "local" { - dbInfo.Address = databaseItem.Address - dbInfo.Port = databaseItem.Port - dbInfo.Username = databaseItem.Username - dbInfo.Password = databaseItem.Password - dbInfo.SSL = databaseItem.SSL - dbInfo.ClientKey = databaseItem.ClientKey - dbInfo.ClientCert = databaseItem.ClientCert - dbInfo.RootCert = databaseItem.RootCert - dbInfo.SkipVerify = databaseItem.SkipVerify - version = databaseItem.Version - - } else { - app, err := appInstallRepo.LoadBaseInfo(databaseItem.Type, database) - if err != nil { - return nil, "", err - } - dbInfo.Address = app.ContainerName - dbInfo.Username = "root" - dbInfo.Password = app.Password - version = app.Version - } - - cli, err := mysql.NewMysqlClient(dbInfo) - if err != nil { - return nil, "", err - } - return cli, version, nil -} diff --git a/backend/app/service/database_postgresql.go b/backend/app/service/database_postgresql.go deleted file mode 100644 index 07843447c..000000000 --- a/backend/app/service/database_postgresql.go +++ /dev/null @@ -1,432 +0,0 @@ -package service - -import ( - "context" - "fmt" - "os" - "path" - "strings" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/encrypt" - "github.com/1Panel-dev/1Panel/backend/utils/postgresql" - "github.com/1Panel-dev/1Panel/backend/utils/postgresql/client" - _ "github.com/jackc/pgx/v5/stdlib" - "github.com/jinzhu/copier" - "github.com/pkg/errors" -) - -type PostgresqlService struct{} - -type IPostgresqlService interface { - SearchWithPage(search dto.PostgresqlDBSearch) (int64, interface{}, error) - ListDBOption() ([]dto.PostgresqlOption, error) - BindUser(req dto.PostgresqlBindUser) error - Create(ctx context.Context, req dto.PostgresqlDBCreate) (*model.DatabasePostgresql, error) - LoadFromRemote(database string) error - ChangePrivileges(req dto.PostgresqlPrivileges) error - ChangePassword(info dto.ChangeDBInfo) error - UpdateDescription(req dto.UpdateDescription) error - DeleteCheck(req dto.PostgresqlDBDeleteCheck) ([]string, error) - Delete(ctx context.Context, req dto.PostgresqlDBDelete) error -} - -func NewIPostgresqlService() IPostgresqlService { - return &PostgresqlService{} -} - -func (u *PostgresqlService) SearchWithPage(search dto.PostgresqlDBSearch) (int64, interface{}, error) { - total, postgresqls, err := postgresqlRepo.Page(search.Page, search.PageSize, - postgresqlRepo.WithByPostgresqlName(search.Database), - commonRepo.WithLikeName(search.Info), - commonRepo.WithOrderRuleBy(search.OrderBy, search.Order), - ) - var dtoPostgresqls []dto.PostgresqlDBInfo - for _, pg := range postgresqls { - var item dto.PostgresqlDBInfo - if err := copier.Copy(&item, &pg); err != nil { - return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - dtoPostgresqls = append(dtoPostgresqls, item) - } - return total, dtoPostgresqls, err -} - -func (u *PostgresqlService) ListDBOption() ([]dto.PostgresqlOption, error) { - postgresqls, err := postgresqlRepo.List() - if err != nil { - return nil, err - } - - databases, err := databaseRepo.GetList(databaseRepo.WithTypeList("postgresql,mariadb")) - if err != nil { - return nil, err - } - var dbs []dto.PostgresqlOption - for _, pg := range postgresqls { - var item dto.PostgresqlOption - if err := copier.Copy(&item, &pg); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - item.Database = pg.PostgresqlName - for _, database := range databases { - if database.Name == item.Database { - item.Type = database.Type - } - } - dbs = append(dbs, item) - } - return dbs, err -} - -func (u *PostgresqlService) BindUser(req dto.PostgresqlBindUser) error { - if cmd.CheckIllegal(req.Name, req.Username, req.Password) { - return buserr.New(constant.ErrCmdIllegal) - } - dbItem, err := postgresqlRepo.Get(postgresqlRepo.WithByPostgresqlName(req.Database), commonRepo.WithByName(req.Name)) - if err != nil { - return err - } - - pgClient, err := LoadPostgresqlClientByFrom(req.Database) - if err != nil { - return err - } - if err := pgClient.CreateUser(client.CreateInfo{ - Name: req.Name, - Username: req.Username, - Password: req.Password, - SuperUser: req.SuperUser, - Timeout: 300, - }, false); err != nil { - return err - } - pass, err := encrypt.StringEncrypt(req.Password) - if err != nil { - return fmt.Errorf("decrypt database db password failed, err: %v", err) - } - if err := postgresqlRepo.Update(dbItem.ID, map[string]interface{}{ - "username": req.Username, - "password": pass, - "super_user": req.SuperUser, - }); err != nil { - return err - } - return nil -} - -func (u *PostgresqlService) Create(ctx context.Context, req dto.PostgresqlDBCreate) (*model.DatabasePostgresql, error) { - if cmd.CheckIllegal(req.Name, req.Username, req.Password, req.Format) { - return nil, buserr.New(constant.ErrCmdIllegal) - } - - pgsql, _ := postgresqlRepo.Get(commonRepo.WithByName(req.Name), postgresqlRepo.WithByPostgresqlName(req.Database), databaseRepo.WithByFrom(req.From)) - if pgsql.ID != 0 { - return nil, constant.ErrRecordExist - } - - var createItem model.DatabasePostgresql - if err := copier.Copy(&createItem, &req); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - - if req.From == "local" && req.Username == "root" { - return nil, errors.New("Cannot set root as user name") - } - - cli, err := LoadPostgresqlClientByFrom(req.Database) - if err != nil { - return nil, err - } - defer cli.Close() - - createItem.PostgresqlName = req.Database - defer cli.Close() - if err := cli.Create(client.CreateInfo{ - Name: req.Name, - Username: req.Username, - Password: req.Password, - SuperUser: req.SuperUser, - Timeout: 300, - }); err != nil { - return nil, err - } - - global.LOG.Infof("create database %s successful!", req.Name) - if err := postgresqlRepo.Create(ctx, &createItem); err != nil { - return nil, err - } - return &createItem, nil -} - -func LoadPostgresqlClientByFrom(database string) (postgresql.PostgresqlClient, error) { - var ( - dbInfo client.DBInfo - err error - ) - - dbInfo.Timeout = 300 - databaseItem, err := databaseRepo.Get(commonRepo.WithByName(database)) - if err != nil { - return nil, err - } - dbInfo.From = databaseItem.From - dbInfo.Database = database - if dbInfo.From != "local" { - dbInfo.Address = databaseItem.Address - dbInfo.Port = databaseItem.Port - dbInfo.Username = databaseItem.Username - dbInfo.Password = databaseItem.Password - } else { - app, err := appInstallRepo.LoadBaseInfo(databaseItem.Type, database) - if err != nil { - return nil, err - } - dbInfo.From = "local" - dbInfo.Address = app.ContainerName - dbInfo.Username = app.UserName - dbInfo.Password = app.Password - dbInfo.Port = uint(app.Port) - } - - cli, err := postgresql.NewPostgresqlClient(dbInfo) - if err != nil { - return nil, err - } - return cli, nil -} - -func (u *PostgresqlService) LoadFromRemote(database string) error { - client, err := LoadPostgresqlClientByFrom(database) - if err != nil { - return err - } - defer client.Close() - - databases, err := postgresqlRepo.List(postgresqlRepo.WithByPostgresqlName(database)) - if err != nil { - return err - } - datas, err := client.SyncDB() - if err != nil { - return err - } - deleteList := databases - for _, data := range datas { - hasOld := false - for i := 0; i < len(databases); i++ { - if strings.EqualFold(databases[i].Name, data.Name) && strings.EqualFold(databases[i].PostgresqlName, data.PostgresqlName) { - hasOld = true - if databases[i].IsDelete { - _ = postgresqlRepo.Update(databases[i].ID, map[string]interface{}{"is_delete": false}) - } - deleteList = append(deleteList[:i], deleteList[i+1:]...) - break - } - } - if !hasOld { - var createItem model.DatabasePostgresql - if err := copier.Copy(&createItem, &data); err != nil { - return errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - if err := postgresqlRepo.Create(context.Background(), &createItem); err != nil { - return err - } - } - } - for _, delItem := range deleteList { - _ = postgresqlRepo.Update(delItem.ID, map[string]interface{}{"is_delete": true}) - } - return nil -} - -func (u *PostgresqlService) UpdateDescription(req dto.UpdateDescription) error { - return postgresqlRepo.Update(req.ID, map[string]interface{}{"description": req.Description}) -} - -func (u *PostgresqlService) DeleteCheck(req dto.PostgresqlDBDeleteCheck) ([]string, error) { - var appInUsed []string - db, err := postgresqlRepo.Get(commonRepo.WithByID(req.ID)) - if err != nil { - return appInUsed, err - } - - if db.From == "local" { - app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database) - if err != nil { - return appInUsed, err - } - apps, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithLinkId(app.ID), appInstallResourceRepo.WithResourceId(db.ID)) - for _, app := range apps { - appInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(app.AppInstallId)) - if appInstall.ID != 0 { - appInUsed = append(appInUsed, appInstall.Name) - } - } - } else { - apps, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithResourceId(db.ID), appRepo.WithKey(req.Type)) - for _, app := range apps { - appInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(app.AppInstallId)) - if appInstall.ID != 0 { - appInUsed = append(appInUsed, appInstall.Name) - } - } - } - - return appInUsed, nil -} - -func (u *PostgresqlService) Delete(ctx context.Context, req dto.PostgresqlDBDelete) error { - db, err := postgresqlRepo.Get(commonRepo.WithByID(req.ID)) - if err != nil && !req.ForceDelete { - return err - } - cli, err := LoadPostgresqlClientByFrom(req.Database) - if err != nil { - return err - } - defer cli.Close() - if err := cli.Delete(client.DeleteInfo{ - Name: db.Name, - Username: db.Username, - ForceDelete: req.ForceDelete, - Timeout: 300, - }); err != nil && !req.ForceDelete { - return err - } - - if req.DeleteBackup { - uploadDir := path.Join(global.CONF.System.BaseDir, fmt.Sprintf("1panel/uploads/database/%s/%s/%s", req.Type, req.Database, db.Name)) - if _, err := os.Stat(uploadDir); err == nil { - _ = os.RemoveAll(uploadDir) - } - localDir, err := loadLocalDir() - if err != nil && !req.ForceDelete { - return err - } - backupDir := path.Join(localDir, fmt.Sprintf("database/%s/%s/%s", req.Type, db.PostgresqlName, db.Name)) - if _, err := os.Stat(backupDir); err == nil { - _ = os.RemoveAll(backupDir) - } - _ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType(req.Type), commonRepo.WithByName(req.Database), backupRepo.WithByDetailName(db.Name)) - global.LOG.Infof("delete database %s-%s backups successful", req.Database, db.Name) - } - - _ = postgresqlRepo.Delete(ctx, commonRepo.WithByID(db.ID)) - return nil -} - -func (u *PostgresqlService) ChangePrivileges(req dto.PostgresqlPrivileges) error { - if cmd.CheckIllegal(req.Database, req.Username) { - return buserr.New(constant.ErrCmdIllegal) - } - dbItem, err := postgresqlRepo.Get(postgresqlRepo.WithByPostgresqlName(req.Database), commonRepo.WithByName(req.Name)) - if err != nil { - return err - } - cli, err := LoadPostgresqlClientByFrom(req.Database) - if err != nil { - return err - } - defer cli.Close() - - if err := cli.ChangePrivileges(client.Privileges{Username: req.Username, SuperUser: req.SuperUser, Timeout: 300}); err != nil { - return err - } - if err := postgresqlRepo.Update(dbItem.ID, map[string]interface{}{ - "super_user": req.SuperUser, - }); err != nil { - return err - } - return nil -} - -func (u *PostgresqlService) ChangePassword(req dto.ChangeDBInfo) error { - if cmd.CheckIllegal(req.Value) { - return buserr.New(constant.ErrCmdIllegal) - } - cli, err := LoadPostgresqlClientByFrom(req.Database) - if err != nil { - return err - } - defer cli.Close() - var ( - postgresqlData model.DatabasePostgresql - passwordInfo client.PasswordChangeInfo - ) - passwordInfo.Password = req.Value - passwordInfo.Timeout = 300 - - if req.ID != 0 { - postgresqlData, err = postgresqlRepo.Get(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - passwordInfo.Username = postgresqlData.Username - } else { - dbItem, err := databaseRepo.Get(commonRepo.WithByType(req.Type), commonRepo.WithByFrom(req.From)) - if err != nil { - return err - } - passwordInfo.Username = dbItem.Username - } - if err := cli.ChangePassword(passwordInfo); err != nil { - return err - } - - if req.ID != 0 { - var appRess []model.AppInstallResource - if req.From == "local" { - app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database) - if err != nil { - return err - } - appRess, _ = appInstallResourceRepo.GetBy(appInstallResourceRepo.WithLinkId(app.ID), appInstallResourceRepo.WithResourceId(postgresqlData.ID)) - } else { - appRess, _ = appInstallResourceRepo.GetBy(appInstallResourceRepo.WithResourceId(postgresqlData.ID)) - } - for _, appRes := range appRess { - appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(appRes.AppInstallId)) - if err != nil { - return err - } - appModel, err := appRepo.GetFirst(commonRepo.WithByID(appInstall.AppId)) - if err != nil { - return err - } - - global.LOG.Infof("start to update postgresql password used by app %s-%s", appModel.Key, appInstall.Name) - if err := updateInstallInfoInDB(appModel.Key, appInstall.Name, "user-password", req.Value); err != nil { - return err - } - } - global.LOG.Info("execute password change sql successful") - pass, err := encrypt.StringEncrypt(req.Value) - if err != nil { - return fmt.Errorf("decrypt database db password failed, err: %v", err) - } - _ = postgresqlRepo.Update(postgresqlData.ID, map[string]interface{}{"password": pass}) - return nil - } - - if err := updateInstallInfoInDB(req.Type, req.Database, "password", req.Value); err != nil { - return err - } - if req.From == "local" { - remote, err := databaseRepo.Get(commonRepo.WithByName(req.Database)) - if err != nil { - return err - } - pass, err := encrypt.StringEncrypt(req.Value) - if err != nil { - return fmt.Errorf("decrypt database password failed, err: %v", err) - } - _ = databaseRepo.Update(remote.ID, map[string]interface{}{"password": pass}) - } - return nil -} diff --git a/backend/app/service/database_redis.go b/backend/app/service/database_redis.go deleted file mode 100644 index 15149f447..000000000 --- a/backend/app/service/database_redis.go +++ /dev/null @@ -1,294 +0,0 @@ -package service - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "os" - "os/exec" - "strings" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/compose" - "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/1Panel-dev/1Panel/backend/utils/encrypt" - "github.com/docker/docker/api/types/container" - _ "github.com/go-sql-driver/mysql" -) - -type RedisService struct{} - -type IRedisService interface { - UpdateConf(req dto.RedisConfUpdate) error - UpdatePersistenceConf(req dto.RedisConfPersistenceUpdate) error - ChangePassword(info dto.ChangeRedisPass) error - - LoadStatus(req dto.OperationWithName) (*dto.RedisStatus, error) - LoadConf(req dto.OperationWithName) (*dto.RedisConf, error) - LoadPersistenceConf(req dto.OperationWithName) (*dto.RedisPersistence, error) - - CheckHasCli() bool - InstallCli() error -} - -func NewIRedisService() IRedisService { - return &RedisService{} -} - -func (u *RedisService) UpdateConf(req dto.RedisConfUpdate) error { - redisInfo, err := appInstallRepo.LoadBaseInfo("redis", req.Database) - if err != nil { - return err - } - - var confs []redisConfig - confs = append(confs, redisConfig{key: "timeout", value: req.Timeout}) - confs = append(confs, redisConfig{key: "maxclients", value: req.Maxclients}) - confs = append(confs, redisConfig{key: "maxmemory", value: req.Maxmemory}) - if err := confSet(redisInfo.Name, "", confs); err != nil { - return err - } - if _, err := compose.Restart(fmt.Sprintf("%s/redis/%s/docker-compose.yml", constant.AppInstallDir, redisInfo.Name)); err != nil { - return err - } - - return nil -} - -func (u *RedisService) CheckHasCli() bool { - client, err := docker.NewDockerClient() - if err != nil { - return false - } - defer client.Close() - containerLists, err := client.ContainerList(context.Background(), container.ListOptions{}) - if err != nil { - return false - } - for _, item := range containerLists { - if strings.ReplaceAll(item.Names[0], "/", "") == "1Panel-redis-cli-tools" { - return true - } - } - return false -} - -func (u *RedisService) InstallCli() error { - item := dto.ContainerOperate{ - Name: "1Panel-redis-cli-tools", - Image: "redis:7.2.4", - Network: "1panel-network", - } - return NewIContainerService().ContainerCreate(item) -} - -func (u *RedisService) ChangePassword(req dto.ChangeRedisPass) error { - if err := updateInstallInfoInDB("redis", req.Database, "password", req.Value); err != nil { - return err - } - remote, err := databaseRepo.Get(commonRepo.WithByName(req.Database)) - if err != nil { - return err - } - if remote.From == "local" { - pass, err := encrypt.StringEncrypt(req.Value) - if err != nil { - return fmt.Errorf("decrypt database password failed, err: %v", err) - } - _ = databaseRepo.Update(remote.ID, map[string]interface{}{"password": pass}) - } - - return nil -} - -func (u *RedisService) UpdatePersistenceConf(req dto.RedisConfPersistenceUpdate) error { - redisInfo, err := appInstallRepo.LoadBaseInfo("redis", req.Database) - if err != nil { - return err - } - - var confs []redisConfig - if req.Type == "rbd" { - confs = append(confs, redisConfig{key: "save", value: req.Save}) - } else { - confs = append(confs, redisConfig{key: "appendonly", value: req.Appendonly}) - confs = append(confs, redisConfig{key: "appendfsync", value: req.Appendfsync}) - } - if err := confSet(redisInfo.Name, req.Type, confs); err != nil { - return err - } - if _, err := compose.Restart(fmt.Sprintf("%s/redis/%s/docker-compose.yml", constant.AppInstallDir, redisInfo.Name)); err != nil { - return err - } - - return nil -} - -func (u *RedisService) LoadStatus(req dto.OperationWithName) (*dto.RedisStatus, error) { - redisInfo, err := appInstallRepo.LoadBaseInfo("redis", req.Name) - if err != nil { - return nil, err - } - commands := append(redisExec(redisInfo.ContainerName, redisInfo.Password), "info") - cmd := exec.Command("docker", commands...) - stdout, err := cmd.CombinedOutput() - if err != nil { - return nil, errors.New(string(stdout)) - } - rows := strings.Split(string(stdout), "\r\n") - rowMap := make(map[string]string) - for _, v := range rows { - itemRow := strings.Split(v, ":") - if len(itemRow) == 2 { - rowMap[itemRow[0]] = itemRow[1] - } - } - var info dto.RedisStatus - arr, err := json.Marshal(rowMap) - if err != nil { - return nil, err - } - _ = json.Unmarshal(arr, &info) - return &info, nil -} - -func (u *RedisService) LoadConf(req dto.OperationWithName) (*dto.RedisConf, error) { - redisInfo, err := appInstallRepo.LoadBaseInfo("redis", req.Name) - if err != nil { - return nil, err - } - - var item dto.RedisConf - item.ContainerName = redisInfo.ContainerName - item.Name = redisInfo.Name - item.Port = redisInfo.Port - item.Requirepass = redisInfo.Password - item.Timeout, _ = configGetStr(redisInfo.ContainerName, redisInfo.Password, "timeout") - item.Maxclients, _ = configGetStr(redisInfo.ContainerName, redisInfo.Password, "maxclients") - item.Maxmemory, _ = configGetStr(redisInfo.ContainerName, redisInfo.Password, "maxmemory") - return &item, nil -} - -func (u *RedisService) LoadPersistenceConf(req dto.OperationWithName) (*dto.RedisPersistence, error) { - redisInfo, err := appInstallRepo.LoadBaseInfo("redis", req.Name) - if err != nil { - return nil, err - } - var item dto.RedisPersistence - if item.Appendonly, err = configGetStr(redisInfo.ContainerName, redisInfo.Password, "appendonly"); err != nil { - return nil, err - } - if item.Appendfsync, err = configGetStr(redisInfo.ContainerName, redisInfo.Password, "appendfsync"); err != nil { - return nil, err - } - if item.Save, err = configGetStr(redisInfo.ContainerName, redisInfo.Password, "save"); err != nil { - return nil, err - } - return &item, nil -} - -func configGetStr(containerName, password, param string) (string, error) { - commands := append(redisExec(containerName, password), []string{"config", "get", param}...) - cmd := exec.Command("docker", commands...) - stdout, err := cmd.CombinedOutput() - if err != nil { - return "", errors.New(string(stdout)) - } - rows := strings.Split(string(stdout), "\r\n") - for _, v := range rows { - itemRow := strings.Split(v, "\n") - if len(itemRow) == 3 { - return itemRow[1], nil - } - } - return "", nil -} - -type redisConfig struct { - key string - value string -} - -func confSet(redisName string, updateType string, changeConf []redisConfig) error { - path := fmt.Sprintf("%s/redis/%s/conf/redis.conf", constant.AppInstallDir, redisName) - lineBytes, err := os.ReadFile(path) - if err != nil { - return err - } - files := strings.Split(string(lineBytes), "\n") - - startIndex, endIndex, emptyLine := 0, 0, 0 - var newFiles []string - for i := 0; i < len(files); i++ { - if files[i] == "# Redis configuration rewrite by 1Panel" { - startIndex = i - newFiles = append(newFiles, files[i]) - continue - } - if files[i] == "# End Redis configuration rewrite by 1Panel" { - endIndex = i - break - } - if startIndex == 0 && strings.HasPrefix(files[i], "save ") { - newFiles = append(newFiles, "# "+files[i]) - continue - } - if startIndex != 0 && endIndex == 0 && (len(files[i]) == 0 || (updateType == "rbd" && strings.HasPrefix(files[i], "save "))) { - emptyLine++ - continue - } - newFiles = append(newFiles, files[i]) - } - endIndex = endIndex - emptyLine - for _, item := range changeConf { - if item.key == "save" { - saveVal := strings.Split(item.value, ",") - for i := 0; i < len(saveVal); i++ { - newFiles = append(newFiles, "save "+saveVal[i]) - } - continue - } - - isExist := false - for i := startIndex; i < endIndex; i++ { - if strings.HasPrefix(newFiles[i], item.key) || strings.HasPrefix(newFiles[i], "# "+item.key) { - if item.value == "0" || len(item.value) == 0 { - newFiles[i] = fmt.Sprintf("# %s %s", item.key, item.value) - } else { - newFiles[i] = fmt.Sprintf("%s %s", item.key, item.value) - } - isExist = true - break - } - } - if !isExist { - if item.value == "0" || len(item.value) == 0 { - newFiles = append(newFiles, fmt.Sprintf("# %s %s", item.key, item.value)) - } else { - newFiles = append(newFiles, fmt.Sprintf("%s %s", item.key, item.value)) - } - } - } - newFiles = append(newFiles, "# End Redis configuration rewrite by 1Panel") - - file, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0666) - if err != nil { - return err - } - defer file.Close() - _, err = file.WriteString(strings.Join(newFiles, "\n")) - if err != nil { - return err - } - return nil -} - -func redisExec(containerName, password string) []string { - cmds := []string{"exec", containerName, "redis-cli", "-a", password, "--no-auth-warning"} - if len(password) == 0 { - cmds = []string{"exec", containerName, "redis-cli"} - } - return cmds -} diff --git a/backend/app/service/device.go b/backend/app/service/device.go deleted file mode 100644 index 8fcf8a8d7..000000000 --- a/backend/app/service/device.go +++ /dev/null @@ -1,431 +0,0 @@ -package service - -import ( - "bufio" - "errors" - "fmt" - "net" - "os" - "path" - "strconv" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/ntp" - "github.com/shirou/gopsutil/v3/mem" -) - -const defaultDNSPath = "/etc/resolv.conf" -const defaultHostPath = "/etc/hosts" -const defaultFstab = "/etc/fstab" - -type DeviceService struct{} - -type IDeviceService interface { - LoadBaseInfo() (dto.DeviceBaseInfo, error) - Update(key, value string) error - UpdateHosts(req []dto.HostHelper) error - UpdatePasswd(req dto.ChangePasswd) error - UpdateSwap(req dto.SwapHelper) error - UpdateByConf(req dto.UpdateByNameAndFile) error - LoadTimeZone() ([]string, error) - CheckDNS(key, value string) (bool, error) - LoadConf(name string) (string, error) - - Scan() dto.CleanData - Clean(req []dto.Clean) - CleanForCronjob() (string, error) -} - -func NewIDeviceService() IDeviceService { - return &DeviceService{} -} - -func (u *DeviceService) LoadBaseInfo() (dto.DeviceBaseInfo, error) { - var baseInfo dto.DeviceBaseInfo - baseInfo.LocalTime = time.Now().Format("2006-01-02 15:04:05 MST -0700") - baseInfo.TimeZone = common.LoadTimeZoneByCmd() - baseInfo.DNS = loadDNS() - baseInfo.Hosts = loadHosts() - baseInfo.Hostname = loadHostname() - baseInfo.User = loadUser() - ntp, err := settingRepo.Get(settingRepo.WithByKey("NtpSite")) - if err == nil { - baseInfo.Ntp = ntp.Value - } - - swapInfo, err := mem.SwapMemory() - if err != nil { - return baseInfo, err - } - baseInfo.SwapMemoryTotal = swapInfo.Total - baseInfo.SwapMemoryAvailable = swapInfo.Free - baseInfo.SwapMemoryUsed = swapInfo.Used - if baseInfo.SwapMemoryTotal != 0 { - baseInfo.SwapDetails = loadSwap() - } - disks := loadDiskInfo() - for _, item := range disks { - baseInfo.MaxSize += item.Free - } - - return baseInfo, nil -} - -func (u *DeviceService) LoadTimeZone() ([]string, error) { - std, err := cmd.Exec("timedatectl list-timezones") - if err != nil { - return []string{}, err - } - return strings.Split(std, "\n"), nil -} - -func (u *DeviceService) CheckDNS(key, value string) (bool, error) { - content, err := os.ReadFile(defaultDNSPath) - if err != nil { - return false, err - } - defer func() { _ = u.UpdateByConf(dto.UpdateByNameAndFile{Name: "DNS", File: string(content)}) }() - if key == "form" { - if err := u.Update("DNS", value); err != nil { - return false, err - } - } else { - if err := u.UpdateByConf(dto.UpdateByNameAndFile{Name: "DNS", File: value}); err != nil { - return false, err - } - } - - conn, err := net.DialTimeout("ip4:icmp", "www.baidu.com", time.Second*2) - if err != nil { - return false, err - } - defer conn.Close() - - return true, nil -} - -func (u *DeviceService) Update(key, value string) error { - switch key { - case "TimeZone": - if cmd.CheckIllegal(value) { - return buserr.New(constant.ErrCmdIllegal) - } - if err := ntp.UpdateSystemTimeZone(value); err != nil { - return err - } - go func() { - _, err := cmd.Exec("systemctl restart 1panel.service") - if err != nil { - global.LOG.Errorf("restart system for new time zone failed, err: %v", err) - } - }() - case "DNS": - if err := updateDNS(strings.Split(value, ",")); err != nil { - return err - } - case "Hostname": - if cmd.CheckIllegal(value) { - return buserr.New(constant.ErrCmdIllegal) - } - std, err := cmd.Execf("%s hostnamectl set-hostname %s", cmd.SudoHandleCmd(), value) - if err != nil { - return errors.New(std) - } - case "Ntp", "LocalTime": - if cmd.CheckIllegal(value) { - return buserr.New(constant.ErrCmdIllegal) - } - ntpValue := value - if key == "LocalTime" { - ntpItem, err := settingRepo.Get(settingRepo.WithByKey("NtpSite")) - if err != nil { - return err - } - ntpValue = ntpItem.Value - } else { - if err := settingRepo.Update("NtpSite", ntpValue); err != nil { - return err - } - } - ntime, err := ntp.GetRemoteTime(ntpValue) - if err != nil { - return err - } - ts := ntime.Format(constant.DateTimeLayout) - if err := ntp.UpdateSystemTime(ts); err != nil { - return err - } - default: - return fmt.Errorf("not support such key %s", key) - } - return nil -} - -func (u *DeviceService) UpdateHosts(req []dto.HostHelper) error { - conf, err := os.ReadFile(defaultHostPath) - if err != nil { - return fmt.Errorf("read namesever conf of %s failed, err: %v", defaultHostPath, err) - } - lines := strings.Split(string(conf), "\n") - newFile := "" - for _, line := range lines { - if len(line) == 0 { - continue - } - parts := strings.Fields(line) - if len(parts) < 2 { - newFile += line + "\n" - continue - } - for index, item := range req { - if item.IP == parts[0] && item.Host == strings.Join(parts[1:], " ") { - newFile += line + "\n" - req = append(req[:index], req[index+1:]...) - break - } - } - } - for _, item := range req { - newFile += fmt.Sprintf("%s %s \n", item.IP, item.Host) - } - file, err := os.OpenFile(defaultHostPath, os.O_WRONLY|os.O_TRUNC, 0640) - if err != nil { - return err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(newFile) - write.Flush() - return nil -} - -func (u *DeviceService) UpdatePasswd(req dto.ChangePasswd) error { - if cmd.CheckIllegal(req.User, req.Passwd) { - return buserr.New(constant.ErrCmdIllegal) - } - std, err := cmd.Execf("%s echo '%s:%s' | %s chpasswd", cmd.SudoHandleCmd(), req.User, req.Passwd, cmd.SudoHandleCmd()) - if err != nil { - if strings.Contains(err.Error(), "does not exist") { - return buserr.New(constant.ErrNotExistUser) - } - return errors.New(std) - } - return nil -} - -func (u *DeviceService) UpdateSwap(req dto.SwapHelper) error { - if cmd.CheckIllegal(req.Path) { - return buserr.New(constant.ErrCmdIllegal) - } - if !req.IsNew { - std, err := cmd.Execf("%s swapoff %s", cmd.SudoHandleCmd(), req.Path) - if err != nil { - return fmt.Errorf("handle swapoff %s failed, err: %s", req.Path, std) - } - } - if req.Size == 0 { - if req.Path == path.Join(global.CONF.System.BaseDir, ".1panel_swap") { - _ = os.Remove(path.Join(global.CONF.System.BaseDir, ".1panel_swap")) - } - return operateSwapWithFile(true, req) - } - std1, err := cmd.Execf("%s dd if=/dev/zero of=%s bs=1024 count=%d", cmd.SudoHandleCmd(), req.Path, req.Size) - if err != nil { - return fmt.Errorf("handle dd path %s failed, err: %s", req.Path, std1) - } - std2, err := cmd.Execf("%s mkswap -f %s", cmd.SudoHandleCmd(), req.Path) - if err != nil { - return fmt.Errorf("handle dd path %s failed, err: %s", req.Path, std2) - } - std3, err := cmd.Execf("%s swapon %s", cmd.SudoHandleCmd(), req.Path) - if err != nil { - _, _ = cmd.Execf("%s swapoff %s", cmd.SudoHandleCmd(), req.Path) - return fmt.Errorf("handle dd path %s failed, err: %s", req.Path, std3) - } - return operateSwapWithFile(false, req) -} - -func (u *DeviceService) LoadConf(name string) (string, error) { - pathItem := "" - switch name { - case "DNS": - pathItem = defaultDNSPath - case "Hosts": - pathItem = defaultHostPath - default: - return "", fmt.Errorf("not support such name %s", name) - } - if _, err := os.Stat(pathItem); err != nil { - return "", err - } - content, err := os.ReadFile(pathItem) - if err != nil { - return "", err - } - return string(content), nil -} - -func (u *DeviceService) UpdateByConf(req dto.UpdateByNameAndFile) error { - if req.Name != "DNS" && req.Name != "Hosts" { - return fmt.Errorf("not support such name %s", req.Name) - } - path := defaultDNSPath - if req.Name == "Hosts" { - path = defaultHostPath - } - file, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0640) - if err != nil { - return err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(req.File) - write.Flush() - return nil -} - -func loadDNS() []string { - var list []string - dnsConf, err := os.ReadFile(defaultDNSPath) - if err == nil { - lines := strings.Split(string(dnsConf), "\n") - for _, line := range lines { - if strings.HasPrefix(line, "nameserver ") { - list = append(list, strings.TrimPrefix(line, "nameserver ")) - } - } - } - return list -} - -func updateDNS(list []string) error { - conf, err := os.ReadFile(defaultDNSPath) - if err != nil { - return fmt.Errorf("read nameserver conf of %s failed, err: %v", defaultDNSPath, err) - } - lines := strings.Split(string(conf), "\n") - newFile := "" - for _, line := range lines { - if len(line) == 0 { - continue - } - parts := strings.Fields(line) - if len(parts) < 2 || parts[0] != "nameserver" { - newFile += line + "\n" - continue - } - itemNs := strings.Join(parts[1:], " ") - for index, item := range list { - if item == itemNs { - newFile += line + "\n" - list = append(list[:index], list[index+1:]...) - break - } - } - } - for _, item := range list { - if len(item) != 0 { - newFile += fmt.Sprintf("nameserver %s \n", item) - } - } - file, err := os.OpenFile(defaultDNSPath, os.O_WRONLY|os.O_TRUNC, 0640) - if err != nil { - return err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(newFile) - write.Flush() - return nil -} - -func loadHosts() []dto.HostHelper { - var list []dto.HostHelper - hostConf, err := os.ReadFile(defaultHostPath) - if err == nil { - lines := strings.Split(string(hostConf), "\n") - for _, line := range lines { - parts := strings.Fields(line) - if len(parts) < 2 || strings.HasPrefix(strings.TrimPrefix(line, " "), "#") { - continue - } - list = append(list, dto.HostHelper{IP: parts[0], Host: strings.Join(parts[1:], " ")}) - } - } - return list -} - -func loadHostname() string { - std, err := cmd.Exec("hostname") - if err != nil { - return "" - } - return strings.ReplaceAll(std, "\n", "") -} - -func loadUser() string { - std, err := cmd.Exec("whoami") - if err != nil { - return "" - } - return strings.ReplaceAll(std, "\n", "") -} - -func loadSwap() []dto.SwapHelper { - var data []dto.SwapHelper - std, err := cmd.Execf("%s swapon --summary", cmd.SudoHandleCmd()) - if err != nil { - return data - } - lines := strings.Split(std, "\n") - for index, line := range lines { - if index == 0 { - continue - } - parts := strings.Fields(line) - if len(parts) < 5 { - continue - } - sizeItem, _ := strconv.Atoi(parts[2]) - data = append(data, dto.SwapHelper{Path: parts[0], Size: uint64(sizeItem), Used: parts[3]}) - } - return data -} - -func operateSwapWithFile(delete bool, req dto.SwapHelper) error { - conf, err := os.ReadFile(defaultFstab) - if err != nil { - return fmt.Errorf("read file %s failed, err: %v", defaultFstab, err) - } - lines := strings.Split(string(conf), "\n") - newFile := "" - for _, line := range lines { - if len(line) == 0 { - continue - } - parts := strings.Fields(line) - if len(parts) == 6 && parts[0] == req.Path { - continue - } - newFile += line + "\n" - } - if !delete { - newFile += fmt.Sprintf("%s swap swap defaults 0 0\n", req.Path) - } - file, err := os.OpenFile(defaultFstab, os.O_WRONLY|os.O_TRUNC, 0640) - if err != nil { - return err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(newFile) - write.Flush() - return nil -} diff --git a/backend/app/service/device_clean.go b/backend/app/service/device_clean.go deleted file mode 100644 index f6dfd53a4..000000000 --- a/backend/app/service/device_clean.go +++ /dev/null @@ -1,735 +0,0 @@ -package service - -import ( - "context" - "fmt" - "os" - "path" - "sort" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/common" - fileUtils "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/google/uuid" -) - -const ( - upgradePath = "1panel/tmp/upgrade" - snapshotTmpPath = "1panel/tmp/system" - rollbackPath = "1panel/tmp" - cachePath = "1panel/cache" - oldOriginalPath = "original" - oldAppBackupPath = "1panel/resource/apps_bak" - oldDownloadPath = "1panel/tmp/download" - oldUpgradePath = "1panel/tmp" - tmpUploadPath = "1panel/tmp/upload" - uploadPath = "1panel/uploads" - downloadPath = "1panel/download" - logPath = "1panel/log" - dockerLogPath = "1panel/tmp/docker_logs" - taskPath = "1panel/task" -) - -func (u *DeviceService) Scan() dto.CleanData { - var ( - SystemClean dto.CleanData - treeData []dto.CleanTree - ) - fileOp := fileUtils.NewFileOp() - - originalPath := path.Join(global.CONF.System.BaseDir, "1panel_original") - originalSize, _ := fileOp.GetDirSize(originalPath) - treeData = append(treeData, dto.CleanTree{ - ID: uuid.NewString(), - Label: "1panel_original", - Size: uint64(originalSize), - IsCheck: true, - IsRecommend: true, - Type: "1panel_original", - Children: loadTreeWithDir(true, "1panel_original", originalPath, fileOp), - }) - - upgradePath := path.Join(global.CONF.System.BaseDir, upgradePath) - upgradeSize, _ := fileOp.GetDirSize(upgradePath) - treeData = append(treeData, dto.CleanTree{ - ID: uuid.NewString(), - Label: "upgrade", - Size: uint64(upgradeSize), - IsCheck: false, - IsRecommend: true, - Type: "upgrade", - Children: loadTreeWithDir(true, "upgrade", upgradePath, fileOp), - }) - - snapTree := loadSnapshotTree(fileOp) - snapSize := uint64(0) - for _, snap := range snapTree { - snapSize += snap.Size - } - treeData = append(treeData, dto.CleanTree{ - ID: uuid.NewString(), - Label: "snapshot", - Size: snapSize, - IsCheck: true, - IsRecommend: true, - Type: "snapshot", - Children: snapTree, - }) - - rollBackTree := loadRollBackTree(fileOp) - rollbackSize := uint64(0) - for _, rollback := range rollBackTree { - rollbackSize += rollback.Size - } - treeData = append(treeData, dto.CleanTree{ - ID: uuid.NewString(), - Label: "rollback", - Size: rollbackSize, - IsCheck: true, - IsRecommend: true, - Type: "rollback", - Children: rollBackTree, - }) - - cachePath := path.Join(global.CONF.System.BaseDir, cachePath) - cacheSize, _ := fileOp.GetDirSize(cachePath) - treeData = append(treeData, dto.CleanTree{ - ID: uuid.NewString(), - Label: "cache", - Size: uint64(cacheSize), - IsCheck: false, - IsRecommend: false, - Type: "cache", - }) - - unusedTree := loadUnusedFile(fileOp) - unusedSize := uint64(0) - for _, unused := range unusedTree { - unusedSize += unused.Size - } - treeData = append(treeData, dto.CleanTree{ - ID: uuid.NewString(), - Label: "unused", - Size: unusedSize, - IsCheck: true, - IsRecommend: true, - Type: "unused", - Children: unusedTree, - }) - SystemClean.SystemClean = treeData - - uploadTreeData := loadUploadTree(fileOp) - SystemClean.UploadClean = append(SystemClean.UploadClean, uploadTreeData...) - - downloadTreeData := loadDownloadTree(fileOp) - SystemClean.DownloadClean = append(SystemClean.DownloadClean, downloadTreeData...) - - logTree := loadLogTree(fileOp) - SystemClean.SystemLogClean = append(SystemClean.SystemLogClean, logTree...) - - containerTree := loadContainerTree() - SystemClean.ContainerClean = append(SystemClean.ContainerClean, containerTree...) - - return SystemClean -} - -func (u *DeviceService) Clean(req []dto.Clean) { - size := uint64(0) - restart := false - for _, item := range req { - size += item.Size - switch item.TreeType { - case "1panel_original": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel_original", item.Name)) - - case "upgrade": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, upgradePath, item.Name)) - - case "snapshot": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, snapshotTmpPath, item.Name)) - dropFileOrDir(path.Join(global.CONF.System.Backup, "system", item.Name)) - case "snapshot_tmp": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, snapshotTmpPath, item.Name)) - case "snapshot_local": - dropFileOrDir(path.Join(global.CONF.System.Backup, "system", item.Name)) - - case "rollback": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, rollbackPath, "app")) - dropFileOrDir(path.Join(global.CONF.System.BaseDir, rollbackPath, "database")) - dropFileOrDir(path.Join(global.CONF.System.BaseDir, rollbackPath, "website")) - case "rollback_app": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, rollbackPath, "app", item.Name)) - case "rollback_database": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, rollbackPath, "database", item.Name)) - case "rollback_website": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, rollbackPath, "website", item.Name)) - - case "cache": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, cachePath, item.Name)) - restart = true - - case "unused": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldOriginalPath)) - dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldAppBackupPath)) - dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldDownloadPath)) - files, _ := os.ReadDir(path.Join(global.CONF.System.BaseDir, oldUpgradePath)) - if len(files) == 0 { - continue - } - for _, file := range files { - if strings.HasPrefix(file.Name(), "upgrade_") { - dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldUpgradePath, file.Name())) - } - } - case "old_original": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldOriginalPath, item.Name)) - case "old_apps_bak": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldAppBackupPath, item.Name)) - case "old_download": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldDownloadPath, item.Name)) - case "old_upgrade": - if len(item.Name) == 0 { - files, _ := os.ReadDir(path.Join(global.CONF.System.BaseDir, oldUpgradePath)) - if len(files) == 0 { - continue - } - for _, file := range files { - if strings.HasPrefix(file.Name(), "upgrade_") { - dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldUpgradePath, file.Name())) - } - } - } else { - dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldUpgradePath, item.Name)) - } - - case "upload": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, uploadPath, item.Name)) - if len(item.Name) == 0 { - dropFileOrDir(path.Join(global.CONF.System.BaseDir, tmpUploadPath)) - } - case "upload_tmp": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, tmpUploadPath, item.Name)) - case "upload_app": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, uploadPath, "app", item.Name)) - case "upload_database": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, uploadPath, "database", item.Name)) - case "upload_website": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, uploadPath, "website", item.Name)) - case "upload_directory": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, uploadPath, "directory", item.Name)) - case "download": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, downloadPath, item.Name)) - case "download_app": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, downloadPath, "app", item.Name)) - case "download_database": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, downloadPath, "database", item.Name)) - case "download_website": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, downloadPath, "website", item.Name)) - case "download_directory": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, downloadPath, "directory", item.Name)) - - case "system_log": - if len(item.Name) == 0 { - files, _ := os.ReadDir(path.Join(global.CONF.System.BaseDir, logPath)) - if len(files) == 0 { - continue - } - for _, file := range files { - if file.Name() == "1Panel.log" || file.IsDir() { - continue - } - dropFileOrDir(path.Join(global.CONF.System.BaseDir, logPath, file.Name())) - } - } else { - dropFileOrDir(path.Join(global.CONF.System.BaseDir, logPath, item.Name)) - } - case "docker_log": - dropFileOrDir(path.Join(global.CONF.System.BaseDir, dockerLogPath, item.Name)) - case "task_log": - pathItem := path.Join(global.CONF.System.BaseDir, taskPath, item.Name) - dropFileOrDir(path.Join(global.CONF.System.BaseDir, taskPath, item.Name)) - if len(item.Name) == 0 { - files, _ := os.ReadDir(pathItem) - if len(files) == 0 { - continue - } - for _, file := range files { - _ = cronjobRepo.DeleteRecord(cronjobRepo.WithByRecordFile(path.Join(pathItem, file.Name()))) - } - } else { - _ = cronjobRepo.DeleteRecord(cronjobRepo.WithByRecordFile(pathItem)) - } - case "images": - dropImages() - case "containers": - dropContainers() - case "volumes": - dropVolumes() - case "build_cache": - dropBuildCache() - } - } - - _ = settingRepo.Update("LastCleanTime", time.Now().Format(constant.DateTimeLayout)) - _ = settingRepo.Update("LastCleanSize", fmt.Sprintf("%v", size)) - _ = settingRepo.Update("LastCleanData", fmt.Sprintf("%v", len(req))) - - if restart { - go func() { - _, err := cmd.Exec("systemctl restart 1panel.service") - if err != nil { - global.LOG.Errorf("restart system port failed, err: %v", err) - } - }() - } -} - -func (u *DeviceService) CleanForCronjob() (string, error) { - logs := "" - size := int64(0) - fileCount := 0 - dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, "1panel_original"), &logs, &size, &fileCount) - - upgradePath := path.Join(global.CONF.System.BaseDir, upgradePath) - upgradeFiles, _ := os.ReadDir(upgradePath) - if len(upgradeFiles) != 0 { - sort.Slice(upgradeFiles, func(i, j int) bool { - return upgradeFiles[i].Name() > upgradeFiles[j].Name() - }) - for i := 0; i < len(upgradeFiles); i++ { - if i != 0 { - dropFileOrDirWithLog(path.Join(upgradePath, upgradeFiles[i].Name()), &logs, &size, &fileCount) - } - } - } - - dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, snapshotTmpPath), &logs, &size, &fileCount) - dropFileOrDirWithLog(path.Join(global.CONF.System.Backup, "system"), &logs, &size, &fileCount) - - dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, rollbackPath, "app"), &logs, &size, &fileCount) - dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, rollbackPath, "website"), &logs, &size, &fileCount) - dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, rollbackPath, "database"), &logs, &size, &fileCount) - - dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, oldOriginalPath), &logs, &size, &fileCount) - dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, oldAppBackupPath), &logs, &size, &fileCount) - dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, oldDownloadPath), &logs, &size, &fileCount) - oldUpgradePath := path.Join(global.CONF.System.BaseDir, oldUpgradePath) - oldUpgradeFiles, _ := os.ReadDir(oldUpgradePath) - if len(oldUpgradeFiles) != 0 { - for i := 0; i < len(oldUpgradeFiles); i++ { - dropFileOrDirWithLog(path.Join(oldUpgradePath, oldUpgradeFiles[i].Name()), &logs, &size, &fileCount) - } - } - - dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, tmpUploadPath), &logs, &size, &fileCount) - dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, uploadPath), &logs, &size, &fileCount) - dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, downloadPath), &logs, &size, &fileCount) - - logPath := path.Join(global.CONF.System.BaseDir, logPath) - logFiles, _ := os.ReadDir(logPath) - if len(logFiles) != 0 { - for i := 0; i < len(logFiles); i++ { - if logFiles[i].Name() != "1Panel.log" { - dropFileOrDirWithLog(path.Join(logPath, logFiles[i].Name()), &logs, &size, &fileCount) - } - } - } - timeNow := time.Now().Format(constant.DateTimeLayout) - dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, dockerLogPath), &logs, &size, &fileCount) - logs += fmt.Sprintf("\n%s: total clean: %s, total count: %d", timeNow, common.LoadSizeUnit2F(float64(size)), fileCount) - - _ = settingRepo.Update("LastCleanTime", timeNow) - _ = settingRepo.Update("LastCleanSize", fmt.Sprintf("%v", size)) - _ = settingRepo.Update("LastCleanData", fmt.Sprintf("%v", fileCount)) - - return logs, nil -} - -func loadSnapshotTree(fileOp fileUtils.FileOp) []dto.CleanTree { - var treeData []dto.CleanTree - path1 := path.Join(global.CONF.System.BaseDir, snapshotTmpPath) - list1 := loadTreeWithAllFile(true, path1, "snapshot_tmp", path1, fileOp) - if len(list1) != 0 { - size, _ := fileOp.GetDirSize(path1) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "snapshot_tmp", Size: uint64(size), Children: list1, Type: "snapshot_tmp", IsRecommend: true}) - } - - path2 := path.Join(global.CONF.System.Backup, "system") - list2 := loadTreeWithAllFile(true, path2, "snapshot_local", path2, fileOp) - if len(list2) != 0 { - size, _ := fileOp.GetDirSize(path2) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "snapshot_local", Size: uint64(size), Children: list2, Type: "snapshot_local", IsRecommend: true}) - } - return treeData -} - -func loadRollBackTree(fileOp fileUtils.FileOp) []dto.CleanTree { - var treeData []dto.CleanTree - path1 := path.Join(global.CONF.System.BaseDir, rollbackPath, "app") - list1 := loadTreeWithAllFile(true, path1, "rollback_app", path1, fileOp) - size1, _ := fileOp.GetDirSize(path1) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "rollback_app", Size: uint64(size1), Children: list1, Type: "rollback_app", IsRecommend: true}) - - path2 := path.Join(global.CONF.System.BaseDir, rollbackPath, "website") - list2 := loadTreeWithAllFile(true, path2, "rollback_website", path2, fileOp) - size2, _ := fileOp.GetDirSize(path2) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "rollback_website", Size: uint64(size2), Children: list2, Type: "rollback_website", IsRecommend: true}) - - path3 := path.Join(global.CONF.System.BaseDir, rollbackPath, "database") - list3 := loadTreeWithAllFile(true, path3, "rollback_database", path3, fileOp) - size3, _ := fileOp.GetDirSize(path3) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "rollback_database", Size: uint64(size3), Children: list3, Type: "rollback_database", IsRecommend: true}) - - return treeData -} - -func loadUnusedFile(fileOp fileUtils.FileOp) []dto.CleanTree { - var treeData []dto.CleanTree - path1 := path.Join(global.CONF.System.BaseDir, oldOriginalPath) - list1 := loadTreeWithAllFile(true, path1, "old_original", path1, fileOp) - if len(list1) != 0 { - size, _ := fileOp.GetDirSize(path1) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "old_original", Size: uint64(size), Children: list1, Type: "old_original"}) - } - - path2 := path.Join(global.CONF.System.BaseDir, oldAppBackupPath) - list2 := loadTreeWithAllFile(true, path2, "old_apps_bak", path2, fileOp) - if len(list2) != 0 { - size, _ := fileOp.GetDirSize(path2) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "old_apps_bak", Size: uint64(size), Children: list2, Type: "old_apps_bak"}) - } - - path3 := path.Join(global.CONF.System.BaseDir, oldDownloadPath) - list3 := loadTreeWithAllFile(true, path3, "old_download", path3, fileOp) - if len(list3) != 0 { - size, _ := fileOp.GetDirSize(path3) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "old_download", Size: uint64(size), Children: list3, Type: "old_download"}) - } - - path4 := path.Join(global.CONF.System.BaseDir, oldUpgradePath) - list4 := loadTreeWithDir(true, "old_upgrade", path4, fileOp) - itemSize := uint64(0) - for _, item := range list4 { - itemSize += item.Size - } - if len(list4) != 0 { - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "old_upgrade", Size: itemSize, Children: list4, Type: "old_upgrade"}) - } - return treeData -} - -func loadUploadTree(fileOp fileUtils.FileOp) []dto.CleanTree { - var treeData []dto.CleanTree - - path0 := path.Join(global.CONF.System.BaseDir, tmpUploadPath) - list0 := loadTreeWithAllFile(true, path0, "upload_tmp", path0, fileOp) - size0, _ := fileOp.GetDirSize(path0) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "upload_tmp", Size: uint64(size0), Children: list0, Type: "upload_tmp", IsRecommend: true}) - - path1 := path.Join(global.CONF.System.BaseDir, uploadPath, "app") - list1 := loadTreeWithAllFile(true, path1, "upload_app", path1, fileOp) - size1, _ := fileOp.GetDirSize(path1) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "upload_app", Size: uint64(size1), Children: list1, Type: "upload_app", IsRecommend: true}) - - path2 := path.Join(global.CONF.System.BaseDir, uploadPath, "website") - list2 := loadTreeWithAllFile(true, path2, "upload_website", path2, fileOp) - size2, _ := fileOp.GetDirSize(path2) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "upload_website", Size: uint64(size2), Children: list2, Type: "upload_website", IsRecommend: true}) - - path3 := path.Join(global.CONF.System.BaseDir, uploadPath, "database") - list3 := loadTreeWithAllFile(true, path3, "upload_database", path3, fileOp) - size3, _ := fileOp.GetDirSize(path3) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "upload_database", Size: uint64(size3), Children: list3, Type: "upload_database", IsRecommend: true}) - - path4 := path.Join(global.CONF.System.BaseDir, uploadPath, "directory") - list4 := loadTreeWithAllFile(true, path4, "upload_directory", path4, fileOp) - size4, _ := fileOp.GetDirSize(path4) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "upload_directory", Size: uint64(size4), Children: list4, Type: "upload_directory", IsRecommend: true}) - - path5 := path.Join(global.CONF.System.BaseDir, uploadPath) - uploadTreeData := loadTreeWithAllFile(true, path5, "upload", path5, fileOp) - treeData = append(treeData, uploadTreeData...) - - return treeData -} - -func loadDownloadTree(fileOp fileUtils.FileOp) []dto.CleanTree { - var treeData []dto.CleanTree - path1 := path.Join(global.CONF.System.BaseDir, downloadPath, "app") - list1 := loadTreeWithAllFile(true, path1, "download_app", path1, fileOp) - size1, _ := fileOp.GetDirSize(path1) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "download_app", Size: uint64(size1), Children: list1, Type: "download_app", IsRecommend: true}) - - path2 := path.Join(global.CONF.System.BaseDir, downloadPath, "website") - list2 := loadTreeWithAllFile(true, path2, "download_website", path2, fileOp) - size2, _ := fileOp.GetDirSize(path2) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "download_website", Size: uint64(size2), Children: list2, Type: "download_website", IsRecommend: true}) - - path3 := path.Join(global.CONF.System.BaseDir, downloadPath, "database") - list3 := loadTreeWithAllFile(true, path3, "download_database", path3, fileOp) - size3, _ := fileOp.GetDirSize(path3) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "download_database", Size: uint64(size3), Children: list3, Type: "download_database", IsRecommend: true}) - - path4 := path.Join(global.CONF.System.BaseDir, downloadPath, "directory") - list4 := loadTreeWithAllFile(true, path4, "download_directory", path4, fileOp) - size4, _ := fileOp.GetDirSize(path4) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "download_directory", Size: uint64(size4), Children: list4, Type: "download_directory", IsRecommend: true}) - - path5 := path.Join(global.CONF.System.BaseDir, downloadPath) - uploadTreeData := loadTreeWithAllFile(true, path5, "download", path5, fileOp) - treeData = append(treeData, uploadTreeData...) - - return treeData -} - -func loadLogTree(fileOp fileUtils.FileOp) []dto.CleanTree { - var treeData []dto.CleanTree - path1 := path.Join(global.CONF.System.BaseDir, logPath) - list1 := loadTreeWithAllFile(true, path1, "system_log", path1, fileOp) - size := uint64(0) - for _, file := range list1 { - size += file.Size - } - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "system_log", Size: uint64(size), Children: list1, Type: "system_log", IsRecommend: true}) - - path2 := path.Join(global.CONF.System.BaseDir, dockerLogPath) - list2 := loadTreeWithAllFile(true, path2, "docker_log", path2, fileOp) - size2, _ := fileOp.GetDirSize(path2) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "docker_log", Size: uint64(size2), Children: list2, Type: "docker_log", IsRecommend: true}) - - path3 := path.Join(global.CONF.System.BaseDir, taskPath) - list3 := loadTreeWithAllFile(false, path3, "task_log", path3, fileOp) - size3, _ := fileOp.GetDirSize(path3) - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "task_log", Size: uint64(size3), Children: list3, Type: "task_log"}) - return treeData -} - -func loadContainerTree() []dto.CleanTree { - var treeData []dto.CleanTree - client, err := docker.NewDockerClient() - if err != nil { - return treeData - } - diskUsage, err := client.DiskUsage(context.Background(), types.DiskUsageOptions{}) - if err != nil { - return treeData - } - imageSize := uint64(0) - for _, file := range diskUsage.Images { - if file.Containers == 0 { - imageSize += uint64(file.Size) - } - } - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "container_images", Size: imageSize, Children: nil, Type: "images", IsRecommend: true}) - - containerSize := uint64(0) - for _, file := range diskUsage.Containers { - if file.State != "running" { - containerSize += uint64(file.SizeRw) - } - } - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "container_containers", Size: containerSize, Children: nil, Type: "containers", IsRecommend: true}) - - volumeSize := uint64(0) - for _, file := range diskUsage.Volumes { - if file.UsageData.RefCount <= 0 { - volumeSize += uint64(file.UsageData.Size) - } - } - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "container_volumes", Size: volumeSize, Children: nil, Type: "volumes", IsRecommend: true}) - - var buildCacheTotalSize int64 - for _, cache := range diskUsage.BuildCache { - if cache.Type == "source.local" { - buildCacheTotalSize += cache.Size - } - } - treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "build_cache", Size: uint64(buildCacheTotalSize), Type: "build_cache", IsRecommend: true}) - return treeData -} - -func loadTreeWithDir(isCheck bool, treeType, pathItem string, fileOp fileUtils.FileOp) []dto.CleanTree { - var lists []dto.CleanTree - files, err := os.ReadDir(pathItem) - if err != nil { - return lists - } - sort.Slice(files, func(i, j int) bool { - return files[i].Name() > files[j].Name() - }) - for _, file := range files { - if (treeType == "old_upgrade" || treeType == "upgrade") && !strings.HasPrefix(file.Name(), "upgrade_2023") { - continue - } - if file.IsDir() { - size, err := fileOp.GetDirSize(path.Join(pathItem, file.Name())) - if err != nil { - continue - } - item := dto.CleanTree{ - ID: uuid.NewString(), - Label: file.Name(), - Type: treeType, - Size: uint64(size), - Name: strings.TrimPrefix(file.Name(), "/"), - IsCheck: isCheck, - IsRecommend: isCheck, - } - if treeType == "upgrade" && len(lists) == 0 { - item.IsCheck = false - item.IsRecommend = false - } - lists = append(lists, item) - } - } - return lists -} - -func loadTreeWithAllFile(isCheck bool, originalPath, treeType, pathItem string, fileOp fileUtils.FileOp) []dto.CleanTree { - var lists []dto.CleanTree - - files, err := os.ReadDir(pathItem) - if err != nil { - return lists - } - for _, file := range files { - if treeType == "system_log" && (file.Name() == "1Panel.log" || file.IsDir()) { - continue - } - if (treeType == "upload" || treeType == "download") && file.IsDir() && (file.Name() == "app" || file.Name() == "database" || file.Name() == "website" || file.Name() == "directory") { - continue - } - size := uint64(0) - name := strings.TrimPrefix(path.Join(pathItem, file.Name()), originalPath+"/") - if file.IsDir() { - sizeItem, err := fileOp.GetDirSize(path.Join(pathItem, file.Name())) - if err != nil { - continue - } - size = uint64(sizeItem) - } else { - fileInfo, err := file.Info() - if err != nil { - continue - } - size = uint64(fileInfo.Size()) - } - item := dto.CleanTree{ - ID: uuid.NewString(), - Label: file.Name(), - Type: treeType, - Size: uint64(size), - Name: name, - IsCheck: isCheck, - IsRecommend: isCheck, - } - if file.IsDir() { - item.Children = loadTreeWithAllFile(isCheck, originalPath, treeType, path.Join(pathItem, file.Name()), fileOp) - } - lists = append(lists, item) - } - return lists -} - -func dropFileOrDir(itemPath string) { - global.LOG.Debugf("drop file %s", itemPath) - if err := os.RemoveAll(itemPath); err != nil { - global.LOG.Errorf("drop file %s failed, err %v", itemPath, err) - } -} - -func dropBuildCache() { - client, err := docker.NewDockerClient() - if err != nil { - global.LOG.Errorf("do not get docker client") - } - opts := types.BuildCachePruneOptions{} - opts.All = true - _, err = client.BuildCachePrune(context.Background(), opts) - if err != nil { - global.LOG.Errorf("drop build cache failed, err %v", err) - } -} - -func dropImages() { - client, err := docker.NewDockerClient() - if err != nil { - global.LOG.Errorf("do not get docker client") - } - pruneFilters := filters.NewArgs() - pruneFilters.Add("dangling", "false") - _, err = client.ImagesPrune(context.Background(), pruneFilters) - if err != nil { - global.LOG.Errorf("drop images failed, err %v", err) - } -} - -func dropContainers() { - client, err := docker.NewDockerClient() - if err != nil { - global.LOG.Errorf("do not get docker client") - } - pruneFilters := filters.NewArgs() - _, err = client.ContainersPrune(context.Background(), pruneFilters) - if err != nil { - global.LOG.Errorf("drop containers failed, err %v", err) - } -} - -func dropVolumes() { - client, err := docker.NewDockerClient() - if err != nil { - global.LOG.Errorf("do not get docker client") - } - pruneFilters := filters.NewArgs() - versions, err := client.ServerVersion(context.Background()) - if err != nil { - global.LOG.Errorf("do not get docker api versions") - } - if common.ComparePanelVersion(versions.APIVersion, "1.42") { - pruneFilters.Add("all", "true") - } - _, err = client.VolumesPrune(context.Background(), pruneFilters) - if err != nil { - global.LOG.Errorf("drop volumes failed, err %v", err) - } -} - -func dropFileOrDirWithLog(itemPath string, log *string, size *int64, count *int) { - itemSize := int64(0) - itemCount := 0 - scanFile(itemPath, &itemSize, &itemCount) - *size += itemSize - *count += itemCount - if err := os.RemoveAll(itemPath); err != nil { - global.LOG.Errorf("drop file %s failed, err %v", itemPath, err) - *log += fmt.Sprintf("- drop file %s failed, err: %v \n\n", itemPath, err) - return - } - *log += fmt.Sprintf("+ drop file %s successful!, size: %s, count: %d \n\n", itemPath, common.LoadSizeUnit2F(float64(itemSize)), itemCount) -} - -func scanFile(pathItem string, size *int64, count *int) { - files, _ := os.ReadDir(pathItem) - for _, f := range files { - if f.IsDir() { - scanFile(path.Join(pathItem, f.Name()), size, count) - } else { - fileInfo, err := f.Info() - if err != nil { - continue - } - *count++ - *size += fileInfo.Size() - } - } -} diff --git a/backend/app/service/docker.go b/backend/app/service/docker.go deleted file mode 100644 index 21418f4d1..000000000 --- a/backend/app/service/docker.go +++ /dev/null @@ -1,388 +0,0 @@ -package service - -import ( - "bufio" - "context" - "encoding/json" - "os" - "path" - "strings" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/pkg/errors" -) - -type DockerService struct{} - -type IDockerService interface { - UpdateConf(req dto.SettingUpdate) error - UpdateLogOption(req dto.LogOption) error - UpdateIpv6Option(req dto.Ipv6Option) error - UpdateConfByFile(info dto.DaemonJsonUpdateByFile) error - LoadDockerStatus() string - LoadDockerConf() *dto.DaemonJsonConf - OperateDocker(req dto.DockerOperation) error -} - -func NewIDockerService() IDockerService { - return &DockerService{} -} - -type daemonJsonItem struct { - Status string `json:"status"` - Mirrors []string `json:"registry-mirrors"` - Registries []string `json:"insecure-registries"` - LiveRestore bool `json:"live-restore"` - Ipv6 bool `json:"ipv6"` - FixedCidrV6 string `json:"fixed-cidr-v6"` - Ip6Tables bool `json:"ip6tables"` - Experimental bool `json:"experimental"` - IPTables bool `json:"iptables"` - ExecOpts []string `json:"exec-opts"` - LogOption logOption `json:"log-opts"` -} -type logOption struct { - LogMaxSize string `json:"max-size"` - LogMaxFile string `json:"max-file"` -} - -func (u *DockerService) LoadDockerStatus() string { - client, err := docker.NewDockerClient() - if err != nil { - return constant.Stopped - } - defer client.Close() - if _, err := client.Ping(context.Background()); err != nil { - return constant.Stopped - } - - return constant.StatusRunning -} - -func (u *DockerService) LoadDockerConf() *dto.DaemonJsonConf { - ctx := context.Background() - var data dto.DaemonJsonConf - data.IPTables = true - data.Status = constant.StatusRunning - data.Version = "-" - client, err := docker.NewDockerClient() - if err != nil { - data.Status = constant.Stopped - } else { - defer client.Close() - if _, err := client.Ping(ctx); err != nil { - data.Status = constant.Stopped - } - itemVersion, err := client.ServerVersion(ctx) - if err == nil { - data.Version = itemVersion.Version - } - } - data.IsSwarm = false - stdout2, _ := cmd.Exec("docker info | grep Swarm") - if string(stdout2) == " Swarm: active\n" { - data.IsSwarm = true - } - if _, err := os.Stat(constant.DaemonJsonPath); err != nil { - return &data - } - file, err := os.ReadFile(constant.DaemonJsonPath) - if err != nil { - return &data - } - var conf daemonJsonItem - daemonMap := make(map[string]interface{}) - if err := json.Unmarshal(file, &daemonMap); err != nil { - return &data - } - arr, err := json.Marshal(daemonMap) - if err != nil { - return &data - } - if err := json.Unmarshal(arr, &conf); err != nil { - return &data - } - if _, ok := daemonMap["iptables"]; !ok { - conf.IPTables = true - } - data.CgroupDriver = "cgroupfs" - for _, opt := range conf.ExecOpts { - if strings.HasPrefix(opt, "native.cgroupdriver=") { - data.CgroupDriver = strings.ReplaceAll(opt, "native.cgroupdriver=", "") - break - } - } - data.Ipv6 = conf.Ipv6 - data.FixedCidrV6 = conf.FixedCidrV6 - data.Ip6Tables = conf.Ip6Tables - data.Experimental = conf.Experimental - data.LogMaxSize = conf.LogOption.LogMaxSize - data.LogMaxFile = conf.LogOption.LogMaxFile - data.Mirrors = conf.Mirrors - data.Registries = conf.Registries - data.IPTables = conf.IPTables - data.LiveRestore = conf.LiveRestore - return &data -} - -func (u *DockerService) UpdateConf(req dto.SettingUpdate) error { - err := createIfNotExistDaemonJsonFile() - if err != nil { - return err - } - file, err := os.ReadFile(constant.DaemonJsonPath) - if err != nil { - return err - } - daemonMap := make(map[string]interface{}) - _ = json.Unmarshal(file, &daemonMap) - - switch req.Key { - case "Registries": - req.Value = strings.TrimSuffix(req.Value, ",") - if len(req.Value) == 0 { - delete(daemonMap, "insecure-registries") - } else { - daemonMap["insecure-registries"] = strings.Split(req.Value, ",") - } - case "Mirrors": - req.Value = strings.TrimSuffix(req.Value, ",") - if len(req.Value) == 0 { - delete(daemonMap, "registry-mirrors") - } else { - daemonMap["registry-mirrors"] = strings.Split(req.Value, ",") - } - case "Ipv6": - if req.Value == "disable" { - delete(daemonMap, "ipv6") - delete(daemonMap, "fixed-cidr-v6") - delete(daemonMap, "ip6tables") - delete(daemonMap, "experimental") - } - case "LogOption": - if req.Value == "disable" { - delete(daemonMap, "log-opts") - } - case "LiveRestore": - if req.Value == "disable" { - delete(daemonMap, "live-restore") - } else { - daemonMap["live-restore"] = true - } - case "IPtables": - if req.Value == "enable" { - delete(daemonMap, "iptables") - } else { - daemonMap["iptables"] = false - } - case "Driver": - if opts, ok := daemonMap["exec-opts"]; ok { - if optsValue, isArray := opts.([]interface{}); isArray { - for i := 0; i < len(optsValue); i++ { - if opt, isStr := optsValue[i].(string); isStr { - if strings.HasPrefix(opt, "native.cgroupdriver=") { - optsValue[i] = "native.cgroupdriver=" + req.Value - break - } - } - } - } - } else { - if req.Value == "systemd" { - daemonMap["exec-opts"] = []string{"native.cgroupdriver=systemd"} - } - } - } - if len(daemonMap) == 0 { - _ = os.Remove(constant.DaemonJsonPath) - return nil - } - newJson, err := json.MarshalIndent(daemonMap, "", "\t") - if err != nil { - return err - } - if err := os.WriteFile(constant.DaemonJsonPath, newJson, 0640); err != nil { - return err - } - - stdout, err := cmd.Exec("systemctl restart docker") - if err != nil { - return errors.New(string(stdout)) - } - return nil -} -func createIfNotExistDaemonJsonFile() error { - if _, err := os.Stat(constant.DaemonJsonPath); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(path.Dir(constant.DaemonJsonPath), os.ModePerm); err != nil { - return err - } - var daemonFile *os.File - daemonFile, err = os.Create(constant.DaemonJsonPath) - if err != nil { - return err - } - defer daemonFile.Close() - } - return nil -} - -func (u *DockerService) UpdateLogOption(req dto.LogOption) error { - err := createIfNotExistDaemonJsonFile() - if err != nil { - return err - } - file, err := os.ReadFile(constant.DaemonJsonPath) - if err != nil { - return err - } - daemonMap := make(map[string]interface{}) - _ = json.Unmarshal(file, &daemonMap) - - changeLogOption(daemonMap, req.LogMaxFile, req.LogMaxSize) - if len(daemonMap) == 0 { - _ = os.Remove(constant.DaemonJsonPath) - return nil - } - newJson, err := json.MarshalIndent(daemonMap, "", "\t") - if err != nil { - return err - } - if err := os.WriteFile(constant.DaemonJsonPath, newJson, 0640); err != nil { - return err - } - - stdout, err := cmd.Exec("systemctl restart docker") - if err != nil { - return errors.New(string(stdout)) - } - return nil -} - -func (u *DockerService) UpdateIpv6Option(req dto.Ipv6Option) error { - err := createIfNotExistDaemonJsonFile() - if err != nil { - return err - } - - file, err := os.ReadFile(constant.DaemonJsonPath) - if err != nil { - return err - } - daemonMap := make(map[string]interface{}) - _ = json.Unmarshal(file, &daemonMap) - - daemonMap["ipv6"] = true - daemonMap["fixed-cidr-v6"] = req.FixedCidrV6 - if req.Ip6Tables { - daemonMap["ip6tables"] = req.Ip6Tables - } - if req.Experimental { - daemonMap["experimental"] = req.Experimental - } - if len(daemonMap) == 0 { - _ = os.Remove(constant.DaemonJsonPath) - return nil - } - newJson, err := json.MarshalIndent(daemonMap, "", "\t") - if err != nil { - return err - } - if err := os.WriteFile(constant.DaemonJsonPath, newJson, 0640); err != nil { - return err - } - - stdout, err := cmd.Exec("systemctl restart docker") - if err != nil { - return errors.New(string(stdout)) - } - return nil -} - -func (u *DockerService) UpdateConfByFile(req dto.DaemonJsonUpdateByFile) error { - if len(req.File) == 0 { - _ = os.Remove(constant.DaemonJsonPath) - return nil - } - err := createIfNotExistDaemonJsonFile() - if err != nil { - return err - } - file, err := os.OpenFile(constant.DaemonJsonPath, os.O_WRONLY|os.O_TRUNC, 0640) - if err != nil { - return err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(req.File) - write.Flush() - - stdout, err := cmd.Exec("systemctl restart docker") - if err != nil { - return errors.New(string(stdout)) - } - return nil -} - -func (u *DockerService) OperateDocker(req dto.DockerOperation) error { - service := "docker" - if req.Operation == "stop" { - service = "docker.socket" - } - stdout, err := cmd.Execf("systemctl %s %s ", req.Operation, service) - if err != nil { - return errors.New(string(stdout)) - } - return nil -} - -func changeLogOption(daemonMap map[string]interface{}, logMaxFile, logMaxSize string) { - if opts, ok := daemonMap["log-opts"]; ok { - if len(logMaxFile) != 0 || len(logMaxSize) != 0 { - daemonMap["log-driver"] = "json-file" - } - optsMap, isMap := opts.(map[string]interface{}) - if isMap { - if len(logMaxFile) != 0 { - optsMap["max-file"] = logMaxFile - } else { - delete(optsMap, "max-file") - } - if len(logMaxSize) != 0 { - optsMap["max-size"] = logMaxSize - } else { - delete(optsMap, "max-size") - } - if len(optsMap) == 0 { - delete(daemonMap, "log-opts") - } - } else { - optsMap := make(map[string]interface{}) - if len(logMaxFile) != 0 { - optsMap["max-file"] = logMaxFile - } - if len(logMaxSize) != 0 { - optsMap["max-size"] = logMaxSize - } - if len(optsMap) != 0 { - daemonMap["log-opts"] = optsMap - } - } - } else { - if len(logMaxFile) != 0 || len(logMaxSize) != 0 { - daemonMap["log-driver"] = "json-file" - } - optsMap := make(map[string]interface{}) - if len(logMaxFile) != 0 { - optsMap["max-file"] = logMaxFile - } - if len(logMaxSize) != 0 { - optsMap["max-size"] = logMaxSize - } - if len(optsMap) != 0 { - daemonMap["log-opts"] = optsMap - } - } -} diff --git a/backend/app/service/entry.go b/backend/app/service/entry.go deleted file mode 100644 index 59c1d6d42..000000000 --- a/backend/app/service/entry.go +++ /dev/null @@ -1,46 +0,0 @@ -package service - -import "github.com/1Panel-dev/1Panel/backend/app/repo" - -var ( - commonRepo = repo.NewCommonRepo() - - appRepo = repo.NewIAppRepo() - appTagRepo = repo.NewIAppTagRepo() - appDetailRepo = repo.NewIAppDetailRepo() - tagRepo = repo.NewITagRepo() - appInstallRepo = repo.NewIAppInstallRepo() - appInstallResourceRepo = repo.NewIAppInstallResourceRpo() - - mysqlRepo = repo.NewIMysqlRepo() - postgresqlRepo = repo.NewIPostgresqlRepo() - databaseRepo = repo.NewIDatabaseRepo() - - imageRepoRepo = repo.NewIImageRepoRepo() - composeRepo = repo.NewIComposeTemplateRepo() - - cronjobRepo = repo.NewICronjobRepo() - - hostRepo = repo.NewIHostRepo() - groupRepo = repo.NewIGroupRepo() - commandRepo = repo.NewICommandRepo() - ftpRepo = repo.NewIFtpRepo() - clamRepo = repo.NewIClamRepo() - - settingRepo = repo.NewISettingRepo() - backupRepo = repo.NewIBackupRepo() - - websiteRepo = repo.NewIWebsiteRepo() - websiteDomainRepo = repo.NewIWebsiteDomainRepo() - websiteDnsRepo = repo.NewIWebsiteDnsAccountRepo() - websiteSSLRepo = repo.NewISSLRepo() - websiteAcmeRepo = repo.NewIAcmeAccountRepo() - websiteCARepo = repo.NewIWebsiteCARepo() - - snapshotRepo = repo.NewISnapshotRepo() - - runtimeRepo = repo.NewIRunTimeRepo() - phpExtensionsRepo = repo.NewIPHPExtensionsRepo() - - favoriteRepo = repo.NewIFavoriteRepo() -) diff --git a/backend/app/service/fail2ban.go b/backend/app/service/fail2ban.go deleted file mode 100644 index a881cd66a..000000000 --- a/backend/app/service/fail2ban.go +++ /dev/null @@ -1,251 +0,0 @@ -package service - -import ( - "bufio" - "fmt" - "os" - "strconv" - "strings" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/utils/firewall" - "github.com/1Panel-dev/1Panel/backend/utils/toolbox" -) - -const defaultFail2BanPath = "/etc/fail2ban/jail.local" - -type Fail2BanService struct{} - -type IFail2BanService interface { - LoadBaseInfo() (dto.Fail2BanBaseInfo, error) - Search(search dto.Fail2BanSearch) ([]string, error) - Operate(operation string) error - OperateSSHD(req dto.Fail2BanSet) error - UpdateConf(req dto.Fail2BanUpdate) error - UpdateConfByFile(req dto.UpdateByFile) error -} - -func NewIFail2BanService() IFail2BanService { - return &Fail2BanService{} -} - -func (u *Fail2BanService) LoadBaseInfo() (dto.Fail2BanBaseInfo, error) { - var baseInfo dto.Fail2BanBaseInfo - client, err := toolbox.NewFail2Ban() - if err != nil { - return baseInfo, err - } - baseInfo.IsEnable, baseInfo.IsActive, baseInfo.IsExist = client.Status() - if !baseInfo.IsActive { - baseInfo.Version = "-" - } else { - baseInfo.Version = client.Version() - } - conf, err := os.ReadFile(defaultFail2BanPath) - if err != nil { - if baseInfo.IsActive { - return baseInfo, fmt.Errorf("read fail2ban conf of %s failed, err: %v", defaultFail2BanPath, err) - } else { - return baseInfo, nil - } - } - lines := strings.Split(string(conf), "\n") - - block := "" - for _, line := range lines { - if strings.HasPrefix(strings.ToLower(line), "[default]") { - block = "default" - continue - } - if strings.HasPrefix(line, "[sshd]") { - block = "sshd" - continue - } - if strings.HasPrefix(line, "[") { - block = "" - continue - } - if block != "default" && block != "sshd" { - continue - } - loadFailValue(line, &baseInfo) - } - - return baseInfo, nil -} - -func (u *Fail2BanService) Search(req dto.Fail2BanSearch) ([]string, error) { - var list []string - client, err := toolbox.NewFail2Ban() - if err != nil { - return nil, err - } - if req.Status == "banned" { - list, err = client.ListBanned() - - } else { - list, err = client.ListIgnore() - } - if err != nil { - return nil, err - } - - return list, nil -} - -func (u *Fail2BanService) Operate(operation string) error { - client, err := toolbox.NewFail2Ban() - if err != nil { - return err - } - return client.Operate(operation) -} - -func (u *Fail2BanService) UpdateConf(req dto.Fail2BanUpdate) error { - if req.Key == "banaction" { - if req.Value == "firewallcmd-ipset" || req.Value == "ufw" { - itemName := "ufw" - if req.Value == "firewallcmd-ipset" { - itemName = "firewalld" - } - client, err := firewall.NewFirewallClient() - if err != nil { - return err - } - if client.Name() != itemName { - return buserr.WithName("ErrBanAction", itemName) - } - status, _ := client.Status() - if status != "running" { - return buserr.WithName("ErrBanAction", itemName) - } - } - } - if req.Key == "logpath" { - if _, err := os.Stat(req.Value); err != nil { - return err - } - } - conf, err := os.ReadFile(defaultFail2BanPath) - if err != nil { - return fmt.Errorf("read fail2ban conf of %s failed, err: %v", defaultFail2BanPath, err) - } - lines := strings.Split(string(conf), "\n") - - isStart, isEnd, hasKey := false, false, false - newFile := "" - for index, line := range lines { - if !isStart && strings.HasPrefix(line, "[sshd]") { - isStart = true - newFile += fmt.Sprintf("%s\n", line) - continue - } - if !isStart || isEnd { - newFile += fmt.Sprintf("%s\n", line) - continue - } - if strings.HasPrefix(line, req.Key) { - hasKey = true - newFile += fmt.Sprintf("%s = %s\n", req.Key, req.Value) - continue - } - if strings.HasPrefix(line, "[") || index == len(lines)-1 { - isEnd = true - if !hasKey { - newFile += fmt.Sprintf("%s = %s\n", req.Key, req.Value) - } - } - newFile += line - if index != len(lines)-1 { - newFile += "\n" - } - } - file, err := os.OpenFile(defaultFail2BanPath, os.O_WRONLY|os.O_TRUNC, 0640) - if err != nil { - return err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(newFile) - write.Flush() - - client, err := toolbox.NewFail2Ban() - if err != nil { - return err - } - if err := client.Operate("restart"); err != nil { - return err - } - return nil -} - -func (u *Fail2BanService) UpdateConfByFile(req dto.UpdateByFile) error { - file, err := os.OpenFile(defaultFail2BanPath, os.O_WRONLY|os.O_TRUNC, 0640) - if err != nil { - return err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(req.File) - write.Flush() - - client, err := toolbox.NewFail2Ban() - if err != nil { - return err - } - if err := client.Operate("restart"); err != nil { - return err - } - return nil -} - -func (u *Fail2BanService) OperateSSHD(req dto.Fail2BanSet) error { - if req.Operate == "ignore" { - if err := u.UpdateConf(dto.Fail2BanUpdate{Key: "ignoreip", Value: strings.Join(req.IPs, ",")}); err != nil { - return err - } - return nil - } - client, err := toolbox.NewFail2Ban() - if err != nil { - return err - } - if err := client.ReBanIPs(req.IPs); err != nil { - return err - } - return nil -} - -func loadFailValue(line string, baseInfo *dto.Fail2BanBaseInfo) { - if strings.HasPrefix(line, "port") { - itemValue := strings.ReplaceAll(line, "port", "") - itemValue = strings.ReplaceAll(itemValue, "=", "") - baseInfo.Port, _ = strconv.Atoi(strings.TrimSpace(itemValue)) - } - if strings.HasPrefix(line, "maxretry") { - itemValue := strings.ReplaceAll(line, "maxretry", "") - itemValue = strings.ReplaceAll(itemValue, "=", "") - baseInfo.MaxRetry, _ = strconv.Atoi(strings.TrimSpace(itemValue)) - } - if strings.HasPrefix(line, "findtime") { - itemValue := strings.ReplaceAll(line, "findtime", "") - itemValue = strings.ReplaceAll(itemValue, "=", "") - baseInfo.FindTime = strings.TrimSpace(itemValue) - } - if strings.HasPrefix(line, "bantime") { - itemValue := strings.ReplaceAll(line, "bantime", "") - itemValue = strings.ReplaceAll(itemValue, "=", "") - baseInfo.BanTime = strings.TrimSpace(itemValue) - } - if strings.HasPrefix(line, "banaction") { - itemValue := strings.ReplaceAll(line, "banaction", "") - itemValue = strings.ReplaceAll(itemValue, "=", "") - baseInfo.BanAction = strings.TrimSpace(itemValue) - } - if strings.HasPrefix(line, "logpath") { - itemValue := strings.ReplaceAll(line, "logpath", "") - itemValue = strings.ReplaceAll(itemValue, "=", "") - baseInfo.LogPath = strings.TrimSpace(itemValue) - } -} diff --git a/backend/app/service/favorite.go b/backend/app/service/favorite.go deleted file mode 100644 index 3d2ae3a90..000000000 --- a/backend/app/service/favorite.go +++ /dev/null @@ -1,83 +0,0 @@ -package service - -import ( - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/spf13/afero" -) - -type FavoriteService struct { -} - -type IFavoriteService interface { - Page(req dto.PageInfo) (int64, []response.FavoriteDTO, error) - Create(req request.FavoriteCreate) (*model.Favorite, error) - Delete(id uint) error -} - -func NewIFavoriteService() IFavoriteService { - return &FavoriteService{} -} - -func (f *FavoriteService) Page(req dto.PageInfo) (int64, []response.FavoriteDTO, error) { - total, favorites, err := favoriteRepo.Page(req.Page, req.PageSize) - if err != nil { - return 0, nil, err - } - var dtoFavorites []response.FavoriteDTO - for _, favorite := range favorites { - dtoFavorites = append(dtoFavorites, response.FavoriteDTO{ - Favorite: favorite, - }) - } - return total, dtoFavorites, nil -} - -func (f *FavoriteService) Create(req request.FavoriteCreate) (*model.Favorite, error) { - exist, _ := favoriteRepo.GetFirst(favoriteRepo.WithByPath(req.Path)) - if exist.ID > 0 { - return nil, buserr.New(constant.ErrFavoriteExist) - } - op := files.NewFileOp() - if !op.Stat(req.Path) { - return nil, buserr.New(constant.ErrLinkPathNotFound) - } - openFile, err := op.OpenFile(req.Path) - if err != nil { - return nil, err - } - fileInfo, err := openFile.Stat() - if err != nil { - return nil, err - } - favorite := &model.Favorite{ - Name: fileInfo.Name(), - IsDir: fileInfo.IsDir(), - Path: req.Path, - } - if fileInfo.Size() <= 10*1024*1024 { - afs := &afero.Afero{Fs: op.Fs} - cByte, err := afs.ReadFile(req.Path) - if err == nil { - if len(cByte) > 0 && !files.DetectBinary(cByte) { - favorite.IsTxt = true - } - } - } - if err := favoriteRepo.Create(favorite); err != nil { - return nil, err - } - return favorite, nil -} - -func (f *FavoriteService) Delete(id uint) error { - if err := favoriteRepo.Delete(commonRepo.WithByID(id)); err != nil { - return err - } - return nil -} diff --git a/backend/app/service/file.go b/backend/app/service/file.go deleted file mode 100644 index 76dced4d8..000000000 --- a/backend/app/service/file.go +++ /dev/null @@ -1,484 +0,0 @@ -package service - -import ( - "fmt" - "io" - "io/fs" - "os" - "os/exec" - "path" - "path/filepath" - "strings" - "time" - "unicode/utf8" - - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "golang.org/x/net/html/charset" - "golang.org/x/sys/unix" - "golang.org/x/text/encoding/simplifiedchinese" - "golang.org/x/text/transform" - - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/pkg/errors" -) - -type FileService struct { -} - -type IFileService interface { - GetFileList(op request.FileOption) (response.FileInfo, error) - SearchUploadWithPage(req request.SearchUploadWithPage) (int64, interface{}, error) - GetFileTree(op request.FileOption) ([]response.FileTree, error) - Create(op request.FileCreate) error - Delete(op request.FileDelete) error - BatchDelete(op request.FileBatchDelete) error - Compress(c request.FileCompress) error - DeCompress(c request.FileDeCompress) error - GetContent(op request.FileContentReq) (response.FileInfo, error) - SaveContent(edit request.FileEdit) error - FileDownload(d request.FileDownload) (string, error) - DirSize(req request.DirSizeReq) (response.DirSizeRes, error) - ChangeName(req request.FileRename) error - Wget(w request.FileWget) (string, error) - MvFile(m request.FileMove) error - ChangeOwner(req request.FileRoleUpdate) error - ChangeMode(op request.FileCreate) error - BatchChangeModeAndOwner(op request.FileRoleReq) error - ReadLogByLine(req request.FileReadByLineReq) (*response.FileLineContent, error) -} - -var filteredPaths = []string{ - "/.1panel_clash", -} - -func NewIFileService() IFileService { - return &FileService{} -} - -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) { - return fileInfo, nil - } - info, err := files.NewFileInfo(op.FileOption) - if err != nil { - return fileInfo, err - } - fileInfo.FileInfo = *info - return fileInfo, nil -} - -func (f *FileService) SearchUploadWithPage(req request.SearchUploadWithPage) (int64, interface{}, error) { - var ( - files []response.UploadInfo - backData []response.UploadInfo - ) - _ = filepath.Walk(req.Path, func(path string, info os.FileInfo, err error) error { - if err != nil { - return nil - } - if !info.IsDir() { - files = append(files, response.UploadInfo{ - CreatedAt: info.ModTime().Format(constant.DateTimeLayout), - Size: int(info.Size()), - Name: info.Name(), - }) - } - return nil - }) - total, start, end := len(files), (req.Page-1)*req.PageSize, req.Page*req.PageSize - if start > total { - backData = make([]response.UploadInfo, 0) - } else { - if end >= total { - end = total - } - backData = files[start:end] - } - return int64(total), backData, nil -} - -func (f *FileService) GetFileTree(op request.FileOption) ([]response.FileTree, error) { - var treeArray []response.FileTree - if _, err := os.Stat(op.Path); err != nil && os.IsNotExist(err) { - return treeArray, nil - } - info, err := files.NewFileInfo(op.FileOption) - if err != nil { - return nil, err - } - node := response.FileTree{ - ID: common.GetUuid(), - Name: info.Name, - Path: info.Path, - IsDir: info.IsDir, - Extension: info.Extension, - } - err = f.buildFileTree(&node, info.Items, op, 2) - if err != nil { - return nil, err - } - return append(treeArray, node), nil -} - -func shouldFilterPath(path string) bool { - cleanedPath := filepath.Clean(path) - for _, filteredPath := range filteredPaths { - cleanedFilteredPath := filepath.Clean(filteredPath) - if cleanedFilteredPath == cleanedPath || strings.HasPrefix(cleanedPath, cleanedFilteredPath+"/") { - return true - } - } - return false -} - -// 递归构建文件树(只取当前目录以及当前目录下的第一层子节点) -func (f *FileService) buildFileTree(node *response.FileTree, items []*files.FileInfo, op request.FileOption, level int) error { - for _, v := range items { - if shouldFilterPath(v.Path) { - global.LOG.Infof("File Tree: Skipping %s due to filter\n", v.Path) - continue - } - childNode := response.FileTree{ - ID: common.GetUuid(), - Name: v.Name, - Path: v.Path, - IsDir: v.IsDir, - Extension: v.Extension, - } - if level > 1 && v.IsDir { - if err := f.buildChildNode(&childNode, v, op, level); err != nil { - return err - } - } - - node.Children = append(node.Children, childNode) - } - return nil -} - -func (f *FileService) buildChildNode(childNode *response.FileTree, fileInfo *files.FileInfo, op request.FileOption, level int) error { - op.Path = fileInfo.Path - subInfo, err := files.NewFileInfo(op.FileOption) - if err != nil { - if os.IsPermission(err) || errors.Is(err, unix.EACCES) { - global.LOG.Infof("File Tree: Skipping %s due to permission denied\n", fileInfo.Path) - return nil - } - global.LOG.Errorf("File Tree: Skipping %s due to error: %s\n", fileInfo.Path, err.Error()) - return nil - } - - return f.buildFileTree(childNode, subInfo.Items, op, level-1) -} - -func (f *FileService) Create(op request.FileCreate) error { - if files.IsInvalidChar(op.Path) { - return buserr.New("ErrInvalidChar") - } - fo := files.NewFileOp() - if fo.Stat(op.Path) { - return buserr.New(constant.ErrFileIsExist) - } - mode := op.Mode - if mode == 0 { - fileInfo, err := os.Stat(filepath.Dir(op.Path)) - if err == nil { - mode = int64(fileInfo.Mode().Perm()) - } else { - mode = 0755 - } - } - if op.IsDir { - return fo.CreateDirWithMode(op.Path, fs.FileMode(mode)) - } - if op.IsLink { - if !fo.Stat(op.LinkPath) { - return buserr.New(constant.ErrLinkPathNotFound) - } - return fo.LinkFile(op.LinkPath, op.Path, op.IsSymlink) - } - return fo.CreateFileWithMode(op.Path, fs.FileMode(mode)) -} - -func (f *FileService) Delete(op request.FileDelete) error { - fo := files.NewFileOp() - recycleBinStatus, _ := settingRepo.Get(settingRepo.WithByKey("FileRecycleBin")) - if recycleBinStatus.Value == "disable" { - op.ForceDelete = true - } - if op.ForceDelete { - if op.IsDir { - return fo.DeleteDir(op.Path) - } else { - return fo.DeleteFile(op.Path) - } - } - if err := NewIRecycleBinService().Create(request.RecycleBinCreate{SourcePath: op.Path}); err != nil { - return err - } - return favoriteRepo.Delete(favoriteRepo.WithByPath(op.Path)) -} - -func (f *FileService) BatchDelete(op request.FileBatchDelete) error { - fo := files.NewFileOp() - if op.IsDir { - for _, file := range op.Paths { - if err := fo.DeleteDir(file); err != nil { - return err - } - } - } else { - for _, file := range op.Paths { - if err := fo.DeleteFile(file); err != nil { - return err - } - } - } - return nil -} - -func (f *FileService) ChangeMode(op request.FileCreate) error { - fo := files.NewFileOp() - return fo.ChmodR(op.Path, op.Mode, op.Sub) -} - -func (f *FileService) BatchChangeModeAndOwner(op request.FileRoleReq) error { - fo := files.NewFileOp() - for _, path := range op.Paths { - if !fo.Stat(path) { - return buserr.New(constant.ErrPathNotFound) - } - if err := fo.ChownR(path, op.User, op.Group, op.Sub); err != nil { - return err - } - if err := fo.ChmodR(path, op.Mode, op.Sub); err != nil { - return err - } - } - return nil - -} - -func (f *FileService) ChangeOwner(req request.FileRoleUpdate) error { - fo := files.NewFileOp() - return fo.ChownR(req.Path, req.User, req.Group, req.Sub) -} - -func (f *FileService) Compress(c request.FileCompress) error { - fo := files.NewFileOp() - if !c.Replace && fo.Stat(filepath.Join(c.Dst, c.Name)) { - return buserr.New(constant.ErrFileIsExist) - } - return fo.Compress(c.Files, c.Dst, c.Name, files.CompressType(c.Type), c.Secret) -} - -func (f *FileService) DeCompress(c request.FileDeCompress) error { - fo := files.NewFileOp() - if c.Type == "tar" && len(c.Secret) != 0 { - c.Type = "tar.gz" - } - return fo.Decompress(c.Path, c.Dst, files.CompressType(c.Type), c.Secret) -} - -func (f *FileService) GetContent(op request.FileContentReq) (response.FileInfo, error) { - info, err := files.NewFileInfo(files.FileOption{ - Path: op.Path, - Expand: true, - IsDetail: op.IsDetail, - }) - if err != nil { - return response.FileInfo{}, err - } - - content := []byte(info.Content) - if len(content) > 1024 { - content = content[:1024] - } - if !utf8.Valid(content) { - _, decodeName, _ := charset.DetermineEncoding(content, "") - if decodeName == "windows-1252" { - reader := strings.NewReader(info.Content) - item := transform.NewReader(reader, simplifiedchinese.GBK.NewDecoder()) - contents, err := io.ReadAll(item) - if err != nil { - return response.FileInfo{}, err - } - info.Content = string(contents) - } - } - return response.FileInfo{FileInfo: *info}, nil -} - -func (f *FileService) SaveContent(edit request.FileEdit) error { - info, err := files.NewFileInfo(files.FileOption{ - Path: edit.Path, - Expand: false, - }) - if err != nil { - return err - } - - fo := files.NewFileOp() - return fo.WriteFile(edit.Path, strings.NewReader(edit.Content), info.FileMode) -} - -func (f *FileService) ChangeName(req request.FileRename) error { - if files.IsInvalidChar(req.NewName) { - return buserr.New("ErrInvalidChar") - } - fo := files.NewFileOp() - return fo.Rename(req.OldName, req.NewName) -} - -func (f *FileService) Wget(w request.FileWget) (string, error) { - fo := files.NewFileOp() - key := "file-wget-" + common.GetUuid() - return key, fo.DownloadFileWithProcess(w.Url, filepath.Join(w.Path, w.Name), key, w.IgnoreCertificate) -} - -func (f *FileService) MvFile(m request.FileMove) error { - fo := files.NewFileOp() - if !fo.Stat(m.NewPath) { - return buserr.New(constant.ErrPathNotFound) - } - for _, oldPath := range m.OldPaths { - if !fo.Stat(oldPath) { - return buserr.WithName(constant.ErrFileNotFound, oldPath) - } - if oldPath == m.NewPath || strings.Contains(m.NewPath, filepath.Clean(oldPath)+"/") { - return buserr.New(constant.ErrMovePathFailed) - } - } - if m.Type == "cut" { - return fo.Cut(m.OldPaths, m.NewPath, m.Name, m.Cover) - } - var errs []error - if m.Type == "copy" { - for _, src := range m.OldPaths { - if err := fo.CopyAndReName(src, m.NewPath, m.Name, m.Cover); err != nil { - errs = append(errs, err) - global.LOG.Errorf("copy file [%s] to [%s] failed, err: %s", src, m.NewPath, err.Error()) - } - } - } - - var errString string - for _, err := range errs { - errString += err.Error() + "\n" - } - if errString != "" { - return errors.New(errString) - } - return nil -} - -func (f *FileService) FileDownload(d request.FileDownload) (string, error) { - filePath := d.Paths[0] - if d.Compress { - tempPath := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().UnixNano())) - if err := os.MkdirAll(tempPath, os.ModePerm); err != nil { - return "", err - } - fo := files.NewFileOp() - if err := fo.Compress(d.Paths, tempPath, d.Name, files.CompressType(d.Type), ""); err != nil { - return "", err - } - filePath = filepath.Join(tempPath, d.Name) - } - return filePath, nil -} - -func (f *FileService) DirSize(req request.DirSizeReq) (response.DirSizeRes, error) { - var ( - res response.DirSizeRes - ) - if req.Path == "/proc" { - return res, nil - } - cmd := exec.Command("du", "-s", req.Path) - output, err := cmd.Output() - if err == nil { - fields := strings.Fields(string(output)) - if len(fields) == 2 { - var cmdSize int64 - _, err = fmt.Sscanf(fields[0], "%d", &cmdSize) - if err == nil { - res.Size = float64(cmdSize * 1024) - return res, nil - } - } - } - fo := files.NewFileOp() - size, err := fo.GetDirSize(req.Path) - if err != nil { - return res, err - } - res.Size = size - return res, nil -} - -func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.FileLineContent, error) { - logFilePath := "" - switch req.Type { - case constant.TypeWebsite: - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return nil, err - } - nginx, err := getNginxFull(&website) - if err != nil { - return nil, err - } - sitePath := path.Join(nginx.SiteDir, "sites", website.Alias) - logFilePath = path.Join(sitePath, "log", req.Name) - case constant.TypePhp: - php, err := runtimeRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return nil, err - } - logFilePath = php.GetLogPath() - case constant.TypeSSL: - ssl, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return nil, err - } - logFilePath = ssl.GetLogPath() - case constant.TypeSystem: - fileName := "" - if len(req.Name) == 0 || req.Name == time.Now().Format("2006-01-02") { - fileName = "1Panel.log" - } else { - fileName = "1Panel-" + req.Name + ".log" - } - logFilePath = path.Join(global.CONF.System.DataDir, "log", fileName) - if _, err := os.Stat(logFilePath); err != nil { - fileGzPath := path.Join(global.CONF.System.DataDir, "log", fileName+".gz") - if _, err := os.Stat(fileGzPath); err != nil { - return nil, buserr.New("ErrHttpReqNotFound") - } - if err := handleGunzip(fileGzPath); err != nil { - return nil, fmt.Errorf("handle ungzip file %s failed, err: %v", fileGzPath, err) - } - } - case "image-pull", "image-push", "image-build", "compose-create": - logFilePath = path.Join(global.CONF.System.TmpDir, fmt.Sprintf("docker_logs/%s", req.Name)) - } - - lines, isEndOfFile, total, err := files.ReadFileByLine(logFilePath, req.Page, req.PageSize, req.Latest) - if err != nil { - return nil, err - } - res := &response.FileLineContent{ - Content: strings.Join(lines, "\n"), - End: isEndOfFile, - Path: logFilePath, - Total: total, - } - return res, nil -} diff --git a/backend/app/service/firewall.go b/backend/app/service/firewall.go deleted file mode 100644 index b5a45860a..000000000 --- a/backend/app/service/firewall.go +++ /dev/null @@ -1,694 +0,0 @@ -package service - -import ( - "fmt" - "os" - "sort" - "strconv" - "strings" - "sync" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/firewall" - fireClient "github.com/1Panel-dev/1Panel/backend/utils/firewall/client" - "github.com/jinzhu/copier" - "github.com/pkg/errors" -) - -const confPath = "/etc/sysctl.conf" - -type FirewallService struct{} - -type IFirewallService interface { - LoadBaseInfo() (dto.FirewallBaseInfo, error) - SearchWithPage(search dto.RuleSearch) (int64, interface{}, error) - OperateFirewall(operation string) error - OperatePortRule(req dto.PortRuleOperate, reload bool) error - OperateForwardRule(req dto.ForwardRuleOperate) error - OperateAddressRule(req dto.AddrRuleOperate, reload bool) error - UpdatePortRule(req dto.PortRuleUpdate) error - UpdateAddrRule(req dto.AddrRuleUpdate) error - UpdateDescription(req dto.UpdateFirewallDescription) error - BatchOperateRule(req dto.BatchRuleOperate) error -} - -func NewIFirewallService() IFirewallService { - return &FirewallService{} -} - -func (u *FirewallService) LoadBaseInfo() (dto.FirewallBaseInfo, error) { - var baseInfo dto.FirewallBaseInfo - baseInfo.Status = "not running" - baseInfo.Version = "-" - baseInfo.Name = "-" - client, err := firewall.NewFirewallClient() - if err != nil { - return baseInfo, err - } - baseInfo.Name = client.Name() - - var wg sync.WaitGroup - wg.Add(3) - go func() { - defer wg.Done() - baseInfo.PingStatus = u.pingStatus() - }() - go func() { - defer wg.Done() - baseInfo.Status, _ = client.Status() - }() - go func() { - defer wg.Done() - baseInfo.Version, _ = client.Version() - }() - wg.Wait() - return baseInfo, nil -} - -func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{}, error) { - var ( - datas []fireClient.FireInfo - backDatas []fireClient.FireInfo - ) - - client, err := firewall.NewFirewallClient() - if err != nil { - return 0, nil, err - } - - var rules []fireClient.FireInfo - switch req.Type { - case "port": - rules, err = client.ListPort() - case "forward": - rules, err = client.ListForward() - case "address": - rules, err = client.ListAddress() - } - if err != nil { - return 0, nil, err - } - - if len(req.Info) != 0 { - for _, addr := range rules { - if strings.Contains(addr.Address, req.Info) || - strings.Contains(addr.Port, req.Info) || - strings.Contains(addr.TargetPort, req.Info) || - strings.Contains(addr.TargetIP, req.Info) { - datas = append(datas, addr) - } - } - } else { - datas = rules - } - if req.Type == "port" { - apps := u.loadPortByApp() - for i := 0; i < len(datas); i++ { - datas[i].UsedStatus = checkPortUsed(datas[i].Port, datas[i].Protocol, apps) - } - } - - var datasFilterStatus []fireClient.FireInfo - if len(req.Status) != 0 { - for _, data := range datas { - if req.Status == "free" && len(data.UsedStatus) == 0 { - datasFilterStatus = append(datasFilterStatus, data) - } - if req.Status == "used" && len(data.UsedStatus) != 0 { - datasFilterStatus = append(datasFilterStatus, data) - } - } - } else { - datasFilterStatus = datas - } - - var datasFilterStrategy []fireClient.FireInfo - if len(req.Strategy) != 0 { - for _, data := range datasFilterStatus { - if req.Strategy == data.Strategy { - datasFilterStrategy = append(datasFilterStrategy, data) - } - } - } else { - datasFilterStrategy = datasFilterStatus - } - - total, start, end := len(datasFilterStrategy), (req.Page-1)*req.PageSize, req.Page*req.PageSize - if start > total { - backDatas = make([]fireClient.FireInfo, 0) - } else { - if end >= total { - end = total - } - backDatas = datasFilterStrategy[start:end] - } - - datasFromDB, _ := hostRepo.ListFirewallRecord() - for i := 0; i < len(backDatas); i++ { - for _, des := range datasFromDB { - if req.Type != des.Type { - continue - } - if backDatas[i].Port == des.Port && - req.Type == "port" && - backDatas[i].Protocol == des.Protocol && - backDatas[i].Strategy == des.Strategy && - backDatas[i].Address == des.Address { - backDatas[i].Description = des.Description - break - } - if req.Type == "address" && backDatas[i].Strategy == des.Strategy && backDatas[i].Address == des.Address { - backDatas[i].Description = des.Description - break - } - } - } - - go u.cleanUnUsedData(client) - - return int64(total), backDatas, nil -} - -func (u *FirewallService) OperateFirewall(operation string) error { - client, err := firewall.NewFirewallClient() - if err != nil { - return err - } - switch operation { - case "start": - if err := client.Start(); err != nil { - return err - } - if err := u.addPortsBeforeStart(client); err != nil { - _ = client.Stop() - return err - } - _, _ = cmd.Exec("systemctl restart docker") - return nil - case "stop": - if err := client.Stop(); err != nil { - return err - } - _, _ = cmd.Exec("systemctl restart docker") - return nil - case "restart": - if err := client.Restart(); err != nil { - return err - } - _, _ = cmd.Exec("systemctl restart docker") - return nil - case "disablePing": - return u.updatePingStatus("0") - case "enablePing": - return u.updatePingStatus("1") - } - return fmt.Errorf("not support such operation: %s", operation) -} - -func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool) error { - client, err := firewall.NewFirewallClient() - if err != nil { - return err - } - protos := strings.Split(req.Protocol, "/") - itemAddress := strings.Split(strings.TrimSuffix(req.Address, ","), ",") - - if client.Name() == "ufw" { - if strings.Contains(req.Port, ",") || strings.Contains(req.Port, "-") { - for _, proto := range protos { - for _, addr := range itemAddress { - if len(addr) == 0 { - addr = "Anywhere" - } - req.Address = addr - req.Port = strings.ReplaceAll(req.Port, "-", ":") - req.Protocol = proto - if err := u.operatePort(client, req); err != nil { - return err - } - req.Port = strings.ReplaceAll(req.Port, ":", "-") - if err := u.addPortRecord(req); err != nil { - return err - } - } - } - return nil - } - for _, addr := range itemAddress { - if len(addr) == 0 { - addr = "Anywhere" - } - if req.Protocol == "tcp/udp" { - req.Protocol = "" - } - req.Address = addr - if err := u.operatePort(client, req); err != nil { - return err - } - if len(req.Protocol) == 0 { - req.Protocol = "tcp/udp" - } - if err := u.addPortRecord(req); err != nil { - return err - } - } - return nil - } - - itemPorts := req.Port - for _, proto := range protos { - if strings.Contains(req.Port, "-") { - for _, addr := range itemAddress { - req.Protocol = proto - req.Address = addr - if err := u.operatePort(client, req); err != nil { - return err - } - if err := u.addPortRecord(req); err != nil { - return err - } - } - } else { - ports := strings.Split(itemPorts, ",") - for _, port := range ports { - if len(port) == 0 { - continue - } - for _, addr := range itemAddress { - req.Address = addr - req.Port = port - req.Protocol = proto - if err := u.operatePort(client, req); err != nil { - return err - } - if err := u.addPortRecord(req); err != nil { - return err - } - } - } - } - } - - if reload { - return client.Reload() - } - return nil -} - -func (u *FirewallService) OperateForwardRule(req dto.ForwardRuleOperate) error { - client, err := firewall.NewFirewallClient() - if err != nil { - return err - } - - rules, _ := client.ListForward() - for _, rule := range rules { - for _, reqRule := range req.Rules { - if reqRule.Operation == "remove" { - continue - } - if reqRule.TargetIP == "" { - reqRule.TargetIP = "127.0.0.1" - } - if reqRule.Port == rule.Port && reqRule.TargetPort == rule.TargetPort && reqRule.TargetIP == rule.TargetIP { - return constant.ErrRecordExist - } - } - } - - sort.SliceStable(req.Rules, func(i, j int) bool { - n1, _ := strconv.Atoi(req.Rules[i].Num) - n2, _ := strconv.Atoi(req.Rules[j].Num) - return n1 > n2 - }) - - for _, r := range req.Rules { - for _, p := range strings.Split(r.Protocol, "/") { - if r.TargetIP == "" { - r.TargetIP = "127.0.0.1" - } - if err = client.PortForward(fireClient.Forward{ - Num: r.Num, - Protocol: p, - Port: r.Port, - TargetIP: r.TargetIP, - TargetPort: r.TargetPort, - }, r.Operation); err != nil { - return err - } - } - } - return nil -} - -func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate, reload bool) error { - client, err := firewall.NewFirewallClient() - if err != nil { - return err - } - - var fireInfo fireClient.FireInfo - if err := copier.Copy(&fireInfo, &req); err != nil { - return err - } - - addressList := strings.Split(req.Address, ",") - for i := 0; i < len(addressList); i++ { - if len(addressList[i]) == 0 { - continue - } - fireInfo.Address = addressList[i] - if err := client.RichRules(fireInfo, req.Operation); err != nil { - return err - } - req.Address = addressList[i] - if err := u.addAddressRecord(req); err != nil { - return err - } - } - if reload { - return client.Reload() - } - return nil -} - -func (u *FirewallService) UpdatePortRule(req dto.PortRuleUpdate) error { - client, err := firewall.NewFirewallClient() - if err != nil { - return err - } - if err := u.OperatePortRule(req.OldRule, false); err != nil { - return err - } - if err := u.OperatePortRule(req.NewRule, false); err != nil { - return err - } - return client.Reload() -} - -func (u *FirewallService) UpdateAddrRule(req dto.AddrRuleUpdate) error { - client, err := firewall.NewFirewallClient() - if err != nil { - return err - } - if err := u.OperateAddressRule(req.OldRule, false); err != nil { - return err - } - if err := u.OperateAddressRule(req.NewRule, false); err != nil { - return err - } - return client.Reload() -} - -func (u *FirewallService) UpdateDescription(req dto.UpdateFirewallDescription) error { - var firewall model.Firewall - if err := copier.Copy(&firewall, &req); err != nil { - return errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - return hostRepo.SaveFirewallRecord(&firewall) -} - -func (u *FirewallService) BatchOperateRule(req dto.BatchRuleOperate) error { - client, err := firewall.NewFirewallClient() - if err != nil { - return err - } - if req.Type == "port" { - for _, rule := range req.Rules { - _ = u.OperatePortRule(rule, false) - } - return client.Reload() - } - for _, rule := range req.Rules { - itemRule := dto.AddrRuleOperate{Operation: rule.Operation, Address: rule.Address, Strategy: rule.Strategy} - _ = u.OperateAddressRule(itemRule, false) - } - return client.Reload() -} - -func OperateFirewallPort(oldPorts, newPorts []int) error { - client, err := firewall.NewFirewallClient() - if err != nil { - return err - } - for _, port := range newPorts { - if err := client.Port(fireClient.FireInfo{Port: strconv.Itoa(port), Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { - return err - } - } - for _, port := range oldPorts { - if err := client.Port(fireClient.FireInfo{Port: strconv.Itoa(port), Protocol: "tcp", Strategy: "accept"}, "remove"); err != nil { - return err - } - } - return client.Reload() -} - -func (u *FirewallService) operatePort(client firewall.FirewallClient, req dto.PortRuleOperate) error { - var fireInfo fireClient.FireInfo - if err := copier.Copy(&fireInfo, &req); err != nil { - return err - } - - if client.Name() == "ufw" { - if len(fireInfo.Address) != 0 && !strings.EqualFold(fireInfo.Address, "Anywhere") { - return client.RichRules(fireInfo, req.Operation) - } - return client.Port(fireInfo, req.Operation) - } - - if len(fireInfo.Address) != 0 || fireInfo.Strategy == "drop" { - return client.RichRules(fireInfo, req.Operation) - } - return client.Port(fireInfo, req.Operation) -} - -type portOfApp struct { - AppName string - HttpPort string - HttpsPort string -} - -func (u *FirewallService) loadPortByApp() []portOfApp { - var datas []portOfApp - apps, err := appInstallRepo.ListBy() - if err != nil { - return datas - } - for i := 0; i < len(apps); i++ { - datas = append(datas, portOfApp{ - AppName: apps[i].App.Key, - HttpPort: strconv.Itoa(apps[i].HttpPort), - HttpsPort: strconv.Itoa(apps[i].HttpsPort), - }) - } - systemPort, err := settingRepo.Get(settingRepo.WithByKey("ServerPort")) - if err != nil { - return datas - } - datas = append(datas, portOfApp{AppName: "1panel", HttpPort: systemPort.Value}) - - return datas -} - -func (u *FirewallService) cleanUnUsedData(client firewall.FirewallClient) { - list, _ := client.ListPort() - addressList, _ := client.ListAddress() - list = append(list, addressList...) - if len(list) == 0 { - return - } - records, _ := hostRepo.ListFirewallRecord() - if len(records) == 0 { - return - } - for _, item := range list { - for i := 0; i < len(records); i++ { - if records[i].Port == item.Port && records[i].Protocol == item.Protocol && records[i].Strategy == item.Strategy && records[i].Address == item.Address { - records = append(records[:i], records[i+1:]...) - } - } - } - - for _, record := range records { - _ = hostRepo.DeleteFirewallRecordByID(record.ID) - } -} -func (u *FirewallService) pingStatus() string { - if _, err := os.Stat("/etc/sysctl.conf"); err != nil { - return constant.StatusNone - } - sudo := cmd.SudoHandleCmd() - command := fmt.Sprintf("%s cat /etc/sysctl.conf | grep net/ipv4/icmp_echo_ignore_all= ", sudo) - stdout, _ := cmd.Exec(command) - if stdout == "net/ipv4/icmp_echo_ignore_all=1\n" { - return constant.StatusEnable - } - return constant.StatusDisable -} - -func (u *FirewallService) updatePingStatus(enable string) error { - lineBytes, err := os.ReadFile(confPath) - if err != nil { - return err - } - files := strings.Split(string(lineBytes), "\n") - var newFiles []string - hasLine := false - for _, line := range files { - if strings.Contains(line, "net/ipv4/icmp_echo_ignore_all") || strings.HasPrefix(line, "net/ipv4/icmp_echo_ignore_all") { - newFiles = append(newFiles, "net/ipv4/icmp_echo_ignore_all="+enable) - hasLine = true - } else { - newFiles = append(newFiles, line) - } - } - if !hasLine { - newFiles = append(newFiles, "net/ipv4/icmp_echo_ignore_all="+enable) - } - file, err := os.OpenFile(confPath, os.O_WRONLY|os.O_TRUNC, 0666) - if err != nil { - return err - } - defer file.Close() - _, err = file.WriteString(strings.Join(newFiles, "\n")) - if err != nil { - return err - } - - sudo := cmd.SudoHandleCmd() - command := fmt.Sprintf("%s sysctl -p", sudo) - stdout, err := cmd.Exec(command) - if err != nil { - return fmt.Errorf("update ping status failed, err: %v", stdout) - } - - return nil -} - -func (u *FirewallService) addPortsBeforeStart(client firewall.FirewallClient) error { - serverPort, err := settingRepo.Get(settingRepo.WithByKey("ServerPort")) - if err != nil { - return err - } - if err := client.Port(fireClient.FireInfo{Port: serverPort.Value, Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { - return err - } - if err := client.Port(fireClient.FireInfo{Port: "22", Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { - return err - } - if err := client.Port(fireClient.FireInfo{Port: "80", Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { - return err - } - if err := client.Port(fireClient.FireInfo{Port: "443", Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { - return err - } - apps := u.loadPortByApp() - for _, app := range apps { - if len(app.HttpPort) != 0 && app.HttpPort != "0" { - if err := client.Port(fireClient.FireInfo{Port: app.HttpPort, Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { - return err - } - } - } - - return client.Reload() -} - -func (u *FirewallService) addPortRecord(req dto.PortRuleOperate) error { - if req.Operation == "remove" { - return hostRepo.DeleteFirewallRecord("port", req.Port, req.Protocol, req.Address, req.Strategy) - } - - if err := hostRepo.SaveFirewallRecord(&model.Firewall{ - Type: "port", - Port: req.Port, - Protocol: req.Protocol, - Address: req.Address, - Strategy: req.Strategy, - Description: req.Description, - }); err != nil { - return fmt.Errorf("add record %s/%s failed (strategy: %s, address: %s), err: %v", req.Port, req.Protocol, req.Strategy, req.Address, err) - } - - return nil -} - -func (u *FirewallService) addAddressRecord(req dto.AddrRuleOperate) error { - if req.Operation == "remove" { - return hostRepo.DeleteFirewallRecord("address", "", "", req.Address, req.Strategy) - } - if err := hostRepo.SaveFirewallRecord(&model.Firewall{ - Type: "address", - Address: req.Address, - Strategy: req.Strategy, - Description: req.Description, - }); err != nil { - return fmt.Errorf("add record failed (strategy: %s, address: %s), err: %v", req.Strategy, req.Address, err) - } - return nil -} - -func checkPortUsed(ports, proto string, apps []portOfApp) string { - var portList []int - if strings.Contains(ports, "-") || strings.Contains(ports, ",") { - if strings.Contains(ports, "-") { - port1, err := strconv.Atoi(strings.Split(ports, "-")[0]) - if err != nil { - global.LOG.Errorf(" convert string %s to int failed, err: %v", strings.Split(ports, "-")[0], err) - return "" - } - port2, err := strconv.Atoi(strings.Split(ports, "-")[1]) - if err != nil { - global.LOG.Errorf(" convert string %s to int failed, err: %v", strings.Split(ports, "-")[1], err) - return "" - } - for i := port1; i <= port2; i++ { - portList = append(portList, i) - } - } else { - portLists := strings.Split(ports, ",") - for _, item := range portLists { - portItem, _ := strconv.Atoi(item) - portList = append(portList, portItem) - } - } - - var usedPorts []string - for _, port := range portList { - portItem := fmt.Sprintf("%v", port) - isUsedByApp := false - for _, app := range apps { - if app.HttpPort == portItem || app.HttpsPort == portItem { - isUsedByApp = true - usedPorts = append(usedPorts, fmt.Sprintf("%s (%s)", portItem, app.AppName)) - break - } - } - if !isUsedByApp && common.ScanPortWithProto(port, proto) { - usedPorts = append(usedPorts, fmt.Sprintf("%v", port)) - } - } - return strings.Join(usedPorts, ",") - } - - for _, app := range apps { - if app.HttpPort == ports || app.HttpsPort == ports { - return fmt.Sprintf("(%s)", app.AppName) - } - } - port, err := strconv.Atoi(ports) - if err != nil { - global.LOG.Errorf(" convert string %v to int failed, err: %v", port, err) - return "" - } - if common.ScanPortWithProto(port, proto) { - return "inUsed" - } - return "" -} diff --git a/backend/app/service/ftp.go b/backend/app/service/ftp.go deleted file mode 100644 index bd9048afd..000000000 --- a/backend/app/service/ftp.go +++ /dev/null @@ -1,245 +0,0 @@ -package service - -import ( - "os" - "sort" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/encrypt" - "github.com/1Panel-dev/1Panel/backend/utils/toolbox" - "github.com/jinzhu/copier" - "github.com/pkg/errors" -) - -type FtpService struct{} - -type IFtpService interface { - LoadBaseInfo() (dto.FtpBaseInfo, error) - SearchWithPage(search dto.SearchWithPage) (int64, interface{}, error) - Operate(operation string) error - Create(req dto.FtpCreate) (uint, error) - Delete(req dto.BatchDeleteReq) error - Update(req dto.FtpUpdate) error - Sync() error - LoadLog(req dto.FtpLogSearch) (int64, interface{}, error) -} - -func NewIFtpService() IFtpService { - return &FtpService{} -} - -func (f *FtpService) LoadBaseInfo() (dto.FtpBaseInfo, error) { - var baseInfo dto.FtpBaseInfo - client, err := toolbox.NewFtpClient() - if err != nil { - return baseInfo, err - } - baseInfo.IsActive, baseInfo.IsExist = client.Status() - return baseInfo, nil -} - -func (f *FtpService) LoadLog(req dto.FtpLogSearch) (int64, interface{}, error) { - client, err := toolbox.NewFtpClient() - if err != nil { - return 0, nil, err - } - logItem, err := client.LoadLogs(req.User, req.Operation) - if err != nil { - return 0, nil, err - } - sort.Slice(logItem, func(i, j int) bool { - return logItem[i].Time > logItem[j].Time - }) - var logs []toolbox.FtpLog - total, start, end := len(logItem), (req.Page-1)*req.PageSize, req.Page*req.PageSize - if start > total { - logs = make([]toolbox.FtpLog, 0) - } else { - if end >= total { - end = total - } - logs = logItem[start:end] - } - return int64(total), logs, nil -} - -func (u *FtpService) Operate(operation string) error { - client, err := toolbox.NewFtpClient() - if err != nil { - return err - } - return client.Operate(operation) -} - -func (f *FtpService) SearchWithPage(req dto.SearchWithPage) (int64, interface{}, error) { - total, lists, err := ftpRepo.Page(req.Page, req.PageSize, ftpRepo.WithByUser(req.Info), commonRepo.WithOrderBy("created_at desc")) - if err != nil { - return 0, nil, err - } - var users []dto.FtpInfo - for _, user := range lists { - var item dto.FtpInfo - if err := copier.Copy(&item, &user); err != nil { - return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - item.Password, _ = encrypt.StringDecrypt(item.Password) - users = append(users, item) - } - return total, users, err -} - -func (f *FtpService) Sync() error { - client, err := toolbox.NewFtpClient() - if err != nil { - return err - } - lists, err := client.LoadList() - if err != nil { - return nil - } - listsInDB, err := ftpRepo.GetList() - if err != nil { - return err - } - sameData := make(map[string]struct{}) - for _, item := range lists { - for _, itemInDB := range listsInDB { - if item.User == itemInDB.User { - sameData[item.User] = struct{}{} - if item.Path != itemInDB.Path || item.Status != itemInDB.Status { - _ = ftpRepo.Update(itemInDB.ID, map[string]interface{}{"path": item.Path, "status": item.Status}) - } - break - } - } - } - for _, item := range lists { - if _, ok := sameData[item.User]; !ok { - _ = ftpRepo.Create(&model.Ftp{User: item.User, Path: item.Path, Status: item.Status}) - } - } - for _, item := range listsInDB { - if _, ok := sameData[item.User]; !ok { - _ = ftpRepo.Update(item.ID, map[string]interface{}{"status": "deleted"}) - } - } - return nil -} - -func (f *FtpService) Create(req dto.FtpCreate) (uint, error) { - if _, err := os.Stat(req.Path); err != nil { - if os.IsNotExist(err) { - if err := os.MkdirAll(req.Path, os.ModePerm); err != nil { - return 0, err - } - } else { - return 0, err - } - } - pass, err := encrypt.StringEncrypt(req.Password) - if err != nil { - return 0, err - } - userInDB, _ := ftpRepo.Get(hostRepo.WithByUser(req.User)) - if userInDB.ID != 0 { - return 0, constant.ErrRecordExist - } - client, err := toolbox.NewFtpClient() - if err != nil { - return 0, err - } - if err := client.UserAdd(req.User, req.Password, req.Path); err != nil { - return 0, err - } - var ftp model.Ftp - if err := copier.Copy(&ftp, &req); err != nil { - return 0, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - ftp.Status = constant.StatusEnable - ftp.Password = pass - if err := ftpRepo.Create(&ftp); err != nil { - return 0, err - } - return ftp.ID, nil -} - -func (f *FtpService) Delete(req dto.BatchDeleteReq) error { - client, err := toolbox.NewFtpClient() - if err != nil { - return err - } - for _, id := range req.Ids { - ftpItem, err := ftpRepo.Get(commonRepo.WithByID(id)) - if err != nil { - return err - } - _ = client.UserDel(ftpItem.User) - _ = ftpRepo.Delete(commonRepo.WithByID(id)) - } - return nil -} - -func (f *FtpService) Update(req dto.FtpUpdate) error { - if _, err := os.Stat(req.Path); err != nil { - if os.IsNotExist(err) { - if err := os.MkdirAll(req.Path, os.ModePerm); err != nil { - return err - } - } else { - return err - } - } - - pass, err := encrypt.StringEncrypt(req.Password) - if err != nil { - return err - } - ftpItem, _ := ftpRepo.Get(commonRepo.WithByID(req.ID)) - if ftpItem.ID == 0 { - return constant.ErrRecordNotFound - } - passItem, err := encrypt.StringDecrypt(ftpItem.Password) - if err != nil { - return err - } - - client, err := toolbox.NewFtpClient() - if err != nil { - return err - } - needReload := false - updates := make(map[string]interface{}) - if req.Password != passItem { - if err := client.SetPasswd(ftpItem.User, req.Password); err != nil { - return err - } - updates["password"] = pass - needReload = true - } - if req.Status != ftpItem.Status { - if err := client.SetStatus(ftpItem.User, req.Status); err != nil { - return err - } - updates["status"] = req.Status - needReload = true - } - if req.Path != ftpItem.Path { - if err := client.SetPath(ftpItem.User, req.Path); err != nil { - return err - } - updates["path"] = req.Path - needReload = true - } - if req.Description != ftpItem.Description { - updates["description"] = req.Description - } - if needReload { - _ = client.Reload() - } - if len(updates) != 0 { - return ftpRepo.Update(ftpItem.ID, updates) - } - return nil -} diff --git a/backend/app/service/group.go b/backend/app/service/group.go deleted file mode 100644 index 33823bdb3..000000000 --- a/backend/app/service/group.go +++ /dev/null @@ -1,90 +0,0 @@ -package service - -import ( - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/jinzhu/copier" - "github.com/pkg/errors" -) - -type GroupService struct{} - -type IGroupService interface { - List(req dto.GroupSearch) ([]dto.GroupInfo, error) - Create(req dto.GroupCreate) error - Update(req dto.GroupUpdate) error - Delete(id uint) error -} - -func NewIGroupService() IGroupService { - return &GroupService{} -} - -func (u *GroupService) List(req dto.GroupSearch) ([]dto.GroupInfo, error) { - groups, err := groupRepo.GetList(commonRepo.WithByType(req.Type), commonRepo.WithOrderBy("is_default desc"), commonRepo.WithOrderBy("created_at desc")) - if err != nil { - return nil, constant.ErrRecordNotFound - } - var dtoUsers []dto.GroupInfo - for _, group := range groups { - var item dto.GroupInfo - if err := copier.Copy(&item, &group); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - dtoUsers = append(dtoUsers, item) - } - return dtoUsers, err -} - -func (u *GroupService) Create(req dto.GroupCreate) error { - group, _ := groupRepo.Get(commonRepo.WithByName(req.Name), commonRepo.WithByType(req.Type)) - if group.ID != 0 { - return constant.ErrRecordExist - } - if err := copier.Copy(&group, &req); err != nil { - return errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - if err := groupRepo.Create(&group); err != nil { - return err - } - return nil -} - -func (u *GroupService) Delete(id uint) error { - group, _ := groupRepo.Get(commonRepo.WithByID(id)) - if group.ID == 0 { - return constant.ErrRecordNotFound - } - switch group.Type { - case "website": - websites, _ := websiteRepo.GetBy(websiteRepo.WithGroupID(id)) - if len(websites) > 0 { - return buserr.New(constant.ErrGroupIsUsed) - } - case "command": - commands, _ := commandRepo.GetList(commonRepo.WithByGroupID(id)) - if len(commands) > 0 { - return buserr.New(constant.ErrGroupIsUsed) - } - case "host": - hosts, _ := hostRepo.GetList(commonRepo.WithByGroupID(id)) - if len(hosts) > 0 { - return buserr.New(constant.ErrGroupIsUsed) - } - } - return groupRepo.Delete(commonRepo.WithByID(id)) -} - -func (u *GroupService) Update(req dto.GroupUpdate) error { - if req.IsDefault { - if err := groupRepo.CancelDefault(req.Type); err != nil { - return err - } - } - upMap := make(map[string]interface{}) - upMap["name"] = req.Name - upMap["is_default"] = req.IsDefault - - return groupRepo.Update(req.ID, upMap) -} diff --git a/backend/app/service/helper.go b/backend/app/service/helper.go deleted file mode 100644 index d498ec1b6..000000000 --- a/backend/app/service/helper.go +++ /dev/null @@ -1,14 +0,0 @@ -package service - -import ( - "context" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm" -) - -func getTxAndContext() (tx *gorm.DB, ctx context.Context) { - tx = global.DB.Begin() - ctx = context.WithValue(context.Background(), constant.DB, tx) - return -} diff --git a/backend/app/service/host.go b/backend/app/service/host.go deleted file mode 100644 index c294a4b9e..000000000 --- a/backend/app/service/host.go +++ /dev/null @@ -1,325 +0,0 @@ -package service - -import ( - "encoding/base64" - "fmt" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/encrypt" - "github.com/1Panel-dev/1Panel/backend/utils/ssh" - "github.com/jinzhu/copier" - "github.com/pkg/errors" -) - -type HostService struct{} - -type IHostService interface { - TestLocalConn(id uint) bool - TestByInfo(req dto.HostConnTest) bool - GetHostInfo(id uint) (*model.Host, error) - SearchForTree(search dto.SearchForTree) ([]dto.HostTree, error) - SearchWithPage(search dto.SearchHostWithPage) (int64, interface{}, error) - Create(hostDto dto.HostOperate) (*dto.HostInfo, error) - Update(id uint, upMap map[string]interface{}) error - Delete(id []uint) error - - EncryptHost(itemVal string) (string, error) -} - -func NewIHostService() IHostService { - return &HostService{} -} - -func (u *HostService) TestByInfo(req dto.HostConnTest) bool { - if req.AuthMode == "password" && len(req.Password) != 0 { - password, err := base64.StdEncoding.DecodeString(req.Password) - if err != nil { - return false - } - req.Password = string(password) - } - if req.AuthMode == "key" && len(req.PrivateKey) != 0 { - privateKey, err := base64.StdEncoding.DecodeString(req.PrivateKey) - if err != nil { - return false - } - req.PrivateKey = string(privateKey) - } - if len(req.Password) == 0 && len(req.PrivateKey) == 0 { - host, err := hostRepo.Get(hostRepo.WithByAddr(req.Addr)) - if err != nil { - return false - } - req.Password = host.Password - req.AuthMode = host.AuthMode - req.PrivateKey = host.PrivateKey - req.PassPhrase = host.PassPhrase - } - - var connInfo ssh.ConnInfo - _ = copier.Copy(&connInfo, &req) - connInfo.PrivateKey = []byte(req.PrivateKey) - if len(req.PassPhrase) != 0 { - connInfo.PassPhrase = []byte(req.PassPhrase) - } - client, err := connInfo.NewClient() - if err != nil { - return false - } - defer client.Close() - return true -} - -func (u *HostService) TestLocalConn(id uint) bool { - var ( - host model.Host - err error - ) - if id == 0 { - host, err = hostRepo.Get(hostRepo.WithByAddr("127.0.0.1")) - if err != nil { - return false - } - } else { - host, err = hostRepo.Get(commonRepo.WithByID(id)) - if err != nil { - return false - } - } - var connInfo ssh.ConnInfo - if err := copier.Copy(&connInfo, &host); err != nil { - return false - } - if len(host.Password) != 0 { - host.Password, err = encrypt.StringDecrypt(host.Password) - if err != nil { - return false - } - connInfo.Password = host.Password - } - if len(host.PrivateKey) != 0 { - host.PrivateKey, err = encrypt.StringDecrypt(host.PrivateKey) - if err != nil { - return false - } - connInfo.PrivateKey = []byte(host.PrivateKey) - } - if len(host.PassPhrase) != 0 { - host.PassPhrase, err = encrypt.StringDecrypt(host.PassPhrase) - if err != nil { - return false - } - connInfo.PassPhrase = []byte(host.PassPhrase) - } - client, err := connInfo.NewClient() - if err != nil { - return false - } - defer client.Close() - - return true -} - -func (u *HostService) GetHostInfo(id uint) (*model.Host, error) { - host, err := hostRepo.Get(commonRepo.WithByID(id)) - if err != nil { - return nil, constant.ErrRecordNotFound - } - if len(host.Password) != 0 { - host.Password, err = encrypt.StringDecrypt(host.Password) - if err != nil { - return nil, err - } - } - if len(host.PrivateKey) != 0 { - host.PrivateKey, err = encrypt.StringDecrypt(host.PrivateKey) - if err != nil { - return nil, err - } - } - - if len(host.PassPhrase) != 0 { - host.PassPhrase, err = encrypt.StringDecrypt(host.PassPhrase) - if err != nil { - return nil, err - } - } - return &host, err -} - -func (u *HostService) SearchWithPage(search dto.SearchHostWithPage) (int64, interface{}, error) { - total, hosts, err := hostRepo.Page(search.Page, search.PageSize, hostRepo.WithByInfo(search.Info), commonRepo.WithByGroupID(search.GroupID)) - if err != nil { - return 0, nil, err - } - var dtoHosts []dto.HostInfo - for _, host := range hosts { - var item dto.HostInfo - if err := copier.Copy(&item, &host); err != nil { - return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - group, _ := groupRepo.Get(commonRepo.WithByID(host.GroupID)) - item.GroupBelong = group.Name - if !item.RememberPassword { - item.Password = "" - item.PrivateKey = "" - item.PassPhrase = "" - } else { - if len(host.Password) != 0 { - item.Password, err = encrypt.StringDecrypt(host.Password) - if err != nil { - return 0, nil, err - } - } - if len(host.PrivateKey) != 0 { - item.PrivateKey, err = encrypt.StringDecrypt(host.PrivateKey) - if err != nil { - return 0, nil, err - } - } - if len(host.PassPhrase) != 0 { - item.PassPhrase, err = encrypt.StringDecrypt(host.PassPhrase) - if err != nil { - return 0, nil, err - } - } - } - dtoHosts = append(dtoHosts, item) - } - return total, dtoHosts, err -} - -func (u *HostService) SearchForTree(search dto.SearchForTree) ([]dto.HostTree, error) { - hosts, err := hostRepo.GetList(hostRepo.WithByInfo(search.Info)) - if err != nil { - return nil, err - } - groups, err := groupRepo.GetList(commonRepo.WithByType("host")) - if err != nil { - return nil, err - } - var datas []dto.HostTree - for _, group := range groups { - var data dto.HostTree - data.ID = group.ID + 10000 - data.Label = group.Name - for _, host := range hosts { - label := fmt.Sprintf("%s@%s:%d", host.User, host.Addr, host.Port) - if len(host.Name) != 0 { - label = fmt.Sprintf("%s - %s@%s:%d", host.Name, host.User, host.Addr, host.Port) - } - if host.GroupID == group.ID { - data.Children = append(data.Children, dto.TreeChild{ID: host.ID, Label: label}) - } - } - if len(data.Children) != 0 { - datas = append(datas, data) - } - } - return datas, err -} - -func (u *HostService) Create(req dto.HostOperate) (*dto.HostInfo, error) { - var err error - if len(req.Password) != 0 && req.AuthMode == "password" { - req.Password, err = u.EncryptHost(req.Password) - if err != nil { - return nil, err - } - req.PrivateKey = "" - req.PassPhrase = "" - } - if len(req.PrivateKey) != 0 && req.AuthMode == "key" { - req.PrivateKey, err = u.EncryptHost(req.PrivateKey) - if err != nil { - return nil, err - } - if len(req.PassPhrase) != 0 { - req.PassPhrase, err = encrypt.StringEncrypt(req.PassPhrase) - if err != nil { - return nil, err - } - } - req.Password = "" - } - var host model.Host - if err := copier.Copy(&host, &req); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - if req.GroupID == 0 { - group, err := groupRepo.Get(groupRepo.WithByHostDefault()) - if err != nil { - return nil, errors.New("get default group failed") - } - host.GroupID = group.ID - req.GroupID = group.ID - } - var sameHostID uint - if req.Addr == "127.0.0.1" { - hostSame, _ := hostRepo.Get(hostRepo.WithByAddr(req.Addr)) - sameHostID = hostSame.ID - } else { - hostSame, _ := hostRepo.Get(hostRepo.WithByAddr(req.Addr), hostRepo.WithByUser(req.User), hostRepo.WithByPort(req.Port)) - sameHostID = hostSame.ID - } - if sameHostID != 0 { - host.ID = sameHostID - upMap := make(map[string]interface{}) - upMap["name"] = req.Name - upMap["group_id"] = req.GroupID - upMap["addr"] = req.Addr - upMap["port"] = req.Port - upMap["user"] = req.User - upMap["auth_mode"] = req.AuthMode - upMap["password"] = req.Password - upMap["private_key"] = req.PrivateKey - upMap["pass_phrase"] = req.PassPhrase - upMap["remember_password"] = req.RememberPassword - upMap["description"] = req.Description - if err := hostRepo.Update(sameHostID, upMap); err != nil { - return nil, err - } - var hostinfo dto.HostInfo - if err := copier.Copy(&hostinfo, &host); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - return &hostinfo, nil - } - - if err := hostRepo.Create(&host); err != nil { - return nil, err - } - var hostinfo dto.HostInfo - if err := copier.Copy(&hostinfo, &host); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - return &hostinfo, nil -} - -func (u *HostService) Delete(ids []uint) error { - hosts, _ := hostRepo.GetList(commonRepo.WithIdsIn(ids)) - for _, host := range hosts { - if host.ID == 0 { - return constant.ErrRecordNotFound - } - if host.Addr == "127.0.0.1" { - return errors.New("the local connection information cannot be deleted!") - } - } - return hostRepo.Delete(commonRepo.WithIdsIn(ids)) -} - -func (u *HostService) Update(id uint, upMap map[string]interface{}) error { - return hostRepo.Update(id, upMap) -} - -func (u *HostService) EncryptHost(itemVal string) (string, error) { - privateKey, err := base64.StdEncoding.DecodeString(itemVal) - if err != nil { - return "", err - } - keyItem, err := encrypt.StringEncrypt(string(privateKey)) - return keyItem, err -} diff --git a/backend/app/service/host_tool.go b/backend/app/service/host_tool.go deleted file mode 100644 index b40bb038c..000000000 --- a/backend/app/service/host_tool.go +++ /dev/null @@ -1,565 +0,0 @@ -package service - -import ( - "bytes" - "fmt" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/1Panel-dev/1Panel/backend/utils/ini_conf" - "github.com/1Panel-dev/1Panel/backend/utils/systemctl" - "github.com/pkg/errors" - "gopkg.in/ini.v1" - "os/exec" - "os/user" - "path" - "strconv" - "strings" -) - -type HostToolService struct{} - -type IHostToolService interface { - GetToolStatus(req request.HostToolReq) (*response.HostToolRes, error) - CreateToolConfig(req request.HostToolCreate) error - OperateTool(req request.HostToolReq) error - OperateToolConfig(req request.HostToolConfig) (*response.HostToolConfig, error) - GetToolLog(req request.HostToolLogReq) (string, error) - OperateSupervisorProcess(req request.SupervisorProcessConfig) error - GetSupervisorProcessConfig() ([]response.SupervisorProcessConfig, error) - OperateSupervisorProcessFile(req request.SupervisorProcessFileReq) (string, error) -} - -func NewIHostToolService() IHostToolService { - return &HostToolService{} -} - -func (h *HostToolService) GetToolStatus(req request.HostToolReq) (*response.HostToolRes, error) { - res := &response.HostToolRes{} - res.Type = req.Type - switch req.Type { - case constant.Supervisord: - supervisorConfig := &response.Supervisor{} - if !cmd.Which(constant.Supervisord) { - supervisorConfig.IsExist = false - res.Config = supervisorConfig - return res, nil - } - supervisorConfig.IsExist = true - serviceExist, _ := systemctl.IsExist(constant.Supervisord) - if !serviceExist { - serviceExist, _ = systemctl.IsExist(constant.Supervisor) - if !serviceExist { - supervisorConfig.IsExist = false - res.Config = supervisorConfig - return res, nil - } else { - supervisorConfig.ServiceName = constant.Supervisor - } - } else { - supervisorConfig.ServiceName = constant.Supervisord - } - - serviceNameSet, _ := settingRepo.Get(settingRepo.WithByKey(constant.SupervisorServiceName)) - if serviceNameSet.ID != 0 || serviceNameSet.Value != "" { - supervisorConfig.ServiceName = serviceNameSet.Value - } - - versionRes, _ := cmd.Exec("supervisord -v") - supervisorConfig.Version = strings.TrimSuffix(versionRes, "\n") - _, ctlRrr := exec.LookPath("supervisorctl") - supervisorConfig.CtlExist = ctlRrr == nil - - active, _ := systemctl.IsActive(supervisorConfig.ServiceName) - if active { - supervisorConfig.Status = "running" - } else { - supervisorConfig.Status = "stopped" - } - - pathSet, _ := settingRepo.Get(settingRepo.WithByKey(constant.SupervisorConfigPath)) - if pathSet.ID != 0 || pathSet.Value != "" { - supervisorConfig.ConfigPath = pathSet.Value - res.Config = supervisorConfig - return res, nil - } else { - supervisorConfig.Init = true - } - - servicePath := "/usr/lib/systemd/system/supervisor.service" - fileOp := files.NewFileOp() - if !fileOp.Stat(servicePath) { - servicePath = "/usr/lib/systemd/system/supervisord.service" - } - if fileOp.Stat(servicePath) { - startCmd, _ := ini_conf.GetIniValue(servicePath, "Service", "ExecStart") - if startCmd != "" { - args := strings.Fields(startCmd) - cIndex := -1 - for i, arg := range args { - if arg == "-c" { - cIndex = i - break - } - } - if cIndex != -1 && cIndex+1 < len(args) { - supervisorConfig.ConfigPath = args[cIndex+1] - } - } - } - if supervisorConfig.ConfigPath == "" { - configPath := "/etc/supervisord.conf" - if !fileOp.Stat(configPath) { - configPath = "/etc/supervisor/supervisord.conf" - if fileOp.Stat(configPath) { - supervisorConfig.ConfigPath = configPath - } - } - } - - res.Config = supervisorConfig - } - return res, nil -} - -func (h *HostToolService) CreateToolConfig(req request.HostToolCreate) error { - switch req.Type { - case constant.Supervisord: - fileOp := files.NewFileOp() - if !fileOp.Stat(req.ConfigPath) { - return buserr.New("ErrConfigNotFound") - } - cfg, err := ini.Load(req.ConfigPath) - if err != nil { - return err - } - service, err := cfg.GetSection("include") - if err != nil { - return err - } - targetKey, err := service.GetKey("files") - if err != nil { - return err - } - if targetKey != nil { - _, err = service.NewKey(";files", targetKey.Value()) - if err != nil { - return err - } - } - supervisorDir := path.Join(global.CONF.System.BaseDir, "1panel", "tools", "supervisord") - includeDir := path.Join(supervisorDir, "supervisor.d") - if !fileOp.Stat(includeDir) { - if err = fileOp.CreateDir(includeDir, 0755); err != nil { - return err - } - } - logDir := path.Join(supervisorDir, "log") - if !fileOp.Stat(logDir) { - if err = fileOp.CreateDir(logDir, 0755); err != nil { - return err - } - } - includePath := path.Join(includeDir, "*.ini") - targetKey.SetValue(includePath) - if err = cfg.SaveTo(req.ConfigPath); err != nil { - return err - } - - serviceNameSet, _ := settingRepo.Get(settingRepo.WithByKey(constant.SupervisorServiceName)) - if serviceNameSet.ID != 0 { - if err = settingRepo.Update(constant.SupervisorServiceName, req.ServiceName); err != nil { - return err - } - } else { - if err = settingRepo.Create(constant.SupervisorServiceName, req.ServiceName); err != nil { - return err - } - } - - configPathSet, _ := settingRepo.Get(settingRepo.WithByKey(constant.SupervisorConfigPath)) - if configPathSet.ID != 0 { - if err = settingRepo.Update(constant.SupervisorConfigPath, req.ConfigPath); err != nil { - return err - } - } else { - if err = settingRepo.Create(constant.SupervisorConfigPath, req.ConfigPath); err != nil { - return err - } - } - if err = systemctl.Restart(req.ServiceName); err != nil { - global.LOG.Errorf("[init] restart %s failed err %s", req.ServiceName, err.Error()) - return err - } - } - return nil -} - -func (h *HostToolService) OperateTool(req request.HostToolReq) error { - serviceName := req.Type - if req.Type == constant.Supervisord { - serviceNameSet, _ := settingRepo.Get(settingRepo.WithByKey(constant.SupervisorServiceName)) - if serviceNameSet.ID != 0 || serviceNameSet.Value != "" { - serviceName = serviceNameSet.Value - } - } - return systemctl.Operate(req.Operate, serviceName) -} - -func (h *HostToolService) OperateToolConfig(req request.HostToolConfig) (*response.HostToolConfig, error) { - fileOp := files.NewFileOp() - res := &response.HostToolConfig{} - configPath := "" - serviceName := "supervisord" - switch req.Type { - case constant.Supervisord: - pathSet, _ := settingRepo.Get(settingRepo.WithByKey(constant.SupervisorConfigPath)) - if pathSet.ID != 0 || pathSet.Value != "" { - configPath = pathSet.Value - } - serviceNameSet, _ := settingRepo.Get(settingRepo.WithByKey(constant.SupervisorServiceName)) - if serviceNameSet.ID != 0 || serviceNameSet.Value != "" { - serviceName = serviceNameSet.Value - } - } - switch req.Operate { - case "get": - content, err := fileOp.GetContent(configPath) - if err != nil { - return nil, err - } - res.Content = string(content) - case "set": - file, err := fileOp.OpenFile(configPath) - if err != nil { - return nil, err - } - oldContent, err := fileOp.GetContent(configPath) - if err != nil { - return nil, err - } - fileInfo, err := file.Stat() - if err != nil { - return nil, err - } - if err = fileOp.WriteFile(configPath, strings.NewReader(req.Content), fileInfo.Mode()); err != nil { - return nil, err - } - if err = systemctl.Restart(serviceName); err != nil { - _ = fileOp.WriteFile(configPath, bytes.NewReader(oldContent), fileInfo.Mode()) - return nil, err - } - } - - return res, nil -} - -func (h *HostToolService) GetToolLog(req request.HostToolLogReq) (string, error) { - fileOp := files.NewFileOp() - logfilePath := "" - switch req.Type { - case constant.Supervisord: - configPath := "/etc/supervisord.conf" - pathSet, _ := settingRepo.Get(settingRepo.WithByKey(constant.SupervisorConfigPath)) - if pathSet.ID != 0 || pathSet.Value != "" { - configPath = pathSet.Value - } - logfilePath, _ = ini_conf.GetIniValue(configPath, "supervisord", "logfile") - } - oldContent, err := fileOp.GetContent(logfilePath) - if err != nil { - return "", err - } - return string(oldContent), nil -} - -func (h *HostToolService) OperateSupervisorProcess(req request.SupervisorProcessConfig) error { - var ( - supervisordDir = path.Join(global.CONF.System.BaseDir, "1panel", "tools", "supervisord") - logDir = path.Join(supervisordDir, "log") - includeDir = path.Join(supervisordDir, "supervisor.d") - outLog = path.Join(logDir, fmt.Sprintf("%s.out.log", req.Name)) - errLog = path.Join(logDir, fmt.Sprintf("%s.err.log", req.Name)) - iniPath = path.Join(includeDir, fmt.Sprintf("%s.ini", req.Name)) - fileOp = files.NewFileOp() - ) - if req.Operate == "update" || req.Operate == "create" { - if !fileOp.Stat(req.Dir) { - return buserr.New("ErrConfigDirNotFound") - } - _, err := user.Lookup(req.User) - if err != nil { - return buserr.WithMap("ErrUserFindErr", map[string]interface{}{"name": req.User, "err": err.Error()}, err) - } - } - - switch req.Operate { - case "create": - if fileOp.Stat(iniPath) { - return buserr.New("ErrConfigAlreadyExist") - } - configFile := ini.Empty() - section, err := configFile.NewSection(fmt.Sprintf("program:%s", req.Name)) - if err != nil { - return err - } - _, _ = section.NewKey("command", strings.TrimSpace(req.Command)) - _, _ = section.NewKey("directory", req.Dir) - _, _ = section.NewKey("autorestart", "true") - _, _ = section.NewKey("startsecs", "3") - _, _ = section.NewKey("stdout_logfile", outLog) - _, _ = section.NewKey("stderr_logfile", errLog) - _, _ = section.NewKey("stdout_logfile_maxbytes", "2MB") - _, _ = section.NewKey("stderr_logfile_maxbytes", "2MB") - _, _ = section.NewKey("user", req.User) - _, _ = section.NewKey("priority", "999") - _, _ = section.NewKey("numprocs", req.Numprocs) - _, _ = section.NewKey("process_name", "%(program_name)s_%(process_num)02d") - - if err = configFile.SaveTo(iniPath); err != nil { - return err - } - if err := operateSupervisorCtl("reread", "", ""); err != nil { - return err - } - return operateSupervisorCtl("update", "", "") - case "update": - configFile, err := ini.Load(iniPath) - if err != nil { - return err - } - section, err := configFile.GetSection(fmt.Sprintf("program:%s", req.Name)) - if err != nil { - return err - } - - commandKey := section.Key("command") - commandKey.SetValue(strings.TrimSpace(req.Command)) - directoryKey := section.Key("directory") - directoryKey.SetValue(req.Dir) - userKey := section.Key("user") - userKey.SetValue(req.User) - numprocsKey := section.Key("numprocs") - numprocsKey.SetValue(req.Numprocs) - - if err = configFile.SaveTo(iniPath); err != nil { - return err - } - if err := operateSupervisorCtl("reread", "", ""); err != nil { - return err - } - return operateSupervisorCtl("update", "", "") - case "restart": - return operateSupervisorCtl("restart", req.Name, "") - case "start": - return operateSupervisorCtl("start", req.Name, "") - case "stop": - return operateSupervisorCtl("stop", req.Name, "") - case "delete": - _ = operateSupervisorCtl("remove", "", req.Name) - _ = files.NewFileOp().DeleteFile(iniPath) - _ = files.NewFileOp().DeleteFile(outLog) - _ = files.NewFileOp().DeleteFile(errLog) - if err := operateSupervisorCtl("reread", "", ""); err != nil { - return err - } - return operateSupervisorCtl("update", "", "") - } - - return nil -} - -func (h *HostToolService) GetSupervisorProcessConfig() ([]response.SupervisorProcessConfig, error) { - var ( - result []response.SupervisorProcessConfig - ) - configDir := path.Join(global.CONF.System.BaseDir, "1panel", "tools", "supervisord", "supervisor.d") - fileList, _ := NewIFileService().GetFileList(request.FileOption{FileOption: files.FileOption{Path: configDir, Expand: true, Page: 1, PageSize: 100}}) - if len(fileList.Items) == 0 { - return result, nil - } - for _, configFile := range fileList.Items { - f, err := ini.Load(configFile.Path) - if err != nil { - global.LOG.Errorf("get %s file err %s", configFile.Name, err.Error()) - continue - } - if strings.HasSuffix(configFile.Name, ".ini") { - config := response.SupervisorProcessConfig{} - name := strings.TrimSuffix(configFile.Name, ".ini") - config.Name = name - section, err := f.GetSection(fmt.Sprintf("program:%s", name)) - if err != nil { - global.LOG.Errorf("get %s file section err %s", configFile.Name, err.Error()) - continue - } - if command, _ := section.GetKey("command"); command != nil { - config.Command = command.Value() - } - if directory, _ := section.GetKey("directory"); directory != nil { - config.Dir = directory.Value() - } - if user, _ := section.GetKey("user"); user != nil { - config.User = user.Value() - } - if numprocs, _ := section.GetKey("numprocs"); numprocs != nil { - config.Numprocs = numprocs.Value() - } - _ = getProcessStatus(&config) - result = append(result, config) - } - } - return result, nil -} - -func (h *HostToolService) OperateSupervisorProcessFile(req request.SupervisorProcessFileReq) (string, error) { - var ( - fileOp = files.NewFileOp() - group = fmt.Sprintf("program:%s", req.Name) - configPath = path.Join(global.CONF.System.BaseDir, "1panel", "tools", "supervisord", "supervisor.d", fmt.Sprintf("%s.ini", req.Name)) - ) - switch req.File { - case "err.log": - logPath, err := ini_conf.GetIniValue(configPath, group, "stderr_logfile") - if err != nil { - return "", err - } - switch req.Operate { - case "get": - content, err := fileOp.GetContent(logPath) - if err != nil { - return "", err - } - return string(content), nil - case "clear": - if err = fileOp.WriteFile(logPath, strings.NewReader(""), 0755); err != nil { - return "", err - } - } - - case "out.log": - logPath, err := ini_conf.GetIniValue(configPath, group, "stdout_logfile") - if err != nil { - return "", err - } - switch req.Operate { - case "get": - content, err := fileOp.GetContent(logPath) - if err != nil { - return "", err - } - return string(content), nil - case "clear": - if err = fileOp.WriteFile(logPath, strings.NewReader(""), 0755); err != nil { - return "", err - } - } - - case "config": - switch req.Operate { - case "get": - content, err := fileOp.GetContent(configPath) - if err != nil { - return "", err - } - return string(content), nil - case "update": - if req.Content == "" { - return "", buserr.New("ErrConfigIsNull") - } - if err := fileOp.WriteFile(configPath, strings.NewReader(req.Content), 0755); err != nil { - return "", err - } - return "", operateSupervisorCtl("update", "", req.Name) - } - - } - return "", nil -} - -func operateSupervisorCtl(operate, name, group string) error { - processNames := []string{operate} - if name != "" { - includeDir := path.Join(global.CONF.System.BaseDir, "1panel", "tools", "supervisord", "supervisor.d") - f, err := ini.Load(path.Join(includeDir, fmt.Sprintf("%s.ini", name))) - if err != nil { - return err - } - section, err := f.GetSection(fmt.Sprintf("program:%s", name)) - if err != nil { - return err - } - numprocsNum := "" - if numprocs, _ := section.GetKey("numprocs"); numprocs != nil { - numprocsNum = numprocs.Value() - } - if numprocsNum == "" { - return buserr.New("ErrConfigParse") - } - processNames = append(processNames, getProcessName(name, numprocsNum)...) - } - if group != "" { - processNames = append(processNames, group) - } - - output, err := exec.Command("supervisorctl", processNames...).Output() - if err != nil { - if output != nil { - return errors.New(string(output)) - } - return err - } - return nil -} - -func getProcessName(name, numprocs string) []string { - var ( - processNames []string - ) - num, err := strconv.Atoi(numprocs) - if err != nil { - return processNames - } - if num == 1 { - processNames = append(processNames, fmt.Sprintf("%s:%s_00", name, name)) - } else { - for i := 0; i < num; i++ { - processName := fmt.Sprintf("%s:%s_0%s", name, name, strconv.Itoa(i)) - if i >= 10 { - processName = fmt.Sprintf("%s:%s_%s", name, name, strconv.Itoa(i)) - } - processNames = append(processNames, processName) - } - } - return processNames -} - -func getProcessStatus(config *response.SupervisorProcessConfig) error { - var ( - processNames = []string{"status"} - ) - processNames = append(processNames, getProcessName(config.Name, config.Numprocs)...) - output, _ := exec.Command("supervisorctl", processNames...).Output() - lines := strings.Split(string(output), "\n") - for _, line := range lines { - fields := strings.Fields(line) - if len(fields) >= 5 { - status := response.ProcessStatus{ - Name: fields[0], - Status: fields[1], - } - if fields[1] == "RUNNING" { - status.PID = strings.TrimSuffix(fields[3], ",") - status.Uptime = fields[5] - } else { - status.Msg = strings.Join(fields[2:], " ") - } - config.Status = append(config.Status, status) - } - } - return nil -} diff --git a/backend/app/service/image.go b/backend/app/service/image.go deleted file mode 100644 index 833b6652b..000000000 --- a/backend/app/service/image.go +++ /dev/null @@ -1,517 +0,0 @@ -package service - -import ( - "bufio" - "context" - "encoding/base64" - "encoding/json" - "errors" - "fmt" - "io" - "os" - "path" - "strings" - "time" - - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/image" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/homedir" -) - -type ImageService struct{} - -type IImageService interface { - Page(req dto.SearchWithPage) (int64, interface{}, error) - List() ([]dto.Options, error) - ListAll() ([]dto.ImageInfo, error) - ImageBuild(req dto.ImageBuild) (string, error) - ImagePull(req dto.ImagePull) (string, error) - ImageLoad(req dto.ImageLoad) error - ImageSave(req dto.ImageSave) error - ImagePush(req dto.ImagePush) (string, error) - ImageRemove(req dto.BatchDelete) error - ImageTag(req dto.ImageTag) error -} - -func NewIImageService() IImageService { - return &ImageService{} -} -func (u *ImageService) Page(req dto.SearchWithPage) (int64, interface{}, error) { - var ( - list []image.Summary - records []dto.ImageInfo - backDatas []dto.ImageInfo - ) - client, err := docker.NewDockerClient() - if err != nil { - return 0, nil, err - } - defer client.Close() - list, err = client.ImageList(context.Background(), image.ListOptions{}) - if err != nil { - return 0, nil, err - } - containers, _ := client.ContainerList(context.Background(), container.ListOptions{All: true}) - if len(req.Info) != 0 { - length, count := len(list), 0 - for count < length { - hasTag := false - for _, tag := range list[count].RepoTags { - if strings.Contains(tag, req.Info) { - hasTag = true - break - } - } - if !hasTag { - list = append(list[:count], list[(count+1):]...) - length-- - } else { - count++ - } - } - } - - for _, image := range list { - size := formatFileSize(image.Size) - records = append(records, dto.ImageInfo{ - ID: image.ID, - Tags: image.RepoTags, - IsUsed: checkUsed(image.ID, containers), - CreatedAt: time.Unix(image.Created, 0), - Size: size, - }) - } - total, start, end := len(records), (req.Page-1)*req.PageSize, req.Page*req.PageSize - if start > total { - backDatas = make([]dto.ImageInfo, 0) - } else { - if end >= total { - end = total - } - backDatas = records[start:end] - } - - return int64(total), backDatas, nil -} - -func (u *ImageService) ListAll() ([]dto.ImageInfo, error) { - var records []dto.ImageInfo - client, err := docker.NewDockerClient() - if err != nil { - return nil, err - } - defer client.Close() - list, err := client.ImageList(context.Background(), image.ListOptions{}) - if err != nil { - return nil, err - } - containers, _ := client.ContainerList(context.Background(), container.ListOptions{All: true}) - for _, image := range list { - size := formatFileSize(image.Size) - records = append(records, dto.ImageInfo{ - ID: image.ID, - Tags: image.RepoTags, - IsUsed: checkUsed(image.ID, containers), - CreatedAt: time.Unix(image.Created, 0), - Size: size, - }) - } - return records, nil -} - -func (u *ImageService) List() ([]dto.Options, error) { - var ( - list []image.Summary - backDatas []dto.Options - ) - client, err := docker.NewDockerClient() - if err != nil { - return nil, err - } - defer client.Close() - list, err = client.ImageList(context.Background(), image.ListOptions{}) - if err != nil { - return nil, err - } - for _, image := range list { - for _, tag := range image.RepoTags { - backDatas = append(backDatas, dto.Options{ - Option: tag, - }) - } - } - return backDatas, nil -} - -func (u *ImageService) ImageBuild(req dto.ImageBuild) (string, error) { - client, err := docker.NewDockerClient() - if err != nil { - return "", err - } - defer client.Close() - fileName := "Dockerfile" - if req.From == "edit" { - dir := fmt.Sprintf("%s/docker/build/%s", constant.DataDir, strings.ReplaceAll(req.Name, ":", "_")) - if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(dir, os.ModePerm); err != nil { - return "", err - } - } - - pathItem := fmt.Sprintf("%s/Dockerfile", dir) - file, err := os.OpenFile(pathItem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) - if err != nil { - return "", err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(string(req.Dockerfile)) - write.Flush() - req.Dockerfile = dir - } else { - fileName = path.Base(req.Dockerfile) - req.Dockerfile = path.Dir(req.Dockerfile) - } - tar, err := archive.TarWithOptions(req.Dockerfile+"/", &archive.TarOptions{}) - if err != nil { - return "", err - } - - opts := types.ImageBuildOptions{ - Dockerfile: fileName, - Tags: []string{req.Name}, - Remove: true, - Labels: stringsToMap(req.Tags), - } - - dockerLogDir := path.Join(global.CONF.System.TmpDir, "docker_logs") - if _, err := os.Stat(dockerLogDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(dockerLogDir, os.ModePerm); err != nil { - return "", err - } - } - logItem := fmt.Sprintf("%s/image_build_%s_%s.log", dockerLogDir, strings.ReplaceAll(req.Name, ":", "_"), time.Now().Format(constant.DateTimeSlimLayout)) - file, err := os.OpenFile(logItem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) - if err != nil { - return "", err - } - go func() { - defer file.Close() - defer tar.Close() - res, err := client.ImageBuild(context.Background(), tar, opts) - if err != nil { - global.LOG.Errorf("build image %s failed, err: %v", req.Name, err) - _, _ = file.WriteString("image build failed!") - return - } - defer res.Body.Close() - body, err := io.ReadAll(res.Body) - if err != nil { - global.LOG.Errorf("build image %s failed, err: %v", req.Name, err) - _, _ = file.WriteString(fmt.Sprintf("build image %s failed, err: %v", req.Name, err)) - _, _ = file.WriteString("image build failed!") - return - } - - if strings.Contains(string(body), "errorDetail") || strings.Contains(string(body), "error:") { - global.LOG.Errorf("build image %s failed", req.Name) - _, _ = file.Write(body) - _, _ = file.WriteString("image build failed!") - return - } - global.LOG.Infof("build image %s successful!", req.Name) - _, _ = file.Write(body) - _, _ = file.WriteString("image build successful!") - }() - - return path.Base(logItem), nil -} - -func (u *ImageService) ImagePull(req dto.ImagePull) (string, error) { - client, err := docker.NewDockerClient() - if err != nil { - return "", err - } - defer client.Close() - dockerLogDir := path.Join(global.CONF.System.TmpDir, "docker_logs") - if _, err := os.Stat(dockerLogDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(dockerLogDir, os.ModePerm); err != nil { - return "", err - } - } - imageItemName := strings.ReplaceAll(path.Base(req.ImageName), ":", "_") - logItem := fmt.Sprintf("%s/image_pull_%s_%s.log", dockerLogDir, imageItemName, time.Now().Format(constant.DateTimeSlimLayout)) - file, err := os.OpenFile(logItem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) - if err != nil { - return "", err - } - options := image.PullOptions{} - if req.RepoID == 0 { - hasAuth, authStr := loadAuthInfo(req.ImageName) - if hasAuth { - options.RegistryAuth = authStr - } - go func() { - defer file.Close() - out, err := client.ImagePull(context.TODO(), req.ImageName, options) - if err != nil { - global.LOG.Errorf("image %s pull failed, err: %v", req.ImageName, err) - return - } - defer out.Close() - global.LOG.Infof("pull image %s successful!", req.ImageName) - _, _ = io.Copy(file, out) - }() - return path.Base(logItem), nil - } - repo, err := imageRepoRepo.Get(commonRepo.WithByID(req.RepoID)) - if err != nil { - return "", err - } - if repo.Auth { - authConfig := registry.AuthConfig{ - Username: repo.Username, - Password: repo.Password, - } - encodedJSON, err := json.Marshal(authConfig) - if err != nil { - return "", err - } - authStr := base64.URLEncoding.EncodeToString(encodedJSON) - options.RegistryAuth = authStr - } - image := repo.DownloadUrl + "/" + req.ImageName - go func() { - defer file.Close() - out, err := client.ImagePull(context.TODO(), image, options) - if err != nil { - _, _ = file.WriteString("image pull failed!") - global.LOG.Errorf("image %s pull failed, err: %v", image, err) - return - } - defer out.Close() - global.LOG.Infof("pull image %s successful!", req.ImageName) - _, _ = io.Copy(file, out) - _, _ = file.WriteString("image pull successful!") - }() - return path.Base(logItem), nil -} - -func (u *ImageService) ImageLoad(req dto.ImageLoad) error { - file, err := os.Open(req.Path) - if err != nil { - return err - } - defer file.Close() - client, err := docker.NewDockerClient() - if err != nil { - return err - } - defer client.Close() - res, err := client.ImageLoad(context.TODO(), file, true) - if err != nil { - return err - } - defer res.Body.Close() - content, err := io.ReadAll(res.Body) - if err != nil { - return err - } - if strings.Contains(string(content), "Error") { - return errors.New(string(content)) - } - return nil -} - -func (u *ImageService) ImageSave(req dto.ImageSave) error { - client, err := docker.NewDockerClient() - if err != nil { - return err - } - defer client.Close() - - out, err := client.ImageSave(context.TODO(), []string{req.TagName}) - if err != nil { - return err - } - defer out.Close() - file, err := os.OpenFile(fmt.Sprintf("%s/%s.tar", req.Path, req.Name), os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666) - if err != nil { - return err - } - defer file.Close() - if _, err = io.Copy(file, out); err != nil { - return err - } - return nil -} - -func (u *ImageService) ImageTag(req dto.ImageTag) error { - client, err := docker.NewDockerClient() - if err != nil { - return err - } - defer client.Close() - - if err := client.ImageTag(context.TODO(), req.SourceID, req.TargetName); err != nil { - return err - } - return nil -} - -func (u *ImageService) ImagePush(req dto.ImagePush) (string, error) { - client, err := docker.NewDockerClient() - if err != nil { - return "", err - } - defer client.Close() - repo, err := imageRepoRepo.Get(commonRepo.WithByID(req.RepoID)) - if err != nil { - return "", err - } - options := image.PushOptions{All: true} - authConfig := registry.AuthConfig{ - Username: repo.Username, - Password: repo.Password, - } - encodedJSON, err := json.Marshal(authConfig) - if err != nil { - return "", err - } - authStr := base64.URLEncoding.EncodeToString(encodedJSON) - options.RegistryAuth = authStr - newName := fmt.Sprintf("%s/%s", repo.DownloadUrl, req.Name) - if newName != req.TagName { - if err := client.ImageTag(context.TODO(), req.TagName, newName); err != nil { - return "", err - } - } - - dockerLogDir := global.CONF.System.TmpDir + "/docker_logs" - if _, err := os.Stat(dockerLogDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(dockerLogDir, os.ModePerm); err != nil { - return "", err - } - } - imageItemName := strings.ReplaceAll(path.Base(req.Name), ":", "_") - logItem := fmt.Sprintf("%s/image_push_%s_%s.log", dockerLogDir, imageItemName, time.Now().Format(constant.DateTimeSlimLayout)) - file, err := os.OpenFile(logItem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) - if err != nil { - return "", err - } - go func() { - defer file.Close() - out, err := client.ImagePush(context.TODO(), newName, options) - if err != nil { - global.LOG.Errorf("image %s push failed, err: %v", req.TagName, err) - _, _ = file.WriteString("image push failed!") - return - } - defer out.Close() - global.LOG.Infof("push image %s successful!", req.Name) - _, _ = io.Copy(file, out) - _, _ = file.WriteString("image push successful!") - }() - - return path.Base(logItem), nil -} - -func (u *ImageService) ImageRemove(req dto.BatchDelete) error { - client, err := docker.NewDockerClient() - if err != nil { - return err - } - defer client.Close() - for _, id := range req.Names { - if _, err := client.ImageRemove(context.TODO(), id, image.RemoveOptions{Force: req.Force, PruneChildren: true}); err != nil { - if strings.Contains(err.Error(), "image is being used") || strings.Contains(err.Error(), "is using") { - if strings.Contains(id, "sha256:") { - return buserr.New(constant.ErrObjectInUsed) - } - return buserr.WithDetail(constant.ErrInUsed, id, nil) - } - return err - } - } - return nil -} - -func formatFileSize(fileSize int64) (size string) { - if fileSize < 1024 { - return fmt.Sprintf("%.2fB", float64(fileSize)/float64(1)) - } else if fileSize < (1024 * 1024) { - return fmt.Sprintf("%.2fKB", float64(fileSize)/float64(1024)) - } else if fileSize < (1024 * 1024 * 1024) { - return fmt.Sprintf("%.2fMB", float64(fileSize)/float64(1024*1024)) - } else if fileSize < (1024 * 1024 * 1024 * 1024) { - return fmt.Sprintf("%.2fGB", float64(fileSize)/float64(1024*1024*1024)) - } else if fileSize < (1024 * 1024 * 1024 * 1024 * 1024) { - return fmt.Sprintf("%.2fTB", float64(fileSize)/float64(1024*1024*1024*1024)) - } else { - return fmt.Sprintf("%.2fEB", float64(fileSize)/float64(1024*1024*1024*1024*1024)) - } -} - -func checkUsed(imageID string, containers []types.Container) bool { - for _, container := range containers { - if container.ImageID == imageID { - return true - } - } - return false -} - -func loadAuthInfo(image string) (bool, string) { - if !strings.Contains(image, "/") { - return false, "" - } - homeDir := homedir.Get() - confPath := path.Join(homeDir, ".docker/config.json") - configFileBytes, err := os.ReadFile(confPath) - if err != nil { - return false, "" - } - var config dockerConfig - if err = json.Unmarshal(configFileBytes, &config); err != nil { - return false, "" - } - var ( - user string - passwd string - ) - imagePrefix := strings.Split(image, "/")[0] - if val, ok := config.Auths[imagePrefix]; ok { - itemByte, _ := base64.StdEncoding.DecodeString(val.Auth) - itemStr := string(itemByte) - if strings.Contains(itemStr, ":") { - user = strings.Split(itemStr, ":")[0] - passwd = strings.Split(itemStr, ":")[1] - } - } - authConfig := registry.AuthConfig{ - Username: user, - Password: passwd, - } - encodedJSON, err := json.Marshal(authConfig) - if err != nil { - return false, "" - } - authStr := base64.URLEncoding.EncodeToString(encodedJSON) - return true, authStr -} - -type dockerConfig struct { - Auths map[string]authConfig `json:"auths"` -} -type authConfig struct { - Auth string `json:"auth"` -} diff --git a/backend/app/service/image_repo.go b/backend/app/service/image_repo.go deleted file mode 100644 index e5dad9e90..000000000 --- a/backend/app/service/image_repo.go +++ /dev/null @@ -1,243 +0,0 @@ -package service - -import ( - "context" - "encoding/json" - "fmt" - "os" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/jinzhu/copier" - "github.com/pkg/errors" -) - -type ImageRepoService struct{} - -type IImageRepoService interface { - Page(search dto.SearchWithPage) (int64, interface{}, error) - List() ([]dto.ImageRepoOption, error) - Login(req dto.OperateByID) error - Create(req dto.ImageRepoCreate) error - Update(req dto.ImageRepoUpdate) error - BatchDelete(req dto.ImageRepoDelete) error -} - -func NewIImageRepoService() IImageRepoService { - return &ImageRepoService{} -} - -func (u *ImageRepoService) Page(req dto.SearchWithPage) (int64, interface{}, error) { - total, ops, err := imageRepoRepo.Page(req.Page, req.PageSize, commonRepo.WithLikeName(req.Info), commonRepo.WithOrderBy("created_at desc")) - var dtoOps []dto.ImageRepoInfo - for _, op := range ops { - var item dto.ImageRepoInfo - if err := copier.Copy(&item, &op); err != nil { - return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - dtoOps = append(dtoOps, item) - } - return total, dtoOps, err -} - -func (u *ImageRepoService) Login(req dto.OperateByID) error { - repo, err := imageRepoRepo.Get(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - if repo.Auth { - if err := u.CheckConn(repo.DownloadUrl, repo.Username, repo.Password); err != nil { - _ = imageRepoRepo.Update(repo.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()}) - return err - } - } - _ = imageRepoRepo.Update(repo.ID, map[string]interface{}{"status": constant.StatusSuccess}) - return nil -} - -func (u *ImageRepoService) List() ([]dto.ImageRepoOption, error) { - ops, err := imageRepoRepo.List(commonRepo.WithOrderBy("created_at desc")) - var dtoOps []dto.ImageRepoOption - for _, op := range ops { - if op.Status == constant.StatusSuccess { - var item dto.ImageRepoOption - if err := copier.Copy(&item, &op); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - dtoOps = append(dtoOps, item) - } - } - return dtoOps, err -} - -func (u *ImageRepoService) Create(req dto.ImageRepoCreate) error { - if cmd.CheckIllegal(req.Username, req.Password, req.DownloadUrl) { - return buserr.New(constant.ErrCmdIllegal) - } - imageRepo, _ := imageRepoRepo.Get(commonRepo.WithByName(req.Name)) - if imageRepo.ID != 0 { - return constant.ErrRecordExist - } - if req.Protocol == "http" { - _ = u.handleRegistries(req.DownloadUrl, "", "create") - stdout, err := cmd.Exec("systemctl restart docker") - if err != nil { - return errors.New(string(stdout)) - } - ticker := time.NewTicker(3 * time.Second) - defer ticker.Stop() - ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) - if err := func() error { - for range ticker.C { - select { - case <-ctx.Done(): - cancel() - return errors.New("the docker service cannot be restarted") - default: - stdout, err := cmd.Exec("systemctl is-active docker") - if string(stdout) == "active\n" && err == nil { - global.LOG.Info("docker restart with new conf successful!") - return nil - } - } - } - return nil - }(); err != nil { - return err - } - } - - if err := copier.Copy(&imageRepo, &req); err != nil { - return errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - - imageRepo.Status = constant.StatusSuccess - if req.Auth { - if err := u.CheckConn(req.DownloadUrl, req.Username, req.Password); err != nil { - imageRepo.Status = constant.StatusFailed - imageRepo.Message = err.Error() - } - } - if err := imageRepoRepo.Create(&imageRepo); err != nil { - return err - } - - return nil -} - -func (u *ImageRepoService) BatchDelete(req dto.ImageRepoDelete) error { - for _, id := range req.Ids { - if id == 1 { - return errors.New("The default value cannot be edit !") - } - } - if err := imageRepoRepo.Delete(commonRepo.WithIdsIn(req.Ids)); err != nil { - return err - } - return nil -} - -func (u *ImageRepoService) Update(req dto.ImageRepoUpdate) error { - if req.ID == 1 { - return errors.New("The default value cannot be deleted !") - } - if cmd.CheckIllegal(req.Username, req.Password, req.DownloadUrl) { - return buserr.New(constant.ErrCmdIllegal) - } - repo, err := imageRepoRepo.Get(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - if repo.DownloadUrl != req.DownloadUrl || (!repo.Auth && req.Auth) { - _ = u.handleRegistries(req.DownloadUrl, repo.DownloadUrl, "update") - if repo.Auth { - _, _ = cmd.ExecWithCheck("docker", "logout", repo.DownloadUrl) - } - stdout, err := cmd.Exec("systemctl restart docker") - if err != nil { - return errors.New(string(stdout)) - } - } - - upMap := make(map[string]interface{}) - upMap["download_url"] = req.DownloadUrl - upMap["protocol"] = req.Protocol - upMap["username"] = req.Username - upMap["password"] = req.Password - upMap["auth"] = req.Auth - - upMap["status"] = constant.StatusSuccess - upMap["message"] = "" - if req.Auth { - if err := u.CheckConn(req.DownloadUrl, req.Username, req.Password); err != nil { - upMap["status"] = constant.StatusFailed - upMap["message"] = err.Error() - } - } - return imageRepoRepo.Update(req.ID, upMap) -} - -func (u *ImageRepoService) CheckConn(host, user, password string) error { - stdout, err := cmd.ExecWithCheck("docker", "login", "-u", user, "-p", password, host) - if err != nil { - return fmt.Errorf("stdout: %s, stderr: %v", stdout, err) - } - if strings.Contains(string(stdout), "Login Succeeded") { - return nil - } - return errors.New(string(stdout)) -} - -func (u *ImageRepoService) handleRegistries(newHost, delHost, handle string) error { - err := createIfNotExistDaemonJsonFile() - if err != nil { - return err - } - daemonMap := make(map[string]interface{}) - file, err := os.ReadFile(constant.DaemonJsonPath) - if err != nil { - return err - } - if err := json.Unmarshal(file, &daemonMap); err != nil { - return err - } - - iRegistries := daemonMap["insecure-registries"] - registries, _ := iRegistries.([]interface{}) - switch handle { - case "create": - registries = common.RemoveRepeatElement(append(registries, newHost)) - case "update": - for i, regi := range registries { - if regi == delHost { - registries = append(registries[:i], registries[i+1:]...) - } - } - registries = common.RemoveRepeatElement(append(registries, newHost)) - case "delete": - for i, regi := range registries { - if regi == delHost { - registries = append(registries[:i], registries[i+1:]...) - } - } - } - if len(registries) == 0 { - delete(daemonMap, "insecure-registries") - } else { - daemonMap["insecure-registries"] = registries - } - newJson, err := json.MarshalIndent(daemonMap, "", "\t") - if err != nil { - return err - } - if err := os.WriteFile(constant.DaemonJsonPath, newJson, 0640); err != nil { - return err - } - return nil -} diff --git a/backend/app/service/logs.go b/backend/app/service/logs.go deleted file mode 100644 index 51cdad04e..000000000 --- a/backend/app/service/logs.go +++ /dev/null @@ -1,81 +0,0 @@ -package service - -import ( - "fmt" - "os" - "path" - "path/filepath" - "sort" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/global" -) - -type LogService struct{} - -type ILogService interface { - ListSystemLogFile() ([]string, error) - LoadSystemLog(name string) (string, error) -} - -func NewILogService() ILogService { - return &LogService{} -} - -func (u *LogService) ListSystemLogFile() ([]string, error) { - logDir := path.Join(global.CONF.System.BaseDir, "1panel/log") - var files []string - if err := filepath.Walk(logDir, func(pathItem string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if !info.IsDir() && strings.HasPrefix(info.Name(), "1Panel") { - if info.Name() == "1Panel.log" { - files = append(files, time.Now().Format("2006-01-02")) - return nil - } - itemFileName := strings.TrimPrefix(info.Name(), "1Panel-") - itemFileName = strings.TrimSuffix(itemFileName, ".gz") - itemFileName = strings.TrimSuffix(itemFileName, ".log") - files = append(files, itemFileName) - return nil - } - return nil - }); err != nil { - return nil, err - } - - if len(files) < 2 { - return files, nil - } - sort.Slice(files, func(i, j int) bool { - return files[i] > files[j] - }) - - return files, nil -} - -func (u *LogService) LoadSystemLog(name string) (string, error) { - if name == time.Now().Format("2006-01-02") { - name = "1Panel.log" - } else { - name = "1Panel-" + name + ".log" - } - filePath := path.Join(global.CONF.System.DataDir, "log", name) - if _, err := os.Stat(filePath); err != nil { - fileGzPath := path.Join(global.CONF.System.DataDir, "log", name+".gz") - if _, err := os.Stat(fileGzPath); err != nil { - return "", buserr.New("ErrHttpReqNotFound") - } - if err := handleGunzip(fileGzPath); err != nil { - return "", fmt.Errorf("handle ungzip file %s failed, err: %v", fileGzPath, err) - } - } - content, err := os.ReadFile(filePath) - if err != nil { - return "", err - } - return string(content), nil -} diff --git a/backend/app/service/monitor.go b/backend/app/service/monitor.go deleted file mode 100644 index 8f907a71f..000000000 --- a/backend/app/service/monitor.go +++ /dev/null @@ -1,216 +0,0 @@ -package service - -import ( - "context" - "fmt" - "strconv" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/robfig/cron/v3" - "github.com/shirou/gopsutil/v3/cpu" - "github.com/shirou/gopsutil/v3/disk" - "github.com/shirou/gopsutil/v3/load" - "github.com/shirou/gopsutil/v3/mem" - "github.com/shirou/gopsutil/v3/net" -) - -type MonitorService struct { - DiskIO chan ([]disk.IOCountersStat) - NetIO chan ([]net.IOCountersStat) -} - -var monitorCancel context.CancelFunc - -type IMonitorService interface { - Run() - - saveIODataToDB(ctx context.Context, interval float64) - saveNetDataToDB(ctx context.Context, interval float64) -} - -func NewIMonitorService() IMonitorService { - return &MonitorService{ - DiskIO: make(chan []disk.IOCountersStat, 2), - NetIO: make(chan []net.IOCountersStat, 2), - } -} - -func (m *MonitorService) Run() { - var itemModel model.MonitorBase - totalPercent, _ := cpu.Percent(3*time.Second, false) - if len(totalPercent) == 1 { - itemModel.Cpu = totalPercent[0] - } - cpuCount, _ := cpu.Counts(false) - - loadInfo, _ := load.Avg() - itemModel.CpuLoad1 = loadInfo.Load1 - itemModel.CpuLoad5 = loadInfo.Load5 - itemModel.CpuLoad15 = loadInfo.Load15 - itemModel.LoadUsage = loadInfo.Load1 / (float64(cpuCount*2) * 0.75) * 100 - - memoryInfo, _ := mem.VirtualMemory() - itemModel.Memory = memoryInfo.UsedPercent - - if err := settingRepo.CreateMonitorBase(itemModel); err != nil { - global.LOG.Errorf("Insert basic monitoring data failed, err: %v", err) - } - - m.loadDiskIO() - m.loadNetIO() - - MonitorStoreDays, err := settingRepo.Get(settingRepo.WithByKey("MonitorStoreDays")) - if err != nil { - return - } - storeDays, _ := strconv.Atoi(MonitorStoreDays.Value) - timeForDelete := time.Now().AddDate(0, 0, -storeDays) - _ = settingRepo.DelMonitorBase(timeForDelete) - _ = settingRepo.DelMonitorIO(timeForDelete) - _ = settingRepo.DelMonitorNet(timeForDelete) -} - -func (m *MonitorService) loadDiskIO() { - ioStat, _ := disk.IOCounters() - var diskIOList []disk.IOCountersStat - for _, io := range ioStat { - diskIOList = append(diskIOList, io) - } - m.DiskIO <- diskIOList -} - -func (m *MonitorService) loadNetIO() { - netStat, _ := net.IOCounters(true) - netStatAll, _ := net.IOCounters(false) - var netList []net.IOCountersStat - netList = append(netList, netStat...) - netList = append(netList, netStatAll...) - m.NetIO <- netList -} - -func (m *MonitorService) saveIODataToDB(ctx context.Context, interval float64) { - defer close(m.DiskIO) - for { - select { - case <-ctx.Done(): - return - case ioStat := <-m.DiskIO: - select { - case <-ctx.Done(): - return - case ioStat2 := <-m.DiskIO: - var ioList []model.MonitorIO - for _, io2 := range ioStat2 { - for _, io1 := range ioStat { - if io2.Name == io1.Name { - var itemIO model.MonitorIO - itemIO.Name = io1.Name - if io2.ReadBytes != 0 && io1.ReadBytes != 0 && io2.ReadBytes > io1.ReadBytes { - itemIO.Read = uint64(float64(io2.ReadBytes-io1.ReadBytes) / interval / 60) - } - if io2.WriteBytes != 0 && io1.WriteBytes != 0 && io2.WriteBytes > io1.WriteBytes { - itemIO.Write = uint64(float64(io2.WriteBytes-io1.WriteBytes) / interval / 60) - } - - if io2.ReadCount != 0 && io1.ReadCount != 0 && io2.ReadCount > io1.ReadCount { - itemIO.Count = uint64(float64(io2.ReadCount-io1.ReadCount) / interval / 60) - } - writeCount := uint64(0) - if io2.WriteCount != 0 && io1.WriteCount != 0 && io2.WriteCount > io1.WriteCount { - writeCount = uint64(float64(io2.WriteCount-io1.WriteCount) / interval * 60) - } - if writeCount > itemIO.Count { - itemIO.Count = writeCount - } - - if io2.ReadTime != 0 && io1.ReadTime != 0 && io2.ReadTime > io1.ReadTime { - itemIO.Time = uint64(float64(io2.ReadTime-io1.ReadTime) / interval / 60) - } - writeTime := uint64(0) - if io2.WriteTime != 0 && io1.WriteTime != 0 && io2.WriteTime > io1.WriteTime { - writeTime = uint64(float64(io2.WriteTime-io1.WriteTime) / interval / 60) - } - if writeTime > itemIO.Time { - itemIO.Time = writeTime - } - ioList = append(ioList, itemIO) - break - } - } - } - if err := settingRepo.BatchCreateMonitorIO(ioList); err != nil { - global.LOG.Errorf("Insert io monitoring data failed, err: %v", err) - } - m.DiskIO <- ioStat2 - } - } - } -} - -func (m *MonitorService) saveNetDataToDB(ctx context.Context, interval float64) { - defer close(m.NetIO) - for { - select { - case <-ctx.Done(): - return - case netStat := <-m.NetIO: - select { - case <-ctx.Done(): - return - case netStat2 := <-m.NetIO: - var netList []model.MonitorNetwork - for _, net2 := range netStat2 { - for _, net1 := range netStat { - if net2.Name == net1.Name { - var itemNet model.MonitorNetwork - itemNet.Name = net1.Name - - if net2.BytesSent != 0 && net1.BytesSent != 0 && net2.BytesSent > net1.BytesSent { - itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / interval / 60 - } - if net2.BytesRecv != 0 && net1.BytesRecv != 0 && net2.BytesRecv > net1.BytesRecv { - itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / interval / 60 - } - netList = append(netList, itemNet) - break - } - } - } - - if err := settingRepo.BatchCreateMonitorNet(netList); err != nil { - global.LOG.Errorf("Insert network monitoring data failed, err: %v", err) - } - m.NetIO <- netStat2 - } - } - } -} - -func StartMonitor(removeBefore bool, interval string) error { - if removeBefore { - monitorCancel() - global.Cron.Remove(cron.EntryID(global.MonitorCronID)) - } - intervalItem, err := strconv.Atoi(interval) - if err != nil { - return err - } - - 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 - } - - service.Run() - - go service.saveIODataToDB(ctx, float64(intervalItem)) - go service.saveNetDataToDB(ctx, float64(intervalItem)) - - global.MonitorCronID = monitorID - return nil -} diff --git a/backend/app/service/nginx.go b/backend/app/service/nginx.go deleted file mode 100644 index 0e4ae72e3..000000000 --- a/backend/app/service/nginx.go +++ /dev/null @@ -1,146 +0,0 @@ -package service - -import ( - "fmt" - "io" - "net/http" - "os" - "path" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/utils/compose" - - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/files" -) - -type NginxService struct { -} - -type INginxService interface { - GetNginxConfig() (*response.NginxFile, error) - GetConfigByScope(req request.NginxScopeReq) ([]response.NginxParam, error) - UpdateConfigByScope(req request.NginxConfigUpdate) error - GetStatus() (response.NginxStatus, error) - UpdateConfigFile(req request.NginxConfigFileUpdate) error - ClearProxyCache() error -} - -func NewINginxService() INginxService { - return &NginxService{} -} - -func (n NginxService) GetNginxConfig() (*response.NginxFile, error) { - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return nil, err - } - configPath := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name, "conf", "nginx.conf") - byteContent, err := files.NewFileOp().GetContent(configPath) - if err != nil { - return nil, err - } - return &response.NginxFile{Content: string(byteContent)}, nil -} - -func (n NginxService) GetConfigByScope(req request.NginxScopeReq) ([]response.NginxParam, error) { - keys, ok := dto.ScopeKeyMap[req.Scope] - if !ok || len(keys) == 0 { - return nil, nil - } - return getNginxParamsByKeys(constant.NginxScopeHttp, keys, nil) -} - -func (n NginxService) UpdateConfigByScope(req request.NginxConfigUpdate) error { - keys, ok := dto.ScopeKeyMap[req.Scope] - if !ok || len(keys) == 0 { - return nil - } - return updateNginxConfig(constant.NginxScopeHttp, getNginxParams(req.Params, keys), nil) -} - -func (n NginxService) GetStatus() (response.NginxStatus, error) { - httpPort, _, err := getAppInstallPort(constant.AppOpenresty) - if err != nil { - return response.NginxStatus{}, err - } - url := "http://127.0.0.1/nginx_status" - if httpPort != 80 { - url = fmt.Sprintf("http://127.0.0.1:%v/nginx_status", httpPort) - } - res, err := http.Get(url) - if err != nil { - return response.NginxStatus{}, err - } - defer res.Body.Close() - content, err := io.ReadAll(res.Body) - if err != nil { - return response.NginxStatus{}, err - } - var status response.NginxStatus - resArray := strings.Split(string(content), " ") - status.Active = resArray[2] - status.Accepts = resArray[7] - status.Handled = resArray[8] - status.Requests = resArray[9] - status.Reading = resArray[11] - status.Writing = resArray[13] - status.Waiting = resArray[15] - return status, nil -} - -func (n NginxService) UpdateConfigFile(req request.NginxConfigFileUpdate) error { - fileOp := files.NewFileOp() - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - filePath := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name, "conf", "nginx.conf") - if err != nil { - return err - } - if req.Backup { - backupPath := path.Join(path.Dir(filePath), "bak") - if !fileOp.Stat(backupPath) { - if err := fileOp.CreateDir(backupPath, 0755); err != nil { - return err - } - } - newFile := path.Join(backupPath, "nginx.bak"+"-"+time.Now().Format("2006-01-02-15-04-05")) - if err := fileOp.Copy(filePath, backupPath); err != nil { - return err - } - if err := fileOp.Rename(path.Join(backupPath, "nginx.conf"), newFile); err != nil { - return err - } - } - oldContent, err := os.ReadFile(filePath) - if err != nil { - return err - } - if err = fileOp.WriteFile(filePath, strings.NewReader(req.Content), 0644); err != nil { - return err - } - return nginxCheckAndReload(string(oldContent), filePath, nginxInstall.ContainerName) -} - -func (n NginxService) ClearProxyCache() error { - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return err - } - cacheDir := path.Join(nginxInstall.GetPath(), "www/common/proxy/proxy_cache_dir") - fileOp := files.NewFileOp() - if fileOp.Stat(cacheDir) { - if err = fileOp.CleanDir(cacheDir); err != nil { - return err - } - _, err = compose.Restart(nginxInstall.GetComposePath()) - if err != nil { - return err - } - } - return nil -} diff --git a/backend/app/service/nginx_utils.go b/backend/app/service/nginx_utils.go deleted file mode 100644 index a032257a9..000000000 --- a/backend/app/service/nginx_utils.go +++ /dev/null @@ -1,231 +0,0 @@ -package service - -import ( - "errors" - "fmt" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/1Panel-dev/1Panel/backend/utils/nginx" - "github.com/1Panel-dev/1Panel/backend/utils/nginx/components" - "github.com/1Panel-dev/1Panel/backend/utils/nginx/parser" - "github.com/1Panel-dev/1Panel/cmd/server/nginx_conf" - "os" - "path" - "strings" - "time" -) - -func getNginxFull(website *model.Website) (dto.NginxFull, error) { - var nginxFull dto.NginxFull - nginxInstall, err := getAppInstallByKey("openresty") - if err != nil { - return nginxFull, err - } - nginxFull.Install = nginxInstall - nginxFull.Dir = path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name) - nginxFull.ConfigDir = path.Join(nginxFull.Dir, "conf") - nginxFull.ConfigFile = "nginx.conf" - nginxFull.SiteDir = path.Join(nginxFull.Dir, "www") - - var nginxConfig dto.NginxConfig - nginxConfig.FilePath = path.Join(nginxFull.Dir, "conf", "nginx.conf") - content, err := os.ReadFile(path.Join(nginxFull.ConfigDir, nginxFull.ConfigFile)) - if err != nil { - return nginxFull, err - } - config, err := parser.NewStringParser(string(content)).Parse() - if err != nil { - return dto.NginxFull{}, err - } - config.FilePath = nginxConfig.FilePath - nginxConfig.OldContent = string(content) - nginxConfig.Config = config - - nginxFull.RootConfig = nginxConfig - - if website != nil { - nginxFull.Website = *website - var siteNginxConfig dto.NginxConfig - nginxFileName := website.Alias + ".conf" - siteConfigPath := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name, "conf", "conf.d", nginxFileName) - siteNginxConfig.FilePath = siteConfigPath - siteNginxContent, err := os.ReadFile(siteConfigPath) - if err != nil { - return nginxFull, err - } - siteConfig, err := parser.NewStringParser(string(siteNginxContent)).Parse() - if err != nil { - return dto.NginxFull{}, err - } - siteConfig.FilePath = siteConfigPath - siteNginxConfig.Config = siteConfig - siteNginxConfig.OldContent = string(siteNginxContent) - nginxFull.SiteConfig = siteNginxConfig - } - - return nginxFull, nil -} - -func getNginxParamsByKeys(scope string, keys []string, website *model.Website) ([]response.NginxParam, error) { - nginxFull, err := getNginxFull(website) - if err != nil { - return nil, err - } - var res []response.NginxParam - var block components.IBlock - if scope == constant.NginxScopeHttp { - block = nginxFull.RootConfig.Config.FindHttp() - } else { - block = nginxFull.SiteConfig.Config.FindServers()[0] - } - for _, key := range keys { - dirs := block.FindDirectives(key) - for _, dir := range dirs { - nginxParam := response.NginxParam{ - Name: dir.GetName(), - Params: dir.GetParameters(), - } - res = append(res, nginxParam) - } - if len(dirs) == 0 { - nginxParam := response.NginxParam{ - Name: key, - Params: []string{}, - } - res = append(res, nginxParam) - } - } - return res, nil -} - -func updateNginxConfig(scope string, params []dto.NginxParam, website *model.Website) error { - nginxFull, err := getNginxFull(website) - if err != nil { - return err - } - var block components.IBlock - var config dto.NginxConfig - if scope == constant.NginxScopeHttp { - config = nginxFull.RootConfig - block = nginxFull.RootConfig.Config.FindHttp() - } else if scope == constant.NginxScopeServer { - config = nginxFull.SiteConfig - block = nginxFull.SiteConfig.Config.FindServers()[0] - } else { - config = nginxFull.SiteConfig - block = config.Config.Block - } - - for _, p := range params { - if p.UpdateScope == constant.NginxScopeOut { - config.Config.UpdateDirective(p.Name, p.Params) - } else { - block.UpdateDirective(p.Name, p.Params) - } - } - if err := nginx.WriteConfig(config.Config, nginx.IndentedStyle); err != nil { - return err - } - return nginxCheckAndReload(config.OldContent, config.FilePath, nginxFull.Install.ContainerName) -} - -func deleteNginxConfig(scope string, params []dto.NginxParam, website *model.Website) error { - nginxFull, err := getNginxFull(website) - if err != nil { - return err - } - var block components.IBlock - var config dto.NginxConfig - if scope == constant.NginxScopeHttp { - config = nginxFull.RootConfig - block = nginxFull.RootConfig.Config.FindHttp() - } else if scope == constant.NginxScopeServer { - config = nginxFull.SiteConfig - block = nginxFull.SiteConfig.Config.FindServers()[0] - } else { - config = nginxFull.SiteConfig - block = config.Config.Block - } - - for _, param := range params { - block.RemoveDirective(param.Name, param.Params) - } - - if err := nginx.WriteConfig(config.Config, nginx.IndentedStyle); err != nil { - return err - } - return nginxCheckAndReload(config.OldContent, config.FilePath, nginxFull.Install.ContainerName) -} - -func getNginxParamsFromStaticFile(scope dto.NginxKey, newParams []dto.NginxParam) []dto.NginxParam { - var ( - newConfig = &components.Config{} - err error - ) - - updateScope := "in" - switch scope { - case dto.SSL: - newConfig, err = parser.NewStringParser(string(nginx_conf.SSL)).Parse() - case dto.CACHE: - newConfig, err = parser.NewStringParser(string(nginx_conf.Cache)).Parse() - case dto.ProxyCache: - newConfig, err = parser.NewStringParser(string(nginx_conf.ProxyCache)).Parse() - } - if err != nil { - return nil - } - for _, dir := range newConfig.GetDirectives() { - addParam := dto.NginxParam{ - Name: dir.GetName(), - Params: dir.GetParameters(), - UpdateScope: updateScope, - } - isExist := false - for _, newParam := range newParams { - if newParam.Name == dir.GetName() { - if components.IsRepeatKey(newParam.Name) { - if len(newParam.Params) > 0 && newParam.Params[0] == dir.GetParameters()[0] { - isExist = true - } - } else { - isExist = true - } - } - } - if !isExist { - newParams = append(newParams, addParam) - } - } - return newParams -} - -func opNginx(containerName, operate string) error { - nginxCmd := fmt.Sprintf("docker exec -i %s %s", containerName, "nginx -s reload") - if operate == constant.NginxCheck { - nginxCmd = fmt.Sprintf("docker exec -i %s %s", containerName, "nginx -t") - } - if out, err := cmd.ExecWithTimeOut(nginxCmd, 20*time.Second); err != nil { - if out != "" { - return errors.New(out) - } - return err - } - return nil -} - -func nginxCheckAndReload(oldContent string, filePath string, containerName string) error { - if err := opNginx(containerName, constant.NginxCheck); err != nil { - _ = files.NewFileOp().WriteFile(filePath, strings.NewReader(oldContent), 0644) - return err - } - if err := opNginx(containerName, constant.NginxReload); err != nil { - _ = files.NewFileOp().WriteFile(filePath, strings.NewReader(oldContent), 0644) - return err - } - return nil -} diff --git a/backend/app/service/php_extensions.go b/backend/app/service/php_extensions.go deleted file mode 100644 index adecc15e5..000000000 --- a/backend/app/service/php_extensions.go +++ /dev/null @@ -1,86 +0,0 @@ -package service - -import ( - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" -) - -type PHPExtensionsService struct { -} - -type IPHPExtensionsService interface { - Page(req request.PHPExtensionsSearch) (int64, []response.PHPExtensionsDTO, error) - List() ([]response.PHPExtensionsDTO, error) - Create(req request.PHPExtensionsCreate) error - Update(req request.PHPExtensionsUpdate) error - Delete(req request.PHPExtensionsDelete) error -} - -func NewIPHPExtensionsService() IPHPExtensionsService { - return &PHPExtensionsService{} -} - -func (p PHPExtensionsService) Page(req request.PHPExtensionsSearch) (int64, []response.PHPExtensionsDTO, error) { - var ( - total int64 - extensions []model.PHPExtensions - err error - result []response.PHPExtensionsDTO - ) - total, extensions, err = phpExtensionsRepo.Page(req.Page, req.PageSize) - if err != nil { - return 0, nil, err - } - for _, extension := range extensions { - result = append(result, response.PHPExtensionsDTO{ - PHPExtensions: extension, - }) - } - return total, result, nil -} - -func (p PHPExtensionsService) List() ([]response.PHPExtensionsDTO, error) { - var ( - extensions []model.PHPExtensions - err error - result []response.PHPExtensionsDTO - ) - extensions, err = phpExtensionsRepo.List() - if err != nil { - return nil, err - } - for _, extension := range extensions { - result = append(result, response.PHPExtensionsDTO{ - PHPExtensions: extension, - }) - } - return result, nil -} - -func (p PHPExtensionsService) Create(req request.PHPExtensionsCreate) error { - exist, _ := phpExtensionsRepo.GetFirst(commonRepo.WithByName(req.Name)) - if exist.ID > 0 { - return buserr.New(constant.ErrNameIsExist) - } - extension := model.PHPExtensions{ - Name: req.Name, - Extensions: req.Extensions, - } - return phpExtensionsRepo.Create(&extension) -} - -func (p PHPExtensionsService) Update(req request.PHPExtensionsUpdate) error { - exist, err := phpExtensionsRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - exist.Extensions = req.Extensions - return phpExtensionsRepo.Save(&exist) -} - -func (p PHPExtensionsService) Delete(req request.PHPExtensionsDelete) error { - return phpExtensionsRepo.DeleteBy(commonRepo.WithByID(req.ID)) -} diff --git a/backend/app/service/process.go b/backend/app/service/process.go deleted file mode 100644 index 494b40282..000000000 --- a/backend/app/service/process.go +++ /dev/null @@ -1,27 +0,0 @@ -package service - -import ( - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/shirou/gopsutil/v3/process" -) - -type ProcessService struct{} - -type IProcessService interface { - StopProcess(req request.ProcessReq) error -} - -func NewIProcessService() IProcessService { - return &ProcessService{} -} - -func (p *ProcessService) StopProcess(req request.ProcessReq) error { - proc, err := process.NewProcess(req.PID) - if err != nil { - return err - } - if err := proc.Kill(); err != nil { - return err - } - return nil -} diff --git a/backend/app/service/recycle_bin.go b/backend/app/service/recycle_bin.go deleted file mode 100644 index 02ce52106..000000000 --- a/backend/app/service/recycle_bin.go +++ /dev/null @@ -1,212 +0,0 @@ -package service - -import ( - "fmt" - "math" - "os" - "path" - "regexp" - "strconv" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/shirou/gopsutil/v3/disk" -) - -type RecycleBinService struct { -} - -type IRecycleBinService interface { - Page(search dto.PageInfo) (int64, []response.RecycleBinDTO, error) - Create(create request.RecycleBinCreate) error - Reduce(reduce request.RecycleBinReduce) error - Clear() error -} - -func NewIRecycleBinService() IRecycleBinService { - return &RecycleBinService{} -} - -func (r RecycleBinService) Page(search dto.PageInfo) (int64, []response.RecycleBinDTO, error) { - var ( - result []response.RecycleBinDTO - ) - partitions, err := disk.Partitions(false) - if err != nil { - return 0, nil, err - } - op := files.NewFileOp() - for _, p := range partitions { - dir := path.Join(p.Mountpoint, ".1panel_clash") - if !op.Stat(dir) { - continue - } - clashFiles, err := os.ReadDir(dir) - if err != nil { - return 0, nil, err - } - for _, file := range clashFiles { - if strings.HasPrefix(file.Name(), "_1p_") { - recycleDTO, err := getRecycleBinDTOFromName(file.Name()) - recycleDTO.IsDir = file.IsDir() - recycleDTO.From = dir - if err == nil { - result = append(result, *recycleDTO) - } - } - } - } - startIndex := (search.Page - 1) * search.PageSize - endIndex := startIndex + search.PageSize - - if startIndex > len(result) { - return int64(len(result)), result, nil - } - if endIndex > len(result) { - endIndex = len(result) - } - return int64(len(result)), result[startIndex:endIndex], nil -} - -func (r RecycleBinService) Create(create request.RecycleBinCreate) error { - op := files.NewFileOp() - if !op.Stat(create.SourcePath) { - return buserr.New(constant.ErrLinkPathNotFound) - } - clashDir, err := getClashDir(create.SourcePath) - if err != nil { - return err - } - paths := strings.Split(create.SourcePath, "/") - rNamePre := strings.Join(paths, "_1p_") - deleteTime := time.Now() - openFile, err := op.OpenFile(create.SourcePath) - if err != nil { - return err - } - fileInfo, err := openFile.Stat() - if err != nil { - return err - } - size := 0 - if fileInfo.IsDir() { - sizeF, err := op.GetDirSize(create.SourcePath) - if err != nil { - return err - } - size = int(sizeF) - } else { - size = int(fileInfo.Size()) - } - - rName := fmt.Sprintf("_1p_%s%s_p_%d_%d", "file", rNamePre, size, deleteTime.Unix()) - return op.Mv(create.SourcePath, path.Join(clashDir, rName)) -} - -func (r RecycleBinService) Reduce(reduce request.RecycleBinReduce) error { - filePath := path.Join(reduce.From, reduce.RName) - op := files.NewFileOp() - if !op.Stat(filePath) { - return buserr.New(constant.ErrLinkPathNotFound) - } - recycleBinDTO, err := getRecycleBinDTOFromName(reduce.RName) - if err != nil { - return err - } - if !op.Stat(path.Dir(recycleBinDTO.SourcePath)) { - return buserr.New("ErrSourcePathNotFound") - } - if op.Stat(recycleBinDTO.SourcePath) { - if err = op.RmRf(recycleBinDTO.SourcePath); err != nil { - return err - } - } - return op.Mv(filePath, recycleBinDTO.SourcePath) -} - -func (r RecycleBinService) Clear() error { - partitions, err := disk.Partitions(false) - if err != nil { - return err - } - op := files.NewFileOp() - for _, p := range partitions { - dir := path.Join(p.Mountpoint, ".1panel_clash") - if !op.Stat(dir) { - continue - } - newDir := path.Join(p.Mountpoint, "1panel_clash") - if err := op.Mv(dir, newDir); err != nil { - return err - } - go func() { - _ = op.DeleteDir(newDir) - }() - } - return nil -} - -func getClashDir(realPath string) (string, error) { - partitions, err := disk.Partitions(false) - if err != nil { - return "", err - } - for _, p := range partitions { - if p.Mountpoint == "/" { - continue - } - if strings.HasPrefix(realPath, p.Mountpoint) { - clashDir := path.Join(p.Mountpoint, ".1panel_clash") - if err = createClashDir(path.Join(p.Mountpoint, ".1panel_clash")); err != nil { - return "", err - } - return clashDir, nil - } - } - return constant.RecycleBinDir, createClashDir(constant.RecycleBinDir) -} - -func createClashDir(clashDir string) error { - op := files.NewFileOp() - if !op.Stat(clashDir) { - if err := op.CreateDir(clashDir, 0755); err != nil { - return err - } - } - return nil -} - -func getRecycleBinDTOFromName(filename string) (*response.RecycleBinDTO, error) { - r := regexp.MustCompile(`_1p_file_1p_(.+)_p_(\d+)_(\d+)`) - matches := r.FindStringSubmatch(filename) - if len(matches) != 4 { - return nil, fmt.Errorf("invalid filename format") - } - sourcePath := "/" + strings.ReplaceAll(matches[1], "_1p_", "/") - size, err := strconv.ParseInt(matches[2], 10, 64) - if err != nil { - return nil, err - } - if size < math.MinInt || size > math.MaxInt { - return nil, fmt.Errorf("size out of int range") - } - - deleteTime, err := strconv.ParseInt(matches[3], 10, 64) - if err != nil { - return nil, err - } - return &response.RecycleBinDTO{ - Name: path.Base(sourcePath), - Size: int(size), - Type: "file", - DeleteTime: time.Unix(deleteTime, 0), - SourcePath: sourcePath, - RName: filename, - }, nil -} diff --git a/backend/app/service/runtime.go b/backend/app/service/runtime.go deleted file mode 100644 index 342ab5dad..000000000 --- a/backend/app/service/runtime.go +++ /dev/null @@ -1,618 +0,0 @@ -package service - -import ( - "context" - "encoding/json" - "fmt" - "os" - "path" - "path/filepath" - "regexp" - "strconv" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/app/repo" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - cmd2 "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/compose" - "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/1Panel-dev/1Panel/backend/utils/env" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/pkg/errors" - "github.com/subosito/gotenv" -) - -type RuntimeService struct { -} - -type IRuntimeService interface { - Page(req request.RuntimeSearch) (int64, []response.RuntimeDTO, error) - Create(create request.RuntimeCreate) (*model.Runtime, error) - Delete(delete request.RuntimeDelete) error - Update(req request.RuntimeUpdate) error - Get(id uint) (res *response.RuntimeDTO, err error) - GetNodePackageRunScript(req request.NodePackageReq) ([]response.PackageScripts, error) - OperateRuntime(req request.RuntimeOperate) error - GetNodeModules(req request.NodeModuleReq) ([]response.NodeModule, error) - OperateNodeModules(req request.NodeModuleOperateReq) error - SyncForRestart() error - SyncRuntimeStatus() error - DeleteCheck(installID uint) ([]dto.AppResource, error) -} - -func NewRuntimeService() IRuntimeService { - return &RuntimeService{} -} - -func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, error) { - var ( - opts []repo.DBOption - ) - if create.Name != "" { - opts = append(opts, commonRepo.WithLikeName(create.Name)) - } - if create.Type != "" { - opts = append(opts, commonRepo.WithByType(create.Type)) - } - exist, _ := runtimeRepo.GetFirst(opts...) - if exist != nil { - return nil, buserr.New(constant.ErrNameIsExist) - } - fileOp := files.NewFileOp() - - switch create.Type { - case constant.RuntimePHP: - if create.Resource == constant.ResourceLocal { - runtime := &model.Runtime{ - Name: create.Name, - Resource: create.Resource, - Type: create.Type, - Version: create.Version, - Status: constant.RuntimeNormal, - } - return nil, runtimeRepo.Create(context.Background(), runtime) - } - exist, _ = runtimeRepo.GetFirst(runtimeRepo.WithImage(create.Image)) - if exist != nil { - return nil, buserr.New(constant.ErrImageExist) - } - case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo: - if !fileOp.Stat(create.CodeDir) { - return nil, buserr.New(constant.ErrPathNotFound) - } - create.Install = true - if err := checkPortExist(create.Port); err != nil { - return nil, err - } - for _, export := range create.ExposedPorts { - if err := checkPortExist(export.HostPort); err != nil { - return nil, err - } - } - if containerName, ok := create.Params["CONTAINER_NAME"]; ok { - if err := checkContainerName(containerName.(string)); err != nil { - return nil, err - } - } - } - - appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(create.AppDetailID)) - if err != nil { - return nil, err - } - app, err := appRepo.GetFirst(commonRepo.WithByID(appDetail.AppId)) - if err != nil { - return nil, err - } - - appVersionDir := filepath.Join(app.GetAppResourcePath(), appDetail.Version) - if !fileOp.Stat(appVersionDir) || appDetail.Update { - if err = downloadApp(app, appDetail, nil); err != nil { - return nil, err - } - } - - runtime := &model.Runtime{ - Name: create.Name, - AppDetailID: create.AppDetailID, - Type: create.Type, - Image: create.Image, - Resource: create.Resource, - Version: create.Version, - } - - switch create.Type { - case constant.RuntimePHP: - if err = handlePHP(create, runtime, fileOp, appVersionDir); err != nil { - return nil, err - } - case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo: - runtime.Port = create.Port - if err = handleNodeAndJava(create, runtime, fileOp, appVersionDir); err != nil { - return nil, err - } - } - if err := runtimeRepo.Create(context.Background(), runtime); err != nil { - return nil, err - } - return runtime, nil -} - -func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.RuntimeDTO, error) { - var ( - opts []repo.DBOption - res []response.RuntimeDTO - ) - if req.Name != "" { - opts = append(opts, commonRepo.WithLikeName(req.Name)) - } - if req.Status != "" { - opts = append(opts, runtimeRepo.WithStatus(req.Status)) - } - if req.Type != "" { - opts = append(opts, commonRepo.WithByType(req.Type)) - } - total, runtimes, err := runtimeRepo.Page(req.Page, req.PageSize, opts...) - if err != nil { - return 0, nil, err - } - for _, runtime := range runtimes { - runtimeDTO := response.NewRuntimeDTO(runtime) - runtimeDTO.Params = make(map[string]interface{}) - envs, err := gotenv.Unmarshal(runtime.Env) - if err != nil { - return 0, nil, err - } - for k, v := range envs { - runtimeDTO.Params[k] = v - } - res = append(res, runtimeDTO) - } - return total, res, nil -} - -func (r *RuntimeService) DeleteCheck(runTimeId uint) ([]dto.AppResource, error) { - var res []dto.AppResource - websites, _ := websiteRepo.GetBy(websiteRepo.WithRuntimeID(runTimeId)) - for _, website := range websites { - res = append(res, dto.AppResource{ - Type: "website", - Name: website.PrimaryDomain, - }) - } - return res, nil -} - -func (r *RuntimeService) Delete(runtimeDelete request.RuntimeDelete) error { - runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(runtimeDelete.ID)) - if err != nil { - return err - } - website, _ := websiteRepo.GetFirst(websiteRepo.WithRuntimeID(runtimeDelete.ID)) - if website.ID > 0 { - return buserr.New(constant.ErrDelWithWebsite) - } - if runtime.Resource == constant.ResourceAppstore { - projectDir := runtime.GetPath() - switch runtime.Type { - case constant.RuntimePHP: - client, err := docker.NewClient() - if err != nil { - return err - } - defer client.Close() - imageID, err := client.GetImageIDByName(runtime.Image) - if err != nil { - return err - } - if imageID != "" { - if err := client.DeleteImage(imageID); err != nil { - global.LOG.Errorf("delete image id [%s] error %v", imageID, err) - } - } - case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo: - if out, err := compose.Down(runtime.GetComposePath()); err != nil && !runtimeDelete.ForceDelete { - if out != "" { - return errors.New(out) - } - return err - } - } - if err := files.NewFileOp().DeleteDir(projectDir); err != nil && !runtimeDelete.ForceDelete { - return err - } - } - return runtimeRepo.DeleteBy(commonRepo.WithByID(runtimeDelete.ID)) -} - -func (r *RuntimeService) Get(id uint) (*response.RuntimeDTO, error) { - runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(id)) - if err != nil { - return nil, err - } - - res := response.NewRuntimeDTO(*runtime) - if runtime.Resource == constant.ResourceLocal { - return &res, nil - } - appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(runtime.AppDetailID)) - if err != nil { - return nil, err - } - res.AppID = appDetail.AppId - switch runtime.Type { - case constant.RuntimePHP: - var ( - appForm dto.AppForm - appParams []response.AppParam - ) - if err := json.Unmarshal([]byte(runtime.Params), &appForm); err != nil { - return nil, err - } - envs, err := gotenv.Unmarshal(runtime.Env) - if err != nil { - return nil, err - } - if v, ok := envs["CONTAINER_PACKAGE_URL"]; ok { - res.Source = v - } - for _, form := range appForm.FormFields { - if v, ok := envs[form.EnvKey]; ok { - appParam := response.AppParam{ - Edit: false, - Key: form.EnvKey, - Rule: form.Rule, - Type: form.Type, - Required: form.Required, - } - if form.Edit { - appParam.Edit = true - } - appParam.LabelZh = form.LabelZh - appParam.LabelEn = form.LabelEn - appParam.Multiple = form.Multiple - appParam.Value = v - if form.Type == "select" { - if form.Multiple { - if v == "" { - appParam.Value = []string{} - } else { - appParam.Value = strings.Split(v, ",") - } - } else { - for _, fv := range form.Values { - if fv.Value == v { - appParam.ShowValue = fv.Label - break - } - } - } - appParam.Values = form.Values - } - appParams = append(appParams, appParam) - } - } - res.AppParams = appParams - case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo: - res.Params = make(map[string]interface{}) - envs, err := gotenv.Unmarshal(runtime.Env) - if err != nil { - return nil, err - } - for k, v := range envs { - switch k { - case "NODE_APP_PORT", "PANEL_APP_PORT_HTTP", "JAVA_APP_PORT", "GO_APP_PORT": - port, err := strconv.Atoi(v) - if err != nil { - return nil, err - } - res.Params[k] = port - default: - if strings.Contains(k, "CONTAINER_PORT") || strings.Contains(k, "HOST_PORT") { - if strings.Contains(k, "CONTAINER_PORT") { - r := regexp.MustCompile(`_(\d+)$`) - matches := r.FindStringSubmatch(k) - containerPort, err := strconv.Atoi(v) - if err != nil { - return nil, err - } - hostPort, err := strconv.Atoi(envs[fmt.Sprintf("HOST_PORT_%s", matches[1])]) - if err != nil { - return nil, err - } - res.ExposedPorts = append(res.ExposedPorts, request.ExposedPort{ - ContainerPort: containerPort, - HostPort: hostPort, - }) - } - } else { - res.Params[k] = v - } - } - } - if v, ok := envs["CONTAINER_PACKAGE_URL"]; ok { - res.Source = v - } - } - - return &res, nil -} - -func (r *RuntimeService) Update(req request.RuntimeUpdate) error { - runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - if runtime.Resource == constant.ResourceLocal { - runtime.Version = req.Version - return runtimeRepo.Save(runtime) - } - oldImage := runtime.Image - switch runtime.Type { - case constant.RuntimePHP: - exist, _ := runtimeRepo.GetFirst(runtimeRepo.WithImage(req.Name), runtimeRepo.WithNotId(req.ID)) - if exist != nil { - return buserr.New(constant.ErrImageExist) - } - case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo: - if runtime.Port != req.Port { - if err = checkPortExist(req.Port); err != nil { - return err - } - runtime.Port = req.Port - } - for _, export := range req.ExposedPorts { - if err = checkPortExist(export.HostPort); err != nil { - return err - } - } - if containerName, ok := req.Params["CONTAINER_NAME"]; ok { - envs, err := gotenv.Unmarshal(runtime.Env) - if err != nil { - return err - } - oldContainerName := envs["CONTAINER_NAME"] - if containerName != oldContainerName { - if err := checkContainerName(containerName.(string)); err != nil { - return err - } - } - } - - appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(runtime.AppDetailID)) - if err != nil { - return err - } - app, err := appRepo.GetFirst(commonRepo.WithByID(appDetail.AppId)) - if err != nil { - return err - } - fileOp := files.NewFileOp() - appVersionDir := path.Join(constant.AppResourceDir, app.Resource, app.Key, appDetail.Version) - if !fileOp.Stat(appVersionDir) || appDetail.Update { - if err := downloadApp(app, appDetail, nil); err != nil { - return err - } - _ = fileOp.Rename(path.Join(runtime.GetPath(), "run.sh"), path.Join(runtime.GetPath(), "run.sh.bak")) - _ = fileOp.CopyFile(path.Join(appVersionDir, "run.sh"), runtime.GetPath()) - } - } - - projectDir := path.Join(constant.RuntimeDir, runtime.Type, runtime.Name) - create := request.RuntimeCreate{ - Image: req.Image, - Type: runtime.Type, - Source: req.Source, - Params: req.Params, - CodeDir: req.CodeDir, - Version: req.Version, - NodeConfig: request.NodeConfig{ - Port: req.Port, - Install: true, - ExposedPorts: req.ExposedPorts, - }, - } - composeContent, envContent, _, err := handleParams(create, projectDir) - if err != nil { - return err - } - runtime.Env = string(envContent) - runtime.DockerCompose = string(composeContent) - - switch runtime.Type { - case constant.RuntimePHP: - runtime.Image = req.Image - runtime.Status = constant.RuntimeBuildIng - _ = runtimeRepo.Save(runtime) - client, err := docker.NewClient() - if err != nil { - return err - } - defer client.Close() - imageID, err := client.GetImageIDByName(oldImage) - if err != nil { - return err - } - go buildRuntime(runtime, imageID, req.Rebuild) - case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo: - runtime.Version = req.Version - runtime.CodeDir = req.CodeDir - runtime.Port = req.Port - runtime.Status = constant.RuntimeReCreating - _ = runtimeRepo.Save(runtime) - go reCreateRuntime(runtime) - } - return nil -} - -func (r *RuntimeService) GetNodePackageRunScript(req request.NodePackageReq) ([]response.PackageScripts, error) { - fileOp := files.NewFileOp() - if !fileOp.Stat(req.CodeDir) { - return nil, buserr.New(constant.ErrPathNotFound) - } - if !fileOp.Stat(path.Join(req.CodeDir, "package.json")) { - return nil, buserr.New(constant.ErrPackageJsonNotFound) - } - content, err := fileOp.GetContent(path.Join(req.CodeDir, "package.json")) - if err != nil { - return nil, err - } - var packageMap map[string]interface{} - err = json.Unmarshal(content, &packageMap) - if err != nil { - return nil, err - } - scripts, ok := packageMap["scripts"] - if !ok { - return nil, buserr.New(constant.ErrScriptsNotFound) - } - var packageScripts []response.PackageScripts - for k, v := range scripts.(map[string]interface{}) { - packageScripts = append(packageScripts, response.PackageScripts{ - Name: k, - Script: v.(string), - }) - } - return packageScripts, nil -} - -func (r *RuntimeService) OperateRuntime(req request.RuntimeOperate) error { - runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - defer func() { - if err != nil { - runtime.Status = constant.RuntimeError - runtime.Message = err.Error() - _ = runtimeRepo.Save(runtime) - } - }() - switch req.Operate { - case constant.RuntimeUp: - if err = runComposeCmdWithLog(req.Operate, runtime.GetComposePath(), runtime.GetLogPath()); err != nil { - return err - } - if err = SyncRuntimeContainerStatus(runtime); err != nil { - return err - } - case constant.RuntimeDown: - if err = runComposeCmdWithLog(req.Operate, runtime.GetComposePath(), runtime.GetLogPath()); err != nil { - return err - } - runtime.Status = constant.RuntimeStopped - case constant.RuntimeRestart: - if err = runComposeCmdWithLog(constant.RuntimeDown, runtime.GetComposePath(), runtime.GetLogPath()); err != nil { - return err - } - if err = runComposeCmdWithLog(constant.RuntimeUp, runtime.GetComposePath(), runtime.GetLogPath()); err != nil { - return err - } - if err = SyncRuntimeContainerStatus(runtime); err != nil { - return err - } - } - return runtimeRepo.Save(runtime) -} - -func (r *RuntimeService) GetNodeModules(req request.NodeModuleReq) ([]response.NodeModule, error) { - runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return nil, err - } - var res []response.NodeModule - nodeModulesPath := path.Join(runtime.CodeDir, "node_modules") - fileOp := files.NewFileOp() - if !fileOp.Stat(nodeModulesPath) { - return nil, buserr.New("ErrNodeModulesNotFound") - } - moduleDirs, err := os.ReadDir(nodeModulesPath) - if err != nil { - return nil, err - } - for _, moduleDir := range moduleDirs { - packagePath := path.Join(nodeModulesPath, moduleDir.Name(), "package.json") - if !fileOp.Stat(packagePath) { - continue - } - content, err := fileOp.GetContent(packagePath) - if err != nil { - continue - } - module := response.NodeModule{} - if err := json.Unmarshal(content, &module); err != nil { - continue - } - res = append(res, module) - } - return res, nil -} - -func (r *RuntimeService) OperateNodeModules(req request.NodeModuleOperateReq) error { - runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - containerName, err := env.GetEnvValueByKey(runtime.GetEnvPath(), "CONTAINER_NAME") - if err != nil { - return err - } - cmd := req.PkgManager - switch req.Operate { - case constant.RuntimeInstall: - if req.PkgManager == constant.RuntimeNpm { - cmd += " install" - } else { - cmd += " add" - } - case constant.RuntimeUninstall: - if req.PkgManager == constant.RuntimeNpm { - cmd += " uninstall" - } else { - cmd += " remove" - } - case constant.RuntimeUpdate: - if req.PkgManager == constant.RuntimeNpm { - cmd += " update" - } else { - cmd += " upgrade" - } - } - cmd += " " + req.Module - return cmd2.ExecContainerScript(containerName, cmd, 5*time.Minute) -} - -func (r *RuntimeService) SyncForRestart() error { - runtimes, err := runtimeRepo.List() - if err != nil { - return err - } - for _, runtime := range runtimes { - if runtime.Status == constant.RuntimeBuildIng || runtime.Status == constant.RuntimeReCreating || runtime.Status == constant.RuntimeStarting || runtime.Status == constant.RuntimeCreating { - runtime.Status = constant.SystemRestart - runtime.Message = "System restart causing interrupt" - _ = runtimeRepo.Save(&runtime) - } - } - return nil -} - -func (r *RuntimeService) SyncRuntimeStatus() error { - runtimes, err := runtimeRepo.List() - if err != nil { - return err - } - for _, runtime := range runtimes { - if runtime.Type == constant.RuntimeNode || runtime.Type == constant.RuntimeJava || runtime.Type == constant.RuntimeGo { - _ = SyncRuntimeContainerStatus(&runtime) - } - } - return nil -} diff --git a/backend/app/service/runtime_utils.go b/backend/app/service/runtime_utils.go deleted file mode 100644 index acebcf24d..000000000 --- a/backend/app/service/runtime_utils.go +++ /dev/null @@ -1,436 +0,0 @@ -package service - -import ( - "bytes" - "fmt" - "io" - "net/http" - "os" - "os/exec" - "path" - "path/filepath" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/1Panel-dev/1Panel/backend/utils/files" - httpUtil "github.com/1Panel-dev/1Panel/backend/utils/http" - "github.com/pkg/errors" - "github.com/subosito/gotenv" - "gopkg.in/yaml.v3" -) - -func handleNodeAndJava(create request.RuntimeCreate, runtime *model.Runtime, fileOp files.FileOp, appVersionDir string) (err error) { - runtimeDir := path.Join(constant.RuntimeDir, create.Type) - if err = fileOp.CopyDir(appVersionDir, runtimeDir); err != nil { - return - } - versionDir := path.Join(runtimeDir, filepath.Base(appVersionDir)) - projectDir := path.Join(runtimeDir, create.Name) - defer func() { - if err != nil { - _ = fileOp.DeleteDir(projectDir) - } - }() - if err = fileOp.Rename(versionDir, projectDir); err != nil { - return - } - composeContent, envContent, _, err := handleParams(create, projectDir) - if err != nil { - return - } - runtime.DockerCompose = string(composeContent) - runtime.Env = string(envContent) - runtime.Status = constant.RuntimeCreating - runtime.CodeDir = create.CodeDir - - nodeDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(runtime.AppDetailID)) - if err != nil { - return err - } - - go func() { - if _, _, err := httpUtil.HandleGet(nodeDetail.DownloadCallBackUrl, http.MethodGet, constant.TimeOut5s); err != nil { - global.LOG.Errorf("http request failed(handleNode), err: %v", err) - return - } - }() - go startRuntime(runtime) - - return -} - -func handlePHP(create request.RuntimeCreate, runtime *model.Runtime, fileOp files.FileOp, appVersionDir string) (err error) { - buildDir := path.Join(appVersionDir, "build") - if !fileOp.Stat(buildDir) { - return buserr.New(constant.ErrDirNotFound) - } - runtimeDir := path.Join(constant.RuntimeDir, create.Type) - tempDir := filepath.Join(runtimeDir, fmt.Sprintf("%d", time.Now().UnixNano())) - if err = fileOp.CopyDir(buildDir, tempDir); err != nil { - return - } - oldDir := path.Join(tempDir, "build") - projectDir := path.Join(runtimeDir, create.Name) - defer func() { - if err != nil { - _ = fileOp.DeleteDir(projectDir) - } - }() - if oldDir != projectDir { - if err = fileOp.Rename(oldDir, projectDir); err != nil { - return - } - if err = fileOp.DeleteDir(tempDir); err != nil { - return - } - } - composeContent, envContent, forms, err := handleParams(create, projectDir) - if err != nil { - return - } - runtime.DockerCompose = string(composeContent) - runtime.Env = string(envContent) - runtime.Params = string(forms) - runtime.Status = constant.RuntimeBuildIng - - go buildRuntime(runtime, "", false) - return -} - -func startRuntime(runtime *model.Runtime) { - if err := runComposeCmdWithLog("up", runtime.GetComposePath(), runtime.GetLogPath()); err != nil { - runtime.Status = constant.RuntimeError - runtime.Message = err.Error() - _ = runtimeRepo.Save(runtime) - return - } - - if err := SyncRuntimeContainerStatus(runtime); err != nil { - runtime.Status = constant.RuntimeError - runtime.Message = err.Error() - _ = runtimeRepo.Save(runtime) - return - } -} - -func reCreateRuntime(runtime *model.Runtime) { - var err error - defer func() { - if err != nil { - runtime.Status = constant.RuntimeError - runtime.Message = err.Error() - _ = runtimeRepo.Save(runtime) - } - }() - if err = runComposeCmdWithLog("down", runtime.GetComposePath(), runtime.GetLogPath()); err != nil { - return - } - if err = runComposeCmdWithLog("up", runtime.GetComposePath(), runtime.GetLogPath()); err != nil { - return - } - if err := SyncRuntimeContainerStatus(runtime); err != nil { - return - } -} - -func runComposeCmdWithLog(operate string, composePath string, logPath string) error { - cmd := exec.Command("docker-compose", "-f", composePath, operate) - if operate == "up" { - cmd = exec.Command("docker-compose", "-f", composePath, operate, "-d") - } - logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666) - if err != nil { - global.LOG.Errorf("Failed to open log file: %v", err) - return err - } - defer logFile.Close() - multiWriterStdout := io.MultiWriter(os.Stdout, logFile) - cmd.Stdout = multiWriterStdout - var stderrBuf bytes.Buffer - multiWriterStderr := io.MultiWriter(&stderrBuf, logFile, os.Stderr) - cmd.Stderr = multiWriterStderr - - err = cmd.Run() - if err != nil { - return errors.New(buserr.New(constant.ErrRuntimeStart).Error() + ":" + stderrBuf.String()) - } - return nil -} - -func SyncRuntimeContainerStatus(runtime *model.Runtime) error { - env, err := gotenv.Unmarshal(runtime.Env) - if err != nil { - return err - } - var containerNames []string - if containerName, ok := env["CONTAINER_NAME"]; !ok { - return buserr.New("ErrContainerNameNotFound") - } else { - containerNames = append(containerNames, containerName) - } - cli, err := docker.NewClient() - if err != nil { - return err - } - defer cli.Close() - containers, err := cli.ListContainersByName(containerNames) - if err != nil { - return err - } - if len(containers) == 0 { - return buserr.WithNameAndErr("ErrContainerNotFound", containerNames[0], nil) - } - container := containers[0] - - switch container.State { - case "exited": - runtime.Status = constant.RuntimeError - case "running": - runtime.Status = constant.RuntimeRunning - case "paused": - runtime.Status = constant.RuntimeStopped - default: - if runtime.Status != constant.RuntimeBuildIng { - runtime.Status = constant.RuntimeStopped - } - } - - return runtimeRepo.Save(runtime) -} - -func buildRuntime(runtime *model.Runtime, oldImageID string, rebuild bool) { - runtimePath := runtime.GetPath() - composePath := runtime.GetComposePath() - logPath := path.Join(runtimePath, "build.log") - - logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666) - if err != nil { - global.LOG.Errorf("failed to open log file: %v", err) - return - } - defer func() { - _ = logFile.Close() - }() - - cmd := exec.Command("docker-compose", "-f", composePath, "build") - multiWriterStdout := io.MultiWriter(os.Stdout, logFile) - cmd.Stdout = multiWriterStdout - var stderrBuf bytes.Buffer - multiWriterStderr := io.MultiWriter(&stderrBuf, logFile, os.Stderr) - cmd.Stderr = multiWriterStderr - - err = cmd.Run() - if err != nil { - runtime.Status = constant.RuntimeError - runtime.Message = buserr.New(constant.ErrImageBuildErr).Error() + ":" + stderrBuf.String() - } else { - runtime.Status = constant.RuntimeNormal - runtime.Message = "" - if oldImageID != "" { - client, err := docker.NewClient() - if err == nil { - defer client.Close() - newImageID, err := client.GetImageIDByName(runtime.Image) - if err == nil && newImageID != oldImageID { - global.LOG.Infof("delete imageID [%s] ", oldImageID) - if err := client.DeleteImage(oldImageID); err != nil { - global.LOG.Errorf("delete imageID [%s] error %v", oldImageID, err) - } else { - global.LOG.Infof("delete old image success") - } - } - } else { - global.LOG.Errorf("delete imageID [%s] error %v", oldImageID, err) - } - } - if rebuild && runtime.ID > 0 { - websites, _ := websiteRepo.GetBy(websiteRepo.WithRuntimeID(runtime.ID)) - if len(websites) > 0 { - installService := NewIAppInstalledService() - installMap := make(map[uint]string) - for _, website := range websites { - if website.AppInstallID > 0 { - installMap[website.AppInstallID] = website.PrimaryDomain - } - } - for installID, domain := range installMap { - go func(installID uint, domain string) { - global.LOG.Infof("rebuild php runtime [%s] domain [%s]", runtime.Name, domain) - if err := installService.Operate(request.AppInstalledOperate{ - InstallId: installID, - Operate: constant.Rebuild, - }); err != nil { - global.LOG.Errorf("rebuild php runtime [%s] domain [%s] error %v", runtime.Name, domain, err) - } - }(installID, domain) - } - } - } - } - _ = runtimeRepo.Save(runtime) -} - -func handleParams(create request.RuntimeCreate, projectDir string) (composeContent []byte, envContent []byte, forms []byte, err error) { - fileOp := files.NewFileOp() - composeContent, err = fileOp.GetContent(path.Join(projectDir, "docker-compose.yml")) - if err != nil { - return - } - envPath := path.Join(projectDir, ".env") - if !fileOp.Stat(envPath) { - _ = fileOp.CreateFile(envPath) - } - env, err := gotenv.Read(envPath) - if err != nil { - return - } - switch create.Type { - case constant.RuntimePHP: - create.Params["IMAGE_NAME"] = create.Image - forms, err = fileOp.GetContent(path.Join(projectDir, "config.json")) - if err != nil { - return - } - if extends, ok := create.Params["PHP_EXTENSIONS"]; ok { - if extendsArray, ok := extends.([]interface{}); ok { - strArray := make([]string, len(extendsArray)) - for i, v := range extendsArray { - strArray[i] = strings.ToLower(fmt.Sprintf("%v", v)) - } - create.Params["PHP_EXTENSIONS"] = strings.Join(strArray, ",") - } - } - create.Params["CONTAINER_PACKAGE_URL"] = create.Source - case constant.RuntimeNode: - create.Params["CODE_DIR"] = create.CodeDir - create.Params["NODE_VERSION"] = create.Version - create.Params["PANEL_APP_PORT_HTTP"] = create.Port - if create.NodeConfig.Install { - create.Params["RUN_INSTALL"] = "1" - } else { - create.Params["RUN_INSTALL"] = "0" - } - create.Params["CONTAINER_PACKAGE_URL"] = create.Source - - composeContent, err = handleCompose(env, composeContent, create, projectDir) - if err != nil { - return - } - case constant.RuntimeJava: - create.Params["CODE_DIR"] = create.CodeDir - create.Params["JAVA_VERSION"] = create.Version - create.Params["PANEL_APP_PORT_HTTP"] = create.Port - composeContent, err = handleCompose(env, composeContent, create, projectDir) - if err != nil { - return - } - case constant.RuntimeGo: - create.Params["CODE_DIR"] = create.CodeDir - create.Params["GO_VERSION"] = create.Version - create.Params["PANEL_APP_PORT_HTTP"] = create.Port - composeContent, err = handleCompose(env, composeContent, create, projectDir) - if err != nil { - return - } - } - - newMap := make(map[string]string) - handleMap(create.Params, newMap) - for k, v := range newMap { - env[k] = v - } - - envStr, err := gotenv.Marshal(env) - if err != nil { - return - } - if err = gotenv.Write(env, envPath); err != nil { - return - } - envContent = []byte(envStr) - return -} - -func handleCompose(env gotenv.Env, composeContent []byte, create request.RuntimeCreate, projectDir string) (composeByte []byte, err error) { - existMap := make(map[string]interface{}) - composeMap := make(map[string]interface{}) - if err = yaml.Unmarshal(composeContent, &composeMap); err != nil { - return - } - services, serviceValid := composeMap["services"].(map[string]interface{}) - if !serviceValid { - err = buserr.New(constant.ErrFileParse) - return - } - serviceName := "" - serviceValue := make(map[string]interface{}) - for name, service := range services { - serviceName = name - serviceValue = service.(map[string]interface{}) - _, ok := serviceValue["ports"].([]interface{}) - if ok { - var ports []interface{} - - switch create.Type { - case constant.RuntimeNode: - ports = append(ports, "${HOST_IP}:${PANEL_APP_PORT_HTTP}:${NODE_APP_PORT}") - case constant.RuntimeJava: - ports = append(ports, "${HOST_IP}:${PANEL_APP_PORT_HTTP}:${JAVA_APP_PORT}") - case constant.RuntimeGo: - ports = append(ports, "${HOST_IP}:${PANEL_APP_PORT_HTTP}:${GO_APP_PORT}") - - } - - for i, port := range create.ExposedPorts { - containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i) - hostPortStr := fmt.Sprintf("HOST_PORT_%d", i) - existMap[containerPortStr] = struct{}{} - existMap[hostPortStr] = struct{}{} - ports = append(ports, fmt.Sprintf("${HOST_IP}:${%s}:${%s}", hostPortStr, containerPortStr)) - create.Params[containerPortStr] = port.ContainerPort - create.Params[hostPortStr] = port.HostPort - } - serviceValue["ports"] = ports - } - break - } - for k := range env { - if strings.Contains(k, "CONTAINER_PORT_") || strings.Contains(k, "HOST_PORT_") { - if _, ok := existMap[k]; !ok { - delete(env, k) - } - } - } - - services[serviceName] = serviceValue - composeMap["services"] = services - composeByte, err = yaml.Marshal(composeMap) - if err != nil { - return - } - fileOp := files.NewFileOp() - _ = fileOp.SaveFile(path.Join(projectDir, "docker-compose.yml"), string(composeByte), 0644) - return -} - -func checkContainerName(name string) error { - dockerCli, err := docker.NewClient() - if err != nil { - return err - } - defer dockerCli.Close() - names, err := dockerCli.ListContainersByName([]string{name}) - if err != nil { - return err - } - if len(names) > 0 { - return buserr.New(constant.ErrContainerName) - } - return nil -} diff --git a/backend/app/service/setting.go b/backend/app/service/setting.go deleted file mode 100644 index 9cb8518be..000000000 --- a/backend/app/service/setting.go +++ /dev/null @@ -1,86 +0,0 @@ -package service - -import ( - "encoding/json" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/robfig/cron/v3" -) - -type SettingService struct{} - -type ISettingService interface { - GetSettingInfo() (*dto.SettingInfo, error) - Update(key, value string) error -} - -func NewISettingService() ISettingService { - return &SettingService{} -} - -func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) { - setting, err := settingRepo.GetList() - if err != nil { - return nil, constant.ErrRecordNotFound - } - settingMap := make(map[string]string) - for _, set := range setting { - settingMap[set.Key] = set.Value - } - var info dto.SettingInfo - arr, err := json.Marshal(settingMap) - if err != nil { - return nil, err - } - if err := json.Unmarshal(arr, &info); err != nil { - return nil, err - } - - info.LocalTime = time.Now().Format("2006-01-02 15:04:05 MST -0700") - return &info, err -} - -func (u *SettingService) Update(key, value string) error { - switch key { - case "MonitorStatus": - if value == "enable" && global.MonitorCronID == 0 { - interval, err := settingRepo.Get(settingRepo.WithByKey("MonitorInterval")) - if err != nil { - return err - } - if err := StartMonitor(false, interval.Value); err != nil { - return err - } - } - if value == "disable" && global.MonitorCronID != 0 { - monitorCancel() - global.Cron.Remove(cron.EntryID(global.MonitorCronID)) - global.MonitorCronID = 0 - } - case "MonitorInterval": - status, err := settingRepo.Get(settingRepo.WithByKey("MonitorStatus")) - if err != nil { - return err - } - if status.Value == "enable" && global.MonitorCronID != 0 { - if err := StartMonitor(true, value); err != nil { - return err - } - } - case "AppStoreLastModified": - exist, _ := settingRepo.Get(settingRepo.WithByKey("AppStoreLastModified")) - if exist.ID == 0 { - _ = settingRepo.Create("AppStoreLastModified", value) - return nil - } - } - - if err := settingRepo.Update(key, value); err != nil { - return err - } - - return nil -} diff --git a/backend/app/service/snapshot.go b/backend/app/service/snapshot.go deleted file mode 100644 index 07f14bfdd..000000000 --- a/backend/app/service/snapshot.go +++ /dev/null @@ -1,556 +0,0 @@ -package service - -import ( - "context" - "encoding/json" - "fmt" - "os" - "path" - "strings" - "sync" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/compose" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/jinzhu/copier" - "github.com/pkg/errors" - "github.com/shirou/gopsutil/v3/host" -) - -type SnapshotService struct { - OriginalPath string -} - -type ISnapshotService interface { - SearchWithPage(req dto.SearchWithPage) (int64, interface{}, error) - SnapshotCreate(req dto.SnapshotCreate) error - SnapshotRecover(req dto.SnapshotRecover) error - SnapshotRollback(req dto.SnapshotRecover) error - SnapshotImport(req dto.SnapshotImport) error - Delete(req dto.SnapshotBatchDelete) error - - LoadSnapShotStatus(id uint) (*dto.SnapshotStatus, error) - - UpdateDescription(req dto.UpdateDescription) error - readFromJson(path string) (SnapshotJson, error) - - HandleSnapshot(isCronjob bool, logPath string, req dto.SnapshotCreate, timeNow string, secret string) (string, error) -} - -func NewISnapshotService() ISnapshotService { - return &SnapshotService{} -} - -func (u *SnapshotService) SearchWithPage(req dto.SearchWithPage) (int64, interface{}, error) { - total, systemBackups, err := snapshotRepo.Page(req.Page, req.PageSize, commonRepo.WithLikeName(req.Info)) - if err != nil { - return 0, nil, err - } - dtoSnap, err := loadSnapSize(systemBackups) - if err != nil { - return 0, nil, err - } - return total, dtoSnap, err -} - -func (u *SnapshotService) SnapshotImport(req dto.SnapshotImport) error { - if len(req.Names) == 0 { - return fmt.Errorf("incorrect snapshot request body: %v", req.Names) - } - for _, snapName := range req.Names { - snap, _ := snapshotRepo.Get(commonRepo.WithByName(strings.ReplaceAll(snapName, ".tar.gz", ""))) - if snap.ID != 0 { - return constant.ErrRecordExist - } - } - for _, snap := range req.Names { - shortName := strings.TrimPrefix(snap, "snapshot_") - nameItems := strings.Split(shortName, "_") - if !strings.HasPrefix(shortName, "1panel_v") || !strings.HasSuffix(shortName, ".tar.gz") || len(nameItems) < 3 { - return fmt.Errorf("incorrect snapshot name format of %s", shortName) - } - if strings.HasSuffix(snap, ".tar.gz") { - snap = strings.ReplaceAll(snap, ".tar.gz", "") - } - itemSnap := model.Snapshot{ - Name: snap, - From: req.From, - DefaultDownload: req.From, - Version: nameItems[1], - Description: req.Description, - Status: constant.StatusSuccess, - } - if err := snapshotRepo.Create(&itemSnap); err != nil { - return err - } - } - return nil -} - -func (u *SnapshotService) UpdateDescription(req dto.UpdateDescription) error { - return snapshotRepo.Update(req.ID, map[string]interface{}{"description": req.Description}) -} - -func (u *SnapshotService) LoadSnapShotStatus(id uint) (*dto.SnapshotStatus, error) { - var data dto.SnapshotStatus - status, err := snapshotRepo.GetStatus(id) - if err != nil { - return nil, err - } - if err := copier.Copy(&data, &status); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - return &data, nil -} - -type SnapshotJson struct { - OldBaseDir string `json:"oldBaseDir"` - OldDockerDataDir string `json:"oldDockerDataDir"` - OldBackupDataDir string `json:"oldBackupDataDir"` - OldPanelDataDir string `json:"oldPanelDataDir"` - - BaseDir string `json:"baseDir"` - DockerDataDir string `json:"dockerDataDir"` - BackupDataDir string `json:"backupDataDir"` - PanelDataDir string `json:"panelDataDir"` - LiveRestoreEnabled bool `json:"liveRestoreEnabled"` -} - -func (u *SnapshotService) SnapshotCreate(req dto.SnapshotCreate) error { - if _, err := u.HandleSnapshot(false, "", req, time.Now().Format(constant.DateTimeSlimLayout), req.Secret); err != nil { - return err - } - return nil -} - -func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error { - global.LOG.Info("start to recover panel by snapshot now") - snap, err := snapshotRepo.Get(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - if hasOs(snap.Name) && !strings.Contains(snap.Name, loadOs()) { - return fmt.Errorf("restoring snapshots(%s) between different server architectures(%s) is not supported", snap.Name, loadOs()) - } - if !req.IsNew && len(snap.InterruptStep) != 0 && len(snap.RollbackStatus) != 0 { - return fmt.Errorf("the snapshot has been rolled back and cannot be restored again") - } - - baseDir := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("system/%s", snap.Name)) - if _, err := os.Stat(baseDir); err != nil && os.IsNotExist(err) { - _ = os.MkdirAll(baseDir, os.ModePerm) - } - - _ = snapshotRepo.Update(snap.ID, map[string]interface{}{"recover_status": constant.StatusWaiting}) - _ = settingRepo.Update("SystemStatus", "Recovering") - go u.HandleSnapshotRecover(snap, true, req) - return nil -} - -func (u *SnapshotService) SnapshotRollback(req dto.SnapshotRecover) error { - global.LOG.Info("start to rollback now") - snap, err := snapshotRepo.Get(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - req.IsNew = false - snap.InterruptStep = "Readjson" - go u.HandleSnapshotRecover(snap, false, req) - return nil -} - -func (u *SnapshotService) readFromJson(path string) (SnapshotJson, error) { - var snap SnapshotJson - if _, err := os.Stat(path); err != nil { - return snap, fmt.Errorf("find snapshot json file in recover package failed, err: %v", err) - } - fileByte, err := os.ReadFile(path) - if err != nil { - return snap, fmt.Errorf("read file from path %s failed, err: %v", path, err) - } - if err := json.Unmarshal(fileByte, &snap); err != nil { - return snap, fmt.Errorf("unmarshal snapjson failed, err: %v", err) - } - return snap, nil -} - -func (u *SnapshotService) HandleSnapshot(isCronjob bool, logPath string, req dto.SnapshotCreate, timeNow string, secret string) (string, error) { - localDir, err := loadLocalDir() - if err != nil { - return "", err - } - var ( - rootDir string - snap model.Snapshot - snapStatus model.SnapshotStatus - ) - - if req.ID == 0 { - versionItem, _ := settingRepo.Get(settingRepo.WithByKey("SystemVersion")) - - name := fmt.Sprintf("1panel_%s_%s_%s", versionItem.Value, loadOs(), timeNow) - if isCronjob { - name = fmt.Sprintf("snapshot_1panel_%s_%s_%s", versionItem.Value, loadOs(), timeNow) - } - rootDir = path.Join(localDir, "system", name) - - snap = model.Snapshot{ - Name: name, - Description: req.Description, - From: req.From, - DefaultDownload: req.DefaultDownload, - Version: versionItem.Value, - Status: constant.StatusWaiting, - } - _ = snapshotRepo.Create(&snap) - snapStatus.SnapID = snap.ID - _ = snapshotRepo.CreateStatus(&snapStatus) - } else { - snap, err = snapshotRepo.Get(commonRepo.WithByID(req.ID)) - if err != nil { - return "", err - } - _ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusWaiting}) - snapStatus, _ = snapshotRepo.GetStatus(snap.ID) - if snapStatus.ID == 0 { - snapStatus.SnapID = snap.ID - _ = snapshotRepo.CreateStatus(&snapStatus) - } - rootDir = path.Join(localDir, fmt.Sprintf("system/%s", snap.Name)) - } - - var wg sync.WaitGroup - itemHelper := snapHelper{SnapID: snap.ID, Status: &snapStatus, Wg: &wg, FileOp: files.NewFileOp(), Ctx: context.Background()} - backupPanelDir := path.Join(rootDir, "1panel") - _ = os.MkdirAll(backupPanelDir, os.ModePerm) - backupDockerDir := path.Join(rootDir, "docker") - _ = os.MkdirAll(backupDockerDir, os.ModePerm) - - jsonItem := SnapshotJson{ - BaseDir: global.CONF.System.BaseDir, - BackupDataDir: localDir, - PanelDataDir: path.Join(global.CONF.System.BaseDir, "1panel"), - } - loadLogByStatus(snapStatus, logPath) - if snapStatus.PanelInfo != constant.StatusDone { - wg.Add(1) - go snapJson(itemHelper, jsonItem, rootDir) - } - if snapStatus.Panel != constant.StatusDone { - wg.Add(1) - go snapPanel(itemHelper, backupPanelDir) - } - if snapStatus.DaemonJson != constant.StatusDone { - wg.Add(1) - go snapDaemonJson(itemHelper, backupDockerDir) - } - if snapStatus.AppData != constant.StatusDone { - wg.Add(1) - go snapAppData(itemHelper, backupDockerDir) - } - if snapStatus.BackupData != constant.StatusDone { - wg.Add(1) - go snapBackup(itemHelper, localDir, backupPanelDir) - } - - if !isCronjob { - go func() { - wg.Wait() - if !checkIsAllDone(snap.ID) { - _ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusFailed}) - return - } - if snapStatus.PanelData != constant.StatusDone { - snapPanelData(itemHelper, localDir, backupPanelDir) - } - if snapStatus.PanelData != constant.StatusDone { - _ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusFailed}) - return - } - if snapStatus.Compress != constant.StatusDone { - snapCompress(itemHelper, rootDir, secret) - } - if snapStatus.Compress != constant.StatusDone { - _ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusFailed}) - return - } - if snapStatus.Upload != constant.StatusDone { - snapUpload(itemHelper, req.From, fmt.Sprintf("%s.tar.gz", rootDir)) - } - if snapStatus.Upload != constant.StatusDone { - _ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusFailed}) - return - } - _ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusSuccess}) - }() - return "", nil - } - wg.Wait() - if !checkIsAllDone(snap.ID) { - _ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusFailed}) - loadLogByStatus(snapStatus, logPath) - return snap.Name, fmt.Errorf("snapshot %s backup failed", snap.Name) - } - loadLogByStatus(snapStatus, logPath) - snapPanelData(itemHelper, localDir, backupPanelDir) - if snapStatus.PanelData != constant.StatusDone { - _ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusFailed}) - loadLogByStatus(snapStatus, logPath) - return snap.Name, fmt.Errorf("snapshot %s 1panel data failed", snap.Name) - } - loadLogByStatus(snapStatus, logPath) - snapCompress(itemHelper, rootDir, secret) - if snapStatus.Compress != constant.StatusDone { - _ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusFailed}) - loadLogByStatus(snapStatus, logPath) - return snap.Name, fmt.Errorf("snapshot %s compress failed", snap.Name) - } - loadLogByStatus(snapStatus, logPath) - snapUpload(itemHelper, req.From, fmt.Sprintf("%s.tar.gz", rootDir)) - if snapStatus.Upload != constant.StatusDone { - _ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusFailed}) - loadLogByStatus(snapStatus, logPath) - return snap.Name, fmt.Errorf("snapshot %s upload failed", snap.Name) - } - _ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusSuccess}) - loadLogByStatus(snapStatus, logPath) - return snap.Name, nil -} - -func (u *SnapshotService) Delete(req dto.SnapshotBatchDelete) error { - snaps, _ := snapshotRepo.GetList(commonRepo.WithIdsIn(req.Ids)) - for _, snap := range snaps { - if req.DeleteWithFile { - targetAccounts, err := loadClientMap(snap.From) - if err != nil { - return err - } - for _, item := range targetAccounts { - global.LOG.Debugf("remove snapshot file %s.tar.gz from %s", snap.Name, item.backType) - _, _ = item.client.Delete(path.Join(item.backupPath, "system_snapshot", snap.Name+".tar.gz")) - } - } - - _ = snapshotRepo.DeleteStatus(snap.ID) - if err := snapshotRepo.Delete(commonRepo.WithByID(snap.ID)); err != nil { - return err - } - } - return nil -} - -func updateRecoverStatus(id uint, isRecover bool, interruptStep, status, message string) { - if isRecover { - if status != constant.StatusSuccess { - global.LOG.Errorf("recover failed, err: %s", message) - } - if err := snapshotRepo.Update(id, map[string]interface{}{ - "interrupt_step": interruptStep, - "recover_status": status, - "recover_message": message, - "last_recovered_at": time.Now().Format(constant.DateTimeLayout), - }); err != nil { - global.LOG.Errorf("update snap recover status failed, err: %v", err) - } - _ = settingRepo.Update("SystemStatus", "Free") - return - } - _ = settingRepo.Update("SystemStatus", "Free") - if status == constant.StatusSuccess { - if err := snapshotRepo.Update(id, map[string]interface{}{ - "recover_status": "", - "recover_message": "", - "interrupt_step": "", - "rollback_status": "", - "rollback_message": "", - "last_rollbacked_at": time.Now().Format(constant.DateTimeLayout), - }); err != nil { - global.LOG.Errorf("update snap recover status failed, err: %v", err) - } - return - } - global.LOG.Errorf("rollback failed, err: %s", message) - if err := snapshotRepo.Update(id, map[string]interface{}{ - "rollback_status": status, - "rollback_message": message, - "last_rollbacked_at": time.Now().Format(constant.DateTimeLayout), - }); err != nil { - global.LOG.Errorf("update snap recover status failed, err: %v", err) - } -} - -func (u *SnapshotService) handleUnTar(sourceDir, targetDir string, secret string) error { - if _, err := os.Stat(targetDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(targetDir, os.ModePerm); err != nil { - return err - } - } - commands := "" - if len(secret) != 0 { - extraCmd := "openssl enc -d -aes-256-cbc -k '" + secret + "' -in " + sourceDir + " | " - commands = fmt.Sprintf("%s tar -zxvf - -C %s", extraCmd, targetDir+" > /dev/null 2>&1") - global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" %s ", secret), "******")) - } else { - commands = fmt.Sprintf("tar zxvfC %s %s", sourceDir, targetDir) - global.LOG.Debug(commands) - } - stdout, err := cmd.ExecWithTimeOut(commands, 30*time.Minute) - if err != nil { - if len(stdout) != 0 { - global.LOG.Errorf("do handle untar failed, stdout: %s, err: %v", stdout, err) - return fmt.Errorf("do handle untar failed, stdout: %s, err: %v", stdout, err) - } - } - return nil -} - -func rebuildAllAppInstall() error { - global.LOG.Debug("start to rebuild all app") - appInstalls, err := appInstallRepo.ListBy() - if err != nil { - global.LOG.Errorf("get all app installed for rebuild failed, err: %v", err) - return err - } - var wg sync.WaitGroup - for i := 0; i < len(appInstalls); i++ { - wg.Add(1) - appInstalls[i].Status = constant.Rebuilding - _ = appInstallRepo.Save(context.Background(), &appInstalls[i]) - go func(app model.AppInstall) { - defer wg.Done() - dockerComposePath := app.GetComposePath() - out, err := compose.Down(dockerComposePath) - if err != nil { - _ = handleErr(app, err, out) - return - } - out, err = compose.Up(dockerComposePath) - if err != nil { - _ = handleErr(app, err, out) - return - } - app.Status = constant.Running - _ = appInstallRepo.Save(context.Background(), &app) - }(appInstalls[i]) - } - wg.Wait() - return nil -} - -func checkIsAllDone(snapID uint) bool { - status, err := snapshotRepo.GetStatus(snapID) - if err != nil { - return false - } - isOK, _ := checkAllDone(status) - return isOK -} - -func checkAllDone(status model.SnapshotStatus) (bool, string) { - if status.Panel != constant.StatusDone { - return false, status.Panel - } - if status.PanelInfo != constant.StatusDone { - return false, status.PanelInfo - } - if status.DaemonJson != constant.StatusDone { - return false, status.DaemonJson - } - if status.AppData != constant.StatusDone { - return false, status.AppData - } - if status.BackupData != constant.StatusDone { - return false, status.BackupData - } - return true, "" -} - -func loadLogByStatus(status model.SnapshotStatus, logPath string) { - logs := "" - logs += fmt.Sprintf("Write 1Panel basic information: %s \n", status.PanelInfo) - logs += fmt.Sprintf("Backup 1Panel system files: %s \n", status.Panel) - logs += fmt.Sprintf("Backup Docker configuration file: %s \n", status.DaemonJson) - logs += fmt.Sprintf("Backup installed apps from 1Panel: %s \n", status.AppData) - logs += fmt.Sprintf("Backup 1Panel data directory: %s \n", status.PanelData) - logs += fmt.Sprintf("Backup local backup directory for 1Panel: %s \n", status.BackupData) - logs += fmt.Sprintf("Create snapshot file: %s \n", status.Compress) - logs += fmt.Sprintf("Snapshot size: %s \n", status.Size) - logs += fmt.Sprintf("Upload snapshot file: %s \n", status.Upload) - - file, err := os.OpenFile(logPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) - if err != nil { - return - } - defer file.Close() - _, _ = file.Write([]byte(logs)) -} - -func hasOs(name string) bool { - return strings.Contains(name, "amd64") || - strings.Contains(name, "arm64") || - strings.Contains(name, "armv7") || - strings.Contains(name, "ppc64le") || - strings.Contains(name, "s390x") -} - -func loadOs() string { - hostInfo, _ := host.Info() - switch hostInfo.KernelArch { - case "x86_64": - return "amd64" - case "armv7l": - return "armv7" - default: - return hostInfo.KernelArch - } -} - -func loadSnapSize(records []model.Snapshot) ([]dto.SnapshotInfo, error) { - var datas []dto.SnapshotInfo - clientMap := make(map[string]loadSizeHelper) - var wg sync.WaitGroup - for i := 0; i < len(records); i++ { - var item dto.SnapshotInfo - if err := copier.Copy(&item, &records[i]); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - itemPath := fmt.Sprintf("system_snapshot/%s.tar.gz", item.Name) - if _, ok := clientMap[records[i].DefaultDownload]; !ok { - backup, err := backupRepo.Get(commonRepo.WithByType(records[i].DefaultDownload)) - if err != nil { - global.LOG.Errorf("load backup model %s from db failed, err: %v", records[i].DefaultDownload, err) - clientMap[records[i].DefaultDownload] = loadSizeHelper{} - datas = append(datas, item) - continue - } - client, err := NewIBackupService().NewClient(&backup) - if err != nil { - global.LOG.Errorf("load backup client %s from db failed, err: %v", records[i].DefaultDownload, err) - clientMap[records[i].DefaultDownload] = loadSizeHelper{} - datas = append(datas, item) - continue - } - item.Size, _ = client.Size(path.Join(strings.TrimLeft(backup.BackupPath, "/"), itemPath)) - datas = append(datas, item) - clientMap[records[i].DefaultDownload] = loadSizeHelper{backupPath: strings.TrimLeft(backup.BackupPath, "/"), client: client, isOk: true} - continue - } - if clientMap[records[i].DefaultDownload].isOk { - wg.Add(1) - go func(index int) { - item.Size, _ = clientMap[records[index].DefaultDownload].client.Size(path.Join(clientMap[records[index].DefaultDownload].backupPath, itemPath)) - datas = append(datas, item) - wg.Done() - }(i) - } else { - datas = append(datas, item) - } - } - wg.Wait() - return datas, nil -} diff --git a/backend/app/service/snapshot_create.go b/backend/app/service/snapshot_create.go deleted file mode 100644 index 9649326c0..000000000 --- a/backend/app/service/snapshot_create.go +++ /dev/null @@ -1,280 +0,0 @@ -package service - -import ( - "context" - "encoding/json" - "fmt" - "os" - "path" - "regexp" - "strings" - "sync" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/files" -) - -type snapHelper struct { - SnapID uint - Status *model.SnapshotStatus - Ctx context.Context - FileOp files.FileOp - Wg *sync.WaitGroup -} - -func snapJson(snap snapHelper, snapJson SnapshotJson, targetDir string) { - defer snap.Wg.Done() - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"panel_info": constant.Running}) - status := constant.StatusDone - remarkInfo, _ := json.MarshalIndent(snapJson, "", "\t") - if err := os.WriteFile(fmt.Sprintf("%s/snapshot.json", targetDir), remarkInfo, 0640); err != nil { - status = err.Error() - } - snap.Status.PanelInfo = status - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"panel_info": status}) -} - -func snapPanel(snap snapHelper, targetDir string) { - defer snap.Wg.Done() - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"panel": constant.Running}) - status := constant.StatusDone - if err := common.CopyFile("/usr/local/bin/1panel", path.Join(targetDir, "1panel")); err != nil { - status = err.Error() - } - - if err := common.CopyFile("/usr/local/bin/1pctl", targetDir); err != nil { - status = err.Error() - } - - if err := common.CopyFile("/etc/systemd/system/1panel.service", targetDir); err != nil { - status = err.Error() - } - snap.Status.Panel = status - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"panel": status}) -} - -func snapDaemonJson(snap snapHelper, targetDir string) { - defer snap.Wg.Done() - status := constant.StatusDone - if !snap.FileOp.Stat("/etc/docker/daemon.json") { - snap.Status.DaemonJson = status - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"daemon_json": status}) - return - } - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"daemon_json": constant.Running}) - if err := common.CopyFile("/etc/docker/daemon.json", targetDir); err != nil { - status = err.Error() - } - snap.Status.DaemonJson = status - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"daemon_json": status}) -} - -func snapAppData(snap snapHelper, targetDir string) { - defer snap.Wg.Done() - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"app_data": constant.Running}) - appInstalls, err := appInstallRepo.ListBy() - if err != nil { - snap.Status.AppData = err.Error() - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"app_data": err.Error()}) - return - } - runtimes, err := runtimeRepo.List() - if err != nil { - snap.Status.AppData = err.Error() - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"app_data": err.Error()}) - return - } - imageRegex := regexp.MustCompile(`image:\s*(.*)`) - var imageSaveList []string - existStr, _ := cmd.Exec("docker images | awk '{print $1\":\"$2}' | grep -v REPOSITORY:TAG") - existImages := strings.Split(existStr, "\n") - duplicateMap := make(map[string]bool) - for _, app := range appInstalls { - matches := imageRegex.FindAllStringSubmatch(app.DockerCompose, -1) - for _, match := range matches { - for _, existImage := range existImages { - if match[1] == existImage && !duplicateMap[match[1]] { - imageSaveList = append(imageSaveList, match[1]) - duplicateMap[match[1]] = true - } - } - } - } - for _, runtime := range runtimes { - for _, existImage := range existImages { - if runtime.Image == existImage && !duplicateMap[runtime.Image] { - imageSaveList = append(imageSaveList, runtime.Image) - duplicateMap[runtime.Image] = true - } - } - } - - if len(imageSaveList) != 0 { - global.LOG.Debugf("docker save %s | gzip -c > %s", strings.Join(imageSaveList, " "), path.Join(targetDir, "docker_image.tar")) - std, err := cmd.Execf("docker save %s | gzip -c > %s", strings.Join(imageSaveList, " "), path.Join(targetDir, "docker_image.tar")) - if err != nil { - snap.Status.AppData = err.Error() - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"app_data": std}) - return - } - } - snap.Status.AppData = constant.StatusDone - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"app_data": constant.StatusDone}) -} - -func snapBackup(snap snapHelper, localDir, targetDir string) { - defer snap.Wg.Done() - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"backup_data": constant.Running}) - status := constant.StatusDone - if err := handleSnapTar(localDir, targetDir, "1panel_backup.tar.gz", "./system;./system_snapshot;", ""); err != nil { - status = err.Error() - } - snap.Status.BackupData = status - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"backup_data": status}) -} - -func snapPanelData(snap snapHelper, localDir, targetDir string) { - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"panel_data": constant.Running}) - status := constant.StatusDone - dataDir := path.Join(global.CONF.System.BaseDir, "1panel") - exclusionRules := "./tmp;./log;./cache;./db/1Panel.db-*;" - if strings.Contains(localDir, dataDir) { - exclusionRules += ("." + strings.ReplaceAll(localDir, dataDir, "") + ";") - } - ignoreVal, _ := settingRepo.Get(settingRepo.WithByKey("SnapshotIgnore")) - rules := strings.Split(ignoreVal.Value, ",") - for _, ignore := range rules { - if len(ignore) == 0 || cmd.CheckIllegal(ignore) { - continue - } - exclusionRules += ("." + strings.ReplaceAll(ignore, dataDir, "") + ";") - } - _ = snapshotRepo.Update(snap.SnapID, map[string]interface{}{"status": "OnSaveData"}) - sysIP, _ := settingRepo.Get(settingRepo.WithByKey("SystemIP")) - _ = settingRepo.Update("SystemIP", "") - checkPointOfWal() - if err := handleSnapTar(dataDir, targetDir, "1panel_data.tar.gz", exclusionRules, ""); err != nil { - status = err.Error() - } - _ = snapshotRepo.Update(snap.SnapID, map[string]interface{}{"status": constant.StatusWaiting}) - - snap.Status.PanelData = status - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"panel_data": status}) - _ = settingRepo.Update("SystemIP", sysIP.Value) -} - -func snapCompress(snap snapHelper, rootDir string, secret string) { - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"compress": constant.StatusRunning}) - tmpDir := path.Join(global.CONF.System.TmpDir, "system") - fileName := fmt.Sprintf("%s.tar.gz", path.Base(rootDir)) - if err := handleSnapTar(rootDir, tmpDir, fileName, "", secret); err != nil { - snap.Status.Compress = err.Error() - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"compress": err.Error()}) - return - } - - stat, err := os.Stat(path.Join(tmpDir, fileName)) - if err != nil { - snap.Status.Compress = err.Error() - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"compress": err.Error()}) - return - } - size := common.LoadSizeUnit2F(float64(stat.Size())) - global.LOG.Debugf("compress successful! size of file: %s", size) - snap.Status.Compress = constant.StatusDone - snap.Status.Size = size - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"compress": constant.StatusDone, "size": size}) - - global.LOG.Debugf("remove snapshot file %s", rootDir) - _ = os.RemoveAll(rootDir) -} - -func snapUpload(snap snapHelper, accounts string, file string) { - source := path.Join(global.CONF.System.TmpDir, "system", path.Base(file)) - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"upload": constant.StatusUploading}) - accountMap, err := loadClientMap(accounts) - if err != nil { - snap.Status.Upload = err.Error() - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"upload": err.Error()}) - return - } - targetAccounts := strings.Split(accounts, ",") - for _, item := range targetAccounts { - global.LOG.Debugf("start upload snapshot to %s, path: %s", item, path.Join(accountMap[item].backupPath, "system_snapshot", path.Base(file))) - if _, err := accountMap[item].client.Upload(source, path.Join(accountMap[item].backupPath, "system_snapshot", path.Base(file))); err != nil { - global.LOG.Debugf("upload to %s failed, err: %v", item, err) - snap.Status.Upload = err.Error() - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"upload": err.Error()}) - return - } - global.LOG.Debugf("upload to %s successful", item) - } - snap.Status.Upload = constant.StatusDone - _ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"upload": constant.StatusDone}) - - global.LOG.Debugf("remove snapshot file %s", source) - _ = os.Remove(source) -} - -func handleSnapTar(sourceDir, targetDir, name, exclusionRules string, secret string) error { - if _, err := os.Stat(targetDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(targetDir, os.ModePerm); err != nil { - return err - } - } - - exMap := make(map[string]struct{}) - exStr := "" - excludes := strings.Split(exclusionRules, ";") - excludes = append(excludes, "*.sock") - for _, exclude := range excludes { - if len(exclude) == 0 { - continue - } - if _, ok := exMap[exclude]; ok { - continue - } - exStr += " --exclude " - exStr += exclude - exMap[exclude] = struct{}{} - } - path := "" - if strings.Contains(sourceDir, "/") { - itemDir := strings.ReplaceAll(sourceDir[strings.LastIndex(sourceDir, "/"):], "/", "") - aheadDir := sourceDir[:strings.LastIndex(sourceDir, "/")] - if len(aheadDir) == 0 { - aheadDir = "/" - } - path += fmt.Sprintf("-C %s %s", aheadDir, itemDir) - } else { - path = sourceDir - } - commands := "" - if len(secret) != 0 { - extraCmd := "| openssl enc -aes-256-cbc -salt -k '" + secret + "' -out" - commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read -zcf %s %s %s %s", " -"+exStr, path, extraCmd, targetDir+"/"+name) - global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" %s ", secret), "******")) - } else { - commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read -zcf %s %s -C %s .", targetDir+"/"+name, exStr, sourceDir) - global.LOG.Debug(commands) - } - stdout, err := cmd.ExecWithTimeOut(commands, 30*time.Minute) - if err != nil { - if len(stdout) != 0 { - global.LOG.Errorf("do handle tar failed, stdout: %s, err: %v", stdout, err) - return fmt.Errorf("do handle tar failed, stdout: %s, err: %v", stdout, err) - } - } - return nil -} - -func checkPointOfWal() { - if err := global.DB.Exec("PRAGMA wal_checkpoint(TRUNCATE);").Error; err != nil { - global.LOG.Errorf("handle check point failed, err: %v", err) - } -} diff --git a/backend/app/service/snapshot_recover.go b/backend/app/service/snapshot_recover.go deleted file mode 100644 index d559c0843..000000000 --- a/backend/app/service/snapshot_recover.go +++ /dev/null @@ -1,265 +0,0 @@ -package service - -import ( - "context" - "fmt" - "os" - "path" - "strings" - "sync" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/pkg/errors" -) - -func (u *SnapshotService) HandleSnapshotRecover(snap model.Snapshot, isRecover bool, req dto.SnapshotRecover) { - _ = global.Cron.Stop() - defer func() { - global.Cron.Start() - }() - - snapFileDir := "" - if isRecover { - baseDir := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("system/%s", snap.Name)) - if _, err := os.Stat(baseDir); err != nil && os.IsNotExist(err) { - _ = os.MkdirAll(baseDir, os.ModePerm) - } - if req.IsNew || snap.InterruptStep == "Download" || req.ReDownload { - if err := handleDownloadSnapshot(snap, baseDir); err != nil { - updateRecoverStatus(snap.ID, isRecover, "Backup", constant.StatusFailed, err.Error()) - return - } - global.LOG.Debugf("download snapshot file to %s successful!", baseDir) - req.IsNew = true - } - if req.IsNew || snap.InterruptStep == "Decompress" { - if err := handleUnTar(fmt.Sprintf("%s/%s.tar.gz", baseDir, snap.Name), baseDir, req.Secret); err != nil { - updateRecoverStatus(snap.ID, isRecover, "Decompress", constant.StatusFailed, fmt.Sprintf("decompress file failed, err: %v", err)) - return - } - global.LOG.Debug("decompress snapshot file successful!", baseDir) - req.IsNew = true - } - if req.IsNew || snap.InterruptStep == "Backup" { - if err := backupBeforeRecover(snap, ""); err != nil { - updateRecoverStatus(snap.ID, isRecover, "Backup", constant.StatusFailed, fmt.Sprintf("handle backup before recover failed, err: %v", err)) - return - } - global.LOG.Debug("handle backup before recover successful!") - req.IsNew = true - } - snapFileDir = fmt.Sprintf("%s/%s", baseDir, snap.Name) - if _, err := os.Stat(snapFileDir); err != nil { - snapFileDir = baseDir - } - } else { - snapFileDir = fmt.Sprintf("%s/1panel_original/original_%s", global.CONF.System.BaseDir, snap.Name) - if _, err := os.Stat(snapFileDir); err != nil { - updateRecoverStatus(snap.ID, isRecover, "", constant.StatusFailed, fmt.Sprintf("cannot find the backup file %s, please try to recover again.", snapFileDir)) - return - } - } - snapJson, err := u.readFromJson(fmt.Sprintf("%s/snapshot.json", snapFileDir)) - if err != nil { - updateRecoverStatus(snap.ID, isRecover, "Readjson", constant.StatusFailed, fmt.Sprintf("decompress file failed, err: %v", err)) - return - } - if snap.InterruptStep == "Readjson" { - req.IsNew = true - } - if isRecover && (req.IsNew || snap.InterruptStep == "AppData") { - if err := recoverAppData(snapFileDir); err != nil { - updateRecoverStatus(snap.ID, isRecover, "DockerDir", constant.StatusFailed, fmt.Sprintf("handle recover app data failed, err: %v", err)) - return - } - global.LOG.Debug("recover app data from snapshot file successful!") - req.IsNew = true - } - if req.IsNew || snap.InterruptStep == "DaemonJson" { - fileOp := files.NewFileOp() - if err := recoverDaemonJson(snapFileDir, fileOp); err != nil { - updateRecoverStatus(snap.ID, isRecover, "DaemonJson", constant.StatusFailed, err.Error()) - return - } - global.LOG.Debug("recover daemon.json from snapshot file successful!") - req.IsNew = true - } - - if req.IsNew || snap.InterruptStep == "1PanelBinary" { - if err := recoverPanel(path.Join(snapFileDir, "1panel/1panel"), "/usr/local/bin"); err != nil { - updateRecoverStatus(snap.ID, isRecover, "1PanelBinary", constant.StatusFailed, err.Error()) - return - } - global.LOG.Debug("recover 1panel binary from snapshot file successful!") - req.IsNew = true - } - if req.IsNew || snap.InterruptStep == "1PctlBinary" { - if err := recoverPanel(path.Join(snapFileDir, "1panel/1pctl"), "/usr/local/bin"); err != nil { - updateRecoverStatus(snap.ID, isRecover, "1PctlBinary", constant.StatusFailed, err.Error()) - return - } - global.LOG.Debug("recover 1pctl from snapshot file successful!") - req.IsNew = true - } - if req.IsNew || snap.InterruptStep == "1PanelService" { - if err := recoverPanel(path.Join(snapFileDir, "1panel/1panel.service"), "/etc/systemd/system"); err != nil { - updateRecoverStatus(snap.ID, isRecover, "1PanelService", constant.StatusFailed, err.Error()) - return - } - global.LOG.Debug("recover 1panel service from snapshot file successful!") - req.IsNew = true - } - - if req.IsNew || snap.InterruptStep == "1PanelBackups" { - if err := u.handleUnTar(path.Join(snapFileDir, "/1panel/1panel_backup.tar.gz"), snapJson.BackupDataDir, ""); err != nil { - updateRecoverStatus(snap.ID, isRecover, "1PanelBackups", constant.StatusFailed, err.Error()) - return - } - global.LOG.Debug("recover 1panel backups from snapshot file successful!") - req.IsNew = true - } - - if req.IsNew || snap.InterruptStep == "1PanelData" { - checkPointOfWal() - if err := u.handleUnTar(path.Join(snapFileDir, "/1panel/1panel_data.tar.gz"), path.Join(snapJson.BaseDir, "1panel"), ""); err != nil { - updateRecoverStatus(snap.ID, isRecover, "1PanelData", constant.StatusFailed, err.Error()) - return - } - global.LOG.Debug("recover 1panel data from snapshot file successful!") - req.IsNew = true - } - _ = rebuildAllAppInstall() - restartCompose(path.Join(snapJson.BaseDir, "1panel/docker/compose")) - - global.LOG.Info("recover successful") - if !isRecover { - oriPath := fmt.Sprintf("%s/1panel_original/original_%s", global.CONF.System.BaseDir, snap.Name) - global.LOG.Debugf("remove the file %s after the operation is successful", oriPath) - _ = os.RemoveAll(oriPath) - } else { - global.LOG.Debugf("remove the file %s after the operation is successful", path.Dir(snapFileDir)) - _ = os.RemoveAll(path.Dir(snapFileDir)) - } - _, _ = cmd.Exec("systemctl daemon-reload && systemctl restart 1panel.service") -} - -func backupBeforeRecover(snap model.Snapshot, secret string) error { - baseDir := fmt.Sprintf("%s/1panel_original/original_%s", global.CONF.System.BaseDir, snap.Name) - var wg sync.WaitGroup - var status model.SnapshotStatus - itemHelper := snapHelper{SnapID: 0, Status: &status, Wg: &wg, FileOp: files.NewFileOp(), Ctx: context.Background()} - - jsonItem := SnapshotJson{ - BaseDir: global.CONF.System.BaseDir, - BackupDataDir: global.CONF.System.Backup, - PanelDataDir: path.Join(global.CONF.System.BaseDir, "1panel"), - } - _ = os.MkdirAll(path.Join(baseDir, "1panel"), os.ModePerm) - _ = os.MkdirAll(path.Join(baseDir, "docker"), os.ModePerm) - - wg.Add(4) - itemHelper.Wg = &wg - go snapJson(itemHelper, jsonItem, baseDir) - go snapPanel(itemHelper, path.Join(baseDir, "1panel")) - go snapDaemonJson(itemHelper, path.Join(baseDir, "docker")) - go snapBackup(itemHelper, global.CONF.System.Backup, path.Join(baseDir, "1panel")) - wg.Wait() - itemHelper.Status.AppData = constant.StatusDone - - allDone, msg := checkAllDone(status) - if !allDone { - return errors.New(msg) - } - snapPanelData(itemHelper, global.CONF.System.BaseDir, path.Join(baseDir, "1panel")) - if status.PanelData != constant.StatusDone { - return errors.New(status.PanelData) - } - return nil -} - -func handleDownloadSnapshot(snap model.Snapshot, targetDir string) error { - backup, err := backupRepo.Get(commonRepo.WithByType(snap.DefaultDownload)) - if err != nil { - return err - } - client, err := NewIBackupService().NewClient(&backup) - if err != nil { - return err - } - pathItem := backup.BackupPath - if backup.BackupPath != "/" { - pathItem = strings.TrimPrefix(backup.BackupPath, "/") - } - filePath := fmt.Sprintf("%s/%s.tar.gz", targetDir, snap.Name) - _ = os.RemoveAll(filePath) - ok, err := client.Download(path.Join(pathItem, fmt.Sprintf("system_snapshot/%s.tar.gz", snap.Name)), filePath) - if err != nil || !ok { - return fmt.Errorf("download file %s from %s failed, err: %v", snap.Name, backup.Type, err) - } - return nil -} - -func recoverAppData(src string) error { - if _, err := os.Stat(path.Join(src, "docker/docker_image.tar")); err != nil { - global.LOG.Debug("no such docker images in snapshot") - return nil - } - std, err := cmd.Execf("docker load < %s", path.Join(src, "docker/docker_image.tar")) - if err != nil { - return errors.New(std) - } - return err -} - -func recoverDaemonJson(src string, fileOp files.FileOp) error { - daemonJsonPath := "/etc/docker/daemon.json" - _, errSrc := os.Stat(path.Join(src, "docker/daemon.json")) - _, errPath := os.Stat(daemonJsonPath) - if os.IsNotExist(errSrc) && os.IsNotExist(errPath) { - global.LOG.Debug("the daemon.json file does not exist, nothing happens.") - return nil - } - if errSrc == nil { - if err := fileOp.CopyFile(path.Join(src, "docker/daemon.json"), "/etc/docker"); err != nil { - return fmt.Errorf("recover docker daemon.json failed, err: %v", err) - } - } - - _, _ = cmd.Exec("systemctl restart docker") - return nil -} - -func recoverPanel(src string, dst string) error { - if _, err := os.Stat(src); err != nil { - return fmt.Errorf("file is not found in %s, err: %v", src, err) - } - if err := common.CopyFile(src, dst); err != nil { - return fmt.Errorf("cp file failed, err: %v", err) - } - return nil -} - -func restartCompose(composePath string) { - composes, err := composeRepo.ListRecord() - if err != nil { - return - } - for _, compose := range composes { - pathItem := path.Join(composePath, compose.Name, "docker-compose.yml") - if _, err := os.Stat(pathItem); err != nil { - continue - } - upCmd := fmt.Sprintf("docker-compose -f %s up -d", pathItem) - stdout, err := cmd.Exec(upCmd) - if err != nil { - global.LOG.Debugf("%s failed, err: %v", upCmd, stdout) - } - } - global.LOG.Debug("restart all compose successful!") -} diff --git a/backend/app/service/ssh.go b/backend/app/service/ssh.go deleted file mode 100644 index 1f51b4701..000000000 --- a/backend/app/service/ssh.go +++ /dev/null @@ -1,573 +0,0 @@ -package service - -import ( - "fmt" - "os" - "os/user" - "path" - "path/filepath" - "sort" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/1Panel-dev/1Panel/backend/utils/qqwry" - "github.com/1Panel-dev/1Panel/backend/utils/systemctl" - "github.com/pkg/errors" -) - -const sshPath = "/etc/ssh/sshd_config" - -type SSHService struct{} - -type ISSHService interface { - GetSSHInfo() (*dto.SSHInfo, error) - OperateSSH(operation string) error - UpdateByFile(value string) error - Update(req dto.SSHUpdate) error - GenerateSSH(req dto.GenerateSSH) error - LoadSSHSecret(mode string) (string, error) - LoadLog(req dto.SearchSSHLog) (*dto.SSHLog, error) - - LoadSSHConf() (string, error) -} - -func NewISSHService() ISSHService { - return &SSHService{} -} - -func (u *SSHService) GetSSHInfo() (*dto.SSHInfo, error) { - data := dto.SSHInfo{ - AutoStart: true, - Status: constant.StatusEnable, - Message: "", - Port: "22", - ListenAddress: "", - PasswordAuthentication: "yes", - PubkeyAuthentication: "yes", - PermitRootLogin: "yes", - UseDNS: "yes", - } - serviceName, err := loadServiceName() - if err != nil { - data.Status = constant.StatusDisable - data.Message = err.Error() - } else { - active, err := systemctl.IsActive(serviceName) - if !active { - data.Status = constant.StatusDisable - if err != nil { - data.Message = err.Error() - } - } else { - data.Status = constant.StatusEnable - } - } - - out, err := systemctl.RunSystemCtl("is-enabled", serviceName) - if err != nil { - data.AutoStart = false - } else { - if out == "alias\n" { - data.AutoStart, _ = systemctl.IsEnable("ssh") - } else { - data.AutoStart = out == "enabled\n" - } - } - - sshConf, err := os.ReadFile(sshPath) - if err != nil { - data.Message = err.Error() - data.Status = constant.StatusDisable - } - lines := strings.Split(string(sshConf), "\n") - for _, line := range lines { - if strings.HasPrefix(line, "Port ") { - data.Port = strings.ReplaceAll(line, "Port ", "") - } - if strings.HasPrefix(line, "ListenAddress ") { - itemAddr := strings.ReplaceAll(line, "ListenAddress ", "") - if len(data.ListenAddress) != 0 { - data.ListenAddress += ("," + itemAddr) - } else { - data.ListenAddress = itemAddr - } - } - if strings.HasPrefix(line, "PasswordAuthentication ") { - data.PasswordAuthentication = strings.ReplaceAll(line, "PasswordAuthentication ", "") - } - if strings.HasPrefix(line, "PubkeyAuthentication ") { - data.PubkeyAuthentication = strings.ReplaceAll(line, "PubkeyAuthentication ", "") - } - if strings.HasPrefix(line, "PermitRootLogin ") { - data.PermitRootLogin = strings.ReplaceAll(strings.ReplaceAll(line, "PermitRootLogin ", ""), "prohibit-password", "without-password") - } - if strings.HasPrefix(line, "UseDNS ") { - data.UseDNS = strings.ReplaceAll(line, "UseDNS ", "") - } - } - return &data, nil -} - -func (u *SSHService) OperateSSH(operation string) error { - serviceName, err := loadServiceName() - if err != nil { - return err - } - sudo := cmd.SudoHandleCmd() - if operation == "enable" || operation == "disable" { - serviceName += ".service" - } - stdout, err := cmd.Execf("%s systemctl %s %s", sudo, operation, serviceName) - if err != nil { - if strings.Contains(stdout, "alias name or linked unit file") { - stdout, err := cmd.Execf("%s systemctl %s ssh", sudo, operation) - if err != nil { - return fmt.Errorf("%s ssh(alias name or linked unit file) failed, stdout: %s, err: %v", operation, stdout, err) - } - } - return fmt.Errorf("%s %s failed, stdout: %s, err: %v", operation, serviceName, stdout, err) - } - return nil -} - -func (u *SSHService) Update(req dto.SSHUpdate) error { - serviceName, err := loadServiceName() - if err != nil { - return err - } - - sshConf, err := os.ReadFile(sshPath) - if err != nil { - return err - } - lines := strings.Split(string(sshConf), "\n") - newFiles := updateSSHConf(lines, req.Key, req.NewValue) - file, err := os.OpenFile(sshPath, os.O_WRONLY|os.O_TRUNC, 0666) - if err != nil { - return err - } - defer file.Close() - if _, err = file.WriteString(strings.Join(newFiles, "\n")); err != nil { - return err - } - sudo := cmd.SudoHandleCmd() - if req.Key == "Port" { - stdout, _ := cmd.Execf("%s getenforce", sudo) - if stdout == "Enforcing\n" { - _, _ = cmd.Execf("%s semanage port -a -t ssh_port_t -p tcp %s", sudo, req.NewValue) - } - - ruleItem := dto.PortRuleUpdate{ - OldRule: dto.PortRuleOperate{ - Operation: "remove", - Port: req.OldValue, - Protocol: "tcp", - Strategy: "accept", - }, - NewRule: dto.PortRuleOperate{ - Operation: "add", - Port: req.NewValue, - Protocol: "tcp", - Strategy: "accept", - }, - } - if err := NewIFirewallService().UpdatePortRule(ruleItem); err != nil { - global.LOG.Errorf("reset firewall rules %s -> %s failed, err: %v", req.OldValue, req.NewValue, err) - } - - if err = NewIHostService().Update(1, map[string]interface{}{"port": req.NewValue}); err != nil { - global.LOG.Errorf("reset host port %s -> %s failed, err: %v", req.OldValue, req.NewValue, err) - } - } - - _, _ = cmd.Execf("%s systemctl restart %s", sudo, serviceName) - return nil -} - -func (u *SSHService) UpdateByFile(value string) error { - serviceName, err := loadServiceName() - if err != nil { - return err - } - - file, err := os.OpenFile(sshPath, os.O_WRONLY|os.O_TRUNC, 0666) - if err != nil { - return err - } - defer file.Close() - if _, err = file.WriteString(value); err != nil { - return err - } - sudo := cmd.SudoHandleCmd() - _, _ = cmd.Execf("%s systemctl restart %s", sudo, serviceName) - return nil -} - -func (u *SSHService) GenerateSSH(req dto.GenerateSSH) error { - if cmd.CheckIllegal(req.EncryptionMode, req.Password) { - return buserr.New(constant.ErrCmdIllegal) - } - currentUser, err := user.Current() - if err != nil { - return fmt.Errorf("load current user failed, err: %v", err) - } - secretFile := fmt.Sprintf("%s/.ssh/id_item_%s", currentUser.HomeDir, req.EncryptionMode) - secretPubFile := fmt.Sprintf("%s/.ssh/id_item_%s.pub", currentUser.HomeDir, req.EncryptionMode) - authFilePath := currentUser.HomeDir + "/.ssh/authorized_keys" - - command := fmt.Sprintf("ssh-keygen -t %s -f %s/.ssh/id_item_%s | echo y", req.EncryptionMode, currentUser.HomeDir, req.EncryptionMode) - if len(req.Password) != 0 { - command = fmt.Sprintf("ssh-keygen -t %s -P %s -f %s/.ssh/id_item_%s | echo y", req.EncryptionMode, req.Password, currentUser.HomeDir, req.EncryptionMode) - } - stdout, err := cmd.Exec(command) - if err != nil { - return fmt.Errorf("generate failed, err: %v, message: %s", err, stdout) - } - defer func() { - _ = os.Remove(secretFile) - }() - defer func() { - _ = os.Remove(secretPubFile) - }() - - if _, err := os.Stat(authFilePath); err != nil && errors.Is(err, os.ErrNotExist) { - authFile, err := os.Create(authFilePath) - if err != nil { - return err - } - defer authFile.Close() - } - stdout1, err := cmd.Execf("cat %s >> %s/.ssh/authorized_keys", secretPubFile, currentUser.HomeDir) - if err != nil { - return fmt.Errorf("generate failed, err: %v, message: %s", err, stdout1) - } - - fileOp := files.NewFileOp() - if err := fileOp.Rename(secretFile, fmt.Sprintf("%s/.ssh/id_%s", currentUser.HomeDir, req.EncryptionMode)); err != nil { - return err - } - if err := fileOp.Rename(secretPubFile, fmt.Sprintf("%s/.ssh/id_%s.pub", currentUser.HomeDir, req.EncryptionMode)); err != nil { - return err - } - - return nil -} - -func (u *SSHService) LoadSSHSecret(mode string) (string, error) { - currentUser, err := user.Current() - if err != nil { - return "", fmt.Errorf("load current user failed, err: %v", err) - } - - homeDir := currentUser.HomeDir - if _, err := os.Stat(fmt.Sprintf("%s/.ssh/id_%s", homeDir, mode)); err != nil { - return "", nil - } - file, err := os.ReadFile(fmt.Sprintf("%s/.ssh/id_%s", homeDir, mode)) - return string(file), err -} - -type sshFileItem struct { - Name string - Year int -} - -func (u *SSHService) LoadLog(req dto.SearchSSHLog) (*dto.SSHLog, error) { - var fileList []sshFileItem - var data dto.SSHLog - baseDir := "/var/log" - if err := filepath.Walk(baseDir, func(pathItem string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if !info.IsDir() && (strings.HasPrefix(info.Name(), "secure") || strings.HasPrefix(info.Name(), "auth")) { - if !strings.HasSuffix(info.Name(), ".gz") { - fileList = append(fileList, sshFileItem{Name: pathItem, Year: info.ModTime().Year()}) - return nil - } - itemFileName := strings.TrimSuffix(pathItem, ".gz") - if _, err := os.Stat(itemFileName); err != nil && os.IsNotExist(err) { - if err := handleGunzip(pathItem); err == nil { - fileList = append(fileList, sshFileItem{Name: itemFileName, Year: info.ModTime().Year()}) - } - } - } - return nil - }); err != nil { - return nil, err - } - fileList = sortFileList(fileList) - - command := "" - if len(req.Info) != 0 { - command = fmt.Sprintf(" | grep '%s'", req.Info) - } - - showCountFrom := (req.Page - 1) * req.PageSize - showCountTo := req.Page * req.PageSize - nyc, _ := time.LoadLocation(common.LoadTimeZone()) - qqWry, err := qqwry.NewQQwry() - if err != nil { - global.LOG.Errorf("load qqwry datas failed: %s", err) - } - for _, file := range fileList { - commandItem := "" - if strings.HasPrefix(path.Base(file.Name), "secure") { - switch req.Status { - case constant.StatusSuccess: - commandItem = fmt.Sprintf("cat %s | grep -a Accepted %s", file.Name, command) - case constant.StatusFailed: - commandItem = fmt.Sprintf("cat %s | grep -a 'Failed password for' %s", file.Name, command) - default: - commandItem = fmt.Sprintf("cat %s | grep -aE '(Failed password for|Accepted)' %s", file.Name, command) - } - } - if strings.HasPrefix(path.Base(file.Name), "auth.log") { - switch req.Status { - case constant.StatusSuccess: - commandItem = fmt.Sprintf("cat %s | grep -a Accepted %s", file.Name, command) - case constant.StatusFailed: - commandItem = fmt.Sprintf("cat %s | grep -aE 'Failed password for|Connection closed by authenticating user' %s", file.Name, command) - default: - commandItem = fmt.Sprintf("cat %s | grep -aE \"(Failed password for|Connection closed by authenticating user|Accepted)\" %s", file.Name, command) - } - } - dataItem, successCount, failedCount := loadSSHData(commandItem, showCountFrom, showCountTo, file.Year, qqWry, nyc) - data.FailedCount += failedCount - data.TotalCount += successCount + failedCount - showCountFrom = showCountFrom - (successCount + failedCount) - showCountTo = showCountTo - (successCount + failedCount) - data.Logs = append(data.Logs, dataItem...) - } - - data.SuccessfulCount = data.TotalCount - data.FailedCount - return &data, nil -} - -func (u *SSHService) LoadSSHConf() (string, error) { - if _, err := os.Stat("/etc/ssh/sshd_config"); err != nil { - return "", buserr.New("ErrHttpReqNotFound") - } - content, err := os.ReadFile("/etc/ssh/sshd_config") - if err != nil { - return "", err - } - return string(content), nil -} - -func sortFileList(fileNames []sshFileItem) []sshFileItem { - if len(fileNames) < 2 { - return fileNames - } - if strings.HasPrefix(path.Base(fileNames[0].Name), "secure") { - var itemFile []sshFileItem - sort.Slice(fileNames, func(i, j int) bool { - return fileNames[i].Name > fileNames[j].Name - }) - itemFile = append(itemFile, fileNames[len(fileNames)-1]) - itemFile = append(itemFile, fileNames[:len(fileNames)-1]...) - return itemFile - } - sort.Slice(fileNames, func(i, j int) bool { - return fileNames[i].Name < fileNames[j].Name - }) - return fileNames -} - -func updateSSHConf(oldFiles []string, param string, value string) []string { - var valueItems []string - if param != "ListenAddress" { - valueItems = append(valueItems, value) - } else { - if value != "" { - valueItems = strings.Split(value, ",") - } - } - var newFiles []string - for _, line := range oldFiles { - lineItem := strings.TrimSpace(line) - if (strings.HasPrefix(lineItem, param) || strings.HasPrefix(lineItem, fmt.Sprintf("#%s", param))) && len(valueItems) != 0 { - newFiles = append(newFiles, fmt.Sprintf("%s %s", param, valueItems[0])) - valueItems = valueItems[1:] - continue - } - if strings.HasPrefix(lineItem, param) && len(valueItems) == 0 { - newFiles = append(newFiles, fmt.Sprintf("#%s", line)) - continue - } - newFiles = append(newFiles, line) - } - if len(valueItems) != 0 { - for _, item := range valueItems { - newFiles = append(newFiles, fmt.Sprintf("%s %s", param, item)) - } - } - return newFiles -} - -func loadSSHData(command string, showCountFrom, showCountTo, currentYear int, qqWry *qqwry.QQwry, nyc *time.Location) ([]dto.SSHHistory, int, int) { - var ( - datas []dto.SSHHistory - successCount int - failedCount int - ) - stdout2, err := cmd.Exec(command) - if err != nil { - return datas, 0, 0 - } - lines := strings.Split(string(stdout2), "\n") - for i := len(lines) - 1; i >= 0; i-- { - var itemData dto.SSHHistory - switch { - case strings.Contains(lines[i], "Failed password for"): - itemData = loadFailedSecureDatas(lines[i]) - if len(itemData.Address) != 0 { - if successCount+failedCount >= showCountFrom && successCount+failedCount < showCountTo { - itemData.Area = qqWry.Find(itemData.Address).Area - itemData.Date = loadDate(currentYear, itemData.DateStr, nyc) - datas = append(datas, itemData) - } - failedCount++ - } - case strings.Contains(lines[i], "Connection closed by authenticating user"): - itemData = loadFailedAuthDatas(lines[i]) - if len(itemData.Address) != 0 { - if successCount+failedCount >= showCountFrom && successCount+failedCount < showCountTo { - itemData.Area = qqWry.Find(itemData.Address).Area - itemData.Date = loadDate(currentYear, itemData.DateStr, nyc) - datas = append(datas, itemData) - } - failedCount++ - } - case strings.Contains(lines[i], "Accepted "): - itemData = loadSuccessDatas(lines[i]) - if len(itemData.Address) != 0 { - if successCount+failedCount >= showCountFrom && successCount+failedCount < showCountTo { - itemData.Area = qqWry.Find(itemData.Address).Area - itemData.Date = loadDate(currentYear, itemData.DateStr, nyc) - datas = append(datas, itemData) - } - successCount++ - } - } - } - return datas, successCount, failedCount -} - -func loadSuccessDatas(line string) dto.SSHHistory { - var data dto.SSHHistory - parts := strings.Fields(line) - index, dataStr := analyzeDateStr(parts) - if dataStr == "" { - return data - } - data.DateStr = dataStr - data.AuthMode = parts[4+index] - data.User = parts[6+index] - data.Address = parts[8+index] - data.Port = parts[10+index] - data.Status = constant.StatusSuccess - return data -} - -func loadFailedAuthDatas(line string) dto.SSHHistory { - var data dto.SSHHistory - parts := strings.Fields(line) - index, dataStr := analyzeDateStr(parts) - if dataStr == "" { - return data - } - data.DateStr = dataStr - switch index { - case 1: - data.User = parts[9] - case 2: - data.User = parts[10] - default: - data.User = parts[7] - } - data.AuthMode = parts[6+index] - data.Address = parts[9+index] - data.Port = parts[11+index] - data.Status = constant.StatusFailed - if strings.Contains(line, ": ") { - data.Message = strings.Split(line, ": ")[1] - } - return data -} -func loadFailedSecureDatas(line string) dto.SSHHistory { - var data dto.SSHHistory - parts := strings.Fields(line) - index, dataStr := analyzeDateStr(parts) - if dataStr == "" { - return data - } - data.DateStr = dataStr - if strings.Contains(line, " invalid ") { - data.AuthMode = parts[4+index] - index += 2 - } else { - data.AuthMode = parts[4+index] - } - data.User = parts[6+index] - data.Address = parts[8+index] - data.Port = parts[10+index] - data.Status = constant.StatusFailed - if strings.Contains(line, ": ") { - data.Message = strings.Split(line, ": ")[1] - } - return data -} - -func handleGunzip(path string) error { - if _, err := cmd.Execf("gunzip %s", path); err != nil { - return err - } - return nil -} - -func loadServiceName() (string, error) { - if exist, _ := systemctl.IsExist("sshd"); exist { - return "sshd", nil - } else if exist, _ := systemctl.IsExist("ssh"); exist { - return "ssh", nil - } - return "", errors.New("The ssh or sshd service is unavailable") -} - -func loadDate(currentYear int, DateStr string, nyc *time.Location) time.Time { - itemDate, err := time.ParseInLocation("2006 Jan 2 15:04:05", fmt.Sprintf("%d %s", currentYear, DateStr), nyc) - if err != nil { - itemDate, _ = time.ParseInLocation("2006 Jan 2 15:04:05", DateStr, nyc) - } - return itemDate -} - -func analyzeDateStr(parts []string) (int, string) { - t, err := time.Parse(time.RFC3339Nano, parts[0]) - if err == nil { - if len(parts) < 12 { - return 0, "" - } - return 0, t.Format("2006 Jan 2 15:04:05") - } - t, err = time.Parse(constant.DateTimeLayout, fmt.Sprintf("%s %s", parts[0], parts[1])) - if err == nil { - if len(parts) < 14 { - return 0, "" - } - return 1, t.Format("2006 Jan 2 15:04:05") - } - - if len(parts) < 14 { - return 0, "" - } - return 2, fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2]) -} diff --git a/backend/app/service/website.go b/backend/app/service/website.go deleted file mode 100644 index f62ababff..000000000 --- a/backend/app/service/website.go +++ /dev/null @@ -1,2565 +0,0 @@ -package service - -import ( - "bufio" - "bytes" - "context" - "crypto/x509" - "encoding/json" - "encoding/pem" - "errors" - "fmt" - "os" - "path" - "reflect" - "regexp" - "strconv" - "strings" - "syscall" - "time" - - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/jinzhu/copier" - - "github.com/1Panel-dev/1Panel/backend/i18n" - "github.com/spf13/afero" - - "github.com/1Panel-dev/1Panel/backend/utils/compose" - "github.com/1Panel-dev/1Panel/backend/utils/env" - - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/nginx" - "github.com/1Panel-dev/1Panel/backend/utils/nginx/components" - "github.com/1Panel-dev/1Panel/backend/utils/nginx/parser" - "github.com/1Panel-dev/1Panel/cmd/server/nginx_conf" - "golang.org/x/crypto/bcrypt" - "gopkg.in/ini.v1" - "gorm.io/gorm" - - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/app/repo" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/global" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/files" -) - -type WebsiteService struct { -} - -type IWebsiteService interface { - PageWebsite(req request.WebsiteSearch) (int64, []response.WebsiteRes, error) - GetWebsites() ([]response.WebsiteDTO, error) - CreateWebsite(create request.WebsiteCreate) error - OpWebsite(req request.WebsiteOp) error - GetWebsiteOptions() ([]response.WebsiteOption, error) - UpdateWebsite(req request.WebsiteUpdate) error - DeleteWebsite(req request.WebsiteDelete) error - GetWebsite(id uint) (response.WebsiteDTO, error) - - CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error) - GetWebsiteDomain(websiteId uint) ([]model.WebsiteDomain, error) - DeleteWebsiteDomain(domainId uint) error - - GetNginxConfigByScope(req request.NginxScopeReq) (*response.WebsiteNginxConfig, error) - UpdateNginxConfigByScope(req request.NginxConfigUpdate) error - GetWebsiteNginxConfig(websiteId uint, configType string) (response.FileInfo, error) - UpdateNginxConfigFile(req request.WebsiteNginxUpdate) error - GetWebsiteHTTPS(websiteId uint) (response.WebsiteHTTPS, error) - OpWebsiteHTTPS(ctx context.Context, req request.WebsiteHTTPSOp) (*response.WebsiteHTTPS, error) - OpWebsiteLog(req request.WebsiteLogReq) (*response.WebsiteLog, error) - ChangeDefaultServer(id uint) error - PreInstallCheck(req request.WebsiteInstallCheckReq) ([]response.WebsitePreInstallCheck, error) - - GetPHPConfig(id uint) (*response.PHPConfig, error) - UpdatePHPConfig(req request.WebsitePHPConfigUpdate) error - UpdatePHPConfigFile(req request.WebsitePHPFileUpdate) error - ChangePHPVersion(req request.WebsitePHPVersionReq) error - - GetRewriteConfig(req request.NginxRewriteReq) (*response.NginxRewriteRes, error) - UpdateRewriteConfig(req request.NginxRewriteUpdate) error - LoadWebsiteDirConfig(req request.WebsiteCommonReq) (*response.WebsiteDirConfig, error) - UpdateSiteDir(req request.WebsiteUpdateDir) error - UpdateSitePermission(req request.WebsiteUpdateDirPermission) error - OperateProxy(req request.WebsiteProxyConfig) (err error) - GetProxies(id uint) (res []request.WebsiteProxyConfig, err error) - UpdateProxyFile(req request.NginxProxyUpdate) (err error) - GetAuthBasics(req request.NginxAuthReq) (res response.NginxAuthRes, err error) - UpdateAuthBasic(req request.NginxAuthUpdate) (err error) - GetAntiLeech(id uint) (*response.NginxAntiLeechRes, error) - UpdateAntiLeech(req request.NginxAntiLeechUpdate) (err error) - OperateRedirect(req request.NginxRedirectReq) (err error) - GetRedirect(id uint) (res []response.NginxRedirectConfig, err error) - UpdateRedirectFile(req request.NginxRedirectUpdate) (err error) - - UpdateDefaultHtml(req request.WebsiteHtmlUpdate) error - GetDefaultHtml(resourceType string) (*response.WebsiteHtmlRes, error) -} - -func NewIWebsiteService() IWebsiteService { - return &WebsiteService{} -} - -func (w WebsiteService) PageWebsite(req request.WebsiteSearch) (int64, []response.WebsiteRes, error) { - var ( - websiteDTOs []response.WebsiteRes - opts []repo.DBOption - ) - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return 0, nil, nil - } - return 0, nil, err - } - opts = append(opts, commonRepo.WithOrderRuleBy(req.OrderBy, req.Order)) - if req.Name != "" { - domains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithDomainLike(req.Name)) - if len(domains) > 0 { - var websiteIds []uint - for _, domain := range domains { - websiteIds = append(websiteIds, domain.WebsiteID) - } - opts = append(opts, websiteRepo.WithIDs(websiteIds)) - } else { - opts = append(opts, websiteRepo.WithDomainLike(req.Name)) - } - } - if req.WebsiteGroupID != 0 { - opts = append(opts, websiteRepo.WithGroupID(req.WebsiteGroupID)) - } - total, websites, err := websiteRepo.Page(req.Page, req.PageSize, opts...) - if err != nil { - return 0, nil, err - } - for _, web := range websites { - var ( - appName string - runtimeName string - ) - switch web.Type { - case constant.Deployment: - appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(web.AppInstallID)) - if err != nil { - return 0, nil, err - } - appName = appInstall.Name - case constant.Runtime: - runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(web.RuntimeID)) - if err != nil { - return 0, nil, err - } - runtimeName = runtime.Name - } - sitePath := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name, "www", "sites", web.Alias) - - websiteDTOs = append(websiteDTOs, response.WebsiteRes{ - ID: web.ID, - CreatedAt: web.CreatedAt, - Protocol: web.Protocol, - PrimaryDomain: web.PrimaryDomain, - Type: web.Type, - Remark: web.Remark, - Status: web.Status, - Alias: web.Alias, - AppName: appName, - ExpireDate: web.ExpireDate, - SSLExpireDate: web.WebsiteSSL.ExpireDate, - SSLStatus: checkSSLStatus(web.WebsiteSSL.ExpireDate), - RuntimeName: runtimeName, - SitePath: sitePath, - }) - } - return total, websiteDTOs, nil -} - -func (w WebsiteService) GetWebsites() ([]response.WebsiteDTO, error) { - var websiteDTOs []response.WebsiteDTO - websites, err := websiteRepo.List(commonRepo.WithOrderRuleBy("primary_domain", "ascending")) - if err != nil { - return nil, err - } - for _, web := range websites { - websiteDTOs = append(websiteDTOs, response.WebsiteDTO{ - Website: web, - }) - } - return websiteDTOs, nil -} - -func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error) { - alias := create.Alias - if alias == "default" { - return buserr.New("ErrDefaultAlias") - } - if common.ContainsChinese(alias) { - alias, err = common.PunycodeEncode(alias) - if err != nil { - return - } - } - if exist, _ := websiteRepo.GetBy(websiteRepo.WithAlias(alias)); len(exist) > 0 { - return buserr.New(constant.ErrAliasIsExist) - } - - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return err - } - defaultHttpPort := nginxInstall.HttpPort - - var ( - otherDomains []model.WebsiteDomain - domains []model.WebsiteDomain - ) - domains, _, _, err = getWebsiteDomains(create.PrimaryDomain, defaultHttpPort, 0) - if err != nil { - return err - } - otherDomains, _, _, err = getWebsiteDomains(create.OtherDomains, defaultHttpPort, 0) - if err != nil { - return err - } - domains = append(domains, otherDomains...) - - defaultDate, _ := time.Parse(constant.DateLayout, constant.DefaultDate) - website := &model.Website{ - PrimaryDomain: create.PrimaryDomain, - Type: create.Type, - Alias: alias, - Remark: create.Remark, - Status: constant.WebRunning, - ExpireDate: defaultDate, - WebsiteGroupID: create.WebsiteGroupID, - Protocol: constant.ProtocolHTTP, - Proxy: create.Proxy, - SiteDir: "/", - AccessLog: true, - ErrorLog: true, - IPV6: create.IPV6, - } - - var ( - appInstall *model.AppInstall - runtime *model.Runtime - ) - - defer func() { - if err != nil { - if website.AppInstallID > 0 { - req := request.AppInstalledOperate{ - InstallId: website.AppInstallID, - Operate: constant.Delete, - ForceDelete: true, - } - if err := NewIAppInstalledService().Operate(req); err != nil { - global.LOG.Errorf(err.Error()) - } - } - } - }() - var proxy string - - switch create.Type { - case constant.Deployment: - if create.AppType == constant.NewApp { - var ( - req request.AppInstallCreate - install *model.AppInstall - ) - req.Name = create.AppInstall.Name - req.AppDetailId = create.AppInstall.AppDetailId - req.Params = create.AppInstall.Params - req.AppContainerConfig = create.AppInstall.AppContainerConfig - tx, installCtx := getTxAndContext() - install, err = NewIAppService().Install(installCtx, req) - if err != nil { - tx.Rollback() - return err - } - tx.Commit() - appInstall = install - website.AppInstallID = install.ID - website.Proxy = fmt.Sprintf("127.0.0.1:%d", appInstall.HttpPort) - } else { - var install model.AppInstall - install, err = appInstallRepo.GetFirst(commonRepo.WithByID(create.AppInstallID)) - if err != nil { - return err - } - appInstall = &install - website.AppInstallID = appInstall.ID - website.Proxy = fmt.Sprintf("127.0.0.1:%d", appInstall.HttpPort) - } - case constant.Runtime: - runtime, err = runtimeRepo.GetFirst(commonRepo.WithByID(create.RuntimeID)) - if err != nil { - return err - } - website.RuntimeID = runtime.ID - switch runtime.Type { - case constant.RuntimePHP: - if runtime.Resource == constant.ResourceAppstore { - var ( - req request.AppInstallCreate - install *model.AppInstall - ) - reg, _ := regexp.Compile(`[^a-z0-9_-]+`) - req.Name = reg.ReplaceAllString(strings.ToLower(alias), "") - req.AppDetailId = create.AppInstall.AppDetailId - req.Params = create.AppInstall.Params - req.Params["IMAGE_NAME"] = runtime.Image - req.AppContainerConfig = create.AppInstall.AppContainerConfig - req.Params["PANEL_WEBSITE_DIR"] = path.Join(nginxInstall.GetPath(), "/www") - tx, installCtx := getTxAndContext() - install, err = NewIAppService().Install(installCtx, req) - if err != nil { - tx.Rollback() - return err - } - tx.Commit() - website.AppInstallID = install.ID - appInstall = install - website.Proxy = fmt.Sprintf("127.0.0.1:%d", appInstall.HttpPort) - } else { - website.ProxyType = create.ProxyType - if website.ProxyType == constant.RuntimeProxyUnix { - proxy = fmt.Sprintf("unix:%s", path.Join("/www/sites", website.Alias, "php-pool", "php-fpm.sock")) - } - if website.ProxyType == constant.RuntimeProxyTcp { - proxy = fmt.Sprintf("127.0.0.1:%d", create.Port) - } - website.Proxy = proxy - } - case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo: - website.Proxy = fmt.Sprintf("127.0.0.1:%d", runtime.Port) - } - } - - if err = configDefaultNginx(website, domains, appInstall, runtime); err != nil { - return err - } - - if len(create.FtpUser) != 0 && len(create.FtpPassword) != 0 { - indexDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "index") - itemID, err := NewIFtpService().Create(dto.FtpCreate{User: create.FtpUser, Password: create.FtpPassword, Path: indexDir}) - if err != nil { - global.LOG.Errorf("create ftp for website failed, err: %v", err) - } - website.FtpID = itemID - } - - if err = createWafConfig(website, domains); err != nil { - return err - } - - tx, ctx := helper.GetTxAndContext() - defer tx.Rollback() - if err = websiteRepo.Create(ctx, website); err != nil { - return err - } - for i := range domains { - domains[i].WebsiteID = website.ID - } - if err = websiteDomainRepo.BatchCreate(ctx, domains); err != nil { - return err - } - tx.Commit() - return nil -} - -func (w WebsiteService) OpWebsite(req request.WebsiteOp) error { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - if err := opWebsite(&website, req.Operate); err != nil { - return err - } - return websiteRepo.Save(context.Background(), &website) -} - -func (w WebsiteService) GetWebsiteOptions() ([]response.WebsiteOption, error) { - webs, err := websiteRepo.List() - if err != nil { - return nil, err - } - var datas []response.WebsiteOption - for _, web := range webs { - var item response.WebsiteOption - if err := copier.Copy(&item, &web); err != nil { - return nil, err - } - datas = append(datas, item) - } - return datas, nil -} - -func (w WebsiteService) UpdateWebsite(req request.WebsiteUpdate) error { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - if website.IPV6 != req.IPV6 { - if err := changeIPV6(website, req.IPV6); err != nil { - return err - } - } - website.PrimaryDomain = req.PrimaryDomain - website.WebsiteGroupID = req.WebsiteGroupID - website.Remark = req.Remark - website.IPV6 = req.IPV6 - - if req.ExpireDate != "" { - expireDate, err := time.Parse(constant.DateLayout, req.ExpireDate) - if err != nil { - return err - } - website.ExpireDate = expireDate - } - - return websiteRepo.Save(context.TODO(), &website) -} - -func (w WebsiteService) GetWebsite(id uint) (response.WebsiteDTO, error) { - var res response.WebsiteDTO - website, err := websiteRepo.GetFirst(commonRepo.WithByID(id)) - if err != nil { - return res, err - } - res.Website = website - - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return res, err - } - sitePath := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name, "www", "sites", website.Alias) - res.ErrorLogPath = path.Join(sitePath, "log", "error.log") - res.AccessLogPath = path.Join(sitePath, "log", "access.log") - res.SitePath = sitePath - res.SiteDir = website.SiteDir - return res, nil -} - -func (w WebsiteService) DeleteWebsite(req request.WebsiteDelete) error { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - if err = delNginxConfig(website, req.ForceDelete); err != nil { - return err - } - - if err = delWafConfig(website, req.ForceDelete); err != nil { - return err - } - - if checkIsLinkApp(website) && req.DeleteApp { - appInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) - if appInstall.ID > 0 { - if err = deleteAppInstall(appInstall, true, req.ForceDelete, true); err != nil && !req.ForceDelete { - return err - } - } - } - - tx, ctx := helper.GetTxAndContext() - defer tx.Rollback() - - go func() { - _ = NewIBackupService().DeleteRecordByName("website", website.PrimaryDomain, website.Alias, req.DeleteBackup) - }() - - if err := websiteRepo.DeleteBy(ctx, commonRepo.WithByID(req.ID)); err != nil { - return err - } - if err := websiteDomainRepo.DeleteBy(ctx, websiteDomainRepo.WithWebsiteId(req.ID)); err != nil { - return err - } - tx.Commit() - - uploadDir := path.Join(global.CONF.System.BaseDir, fmt.Sprintf("1panel/uploads/website/%s", website.Alias)) - if _, err := os.Stat(uploadDir); err == nil { - _ = os.RemoveAll(uploadDir) - } - return nil -} - -func (w WebsiteService) CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error) { - var ( - domainModels []model.WebsiteDomain - addPorts []int - addDomains []string - ) - httpPort, _, err := getAppInstallPort(constant.AppOpenresty) - if err != nil { - return nil, err - } - website, err := websiteRepo.GetFirst(commonRepo.WithByID(create.WebsiteID)) - if err != nil { - return nil, err - } - - domainModels, addPorts, addDomains, err = getWebsiteDomains(create.Domains, httpPort, create.WebsiteID) - if err != nil { - return nil, err - } - go func() { - _ = OperateFirewallPort(nil, addPorts) - }() - - if err := addListenAndServerName(website, addPorts, addDomains); err != nil { - return nil, err - } - - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return nil, err - } - wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data") - fileOp := files.NewFileOp() - if fileOp.Stat(wafDataPath) { - websitesConfigPath := path.Join(wafDataPath, "conf", "sites.json") - content, err := fileOp.GetContent(websitesConfigPath) - if err != nil { - return nil, err - } - var websitesArray []request.WafWebsite - if content != nil { - if err := json.Unmarshal(content, &websitesArray); err != nil { - return nil, err - } - } - for index, wafWebsite := range websitesArray { - if wafWebsite.Key == website.Alias { - wafSite := request.WafWebsite{ - Key: website.Alias, - Domains: wafWebsite.Domains, - Host: wafWebsite.Host, - } - for _, domain := range domainModels { - wafSite.Domains = append(wafSite.Domains, domain.Domain) - wafSite.Host = append(wafSite.Host, domain.Domain+":"+strconv.Itoa(domain.Port)) - } - if len(wafSite.Host) == 0 { - wafSite.Host = []string{} - } - websitesArray[index] = wafSite - break - } - } - websitesContent, err := json.Marshal(websitesArray) - if err != nil { - return nil, err - } - if err := fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, 0644); err != nil { - return nil, err - } - } - - return domainModels, websiteDomainRepo.BatchCreate(context.TODO(), domainModels) -} - -func (w WebsiteService) GetWebsiteDomain(websiteId uint) ([]model.WebsiteDomain, error) { - return websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(websiteId)) -} - -func (w WebsiteService) DeleteWebsiteDomain(domainId uint) error { - webSiteDomain, err := websiteDomainRepo.GetFirst(commonRepo.WithByID(domainId)) - if err != nil { - return err - } - - if websiteDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(webSiteDomain.WebsiteID)); len(websiteDomains) == 1 { - return fmt.Errorf("can not delete last domain") - } - website, err := websiteRepo.GetFirst(commonRepo.WithByID(webSiteDomain.WebsiteID)) - if err != nil { - return err - } - var ports []int - if oldDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(webSiteDomain.WebsiteID), websiteDomainRepo.WithPort(webSiteDomain.Port)); len(oldDomains) == 1 { - ports = append(ports, webSiteDomain.Port) - } - - var domains []string - if oldDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(webSiteDomain.WebsiteID), websiteDomainRepo.WithDomain(webSiteDomain.Domain)); len(oldDomains) == 1 { - domains = append(domains, webSiteDomain.Domain) - } - - if len(ports) > 0 || len(domains) > 0 { - stringBinds := make([]string, len(ports)) - for i := 0; i < len(ports); i++ { - stringBinds[i] = strconv.Itoa(ports[i]) - } - if err := deleteListenAndServerName(website, stringBinds, domains); err != nil { - return err - } - } - - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return err - } - wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data") - fileOp := files.NewFileOp() - if fileOp.Stat(wafDataPath) { - websitesConfigPath := path.Join(wafDataPath, "conf", "sites.json") - content, err := fileOp.GetContent(websitesConfigPath) - if err != nil { - return err - } - var websitesArray []request.WafWebsite - var newWebsitesArray []request.WafWebsite - if content != nil { - if err := json.Unmarshal(content, &websitesArray); err != nil { - return err - } - } - for _, wafWebsite := range websitesArray { - if wafWebsite.Key == website.Alias { - wafSite := wafWebsite - oldDomains := wafSite.Domains - var newDomains []string - for _, domain := range oldDomains { - if domain == webSiteDomain.Domain { - continue - } - newDomains = append(newDomains, domain) - } - wafSite.Domains = newDomains - oldHostArray := wafSite.Host - var newHostArray []string - for _, host := range oldHostArray { - if host == webSiteDomain.Domain+":"+strconv.Itoa(webSiteDomain.Port) { - continue - } - newHostArray = append(newHostArray, host) - } - wafSite.Host = newHostArray - if len(wafSite.Host) == 0 { - wafSite.Host = []string{} - } - newWebsitesArray = append(newWebsitesArray, wafSite) - } else { - newWebsitesArray = append(newWebsitesArray, wafWebsite) - } - } - websitesContent, err := json.Marshal(newWebsitesArray) - if err != nil { - return err - } - if err = fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, 0644); err != nil { - return err - } - } - - return websiteDomainRepo.DeleteBy(context.TODO(), commonRepo.WithByID(domainId)) -} - -func (w WebsiteService) GetNginxConfigByScope(req request.NginxScopeReq) (*response.WebsiteNginxConfig, error) { - keys, ok := dto.ScopeKeyMap[req.Scope] - if !ok || len(keys) == 0 { - return nil, nil - } - - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID)) - if err != nil { - return nil, err - } - var config response.WebsiteNginxConfig - params, err := getNginxParamsByKeys(constant.NginxScopeServer, keys, &website) - if err != nil { - return nil, err - } - config.Params = params - config.Enable = len(params[0].Params) > 0 - - return &config, nil -} - -func (w WebsiteService) UpdateNginxConfigByScope(req request.NginxConfigUpdate) error { - keys, ok := dto.ScopeKeyMap[req.Scope] - if !ok || len(keys) == 0 { - return nil - } - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID)) - if err != nil { - return err - } - if req.Operate == constant.ConfigDel { - var nginxParams []dto.NginxParam - for _, key := range keys { - nginxParams = append(nginxParams, dto.NginxParam{ - Name: key, - }) - } - return deleteNginxConfig(constant.NginxScopeServer, nginxParams, &website) - } - params := getNginxParams(req.Params, keys) - if req.Operate == constant.ConfigNew { - if _, ok := dto.StaticFileKeyMap[req.Scope]; ok { - params = getNginxParamsFromStaticFile(req.Scope, params) - } - } - return updateNginxConfig(constant.NginxScopeServer, params, &website) -} - -func (w WebsiteService) GetWebsiteNginxConfig(websiteId uint, configType string) (response.FileInfo, error) { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(websiteId)) - if err != nil { - return response.FileInfo{}, err - } - configPath := "" - switch configType { - case constant.AppOpenresty: - nginxApp, err := appRepo.GetFirst(appRepo.WithKey(constant.AppOpenresty)) - if err != nil { - return response.FileInfo{}, err - } - nginxInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithAppId(nginxApp.ID)) - if err != nil { - return response.FileInfo{}, err - } - configPath = path.Join(nginxInstall.GetPath(), "conf", "conf.d", website.Alias+".conf") - case constant.ConfigFPM: - runtimeInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) - if err != nil { - return response.FileInfo{}, err - } - configPath = path.Join(runtimeInstall.GetPath(), "conf", "php-fpm.conf") - case constant.ConfigPHP: - runtimeInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) - if err != nil { - return response.FileInfo{}, err - } - configPath = path.Join(runtimeInstall.GetPath(), "conf", "php.ini") - } - info, err := files.NewFileInfo(files.FileOption{ - Path: configPath, - Expand: true, - }) - if err != nil { - return response.FileInfo{}, err - } - return response.FileInfo{FileInfo: *info}, nil -} - -func (w WebsiteService) GetWebsiteHTTPS(websiteId uint) (response.WebsiteHTTPS, error) { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(websiteId)) - if err != nil { - return response.WebsiteHTTPS{}, err - } - var res response.WebsiteHTTPS - if website.WebsiteSSLID == 0 { - res.Enable = false - return res, nil - } - websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(website.WebsiteSSLID)) - if err != nil { - return response.WebsiteHTTPS{}, err - } - res.SSL = *websiteSSL - res.Enable = true - if website.HttpConfig != "" { - res.HttpConfig = website.HttpConfig - } else { - res.HttpConfig = constant.HTTPToHTTPS - } - params, err := getNginxParamsByKeys(constant.NginxScopeServer, []string{"ssl_protocols", "ssl_ciphers", "add_header"}, &website) - if err != nil { - return res, err - } - for _, p := range params { - if p.Name == "ssl_protocols" { - res.SSLProtocol = p.Params - } - if p.Name == "ssl_ciphers" { - res.Algorithm = p.Params[0] - } - if p.Name == "add_header" && len(p.Params) > 0 && p.Params[0] == "Strict-Transport-Security" { - res.Hsts = true - } - } - return res, nil -} - -func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteHTTPSOp) (*response.WebsiteHTTPS, error) { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID)) - if err != nil { - return nil, err - } - var ( - res response.WebsiteHTTPS - websiteSSL model.WebsiteSSL - ) - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return nil, err - } - if err = ChangeHSTSConfig(req.Hsts, nginxInstall, website); err != nil { - return nil, err - } - res.Enable = req.Enable - res.SSLProtocol = req.SSLProtocol - res.Algorithm = req.Algorithm - if !req.Enable { - website.Protocol = constant.ProtocolHTTP - website.WebsiteSSLID = 0 - _, httpsPort, err := getAppInstallPort(constant.AppOpenresty) - if err != nil { - return nil, err - } - httpsPortStr := strconv.Itoa(httpsPort) - if err := deleteListenAndServerName(website, []string{httpsPortStr, "[::]:" + httpsPortStr}, []string{}); err != nil { - return nil, err - } - nginxParams := getNginxParamsFromStaticFile(dto.SSL, nil) - nginxParams = append(nginxParams, - dto.NginxParam{ - Name: "if", - Params: []string{"($scheme", "=", "http)"}, - }, - dto.NginxParam{ - Name: "ssl_certificate", - }, - dto.NginxParam{ - Name: "ssl_certificate_key", - }, - dto.NginxParam{ - Name: "ssl_protocols", - }, - dto.NginxParam{ - Name: "ssl_ciphers", - }, - ) - if err = deleteNginxConfig(constant.NginxScopeServer, nginxParams, &website); err != nil { - return nil, err - } - if err = websiteRepo.Save(ctx, &website); err != nil { - return nil, err - } - return nil, nil - } - - if req.Type == constant.SSLExisted { - websiteModel, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(req.WebsiteSSLID)) - if err != nil { - return nil, err - } - website.WebsiteSSLID = websiteModel.ID - res.SSL = *websiteModel - websiteSSL = *websiteModel - } - if req.Type == constant.SSLManual { - var ( - certificate string - privateKey string - ) - switch req.ImportType { - case "paste": - certificate = req.Certificate - privateKey = req.PrivateKey - case "local": - fileOp := files.NewFileOp() - if !fileOp.Stat(req.PrivateKeyPath) { - return nil, buserr.New("ErrSSLKeyNotFound") - } - if !fileOp.Stat(req.CertificatePath) { - return nil, buserr.New("ErrSSLCertificateNotFound") - } - if content, err := fileOp.GetContent(req.PrivateKeyPath); err != nil { - return nil, err - } else { - privateKey = string(content) - } - if content, err := fileOp.GetContent(req.CertificatePath); err != nil { - return nil, err - } else { - certificate = string(content) - } - } - - privateKeyCertBlock, _ := pem.Decode([]byte(privateKey)) - if privateKeyCertBlock == nil { - return nil, buserr.New("ErrSSLKeyFormat") - } - - certBlock, _ := pem.Decode([]byte(certificate)) - if certBlock == nil { - return nil, buserr.New("ErrSSLCertificateFormat") - } - cert, err := x509.ParseCertificate(certBlock.Bytes) - if err != nil { - return nil, err - } - websiteSSL.ExpireDate = cert.NotAfter - websiteSSL.StartDate = cert.NotBefore - websiteSSL.Type = cert.Issuer.CommonName - if len(cert.Issuer.Organization) > 0 { - websiteSSL.Organization = cert.Issuer.Organization[0] - } else { - websiteSSL.Organization = cert.Issuer.CommonName - } - if len(cert.DNSNames) > 0 { - websiteSSL.PrimaryDomain = cert.DNSNames[0] - websiteSSL.Domains = strings.Join(cert.DNSNames, ",") - } - websiteSSL.Provider = constant.Manual - websiteSSL.PrivateKey = privateKey - websiteSSL.Pem = certificate - - res.SSL = websiteSSL - } - - website.Protocol = constant.ProtocolHTTPS - if err := applySSL(website, websiteSSL, req); err != nil { - return nil, err - } - website.HttpConfig = req.HttpConfig - - if websiteSSL.ID == 0 { - if err := websiteSSLRepo.Create(ctx, &websiteSSL); err != nil { - return nil, err - } - website.WebsiteSSLID = websiteSSL.ID - } - if err := websiteRepo.Save(ctx, &website); err != nil { - return nil, err - } - return &res, nil -} - -func (w WebsiteService) PreInstallCheck(req request.WebsiteInstallCheckReq) ([]response.WebsitePreInstallCheck, error) { - var ( - res []response.WebsitePreInstallCheck - checkIds []uint - showErr = false - ) - - app, err := appRepo.GetFirst(appRepo.WithKey(constant.AppOpenresty)) - if err != nil { - return nil, err - } - appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithAppId(app.ID)) - if reflect.DeepEqual(appInstall, model.AppInstall{}) { - res = append(res, response.WebsitePreInstallCheck{ - Name: appInstall.Name, - AppName: app.Name, - Status: buserr.WithDetail(constant.ErrNotInstall, app.Name, nil).Error(), - Version: appInstall.Version, - }) - showErr = true - } else { - checkIds = append(req.InstallIds, appInstall.ID) - } - if len(checkIds) > 0 { - installList, _ := appInstallRepo.ListBy(commonRepo.WithIdsIn(checkIds)) - for _, install := range installList { - if err = syncAppInstallStatus(&install, false); err != nil { - return nil, err - } - res = append(res, response.WebsitePreInstallCheck{ - Name: install.Name, - Status: install.Status, - Version: install.Version, - AppName: install.App.Name, - }) - if install.Status != constant.Running { - showErr = true - } - } - } - if showErr { - return res, nil - } - return nil, nil -} - -func (w WebsiteService) UpdateNginxConfigFile(req request.WebsiteNginxUpdate) error { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - nginxFull, err := getNginxFull(&website) - if err != nil { - return err - } - filePath := nginxFull.SiteConfig.FilePath - if err := files.NewFileOp().WriteFile(filePath, strings.NewReader(req.Content), 0755); err != nil { - return err - } - return nginxCheckAndReload(nginxFull.SiteConfig.OldContent, filePath, nginxFull.Install.ContainerName) -} - -func (w WebsiteService) OpWebsiteLog(req request.WebsiteLogReq) (*response.WebsiteLog, error) { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return nil, err - } - nginx, err := getNginxFull(&website) - if err != nil { - return nil, err - } - sitePath := path.Join(nginx.SiteDir, "sites", website.Alias) - res := &response.WebsiteLog{ - Content: "", - } - switch req.Operate { - case constant.GetLog: - switch req.LogType { - case constant.AccessLog: - res.Enable = website.AccessLog - if !website.AccessLog { - return res, nil - } - case constant.ErrorLog: - res.Enable = website.ErrorLog - if !website.ErrorLog { - return res, nil - } - } - filePath := path.Join(sitePath, "log", req.LogType) - lines, end, _, err := files.ReadFileByLine(filePath, req.Page, req.PageSize, false) - if err != nil { - return nil, err - } - res.End = end - res.Path = filePath - res.Content = strings.Join(lines, "\n") - return res, nil - case constant.DisableLog: - key := "access_log" - switch req.LogType { - case constant.AccessLog: - website.AccessLog = false - case constant.ErrorLog: - key = "error_log" - website.ErrorLog = false - } - var nginxParams []dto.NginxParam - nginxParams = append(nginxParams, dto.NginxParam{ - Name: key, - Params: []string{"off"}, - }) - - if err := updateNginxConfig(constant.NginxScopeServer, nginxParams, &website); err != nil { - return nil, err - } - if err := websiteRepo.Save(context.Background(), &website); err != nil { - return nil, err - } - case constant.EnableLog: - key := "access_log" - logPath := path.Join("/www", "sites", website.Alias, "log", req.LogType) - params := []string{logPath} - switch req.LogType { - case constant.AccessLog: - params = append(params, "main") - website.AccessLog = true - case constant.ErrorLog: - key = "error_log" - website.ErrorLog = true - } - if err := updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: key, Params: params}}, &website); err != nil { - return nil, err - } - if err := websiteRepo.Save(context.Background(), &website); err != nil { - return nil, err - } - case constant.DeleteLog: - logPath := path.Join(nginx.Install.GetPath(), "www", "sites", website.Alias, "log", req.LogType) - if err := files.NewFileOp().WriteFile(logPath, strings.NewReader(""), 0755); err != nil { - return nil, err - } - } - return res, nil -} - -func (w WebsiteService) ChangeDefaultServer(id uint) error { - defaultWebsite, _ := websiteRepo.GetFirst(websiteRepo.WithDefaultServer()) - if defaultWebsite.ID > 0 { - params, err := getNginxParamsByKeys(constant.NginxScopeServer, []string{"listen"}, &defaultWebsite) - if err != nil { - return err - } - var changeParams []dto.NginxParam - for _, param := range params { - paramLen := len(param.Params) - var newParam []string - if paramLen > 1 && param.Params[paramLen-1] == components.DefaultServer { - newParam = param.Params[:paramLen-1] - } - changeParams = append(changeParams, dto.NginxParam{ - Name: param.Name, - Params: newParam, - }) - } - if err := updateNginxConfig(constant.NginxScopeServer, changeParams, &defaultWebsite); err != nil { - return err - } - defaultWebsite.DefaultServer = false - if err := websiteRepo.Save(context.Background(), &defaultWebsite); err != nil { - return err - } - } - if id > 0 { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(id)) - if err != nil { - return err - } - params, err := getNginxParamsByKeys(constant.NginxScopeServer, []string{"listen"}, &website) - if err != nil { - return err - } - httpPort, httpsPort, err := getAppInstallPort(constant.AppOpenresty) - if err != nil { - return err - } - - var changeParams []dto.NginxParam - for _, param := range params { - paramLen := len(param.Params) - bind := param.Params[0] - var newParam []string - if bind == strconv.Itoa(httpPort) || bind == strconv.Itoa(httpsPort) || bind == "[::]:"+strconv.Itoa(httpPort) || bind == "[::]:"+strconv.Itoa(httpsPort) { - if param.Params[paramLen-1] == components.DefaultServer { - newParam = param.Params - } else { - newParam = append(param.Params, components.DefaultServer) - } - } - changeParams = append(changeParams, dto.NginxParam{ - Name: param.Name, - Params: newParam, - }) - } - if err := updateNginxConfig(constant.NginxScopeServer, changeParams, &website); err != nil { - return err - } - website.DefaultServer = true - return websiteRepo.Save(context.Background(), &website) - } - return nil -} - -func (w WebsiteService) GetPHPConfig(id uint) (*response.PHPConfig, error) { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(id)) - if err != nil { - return nil, err - } - appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) - if err != nil { - return nil, err - } - phpConfigPath := path.Join(appInstall.GetPath(), "conf", "php.ini") - fileOp := files.NewFileOp() - if !fileOp.Stat(phpConfigPath) { - return nil, buserr.WithMap("ErrFileNotFound", map[string]interface{}{"name": "php.ini"}, nil) - } - params := make(map[string]string) - configFile, err := fileOp.OpenFile(phpConfigPath) - if err != nil { - return nil, err - } - defer configFile.Close() - scanner := bufio.NewScanner(configFile) - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if strings.HasPrefix(line, ";") { - continue - } - matches := regexp.MustCompile(`^\s*([a-z_]+)\s*=\s*(.*)$`).FindStringSubmatch(line) - if len(matches) == 3 { - params[matches[1]] = matches[2] - } - } - cfg, err := ini.Load(phpConfigPath) - if err != nil { - return nil, err - } - phpConfig, err := cfg.GetSection("PHP") - if err != nil { - return nil, err - } - disableFunctionStr := phpConfig.Key("disable_functions").Value() - res := &response.PHPConfig{Params: params} - if disableFunctionStr != "" { - disableFunctions := strings.Split(disableFunctionStr, ",") - if len(disableFunctions) > 0 { - res.DisableFunctions = disableFunctions - } - } - uploadMaxSize := phpConfig.Key("upload_max_filesize").Value() - if uploadMaxSize != "" { - res.UploadMaxSize = uploadMaxSize - } - return res, nil -} - -func (w WebsiteService) UpdatePHPConfig(req request.WebsitePHPConfigUpdate) (err error) { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) - if err != nil { - return err - } - phpConfigPath := path.Join(appInstall.GetPath(), "conf", "php.ini") - fileOp := files.NewFileOp() - if !fileOp.Stat(phpConfigPath) { - return buserr.WithMap("ErrFileNotFound", map[string]interface{}{"name": "php.ini"}, nil) - } - configFile, err := fileOp.OpenFile(phpConfigPath) - if err != nil { - return err - } - defer configFile.Close() - - contentBytes, err := fileOp.GetContent(phpConfigPath) - if err != nil { - return err - } - - content := string(contentBytes) - lines := strings.Split(content, "\n") - for i, line := range lines { - if strings.HasPrefix(line, ";") { - continue - } - switch req.Scope { - case "params": - for key, value := range req.Params { - pattern := "^" + regexp.QuoteMeta(key) + "\\s*=\\s*.*$" - if matched, _ := regexp.MatchString(pattern, line); matched { - lines[i] = key + " = " + value - } - } - case "disable_functions": - pattern := "^" + regexp.QuoteMeta("disable_functions") + "\\s*=\\s*.*$" - if matched, _ := regexp.MatchString(pattern, line); matched { - lines[i] = "disable_functions" + " = " + strings.Join(req.DisableFunctions, ",") - break - } - case "upload_max_filesize": - pattern := "^" + regexp.QuoteMeta("post_max_size") + "\\s*=\\s*.*$" - if matched, _ := regexp.MatchString(pattern, line); matched { - lines[i] = "post_max_size" + " = " + req.UploadMaxSize - } - patternUpload := "^" + regexp.QuoteMeta("upload_max_filesize") + "\\s*=\\s*.*$" - if matched, _ := regexp.MatchString(patternUpload, line); matched { - lines[i] = "upload_max_filesize" + " = " + req.UploadMaxSize - } - } - } - updatedContent := strings.Join(lines, "\n") - if err := fileOp.WriteFile(phpConfigPath, strings.NewReader(updatedContent), 0755); err != nil { - return err - } - - appInstallReq := request.AppInstalledOperate{ - InstallId: appInstall.ID, - Operate: constant.Restart, - } - if err = NewIAppInstalledService().Operate(appInstallReq); err != nil { - _ = fileOp.WriteFile(phpConfigPath, strings.NewReader(string(contentBytes)), 0755) - return err - } - - return nil -} - -func (w WebsiteService) UpdatePHPConfigFile(req request.WebsitePHPFileUpdate) error { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - if website.Type != constant.Runtime { - return nil - } - runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID)) - if err != nil { - return err - } - if runtime.Resource != constant.ResourceAppstore { - return nil - } - runtimeInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) - if err != nil { - return err - } - configPath := "" - if req.Type == constant.ConfigFPM { - configPath = path.Join(runtimeInstall.GetPath(), "conf", "php-fpm.conf") - } else { - configPath = path.Join(runtimeInstall.GetPath(), "conf", "php.ini") - } - if err := files.NewFileOp().WriteFile(configPath, strings.NewReader(req.Content), 0755); err != nil { - return err - } - if _, err := compose.Restart(runtimeInstall.GetComposePath()); err != nil { - return err - } - return nil -} - -func (w WebsiteService) ChangePHPVersion(req request.WebsitePHPVersionReq) error { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID)) - if err != nil { - return err - } - runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(req.RuntimeID)) - if err != nil { - return err - } - oldRuntime, err := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID)) - if err != nil { - return err - } - if runtime.Resource == constant.ResourceLocal || oldRuntime.Resource == constant.ResourceLocal { - return buserr.New("ErrPHPResource") - } - appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) - if err != nil { - return err - } - appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(runtime.AppDetailID)) - if err != nil { - return err - } - - envs := make(map[string]interface{}) - if err = json.Unmarshal([]byte(appInstall.Env), &envs); err != nil { - return err - } - if out, err := compose.Down(appInstall.GetComposePath()); err != nil { - if out != "" { - return errors.New(out) - } - return err - } - - var ( - busErr error - fileOp = files.NewFileOp() - envPath = appInstall.GetEnvPath() - composePath = appInstall.GetComposePath() - confDir = path.Join(appInstall.GetPath(), "conf") - backupConfDir = path.Join(appInstall.GetPath(), "conf_bak") - fpmConfDir = path.Join(confDir, "php-fpm.conf") - phpDir = path.Join(constant.RuntimeDir, runtime.Type, runtime.Name, "php") - oldFmContent, _ = fileOp.GetContent(fpmConfDir) - newComposeByte []byte - ) - envParams := make(map[string]string, len(envs)) - handleMap(envs, envParams) - envParams["IMAGE_NAME"] = runtime.Image - defer func() { - if busErr != nil { - envParams["IMAGE_NAME"] = oldRuntime.Image - _ = env.Write(envParams, envPath) - _ = fileOp.WriteFile(composePath, strings.NewReader(appInstall.DockerCompose), 0775) - if fileOp.Stat(backupConfDir) { - _ = fileOp.DeleteDir(confDir) - _ = fileOp.Rename(backupConfDir, confDir) - } - } - }() - - if busErr = env.Write(envParams, envPath); busErr != nil { - return busErr - } - - newComposeByte, busErr = changeServiceName(appDetail.DockerCompose, appInstall.ServiceName) - if busErr != nil { - return err - } - - if busErr = fileOp.WriteFile(composePath, bytes.NewReader(newComposeByte), 0775); busErr != nil { - return busErr - } - if !req.RetainConfig { - if busErr = fileOp.Rename(confDir, backupConfDir); busErr != nil { - return busErr - } - _ = fileOp.CreateDir(confDir, 0755) - if busErr = fileOp.CopyFile(path.Join(phpDir, "php-fpm.conf"), confDir); busErr != nil { - return busErr - } - if busErr = fileOp.CopyFile(path.Join(phpDir, "php.ini"), confDir); busErr != nil { - _ = fileOp.WriteFile(fpmConfDir, bytes.NewReader(oldFmContent), 0775) - return busErr - } - } - - if out, err := compose.Up(appInstall.GetComposePath()); err != nil { - if out != "" { - busErr = errors.New(out) - return busErr - } - busErr = err - return busErr - } - - _ = fileOp.DeleteDir(backupConfDir) - - appInstall.AppDetailId = runtime.AppDetailID - appInstall.AppId = appDetail.AppId - appInstall.Version = appDetail.Version - appInstall.DockerCompose = string(newComposeByte) - - _ = appInstallRepo.Save(context.Background(), &appInstall) - website.RuntimeID = req.RuntimeID - return websiteRepo.Save(context.Background(), &website) -} - -func (w WebsiteService) UpdateRewriteConfig(req request.NginxRewriteUpdate) error { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID)) - if err != nil { - return err - } - nginxFull, err := getNginxFull(&website) - if err != nil { - return err - } - includePath := fmt.Sprintf("/www/sites/%s/rewrite/%s.conf", website.Alias, website.PrimaryDomain) - absolutePath := path.Join(nginxFull.Install.GetPath(), includePath) - fileOp := files.NewFileOp() - var oldRewriteContent []byte - if !fileOp.Stat(path.Dir(absolutePath)) { - if err := fileOp.CreateDir(path.Dir(absolutePath), 0755); err != nil { - return err - } - } - if !fileOp.Stat(absolutePath) { - if err := fileOp.CreateFile(absolutePath); err != nil { - return err - } - } else { - oldRewriteContent, err = fileOp.GetContent(absolutePath) - if err != nil { - return err - } - } - if err := fileOp.WriteFile(absolutePath, strings.NewReader(req.Content), 0755); err != nil { - return err - } - - if err := updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "include", Params: []string{includePath}}}, &website); err != nil { - _ = fileOp.WriteFile(absolutePath, bytes.NewReader(oldRewriteContent), 0755) - return err - } - website.Rewrite = req.Name - return websiteRepo.Save(context.Background(), &website) -} - -func (w WebsiteService) GetRewriteConfig(req request.NginxRewriteReq) (*response.NginxRewriteRes, error) { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID)) - if err != nil { - return nil, err - } - var contentByte []byte - if req.Name == "current" { - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return nil, err - } - rewriteConfPath := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "rewrite", fmt.Sprintf("%s.conf", website.PrimaryDomain)) - fileOp := files.NewFileOp() - if fileOp.Stat(rewriteConfPath) { - contentByte, err = fileOp.GetContent(rewriteConfPath) - if err != nil { - return nil, err - } - } - } else { - rewriteFile := fmt.Sprintf("rewrite/%s.conf", strings.ToLower(req.Name)) - contentByte, err = nginx_conf.Rewrites.ReadFile(rewriteFile) - if err != nil { - return nil, err - } - } - return &response.NginxRewriteRes{ - Content: string(contentByte), - }, err -} - -func (w WebsiteService) UpdateSiteDir(req request.WebsiteUpdateDir) error { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - runDir := req.SiteDir - siteDir := path.Join("/www/sites", website.Alias, "index") - if req.SiteDir != "/" { - siteDir = fmt.Sprintf("%s%s", siteDir, req.SiteDir) - } - if err := updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "root", Params: []string{siteDir}}}, &website); err != nil { - return err - } - website.SiteDir = runDir - return websiteRepo.Save(context.Background(), &website) -} - -func (w WebsiteService) UpdateSitePermission(req request.WebsiteUpdateDirPermission) error { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return err - } - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return err - } - absoluteIndexPath := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "index") - chownCmd := fmt.Sprintf("chown -R %s:%s %s", req.User, req.Group, absoluteIndexPath) - if cmd.HasNoPasswordSudo() { - chownCmd = fmt.Sprintf("sudo %s", chownCmd) - } - if out, err := cmd.ExecWithTimeOut(chownCmd, 10*time.Second); err != nil { - if out != "" { - return errors.New(out) - } - return err - } - website.User = req.User - website.Group = req.Group - return websiteRepo.Save(context.Background(), &website) -} - -func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error) { - var ( - website model.Website - params []response.NginxParam - nginxInstall model.AppInstall - par *parser.Parser - oldContent []byte - ) - - website, err = websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return - } - params, err = getNginxParamsByKeys(constant.NginxScopeHttp, []string{"proxy_cache"}, &website) - if err != nil { - return - } - nginxInstall, err = getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return - } - fileOp := files.NewFileOp() - if len(params) == 0 || len(params[0].Params) == 0 { - commonDir := path.Join(nginxInstall.GetPath(), "www", "common", "proxy") - proxyTempPath := path.Join(commonDir, "proxy_temp_dir") - if !fileOp.Stat(proxyTempPath) { - _ = fileOp.CreateDir(proxyTempPath, 0755) - } - proxyCacheDir := path.Join(commonDir, "proxy_temp_dir") - if !fileOp.Stat(proxyCacheDir) { - _ = fileOp.CreateDir(proxyCacheDir, 0755) - } - nginxParams := getNginxParamsFromStaticFile(dto.CACHE, nil) - if err = updateNginxConfig(constant.NginxScopeHttp, nginxParams, &website); err != nil { - return - } - } - includeDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "proxy") - if !fileOp.Stat(includeDir) { - _ = fileOp.CreateDir(includeDir, 0755) - } - fileName := fmt.Sprintf("%s.conf", req.Name) - includePath := path.Join(includeDir, fileName) - backName := fmt.Sprintf("%s.bak", req.Name) - backPath := path.Join(includeDir, backName) - - if req.Operate == "create" && (fileOp.Stat(includePath) || fileOp.Stat(backPath)) { - err = buserr.New(constant.ErrNameIsExist) - return - } - - defer func() { - if err != nil { - switch req.Operate { - case "create": - _ = fileOp.DeleteFile(includePath) - case "edit": - _ = fileOp.WriteFile(includePath, bytes.NewReader(oldContent), 0755) - } - } - }() - - var config *components.Config - - switch req.Operate { - case "create": - config, err = parser.NewStringParser(string(nginx_conf.Proxy)).Parse() - if err != nil { - return - } - case "edit": - par, err = parser.NewParser(includePath) - if err != nil { - return - } - config, err = par.Parse() - if err != nil { - return - } - oldContent, err = fileOp.GetContent(includePath) - if err != nil { - return - } - case "delete": - _ = fileOp.DeleteFile(includePath) - _ = fileOp.DeleteFile(backPath) - return updateNginxConfig(constant.NginxScopeServer, nil, &website) - case "disable": - _ = fileOp.Rename(includePath, backPath) - return updateNginxConfig(constant.NginxScopeServer, nil, &website) - case "enable": - _ = fileOp.Rename(backPath, includePath) - return updateNginxConfig(constant.NginxScopeServer, nil, &website) - } - - config.FilePath = includePath - directives := config.Directives - location, ok := directives[0].(*components.Location) - if !ok { - err = errors.New("error") - return - } - location.UpdateDirective("proxy_pass", []string{req.ProxyPass}) - location.UpdateDirective("proxy_set_header", []string{"Host", req.ProxyHost}) - location.ChangePath(req.Modifier, req.Match) - if req.Cache { - location.AddCache(req.CacheTime, req.CacheUnit) - } else { - location.RemoveCache() - } - if len(req.Replaces) > 0 { - location.AddSubFilter(req.Replaces) - } else { - location.RemoveSubFilter() - } - if req.SNI { - location.UpdateDirective("proxy_ssl_server_name", []string{"on"}) - } else { - location.UpdateDirective("proxy_ssl_server_name", []string{"off"}) - } - if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { - return buserr.WithErr(constant.ErrUpdateBuWebsite, err) - } - nginxInclude := fmt.Sprintf("/www/sites/%s/proxy/*.conf", website.Alias) - if err = updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "include", Params: []string{nginxInclude}}}, &website); err != nil { - return - } - return -} - -func (w WebsiteService) GetProxies(id uint) (res []request.WebsiteProxyConfig, err error) { - var ( - website model.Website - nginxInstall model.AppInstall - fileList response.FileInfo - ) - website, err = websiteRepo.GetFirst(commonRepo.WithByID(id)) - if err != nil { - return - } - nginxInstall, err = getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return - } - includeDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "proxy") - fileOp := files.NewFileOp() - if !fileOp.Stat(includeDir) { - return - } - fileList, err = NewIFileService().GetFileList(request.FileOption{FileOption: files.FileOption{Path: includeDir, Expand: true, Page: 1, PageSize: 100}}) - if len(fileList.Items) == 0 { - return - } - var ( - content []byte - config *components.Config - ) - for _, configFile := range fileList.Items { - proxyConfig := request.WebsiteProxyConfig{ - ID: website.ID, - } - parts := strings.Split(configFile.Name, ".") - proxyConfig.Name = parts[0] - if parts[1] == "conf" { - proxyConfig.Enable = true - } else { - proxyConfig.Enable = false - } - proxyConfig.FilePath = configFile.Path - content, err = fileOp.GetContent(configFile.Path) - if err != nil { - return - } - proxyConfig.Content = string(content) - config, err = parser.NewStringParser(string(content)).Parse() - if err != nil { - return nil, err - } - directives := config.GetDirectives() - - location, ok := directives[0].(*components.Location) - if !ok { - err = errors.New("error") - return - } - proxyConfig.ProxyPass = location.ProxyPass - proxyConfig.Cache = location.Cache - if location.CacheTime > 0 { - proxyConfig.CacheTime = location.CacheTime - proxyConfig.CacheUnit = location.CacheUint - } - proxyConfig.Match = location.Match - proxyConfig.Modifier = location.Modifier - proxyConfig.ProxyHost = location.Host - proxyConfig.Replaces = location.Replaces - for _, directive := range location.Directives { - if directive.GetName() == "proxy_ssl_server_name" { - proxyConfig.SNI = directive.GetParameters()[0] == "on" - } - } - res = append(res, proxyConfig) - } - return -} - -func (w WebsiteService) UpdateProxyFile(req request.NginxProxyUpdate) (err error) { - var ( - website model.Website - nginxFull dto.NginxFull - oldRewriteContent []byte - ) - website, err = websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID)) - if err != nil { - return err - } - nginxFull, err = getNginxFull(&website) - if err != nil { - return err - } - includePath := fmt.Sprintf("/www/sites/%s/proxy/%s.conf", website.Alias, req.Name) - absolutePath := path.Join(nginxFull.Install.GetPath(), includePath) - fileOp := files.NewFileOp() - oldRewriteContent, err = fileOp.GetContent(absolutePath) - if err != nil { - return err - } - if err = fileOp.WriteFile(absolutePath, strings.NewReader(req.Content), 0755); err != nil { - return err - } - defer func() { - if err != nil { - _ = fileOp.WriteFile(absolutePath, bytes.NewReader(oldRewriteContent), 0755) - } - }() - return updateNginxConfig(constant.NginxScopeServer, nil, &website) -} - -func (w WebsiteService) UpdateAuthBasic(req request.NginxAuthUpdate) (err error) { - var ( - website model.Website - nginxInstall model.AppInstall - params []dto.NginxParam - authContent []byte - authArray []string - ) - website, err = websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID)) - if err != nil { - return err - } - nginxInstall, err = getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return - } - authPath := fmt.Sprintf("/www/sites/%s/auth_basic/auth.pass", website.Alias) - absoluteAuthPath := path.Join(nginxInstall.GetPath(), authPath) - fileOp := files.NewFileOp() - if !fileOp.Stat(path.Dir(absoluteAuthPath)) { - _ = fileOp.CreateDir(path.Dir(absoluteAuthPath), 0755) - } - if !fileOp.Stat(absoluteAuthPath) { - _ = fileOp.CreateFile(absoluteAuthPath) - } - - params = append(params, dto.NginxParam{Name: "auth_basic", Params: []string{`"Authentication"`}}) - params = append(params, dto.NginxParam{Name: "auth_basic_user_file", Params: []string{authPath}}) - authContent, err = fileOp.GetContent(absoluteAuthPath) - if err != nil { - return - } - if len(authContent) > 0 { - authArray = strings.Split(string(authContent), "\n") - } - switch req.Operate { - case "disable": - return deleteNginxConfig(constant.NginxScopeServer, params, &website) - case "enable": - return updateNginxConfig(constant.NginxScopeServer, params, &website) - case "create": - for _, line := range authArray { - authParams := strings.Split(line, ":") - username := authParams[0] - if username == req.Username { - err = buserr.New(constant.ErrUsernameIsExist) - return - } - } - var passwdHash []byte - passwdHash, err = bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost) - if err != nil { - return - } - line := fmt.Sprintf("%s:%s\n", req.Username, passwdHash) - if req.Remark != "" { - line = fmt.Sprintf("%s:%s:%s\n", req.Username, passwdHash, req.Remark) - } - authArray = append(authArray, line) - case "edit": - userExist := false - for index, line := range authArray { - authParams := strings.Split(line, ":") - username := authParams[0] - if username == req.Username { - userExist = true - var passwdHash []byte - passwdHash, err = bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost) - if err != nil { - return - } - userPasswd := fmt.Sprintf("%s:%s\n", req.Username, passwdHash) - if req.Remark != "" { - userPasswd = fmt.Sprintf("%s:%s:%s\n", req.Username, passwdHash, req.Remark) - } - authArray[index] = userPasswd - } - } - if !userExist { - err = buserr.New(constant.ErrUsernameIsNotExist) - return - } - case "delete": - deleteIndex := -1 - for index, line := range authArray { - authParams := strings.Split(line, ":") - username := authParams[0] - if username == req.Username { - deleteIndex = index - } - } - if deleteIndex < 0 { - return - } - authArray = append(authArray[:deleteIndex], authArray[deleteIndex+1:]...) - } - - var passFile *os.File - passFile, err = os.Create(absoluteAuthPath) - if err != nil { - return - } - defer passFile.Close() - writer := bufio.NewWriter(passFile) - for _, line := range authArray { - if line == "" { - continue - } - _, err = writer.WriteString(line + "\n") - if err != nil { - return - } - } - err = writer.Flush() - if err != nil { - return - } - authContent, err = fileOp.GetContent(absoluteAuthPath) - if err != nil { - return - } - if len(authContent) == 0 { - if err = deleteNginxConfig(constant.NginxScopeServer, params, &website); err != nil { - return - } - } - return -} - -func (w WebsiteService) GetAuthBasics(req request.NginxAuthReq) (res response.NginxAuthRes, err error) { - var ( - website model.Website - nginxInstall model.AppInstall - authContent []byte - nginxParams []response.NginxParam - ) - website, err = websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID)) - if err != nil { - return - } - nginxInstall, err = getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return - } - authPath := fmt.Sprintf("/www/sites/%s/auth_basic/auth.pass", website.Alias) - absoluteAuthPath := path.Join(nginxInstall.GetPath(), authPath) - fileOp := files.NewFileOp() - if !fileOp.Stat(absoluteAuthPath) { - return - } - nginxParams, err = getNginxParamsByKeys(constant.NginxScopeServer, []string{"auth_basic"}, &website) - if err != nil { - return - } - res.Enable = len(nginxParams[0].Params) > 0 - authContent, err = fileOp.GetContent(absoluteAuthPath) - authArray := strings.Split(string(authContent), "\n") - for _, line := range authArray { - if line == "" { - continue - } - params := strings.Split(line, ":") - auth := dto.NginxAuth{ - Username: params[0], - } - if len(params) == 3 { - auth.Remark = params[2] - } - res.Items = append(res.Items, auth) - } - return -} - -func (w WebsiteService) UpdateAntiLeech(req request.NginxAntiLeechUpdate) (err error) { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID)) - if err != nil { - return - } - nginxFull, err := getNginxFull(&website) - if err != nil { - return - } - fileOp := files.NewFileOp() - backupContent, err := fileOp.GetContent(nginxFull.SiteConfig.Config.FilePath) - if err != nil { - return - } - block := nginxFull.SiteConfig.Config.FindServers()[0] - locations := block.FindDirectives("location") - for _, location := range locations { - loParams := location.GetParameters() - if len(loParams) > 1 || loParams[0] == "~" { - extendStr := loParams[1] - if strings.HasPrefix(extendStr, `.*\.(`) && strings.HasSuffix(extendStr, `)$`) { - block.RemoveDirective("location", loParams) - } - } - } - if req.Enable { - exts := strings.Split(req.Extends, ",") - newDirective := components.Directive{ - Name: "location", - Parameters: []string{"~", fmt.Sprintf(`.*\.(%s)$`, strings.Join(exts, "|"))}, - } - - newBlock := &components.Block{} - newBlock.Directives = make([]components.IDirective, 0) - if req.Cache { - newBlock.Directives = append(newBlock.Directives, &components.Directive{ - Name: "expires", - Parameters: []string{strconv.Itoa(req.CacheTime) + req.CacheUint}, - }) - } - newBlock.Directives = append(newBlock.Directives, &components.Directive{ - Name: "log_not_found", - Parameters: []string{"off"}, - }) - validDir := &components.Directive{ - Name: "valid_referers", - Parameters: []string{}, - } - if req.NoneRef { - validDir.Parameters = append(validDir.Parameters, "none") - } - if len(req.ServerNames) > 0 { - validDir.Parameters = append(validDir.Parameters, strings.Join(req.ServerNames, " ")) - } - newBlock.Directives = append(newBlock.Directives, validDir) - - ifDir := &components.Directive{ - Name: "if", - Parameters: []string{"($invalid_referer)"}, - } - ifDir.Block = &components.Block{ - Directives: []components.IDirective{ - &components.Directive{ - Name: "return", - Parameters: []string{req.Return}, - }, - &components.Directive{ - Name: "access_log", - Parameters: []string{"off"}, - }, - }, - } - newBlock.Directives = append(newBlock.Directives, ifDir) - newDirective.Block = newBlock - block.Directives = append(block.Directives, &newDirective) - } - - if err = nginx.WriteConfig(nginxFull.SiteConfig.Config, nginx.IndentedStyle); err != nil { - return - } - if err = updateNginxConfig(constant.NginxScopeServer, nil, &website); err != nil { - _ = fileOp.WriteFile(nginxFull.SiteConfig.Config.FilePath, bytes.NewReader(backupContent), 0755) - return - } - return -} - -func (w WebsiteService) GetAntiLeech(id uint) (*response.NginxAntiLeechRes, error) { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(id)) - if err != nil { - return nil, err - } - nginxFull, err := getNginxFull(&website) - if err != nil { - return nil, err - } - res := &response.NginxAntiLeechRes{ - LogEnable: true, - ServerNames: []string{}, - } - block := nginxFull.SiteConfig.Config.FindServers()[0] - locations := block.FindDirectives("location") - for _, location := range locations { - loParams := location.GetParameters() - if len(loParams) > 1 || loParams[0] == "~" { - extendStr := loParams[1] - if strings.HasPrefix(extendStr, `.*\.(`) && strings.HasSuffix(extendStr, `)$`) { - str1 := strings.TrimPrefix(extendStr, `.*\.(`) - str2 := strings.TrimSuffix(str1, ")$") - res.Extends = strings.Join(strings.Split(str2, "|"), ",") - } - } - lDirectives := location.GetBlock().GetDirectives() - for _, lDir := range lDirectives { - if lDir.GetName() == "valid_referers" { - res.Enable = true - params := lDir.GetParameters() - for _, param := range params { - if param == "none" { - res.NoneRef = true - continue - } - if param == "blocked" { - res.Blocked = true - continue - } - if param == "server_names" { - continue - } - res.ServerNames = append(res.ServerNames, param) - } - } - if lDir.GetName() == "if" && lDir.GetParameters()[0] == "($invalid_referer)" { - directives := lDir.GetBlock().GetDirectives() - for _, dir := range directives { - if dir.GetName() == "return" { - res.Return = strings.Join(dir.GetParameters(), " ") - } - if dir.GetName() == "access_log" { - if strings.Join(dir.GetParameters(), "") == "off" { - res.LogEnable = false - } - } - } - } - if lDir.GetName() == "expires" { - res.Cache = true - re := regexp.MustCompile(`^(\d+)(\w+)$`) - matches := re.FindStringSubmatch(lDir.GetParameters()[0]) - if matches == nil { - continue - } - cacheTime, err := strconv.Atoi(matches[1]) - if err != nil { - continue - } - unit := matches[2] - res.CacheUint = unit - res.CacheTime = cacheTime - } - } - } - return res, nil -} - -func (w WebsiteService) OperateRedirect(req request.NginxRedirectReq) (err error) { - var ( - website model.Website - nginxInstall model.AppInstall - oldContent []byte - ) - - website, err = websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID)) - if err != nil { - return err - } - nginxInstall, err = getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return - } - includeDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "redirect") - fileOp := files.NewFileOp() - if !fileOp.Stat(includeDir) { - _ = fileOp.CreateDir(includeDir, 0755) - } - fileName := fmt.Sprintf("%s.conf", req.Name) - includePath := path.Join(includeDir, fileName) - backName := fmt.Sprintf("%s.bak", req.Name) - backPath := path.Join(includeDir, backName) - - if req.Operate == "create" && (fileOp.Stat(includePath) || fileOp.Stat(backPath)) { - err = buserr.New(constant.ErrNameIsExist) - return - } - - defer func() { - if err != nil { - switch req.Operate { - case "create": - _ = fileOp.DeleteFile(includePath) - case "edit": - _ = fileOp.WriteFile(includePath, bytes.NewReader(oldContent), 0755) - } - } - }() - - var ( - config *components.Config - oldPar *parser.Parser - ) - - switch req.Operate { - case "create": - config = &components.Config{} - case "edit": - oldPar, err = parser.NewParser(includePath) - if err != nil { - return - } - config, err = oldPar.Parse() - if err != nil { - return - } - oldContent, err = fileOp.GetContent(includePath) - if err != nil { - return - } - case "delete": - _ = fileOp.DeleteFile(includePath) - _ = fileOp.DeleteFile(backPath) - return updateNginxConfig(constant.NginxScopeServer, nil, &website) - case "disable": - _ = fileOp.Rename(includePath, backPath) - return updateNginxConfig(constant.NginxScopeServer, nil, &website) - case "enable": - _ = fileOp.Rename(backPath, includePath) - return updateNginxConfig(constant.NginxScopeServer, nil, &website) - } - - target := req.Target - block := &components.Block{} - - switch req.Type { - case "path": - if req.KeepPath { - target = req.Target + "$1" - } else { - target = req.Target + "?" - } - redirectKey := "permanent" - if req.Redirect == "302" { - redirectKey = "redirect" - } - block = &components.Block{ - Directives: []components.IDirective{ - &components.Directive{ - Name: "rewrite", - Parameters: []string{fmt.Sprintf("^%s(.*)", req.Path), target, redirectKey}, - }, - }, - } - case "domain": - if req.KeepPath { - target = req.Target + "$request_uri" - } - returnBlock := &components.Block{ - Directives: []components.IDirective{ - &components.Directive{ - Name: "return", - Parameters: []string{req.Redirect, target}, - }, - }, - } - for _, domain := range req.Domains { - block.Directives = append(block.Directives, &components.Directive{ - Name: "if", - Parameters: []string{"($host", "~", fmt.Sprintf("'^%s')", domain)}, - Block: returnBlock, - }) - } - case "404": - if req.RedirectRoot { - target = "/" - } - block = &components.Block{ - Directives: []components.IDirective{ - &components.Directive{ - Name: "error_page", - Parameters: []string{"404", "=", "@notfound"}, - }, - &components.Directive{ - Name: "location", - Parameters: []string{"@notfound"}, - Block: &components.Block{ - Directives: []components.IDirective{ - &components.Directive{ - Name: "return", - Parameters: []string{req.Redirect, target}, - }, - }, - }, - }, - }, - } - } - config.FilePath = includePath - config.Block = block - - if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { - return buserr.WithErr(constant.ErrUpdateBuWebsite, err) - } - - nginxInclude := fmt.Sprintf("/www/sites/%s/redirect/*.conf", website.Alias) - if err = updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "include", Params: []string{nginxInclude}}}, &website); err != nil { - return - } - return -} - -func (w WebsiteService) GetRedirect(id uint) (res []response.NginxRedirectConfig, err error) { - var ( - website model.Website - nginxInstall model.AppInstall - fileList response.FileInfo - ) - website, err = websiteRepo.GetFirst(commonRepo.WithByID(id)) - if err != nil { - return - } - nginxInstall, err = getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return - } - includeDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "redirect") - fileOp := files.NewFileOp() - if !fileOp.Stat(includeDir) { - return - } - fileList, err = NewIFileService().GetFileList(request.FileOption{FileOption: files.FileOption{Path: includeDir, Expand: true, Page: 1, PageSize: 100}}) - if len(fileList.Items) == 0 { - return - } - var ( - content []byte - config *components.Config - ) - for _, configFile := range fileList.Items { - redirectConfig := response.NginxRedirectConfig{ - WebsiteID: website.ID, - } - parts := strings.Split(configFile.Name, ".") - redirectConfig.Name = parts[0] - if parts[1] == "conf" { - redirectConfig.Enable = true - } else { - redirectConfig.Enable = false - } - redirectConfig.FilePath = configFile.Path - content, err = fileOp.GetContent(configFile.Path) - if err != nil { - return - } - redirectConfig.Content = string(content) - config, err = parser.NewStringParser(string(content)).Parse() - if err != nil { - return - } - - dirs := config.GetDirectives() - if len(dirs) > 0 { - firstName := dirs[0].GetName() - switch firstName { - case "if": - for _, ifDir := range dirs { - params := ifDir.GetParameters() - if len(params) > 2 && params[0] == "($host" { - domain := strings.Trim(strings.Trim(params[2], "'"), "^") - redirectConfig.Domains = append(redirectConfig.Domains, domain) - if len(redirectConfig.Domains) > 1 { - continue - } - redirectConfig.Type = "domain" - } - childDirs := ifDir.GetBlock().GetDirectives() - for _, dir := range childDirs { - if dir.GetName() == "return" { - dirParams := dir.GetParameters() - if len(dirParams) > 1 { - redirectConfig.Redirect = dirParams[0] - if strings.HasSuffix(dirParams[1], "$request_uri") { - redirectConfig.KeepPath = true - redirectConfig.Target = strings.TrimSuffix(dirParams[1], "$request_uri") - } else { - redirectConfig.KeepPath = false - redirectConfig.Target = dirParams[1] - } - } - } - } - } - case "rewrite": - redirectConfig.Type = "path" - for _, pathDir := range dirs { - if pathDir.GetName() == "rewrite" { - params := pathDir.GetParameters() - if len(params) > 2 { - redirectConfig.Path = strings.Trim(strings.Trim(params[0], "^"), "(.*)") - if strings.HasSuffix(params[1], "$1") { - redirectConfig.KeepPath = true - redirectConfig.Target = strings.TrimSuffix(params[1], "$1") - } else { - redirectConfig.KeepPath = false - redirectConfig.Target = strings.TrimSuffix(params[1], "?") - } - if params[2] == "permanent" { - redirectConfig.Redirect = "301" - } else { - redirectConfig.Redirect = "302" - } - } - } - } - case "error_page": - redirectConfig.Type = "404" - for _, errDir := range dirs { - if errDir.GetName() == "location" { - childDirs := errDir.GetBlock().GetDirectives() - for _, dir := range childDirs { - if dir.GetName() == "return" { - dirParams := dir.GetParameters() - if len(dirParams) > 1 { - redirectConfig.Redirect = dirParams[0] - if strings.HasSuffix(dirParams[1], "$request_uri") { - redirectConfig.KeepPath = true - redirectConfig.Target = strings.TrimSuffix(dirParams[1], "$request_uri") - redirectConfig.RedirectRoot = false - } else { - redirectConfig.KeepPath = false - redirectConfig.Target = dirParams[1] - redirectConfig.RedirectRoot = redirectConfig.Target == "/" - } - } - } - } - } - } - } - } - res = append(res, redirectConfig) - } - return -} - -func (w WebsiteService) UpdateRedirectFile(req request.NginxRedirectUpdate) (err error) { - var ( - website model.Website - nginxFull dto.NginxFull - oldRewriteContent []byte - ) - website, err = websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID)) - if err != nil { - return err - } - nginxFull, err = getNginxFull(&website) - if err != nil { - return err - } - includePath := fmt.Sprintf("/www/sites/%s/redirect/%s.conf", website.Alias, req.Name) - absolutePath := path.Join(nginxFull.Install.GetPath(), includePath) - fileOp := files.NewFileOp() - oldRewriteContent, err = fileOp.GetContent(absolutePath) - if err != nil { - return err - } - if err = fileOp.WriteFile(absolutePath, strings.NewReader(req.Content), 0755); err != nil { - return err - } - defer func() { - if err != nil { - _ = fileOp.WriteFile(absolutePath, bytes.NewReader(oldRewriteContent), 0755) - } - }() - return updateNginxConfig(constant.NginxScopeServer, nil, &website) -} - -func (w WebsiteService) LoadWebsiteDirConfig(req request.WebsiteCommonReq) (*response.WebsiteDirConfig, error) { - website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return nil, err - } - res := &response.WebsiteDirConfig{} - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return nil, err - } - absoluteIndexPath := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "index") - var appFs = afero.NewOsFs() - info, err := appFs.Stat(absoluteIndexPath) - if err != nil { - return nil, err - } - res.User = strconv.FormatUint(uint64(info.Sys().(*syscall.Stat_t).Uid), 10) - res.UserGroup = strconv.FormatUint(uint64(info.Sys().(*syscall.Stat_t).Gid), 10) - - indexFiles, err := os.ReadDir(absoluteIndexPath) - if err != nil { - return nil, err - } - res.Dirs = []string{"/"} - for _, file := range indexFiles { - if !file.IsDir() { - continue - } - res.Dirs = append(res.Dirs, fmt.Sprintf("/%s", file.Name())) - fileInfo, _ := file.Info() - if fileInfo.Sys().(*syscall.Stat_t).Uid != 1000 || fileInfo.Sys().(*syscall.Stat_t).Gid != 1000 { - res.Msg = i18n.GetMsgByKey("ErrPathPermission") - } - childFiles, _ := os.ReadDir(absoluteIndexPath + "/" + file.Name()) - for _, childFile := range childFiles { - if !childFile.IsDir() { - continue - } - childInfo, _ := childFile.Info() - if childInfo.Sys().(*syscall.Stat_t).Uid != 1000 || childInfo.Sys().(*syscall.Stat_t).Gid != 1000 { - res.Msg = i18n.GetMsgByKey("ErrPathPermission") - } - res.Dirs = append(res.Dirs, fmt.Sprintf("/%s/%s", file.Name(), childFile.Name())) - } - } - - return res, nil -} - -func (w WebsiteService) GetDefaultHtml(resourceType string) (*response.WebsiteHtmlRes, error) { - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return nil, err - } - rootPath := path.Join(nginxInstall.GetPath(), "root") - fileOp := files.NewFileOp() - defaultPath := path.Join(rootPath, "default") - if !fileOp.Stat(defaultPath) { - _ = fileOp.CreateDir(defaultPath, 0755) - } - - res := &response.WebsiteHtmlRes{} - - switch resourceType { - case "404": - resourcePath := path.Join(defaultPath, "404.html") - if content, _ := getResourceContent(fileOp, resourcePath); content != "" { - res.Content = content - return res, nil - } - res.Content = string(nginx_conf.NotFoundHTML) - return res, nil - case "php": - resourcePath := path.Join(defaultPath, "index.php") - if content, _ := getResourceContent(fileOp, resourcePath); content != "" { - res.Content = content - return res, nil - } - res.Content = string(nginx_conf.IndexPHP) - return res, nil - case "index": - resourcePath := path.Join(defaultPath, "index.html") - if content, _ := getResourceContent(fileOp, resourcePath); content != "" { - res.Content = content - return res, nil - } - res.Content = string(nginx_conf.Index) - return res, nil - case "domain404": - resourcePath := path.Join(rootPath, "404.html") - if content, _ := getResourceContent(fileOp, resourcePath); content != "" { - res.Content = content - return res, nil - } - res.Content = string(nginx_conf.DomainNotFoundHTML) - return res, nil - case "stop": - resourcePath := path.Join(rootPath, "stop", "index.html") - if content, _ := getResourceContent(fileOp, resourcePath); content != "" { - res.Content = content - return res, nil - } - res.Content = string(nginx_conf.StopHTML) - return res, nil - } - return res, nil -} - -func (w WebsiteService) UpdateDefaultHtml(req request.WebsiteHtmlUpdate) error { - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return err - } - rootPath := path.Join(nginxInstall.GetPath(), "root") - fileOp := files.NewFileOp() - defaultPath := path.Join(rootPath, "default") - if !fileOp.Stat(defaultPath) { - _ = fileOp.CreateDir(defaultPath, 0755) - } - var resourcePath string - switch req.Type { - case "404": - resourcePath = path.Join(defaultPath, "404.html") - case "php": - resourcePath = path.Join(defaultPath, "index.php") - case "index": - resourcePath = path.Join(defaultPath, "index.html") - case "domain404": - resourcePath = path.Join(rootPath, "404.html") - case "stop": - resourcePath = path.Join(rootPath, "stop", "index.html") - default: - return nil - } - return fileOp.SaveFile(resourcePath, req.Content, 0644) -} diff --git a/backend/app/service/website_acme_account.go b/backend/app/service/website_acme_account.go deleted file mode 100644 index a433e95a2..000000000 --- a/backend/app/service/website_acme_account.go +++ /dev/null @@ -1,78 +0,0 @@ -package service - -import ( - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/ssl" -) - -type WebsiteAcmeAccountService struct { -} - -type IWebsiteAcmeAccountService interface { - Page(search dto.PageInfo) (int64, []response.WebsiteAcmeAccountDTO, error) - Create(create request.WebsiteAcmeAccountCreate) (*response.WebsiteAcmeAccountDTO, error) - Delete(id uint) error -} - -func NewIWebsiteAcmeAccountService() IWebsiteAcmeAccountService { - return &WebsiteAcmeAccountService{} -} - -func (w WebsiteAcmeAccountService) Page(search dto.PageInfo) (int64, []response.WebsiteAcmeAccountDTO, error) { - total, accounts, err := websiteAcmeRepo.Page(search.Page, search.PageSize, commonRepo.WithOrderBy("created_at desc")) - var accountDTOs []response.WebsiteAcmeAccountDTO - for _, account := range accounts { - accountDTOs = append(accountDTOs, response.WebsiteAcmeAccountDTO{ - WebsiteAcmeAccount: account, - }) - } - return total, accountDTOs, err -} - -func (w WebsiteAcmeAccountService) Create(create request.WebsiteAcmeAccountCreate) (*response.WebsiteAcmeAccountDTO, error) { - exist, _ := websiteAcmeRepo.GetFirst(websiteAcmeRepo.WithEmail(create.Email), websiteAcmeRepo.WithType(create.Type)) - if exist != nil { - return nil, buserr.New(constant.ErrEmailIsExist) - } - acmeAccount := &model.WebsiteAcmeAccount{ - Email: create.Email, - Type: create.Type, - KeyType: create.KeyType, - } - - if create.Type == "google" { - if create.EabKid == "" || create.EabHmacKey == "" { - return nil, buserr.New(constant.ErrEabKidOrEabHmacKeyCannotBlank) - } - acmeAccount.EabKid = create.EabKid - acmeAccount.EabHmacKey = create.EabHmacKey - } - - client, err := ssl.NewAcmeClient(acmeAccount) - if err != nil { - return nil, err - } - privateKey, err := ssl.GetPrivateKey(client.User.GetPrivateKey(), ssl.KeyType(create.KeyType)) - if err != nil { - return nil, err - } - acmeAccount.PrivateKey = string(privateKey) - acmeAccount.URL = client.User.Registration.URI - - if err := websiteAcmeRepo.Create(*acmeAccount); err != nil { - return nil, err - } - return &response.WebsiteAcmeAccountDTO{WebsiteAcmeAccount: *acmeAccount}, nil -} - -func (w WebsiteAcmeAccountService) Delete(id uint) error { - if ssls, _ := websiteSSLRepo.List(websiteSSLRepo.WithByAcmeAccountId(id)); len(ssls) > 0 { - return buserr.New(constant.ErrAccountCannotDelete) - } - return websiteAcmeRepo.DeleteBy(commonRepo.WithByID(id)) -} diff --git a/backend/app/service/website_ca.go b/backend/app/service/website_ca.go deleted file mode 100644 index a93b6ad34..000000000 --- a/backend/app/service/website_ca.go +++ /dev/null @@ -1,446 +0,0 @@ -package service - -import ( - "bytes" - "context" - "crypto/ecdsa" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "fmt" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/i18n" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/1Panel-dev/1Panel/backend/utils/ssl" - "github.com/go-acme/lego/v4/certcrypto" - "log" - "math/big" - "net" - "os" - "path" - "strings" - "time" -) - -type WebsiteCAService struct { -} - -type IWebsiteCAService interface { - Page(search request.WebsiteCASearch) (int64, []response.WebsiteCADTO, error) - Create(create request.WebsiteCACreate) (*request.WebsiteCACreate, error) - GetCA(id uint) (*response.WebsiteCADTO, error) - Delete(id uint) error - ObtainSSL(req request.WebsiteCAObtain) (*model.WebsiteSSL, error) - DownloadFile(id uint) (*os.File, error) -} - -func NewIWebsiteCAService() IWebsiteCAService { - return &WebsiteCAService{} -} - -func (w WebsiteCAService) Page(search request.WebsiteCASearch) (int64, []response.WebsiteCADTO, error) { - total, cas, err := websiteCARepo.Page(search.Page, search.PageSize, commonRepo.WithOrderBy("created_at desc")) - if err != nil { - return 0, nil, err - } - var caDTOs []response.WebsiteCADTO - for _, ca := range cas { - caDTOs = append(caDTOs, response.WebsiteCADTO{ - WebsiteCA: ca, - }) - } - return total, caDTOs, err -} - -func (w WebsiteCAService) Create(create request.WebsiteCACreate) (*request.WebsiteCACreate, error) { - if exist, _ := websiteCARepo.GetFirst(commonRepo.WithByName(create.Name)); exist.ID > 0 { - return nil, buserr.New(constant.ErrNameIsExist) - } - - ca := &model.WebsiteCA{ - Name: create.Name, - KeyType: create.KeyType, - } - - pkixName := pkix.Name{ - CommonName: create.CommonName, - Country: []string{create.Country}, - Organization: []string{create.Organization}, - OrganizationalUnit: []string{create.OrganizationUint}, - } - if create.Province != "" { - pkixName.Province = []string{create.Province} - } - if create.City != "" { - pkixName.Locality = []string{create.City} - } - - rootCA := &x509.Certificate{ - SerialNumber: big.NewInt(time.Now().Unix() + 1), - Subject: pkixName, - NotBefore: time.Now(), - NotAfter: time.Now().AddDate(10, 0, 0), - BasicConstraintsValid: true, - IsCA: true, - MaxPathLen: 1, - MaxPathLenZero: false, - KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, - } - - interPrivateKey, interPublicKey, privateBytes, err := createPrivateKey(create.KeyType) - if err != nil { - return nil, err - } - ca.PrivateKey = string(privateBytes) - - rootDer, err := x509.CreateCertificate(rand.Reader, rootCA, rootCA, interPublicKey, interPrivateKey) - if err != nil { - return nil, err - } - rootCert, err := x509.ParseCertificate(rootDer) - if err != nil { - return nil, err - } - certBlock := &pem.Block{ - Type: "CERTIFICATE", - Bytes: rootCert.Raw, - } - pemData := pem.EncodeToMemory(certBlock) - ca.CSR = string(pemData) - - if err := websiteCARepo.Create(context.Background(), ca); err != nil { - return nil, err - } - return &create, nil -} - -func (w WebsiteCAService) GetCA(id uint) (*response.WebsiteCADTO, error) { - res := &response.WebsiteCADTO{} - ca, err := websiteCARepo.GetFirst(commonRepo.WithByID(id)) - if err != nil { - return nil, err - } - res.WebsiteCA = ca - certBlock, _ := pem.Decode([]byte(ca.CSR)) - if certBlock == nil { - return nil, buserr.New("ErrSSLCertificateFormat") - } - cert, err := x509.ParseCertificate(certBlock.Bytes) - if err != nil { - return nil, err - } - res.CommonName = cert.Issuer.CommonName - res.Organization = strings.Join(cert.Issuer.Organization, ",") - res.Country = strings.Join(cert.Issuer.Country, ",") - res.Province = strings.Join(cert.Issuer.Province, ",") - res.City = strings.Join(cert.Issuer.Locality, ",") - res.OrganizationUint = strings.Join(cert.Issuer.OrganizationalUnit, ",") - - return res, nil -} - -func (w WebsiteCAService) Delete(id uint) error { - ssls, _ := websiteSSLRepo.List(websiteSSLRepo.WithByCAID(id)) - if len(ssls) > 0 { - return buserr.New("ErrDeleteCAWithSSL") - } - exist, err := websiteCARepo.GetFirst(commonRepo.WithByID(id)) - if err != nil { - return err - } - if exist.Name == "1Panel" { - return buserr.New("ErrDefaultCA") - } - return websiteCARepo.DeleteBy(commonRepo.WithByID(id)) -} - -func (w WebsiteCAService) ObtainSSL(req request.WebsiteCAObtain) (*model.WebsiteSSL, error) { - var ( - domains []string - ips []net.IP - websiteSSL = &model.WebsiteSSL{} - err error - ca model.WebsiteCA - ) - if req.Renew { - websiteSSL, err = websiteSSLRepo.GetFirst(commonRepo.WithByID(req.SSLID)) - if err != nil { - return nil, err - } - ca, err = websiteCARepo.GetFirst(commonRepo.WithByID(websiteSSL.CaID)) - if err != nil { - return nil, err - } - existDomains := []string{websiteSSL.PrimaryDomain} - if websiteSSL.Domains != "" { - existDomains = append(existDomains, strings.Split(websiteSSL.Domains, ",")...) - } - for _, domain := range existDomains { - if ipAddress := net.ParseIP(domain); ipAddress == nil { - domains = append(domains, domain) - } else { - ips = append(ips, ipAddress) - } - } - } else { - ca, err = websiteCARepo.GetFirst(commonRepo.WithByID(req.ID)) - if err != nil { - return nil, err - } - websiteSSL = &model.WebsiteSSL{ - Provider: constant.SelfSigned, - KeyType: req.KeyType, - PushDir: req.PushDir, - CaID: ca.ID, - AutoRenew: req.AutoRenew, - Description: req.Description, - ExecShell: req.ExecShell, - } - if req.ExecShell { - websiteSSL.Shell = req.Shell - } - if req.PushDir { - if !files.NewFileOp().Stat(req.Dir) { - return nil, buserr.New(constant.ErrLinkPathNotFound) - } - websiteSSL.Dir = req.Dir - } - if req.Domains != "" { - domainArray := strings.Split(req.Domains, "\n") - for _, domain := range domainArray { - if !common.IsValidDomain(domain) { - err = buserr.WithName("ErrDomainFormat", domain) - return nil, err - } else { - if ipAddress := net.ParseIP(domain); ipAddress == nil { - domains = append(domains, domain) - } else { - ips = append(ips, ipAddress) - } - } - } - if len(domains) > 0 { - websiteSSL.PrimaryDomain = domains[0] - websiteSSL.Domains = strings.Join(domains[1:], ",") - } - ipStrings := make([]string, len(ips)) - for i, ip := range ips { - ipStrings[i] = ip.String() - } - if websiteSSL.PrimaryDomain == "" && len(ips) > 0 { - websiteSSL.PrimaryDomain = ipStrings[0] - ipStrings = ipStrings[1:] - } - if len(ipStrings) > 0 { - if websiteSSL.Domains != "" { - websiteSSL.Domains += "," - } - websiteSSL.Domains += strings.Join(ipStrings, ",") - } - - } - } - - rootCertBlock, _ := pem.Decode([]byte(ca.CSR)) - if rootCertBlock == nil { - return nil, buserr.New("ErrSSLCertificateFormat") - } - rootCsr, err := x509.ParseCertificate(rootCertBlock.Bytes) - if err != nil { - return nil, err - } - rootPrivateKeyBlock, _ := pem.Decode([]byte(ca.PrivateKey)) - if rootPrivateKeyBlock == nil { - return nil, buserr.New("ErrSSLCertificateFormat") - } - - var rootPrivateKey any - if ssl.KeyType(ca.KeyType) == certcrypto.EC256 || ssl.KeyType(ca.KeyType) == certcrypto.EC384 { - rootPrivateKey, err = x509.ParseECPrivateKey(rootPrivateKeyBlock.Bytes) - if err != nil { - return nil, err - } - } else { - rootPrivateKey, err = x509.ParsePKCS1PrivateKey(rootPrivateKeyBlock.Bytes) - if err != nil { - return nil, err - } - } - interPrivateKey, interPublicKey, _, err := createPrivateKey(websiteSSL.KeyType) - if err != nil { - return nil, err - } - notAfter := time.Now() - if req.Unit == "year" { - notAfter = notAfter.AddDate(req.Time, 0, 0) - } else { - notAfter = notAfter.AddDate(0, 0, req.Time) - } - interCsr := &x509.Certificate{ - SerialNumber: big.NewInt(time.Now().Unix() + 2), - Subject: rootCsr.Subject, - NotBefore: time.Now(), - NotAfter: notAfter, - BasicConstraintsValid: true, - IsCA: true, - MaxPathLen: 0, - MaxPathLenZero: true, - KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, - } - interDer, err := x509.CreateCertificate(rand.Reader, interCsr, rootCsr, interPublicKey, rootPrivateKey) - if err != nil { - return nil, err - } - interCert, err := x509.ParseCertificate(interDer) - if err != nil { - return nil, err - } - interCertBlock := &pem.Block{ - Type: "CERTIFICATE", - Bytes: interCert.Raw, - } - _, publicKey, privateKeyBytes, err := createPrivateKey(websiteSSL.KeyType) - if err != nil { - return nil, err - } - commonName := "" - if len(domains) > 0 { - commonName = domains[0] - } - if len(ips) > 0 { - commonName = ips[0].String() - } - subject := rootCsr.Subject - subject.CommonName = commonName - csr := &x509.Certificate{ - SerialNumber: big.NewInt(time.Now().Unix() + 3), - Subject: subject, - NotBefore: time.Now(), - NotAfter: notAfter, - BasicConstraintsValid: true, - IsCA: false, - KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - DNSNames: domains, - IPAddresses: ips, - } - - der, err := x509.CreateCertificate(rand.Reader, csr, interCert, publicKey, interPrivateKey) - if err != nil { - return nil, err - } - cert, err := x509.ParseCertificate(der) - if err != nil { - return nil, err - } - - certBlock := &pem.Block{ - Type: "CERTIFICATE", - Bytes: cert.Raw, - } - websiteSSL.Pem = string(pem.EncodeToMemory(certBlock)) + string(pem.EncodeToMemory(rootCertBlock)) + string(pem.EncodeToMemory(interCertBlock)) - websiteSSL.PrivateKey = string(privateKeyBytes) - websiteSSL.ExpireDate = cert.NotAfter - websiteSSL.StartDate = cert.NotBefore - websiteSSL.Type = cert.Issuer.CommonName - websiteSSL.Organization = rootCsr.Subject.Organization[0] - websiteSSL.Status = constant.SSLReady - - if req.Renew { - if err := websiteSSLRepo.Save(websiteSSL); err != nil { - return nil, err - } - } else { - if err := websiteSSLRepo.Create(context.Background(), websiteSSL); err != nil { - return nil, err - } - } - - logFile, _ := os.OpenFile(path.Join(constant.SSLLogDir, fmt.Sprintf("%s-ssl-%d.log", websiteSSL.PrimaryDomain, websiteSSL.ID)), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666) - defer logFile.Close() - logger := log.New(logFile, "", log.LstdFlags) - logger.Println(i18n.GetMsgWithMap("ApplySSLSuccess", map[string]interface{}{"domain": strings.Join(domains, ",")})) - saveCertificateFile(websiteSSL, logger) - if websiteSSL.ExecShell { - workDir := constant.DataDir - if websiteSSL.PushDir { - workDir = websiteSSL.Dir - } - logger.Println(i18n.GetMsgByKey("ExecShellStart")) - if err = cmd.ExecShellWithTimeOut(websiteSSL.Shell, workDir, logger, 30*time.Minute); err != nil { - logger.Println(i18n.GetMsgWithMap("ErrExecShell", map[string]interface{}{"err": err.Error()})) - } else { - logger.Println(i18n.GetMsgByKey("ExecShellSuccess")) - } - } - return websiteSSL, nil -} - -func createPrivateKey(keyType string) (privateKey any, publicKey any, privateKeyBytes []byte, err error) { - privateKey, err = certcrypto.GeneratePrivateKey(ssl.KeyType(keyType)) - if err != nil { - return - } - var ( - caPrivateKeyPEM = new(bytes.Buffer) - ) - if ssl.KeyType(keyType) == certcrypto.EC256 || ssl.KeyType(keyType) == certcrypto.EC384 { - publicKey = &privateKey.(*ecdsa.PrivateKey).PublicKey - publicKey = publicKey.(*ecdsa.PublicKey) - block := &pem.Block{ - Type: "EC PRIVATE KEY", - } - privateBytes, sErr := x509.MarshalECPrivateKey(privateKey.(*ecdsa.PrivateKey)) - if sErr != nil { - err = sErr - return - } - block.Bytes = privateBytes - _ = pem.Encode(caPrivateKeyPEM, block) - } else { - publicKey = &privateKey.(*rsa.PrivateKey).PublicKey - _ = pem.Encode(caPrivateKeyPEM, &pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: x509.MarshalPKCS1PrivateKey(privateKey.(*rsa.PrivateKey)), - }) - } - privateKeyBytes = caPrivateKeyPEM.Bytes() - return -} - -func (w WebsiteCAService) DownloadFile(id uint) (*os.File, error) { - ca, err := websiteCARepo.GetFirst(commonRepo.WithByID(id)) - if err != nil { - return nil, err - } - fileOp := files.NewFileOp() - dir := path.Join(global.CONF.System.BaseDir, "1panel/tmp/ssl", ca.Name) - if fileOp.Stat(dir) { - if err = fileOp.DeleteDir(dir); err != nil { - return nil, err - } - } - if err = fileOp.CreateDir(dir, 0666); err != nil { - return nil, err - } - if err = fileOp.WriteFile(path.Join(dir, "ca.csr"), strings.NewReader(ca.CSR), 0644); err != nil { - return nil, err - } - if err = fileOp.WriteFile(path.Join(dir, "private.key"), strings.NewReader(ca.PrivateKey), 0644); err != nil { - return nil, err - } - fileName := ca.Name + ".zip" - if err = fileOp.Compress([]string{path.Join(dir, "ca.csr"), path.Join(dir, "private.key")}, dir, fileName, files.SdkZip, ""); err != nil { - return nil, err - } - return os.Open(path.Join(dir, fileName)) -} diff --git a/backend/app/service/website_dns_account.go b/backend/app/service/website_dns_account.go deleted file mode 100644 index 152853661..000000000 --- a/backend/app/service/website_dns_account.go +++ /dev/null @@ -1,93 +0,0 @@ -package service - -import ( - "encoding/json" - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" -) - -type WebsiteDnsAccountService struct { -} - -type IWebsiteDnsAccountService interface { - Page(search dto.PageInfo) (int64, []response.WebsiteDnsAccountDTO, error) - Create(create request.WebsiteDnsAccountCreate) (request.WebsiteDnsAccountCreate, error) - Update(update request.WebsiteDnsAccountUpdate) (request.WebsiteDnsAccountUpdate, error) - Delete(id uint) error -} - -func NewIWebsiteDnsAccountService() IWebsiteDnsAccountService { - return &WebsiteDnsAccountService{} -} - -func (w WebsiteDnsAccountService) Page(search dto.PageInfo) (int64, []response.WebsiteDnsAccountDTO, error) { - total, accounts, err := websiteDnsRepo.Page(search.Page, search.PageSize, commonRepo.WithOrderBy("created_at desc")) - var accountDTOs []response.WebsiteDnsAccountDTO - for _, account := range accounts { - auth := make(map[string]string) - _ = json.Unmarshal([]byte(account.Authorization), &auth) - accountDTOs = append(accountDTOs, response.WebsiteDnsAccountDTO{ - WebsiteDnsAccount: account, - Authorization: auth, - }) - } - return total, accountDTOs, err -} - -func (w WebsiteDnsAccountService) Create(create request.WebsiteDnsAccountCreate) (request.WebsiteDnsAccountCreate, error) { - exist, _ := websiteDnsRepo.GetFirst(commonRepo.WithByName(create.Name)) - if exist != nil { - return request.WebsiteDnsAccountCreate{}, buserr.New(constant.ErrNameIsExist) - } - - authorization, err := json.Marshal(create.Authorization) - if err != nil { - return request.WebsiteDnsAccountCreate{}, err - } - - if err := websiteDnsRepo.Create(model.WebsiteDnsAccount{ - Name: create.Name, - Type: create.Type, - Authorization: string(authorization), - }); err != nil { - return request.WebsiteDnsAccountCreate{}, err - } - - return create, nil -} - -func (w WebsiteDnsAccountService) Update(update request.WebsiteDnsAccountUpdate) (request.WebsiteDnsAccountUpdate, error) { - authorization, err := json.Marshal(update.Authorization) - if err != nil { - return request.WebsiteDnsAccountUpdate{}, err - } - exists, _ := websiteDnsRepo.List(commonRepo.WithByName(update.Name)) - for _, exist := range exists { - if exist.ID != update.ID { - return request.WebsiteDnsAccountUpdate{}, buserr.New(constant.ErrNameIsExist) - } - } - if err := websiteDnsRepo.Save(model.WebsiteDnsAccount{ - BaseModel: model.BaseModel{ - ID: update.ID, - }, - Name: update.Name, - Type: update.Type, - Authorization: string(authorization), - }); err != nil { - return request.WebsiteDnsAccountUpdate{}, err - } - - return update, nil -} - -func (w WebsiteDnsAccountService) Delete(id uint) error { - if ssls, _ := websiteSSLRepo.List(websiteSSLRepo.WithByDnsAccountId(id)); len(ssls) > 0 { - return buserr.New(constant.ErrAccountCannotDelete) - } - return websiteDnsRepo.DeleteBy(commonRepo.WithByID(id)) -} diff --git a/backend/app/service/website_ssl.go b/backend/app/service/website_ssl.go deleted file mode 100644 index 761903242..000000000 --- a/backend/app/service/website_ssl.go +++ /dev/null @@ -1,624 +0,0 @@ -package service - -import ( - "context" - "crypto" - "crypto/x509" - "encoding/pem" - "fmt" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/app/repo" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/i18n" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/1Panel-dev/1Panel/backend/utils/ssl" - "github.com/go-acme/lego/v4/certcrypto" - legoLogger "github.com/go-acme/lego/v4/log" - "github.com/jinzhu/gorm" - "log" - "os" - "path" - "strconv" - "strings" - "time" -) - -type WebsiteSSLService struct { -} - -type IWebsiteSSLService interface { - Page(search request.WebsiteSSLSearch) (int64, []response.WebsiteSSLDTO, error) - GetSSL(id uint) (*response.WebsiteSSLDTO, error) - Search(req request.WebsiteSSLSearch) ([]response.WebsiteSSLDTO, error) - Create(create request.WebsiteSSLCreate) (request.WebsiteSSLCreate, error) - GetDNSResolve(req request.WebsiteDNSReq) ([]response.WebsiteDNSRes, error) - GetWebsiteSSL(websiteId uint) (response.WebsiteSSLDTO, error) - Delete(ids []uint) error - Update(update request.WebsiteSSLUpdate) error - Upload(req request.WebsiteSSLUpload) error - ObtainSSL(apply request.WebsiteSSLApply) error - SyncForRestart() error - DownloadFile(id uint) (*os.File, error) -} - -func NewIWebsiteSSLService() IWebsiteSSLService { - return &WebsiteSSLService{} -} - -func (w WebsiteSSLService) Page(search request.WebsiteSSLSearch) (int64, []response.WebsiteSSLDTO, error) { - var ( - result []response.WebsiteSSLDTO - ) - total, sslList, err := websiteSSLRepo.Page(search.Page, search.PageSize, commonRepo.WithOrderBy("created_at desc")) - if err != nil { - return 0, nil, err - } - for _, model := range sslList { - result = append(result, response.WebsiteSSLDTO{ - WebsiteSSL: model, - LogPath: path.Join(constant.SSLLogDir, fmt.Sprintf("%s-ssl-%d.log", model.PrimaryDomain, model.ID)), - }) - } - return total, result, err -} - -func (w WebsiteSSLService) GetSSL(id uint) (*response.WebsiteSSLDTO, error) { - var res response.WebsiteSSLDTO - websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(id)) - if err != nil { - return nil, err - } - res.WebsiteSSL = *websiteSSL - return &res, nil -} - -func (w WebsiteSSLService) Search(search request.WebsiteSSLSearch) ([]response.WebsiteSSLDTO, error) { - var ( - opts []repo.DBOption - result []response.WebsiteSSLDTO - ) - opts = append(opts, commonRepo.WithOrderBy("created_at desc")) - if search.AcmeAccountID != "" { - acmeAccountID, err := strconv.ParseUint(search.AcmeAccountID, 10, 64) - if err != nil { - return nil, err - } - opts = append(opts, websiteSSLRepo.WithByAcmeAccountId(uint(acmeAccountID))) - } - sslList, err := websiteSSLRepo.List(opts...) - if err != nil { - return nil, err - } - for _, sslModel := range sslList { - result = append(result, response.WebsiteSSLDTO{ - WebsiteSSL: sslModel, - }) - } - return result, err -} - -func (w WebsiteSSLService) Create(create request.WebsiteSSLCreate) (request.WebsiteSSLCreate, error) { - if create.Nameserver1 != "" && !common.IsValidIP(create.Nameserver1) { - return create, buserr.New("ErrParseIP") - } - if create.Nameserver2 != "" && !common.IsValidIP(create.Nameserver2) { - return create, buserr.New("ErrParseIP") - } - var res request.WebsiteSSLCreate - acmeAccount, err := websiteAcmeRepo.GetFirst(commonRepo.WithByID(create.AcmeAccountID)) - if err != nil { - return res, err - } - websiteSSL := model.WebsiteSSL{ - Status: constant.SSLInit, - Provider: create.Provider, - AcmeAccountID: acmeAccount.ID, - PrimaryDomain: create.PrimaryDomain, - ExpireDate: time.Now(), - KeyType: create.KeyType, - PushDir: create.PushDir, - Description: create.Description, - Nameserver1: create.Nameserver1, - Nameserver2: create.Nameserver2, - SkipDNS: create.SkipDNS, - DisableCNAME: create.DisableCNAME, - ExecShell: create.ExecShell, - } - if create.ExecShell { - websiteSSL.Shell = create.Shell - } - if create.PushDir { - fileOP := files.NewFileOp() - if !fileOP.Stat(create.Dir) { - _ = fileOP.CreateDir(create.Dir, 0755) - } - websiteSSL.Dir = create.Dir - } - - var domains []string - if create.OtherDomains != "" { - otherDomainArray := strings.Split(create.OtherDomains, "\n") - for _, domain := range otherDomainArray { - if !common.IsValidDomain(domain) { - err = buserr.WithName("ErrDomainFormat", domain) - return res, err - } - domains = append(domains, domain) - } - } - websiteSSL.Domains = strings.Join(domains, ",") - - if create.Provider == constant.DNSAccount || create.Provider == constant.Http { - websiteSSL.AutoRenew = create.AutoRenew - } - if create.Provider == constant.DNSAccount { - dnsAccount, err := websiteDnsRepo.GetFirst(commonRepo.WithByID(create.DnsAccountID)) - if err != nil { - return res, err - } - websiteSSL.DnsAccountID = dnsAccount.ID - } - - if err := websiteSSLRepo.Create(context.TODO(), &websiteSSL); err != nil { - return res, err - } - create.ID = websiteSSL.ID - go func() { - if create.Provider != constant.DnsManual { - if err = w.ObtainSSL(request.WebsiteSSLApply{ - ID: websiteSSL.ID, - }); err != nil { - global.LOG.Errorf("obtain ssl failed, err: %v", err) - } - } - }() - return create, nil -} - -func (w WebsiteSSLService) ObtainSSL(apply request.WebsiteSSLApply) error { - var ( - err error - websiteSSL *model.WebsiteSSL - acmeAccount *model.WebsiteAcmeAccount - dnsAccount *model.WebsiteDnsAccount - ) - - websiteSSL, err = websiteSSLRepo.GetFirst(commonRepo.WithByID(apply.ID)) - if err != nil { - return err - } - acmeAccount, err = websiteAcmeRepo.GetFirst(commonRepo.WithByID(websiteSSL.AcmeAccountID)) - if err != nil { - return err - } - client, err := ssl.NewAcmeClient(acmeAccount) - if err != nil { - return err - } - - switch websiteSSL.Provider { - case constant.DNSAccount: - dnsAccount, err = websiteDnsRepo.GetFirst(commonRepo.WithByID(websiteSSL.DnsAccountID)) - if err != nil { - return err - } - if err = client.UseDns(ssl.DnsType(dnsAccount.Type), dnsAccount.Authorization, *websiteSSL); err != nil { - return err - } - case constant.Http: - appInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - if gorm.IsRecordNotFoundError(err) { - return buserr.New("ErrOpenrestyNotFound") - } - return err - } - if err := client.UseHTTP(path.Join(appInstall.GetPath(), "root")); err != nil { - return err - } - case constant.DnsManual: - if err := client.UseManualDns(); err != nil { - return err - } - } - - domains := []string{websiteSSL.PrimaryDomain} - if websiteSSL.Domains != "" { - domains = append(domains, strings.Split(websiteSSL.Domains, ",")...) - } - - var privateKey crypto.PrivateKey - if websiteSSL.PrivateKey == "" { - privateKey, err = certcrypto.GeneratePrivateKey(ssl.KeyType(websiteSSL.KeyType)) - if err != nil { - return err - } - } else { - block, _ := pem.Decode([]byte(websiteSSL.PrivateKey)) - if block == nil { - return buserr.New("invalid PEM block") - } - var privKey crypto.PrivateKey - keyType := ssl.KeyType(websiteSSL.KeyType) - switch keyType { - case certcrypto.EC256, certcrypto.EC384: - privKey, err = x509.ParseECPrivateKey(block.Bytes) - if err != nil { - return nil - } - case certcrypto.RSA2048, certcrypto.RSA3072, certcrypto.RSA4096: - privKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - return nil - } - } - privateKey = privKey - } - - websiteSSL.Status = constant.SSLApply - err = websiteSSLRepo.Save(websiteSSL) - if err != nil { - return err - } - - go func() { - logFile, _ := os.OpenFile(path.Join(constant.SSLLogDir, fmt.Sprintf("%s-ssl-%d.log", websiteSSL.PrimaryDomain, websiteSSL.ID)), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666) - defer logFile.Close() - logger := log.New(logFile, "", log.LstdFlags) - legoLogger.Logger = logger - startMsg := i18n.GetMsgWithMap("ApplySSLStart", map[string]interface{}{"domain": strings.Join(domains, ","), "type": i18n.GetMsgByKey(websiteSSL.Provider)}) - if websiteSSL.Provider == constant.DNSAccount { - startMsg = startMsg + i18n.GetMsgWithMap("DNSAccountName", map[string]interface{}{"name": dnsAccount.Name, "type": dnsAccount.Type}) - } - legoLogger.Logger.Println(startMsg) - resource, err := client.ObtainSSL(domains, privateKey) - if err != nil { - handleError(websiteSSL, err) - return - } - websiteSSL.PrivateKey = string(resource.PrivateKey) - websiteSSL.Pem = string(resource.Certificate) - websiteSSL.CertURL = resource.CertURL - certBlock, _ := pem.Decode(resource.Certificate) - cert, err := x509.ParseCertificate(certBlock.Bytes) - if err != nil { - handleError(websiteSSL, err) - return - } - websiteSSL.ExpireDate = cert.NotAfter - websiteSSL.StartDate = cert.NotBefore - websiteSSL.Type = cert.Issuer.CommonName - websiteSSL.Organization = cert.Issuer.Organization[0] - websiteSSL.Status = constant.SSLReady - legoLogger.Logger.Println(i18n.GetMsgWithMap("ApplySSLSuccess", map[string]interface{}{"domain": strings.Join(domains, ",")})) - saveCertificateFile(websiteSSL, logger) - - if websiteSSL.ExecShell { - workDir := constant.DataDir - if websiteSSL.PushDir { - workDir = websiteSSL.Dir - } - legoLogger.Logger.Println(i18n.GetMsgByKey("ExecShellStart")) - if err = cmd.ExecShellWithTimeOut(websiteSSL.Shell, workDir, logger, 30*time.Minute); err != nil { - legoLogger.Logger.Println(i18n.GetMsgWithMap("ErrExecShell", map[string]interface{}{"err": err.Error()})) - } else { - legoLogger.Logger.Println(i18n.GetMsgByKey("ExecShellSuccess")) - } - } - - err = websiteSSLRepo.Save(websiteSSL) - if err != nil { - return - } - - websites, _ := websiteRepo.GetBy(websiteRepo.WithWebsiteSSLID(websiteSSL.ID)) - if len(websites) > 0 { - for _, website := range websites { - legoLogger.Logger.Println(i18n.GetMsgWithMap("ApplyWebSiteSSLLog", map[string]interface{}{"name": website.PrimaryDomain})) - if err := createPemFile(website, *websiteSSL); err != nil { - legoLogger.Logger.Println(i18n.GetMsgWithMap("ErrUpdateWebsiteSSL", map[string]interface{}{"name": website.PrimaryDomain, "err": err.Error()})) - } - } - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return - } - if err := opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil { - legoLogger.Logger.Println(i18n.GetMsgByKey(constant.ErrSSLApply)) - return - } - legoLogger.Logger.Println(i18n.GetMsgByKey("ApplyWebSiteSSLSuccess")) - } - }() - - return nil -} - -func handleError(websiteSSL *model.WebsiteSSL, err error) { - if websiteSSL.Status == constant.SSLInit || websiteSSL.Status == constant.SSLError { - websiteSSL.Status = constant.Error - } else { - websiteSSL.Status = constant.SSLApplyError - } - websiteSSL.Message = err.Error() - legoLogger.Logger.Println(i18n.GetErrMsg("ApplySSLFailed", map[string]interface{}{"domain": websiteSSL.PrimaryDomain, "detail": err.Error()})) - _ = websiteSSLRepo.Save(websiteSSL) -} - -func (w WebsiteSSLService) GetDNSResolve(req request.WebsiteDNSReq) ([]response.WebsiteDNSRes, error) { - acmeAccount, err := websiteAcmeRepo.GetFirst(commonRepo.WithByID(req.AcmeAccountID)) - if err != nil { - return nil, err - } - - client, err := ssl.NewAcmeClient(acmeAccount) - if err != nil { - return nil, err - } - resolves, err := client.GetDNSResolve(req.Domains) - if err != nil { - return nil, err - } - var res []response.WebsiteDNSRes - for k, v := range resolves { - res = append(res, response.WebsiteDNSRes{ - Domain: k, - Key: v.Key, - Value: v.Value, - Err: v.Err, - }) - } - return res, nil -} - -func (w WebsiteSSLService) GetWebsiteSSL(websiteId uint) (response.WebsiteSSLDTO, error) { - var res response.WebsiteSSLDTO - website, err := websiteRepo.GetFirst(commonRepo.WithByID(websiteId)) - if err != nil { - return res, err - } - websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(website.WebsiteSSLID)) - if err != nil { - return res, err - } - res.WebsiteSSL = *websiteSSL - return res, nil -} - -func (w WebsiteSSLService) Delete(ids []uint) error { - var names []string - for _, id := range ids { - if websites, _ := websiteRepo.GetBy(websiteRepo.WithWebsiteSSLID(id)); len(websites) > 0 { - oldSSL, _ := websiteSSLRepo.GetFirst(commonRepo.WithByID(id)) - if oldSSL.ID > 0 { - names = append(names, oldSSL.PrimaryDomain) - } - continue - } - sslSetting, _ := settingRepo.Get(settingRepo.WithByKey("SSL")) - if sslSetting.Value == "enable" { - sslID, _ := settingRepo.Get(settingRepo.WithByKey("SSLID")) - idValue, _ := strconv.Atoi(sslID.Value) - if idValue > 0 && uint(idValue) == id { - return buserr.New("ErrDeleteWithPanelSSL") - } - } - _ = websiteSSLRepo.DeleteBy(commonRepo.WithByID(id)) - } - if len(names) > 0 { - return buserr.WithName("ErrSSLCannotDelete", strings.Join(names, ",")) - } - return nil -} - -func (w WebsiteSSLService) Update(update request.WebsiteSSLUpdate) error { - websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(update.ID)) - if err != nil { - return err - } - updateParams := make(map[string]interface{}) - updateParams["primary_domain"] = update.PrimaryDomain - updateParams["description"] = update.Description - updateParams["provider"] = update.Provider - updateParams["push_dir"] = update.PushDir - updateParams["disable_cname"] = update.DisableCNAME - updateParams["skip_dns"] = update.SkipDNS - updateParams["nameserver1"] = update.Nameserver1 - updateParams["nameserver2"] = update.Nameserver2 - updateParams["exec_shell"] = update.ExecShell - if update.ExecShell { - updateParams["shell"] = update.Shell - } else { - updateParams["shell"] = "" - } - - if websiteSSL.Provider != constant.SelfSigned { - acmeAccount, err := websiteAcmeRepo.GetFirst(commonRepo.WithByID(update.AcmeAccountID)) - if err != nil { - return err - } - updateParams["acme_account_id"] = acmeAccount.ID - } - - if update.PushDir { - fileOP := files.NewFileOp() - if !fileOP.Stat(update.Dir) { - _ = fileOP.CreateDir(update.Dir, 0755) - } - updateParams["dir"] = update.Dir - } - var domains []string - if update.OtherDomains != "" { - otherDomainArray := strings.Split(update.OtherDomains, "\n") - for _, domain := range otherDomainArray { - if !common.IsValidDomain(domain) { - return buserr.WithName("ErrDomainFormat", domain) - } - domains = append(domains, domain) - } - } - updateParams["domains"] = strings.Join(domains, ",") - if update.Provider == constant.DNSAccount || update.Provider == constant.Http || update.Provider == constant.SelfSigned { - updateParams["auto_renew"] = update.AutoRenew - } else { - updateParams["auto_renew"] = false - } - if update.Provider == constant.DNSAccount { - dnsAccount, err := websiteDnsRepo.GetFirst(commonRepo.WithByID(update.DnsAccountID)) - if err != nil { - return err - } - updateParams["dns_account_id"] = dnsAccount.ID - } - return websiteSSLRepo.SaveByMap(websiteSSL, updateParams) -} - -func (w WebsiteSSLService) Upload(req request.WebsiteSSLUpload) error { - websiteSSL := &model.WebsiteSSL{ - Provider: constant.Manual, - Description: req.Description, - Status: constant.SSLReady, - } - var err error - if req.SSLID > 0 { - websiteSSL, err = websiteSSLRepo.GetFirst(commonRepo.WithByID(req.SSLID)) - if err != nil { - return err - } - websiteSSL.Description = req.Description - } - if req.Type == "local" { - fileOp := files.NewFileOp() - if !fileOp.Stat(req.PrivateKeyPath) { - return buserr.New("ErrSSLKeyNotFound") - } - if !fileOp.Stat(req.CertificatePath) { - return buserr.New("ErrSSLCertificateNotFound") - } - if content, err := fileOp.GetContent(req.PrivateKeyPath); err != nil { - return err - } else { - websiteSSL.PrivateKey = string(content) - } - if content, err := fileOp.GetContent(req.CertificatePath); err != nil { - return err - } else { - websiteSSL.Pem = string(content) - } - } else { - websiteSSL.PrivateKey = req.PrivateKey - websiteSSL.Pem = req.Certificate - } - - privateKeyCertBlock, _ := pem.Decode([]byte(websiteSSL.PrivateKey)) - if privateKeyCertBlock == nil { - return buserr.New("ErrSSLKeyFormat") - } - - var ( - cert *x509.Certificate - pemData = []byte(websiteSSL.Pem) - ) - for { - certBlock, reset := pem.Decode(pemData) - if certBlock == nil { - break - } - cert, err = x509.ParseCertificate(certBlock.Bytes) - if err != nil { - return err - } - if len(cert.DNSNames) > 0 || len(cert.IPAddresses) > 0 { - break - } - pemData = reset - } - if pemData == nil { - return buserr.New("ErrSSLCertificateFormat") - } - - websiteSSL.ExpireDate = cert.NotAfter - websiteSSL.StartDate = cert.NotBefore - websiteSSL.Type = cert.Issuer.CommonName - if len(cert.Issuer.Organization) > 0 { - websiteSSL.Organization = cert.Issuer.Organization[0] - } else { - websiteSSL.Organization = cert.Issuer.CommonName - } - - var domains []string - if len(cert.DNSNames) > 0 { - websiteSSL.PrimaryDomain = cert.DNSNames[0] - domains = cert.DNSNames[1:] - } - if len(cert.IPAddresses) > 0 { - if websiteSSL.PrimaryDomain == "" { - websiteSSL.PrimaryDomain = cert.IPAddresses[0].String() - for _, ip := range cert.IPAddresses[1:] { - domains = append(domains, ip.String()) - } - } else { - for _, ip := range cert.IPAddresses { - domains = append(domains, ip.String()) - } - } - } - websiteSSL.Domains = strings.Join(domains, ",") - - if websiteSSL.ID > 0 { - if err := UpdateSSLConfig(*websiteSSL); err != nil { - return err - } - return websiteSSLRepo.Save(websiteSSL) - } - return websiteSSLRepo.Create(context.Background(), websiteSSL) -} - -func (w WebsiteSSLService) DownloadFile(id uint) (*os.File, error) { - websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(id)) - if err != nil { - return nil, err - } - fileOp := files.NewFileOp() - dir := path.Join(global.CONF.System.BaseDir, "1panel/tmp/ssl", websiteSSL.PrimaryDomain) - if fileOp.Stat(dir) { - if err = fileOp.DeleteDir(dir); err != nil { - return nil, err - } - } - if err = fileOp.CreateDir(dir, 0666); err != nil { - return nil, err - } - if err = fileOp.WriteFile(path.Join(dir, "fullchain.pem"), strings.NewReader(websiteSSL.Pem), 0644); err != nil { - return nil, err - } - if err = fileOp.WriteFile(path.Join(dir, "privkey.pem"), strings.NewReader(websiteSSL.PrivateKey), 0644); err != nil { - return nil, err - } - fileName := websiteSSL.PrimaryDomain + ".zip" - if err = fileOp.Compress([]string{path.Join(dir, "fullchain.pem"), path.Join(dir, "privkey.pem")}, dir, fileName, files.SdkZip, ""); err != nil { - return nil, err - } - return os.Open(path.Join(dir, fileName)) -} - -func (w WebsiteSSLService) SyncForRestart() error { - sslList, err := websiteSSLRepo.List() - if err != nil { - return err - } - for _, ssl := range sslList { - if ssl.Status == constant.SSLApply { - ssl.Status = constant.SystemRestart - ssl.Message = "System restart causing interrupt" - _ = websiteSSLRepo.Save(&ssl) - } - } - return nil -} diff --git a/backend/app/service/website_utils.go b/backend/app/service/website_utils.go deleted file mode 100644 index bad21c998..000000000 --- a/backend/app/service/website_utils.go +++ /dev/null @@ -1,1117 +0,0 @@ -package service - -import ( - "encoding/json" - "fmt" - "github.com/1Panel-dev/1Panel/backend/utils/xpack" - "log" - "os" - "path" - "path/filepath" - "reflect" - "strconv" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/i18n" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/nginx/components" - "gopkg.in/yaml.v3" - - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/1Panel-dev/1Panel/backend/utils/nginx" - "github.com/1Panel-dev/1Panel/backend/utils/nginx/parser" - "github.com/1Panel-dev/1Panel/cmd/server/nginx_conf" - "github.com/pkg/errors" - "gorm.io/gorm" -) - -func getDomain(domainStr string, defaultPort int) (model.WebsiteDomain, error) { - var ( - err error - domain = model.WebsiteDomain{} - portN int - ) - domainArray := strings.Split(domainStr, ":") - if len(domainArray) == 1 { - domain.Domain, err = handleChineseDomain(domainArray[0]) - if err != nil { - return domain, err - } - domain.Port = defaultPort - return domain, nil - } - if len(domainArray) > 1 { - domain.Domain, err = handleChineseDomain(domainArray[0]) - if err != nil { - return domain, err - } - portStr := domainArray[1] - portN, err = strconv.Atoi(portStr) - if err != nil { - return domain, buserr.WithName("ErrTypePort", portStr) - } - if portN <= 0 || portN > 65535 { - return domain, buserr.New("ErrTypePortRange") - } - domain.Port = portN - return domain, nil - } - return domain, nil -} - -func handleChineseDomain(domain string) (string, error) { - if common.ContainsChinese(domain) { - return common.PunycodeEncode(domain) - } - return domain, nil -} - -func createIndexFile(website *model.Website, runtime *model.Runtime) error { - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return err - } - var ( - indexPath string - indexContent string - websiteService = NewIWebsiteService() - indexFolder = path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "index") - ) - - switch website.Type { - case constant.Static: - indexPath = path.Join(indexFolder, "index.html") - indexHtml, _ := websiteService.GetDefaultHtml("index") - indexContent = indexHtml.Content - case constant.Runtime: - if runtime.Type == constant.RuntimePHP { - indexPath = path.Join(indexFolder, "index.php") - indexPhp, _ := websiteService.GetDefaultHtml("php") - indexContent = indexPhp.Content - } - } - - fileOp := files.NewFileOp() - if !fileOp.Stat(indexFolder) { - if err := fileOp.CreateDir(indexFolder, 0755); err != nil { - return err - } - } - if !fileOp.Stat(indexPath) { - if err := fileOp.CreateFile(indexPath); err != nil { - return err - } - } - if website.Type == constant.Runtime && runtime.Resource == constant.ResourceAppstore { - if err := chownRootDir(indexFolder); err != nil { - return err - } - } - if err := fileOp.WriteFile(indexPath, strings.NewReader(indexContent), 0755); err != nil { - return err - } - - html404, _ := websiteService.GetDefaultHtml("404") - path404 := path.Join(indexFolder, "404.html") - if err := fileOp.WriteFile(path404, strings.NewReader(html404.Content), 0755); err != nil { - return err - } - - return nil -} - -func createProxyFile(website *model.Website) error { - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return err - } - proxyFolder := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name, "www", "sites", website.Alias, "proxy") - filePath := path.Join(proxyFolder, "root.conf") - fileOp := files.NewFileOp() - if !fileOp.Stat(proxyFolder) { - if err := fileOp.CreateDir(proxyFolder, 0755); err != nil { - return err - } - } - if !fileOp.Stat(filePath) { - if err := fileOp.CreateFile(filePath); err != nil { - return err - } - } - config, err := parser.NewStringParser(string(nginx_conf.Proxy)).Parse() - if err != nil { - return err - } - config.FilePath = filePath - directives := config.Directives - location, ok := directives[0].(*components.Location) - if !ok { - return errors.New("error") - } - location.ChangePath("^~", "/") - location.UpdateDirective("proxy_pass", []string{website.Proxy}) - location.UpdateDirective("proxy_set_header", []string{"Host", "$host"}) - if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { - return buserr.WithErr(constant.ErrUpdateBuWebsite, err) - } - return nil -} - -func createWebsiteFolder(nginxInstall model.AppInstall, website *model.Website, runtime *model.Runtime) error { - nginxFolder := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name) - siteFolder := path.Join(nginxFolder, "www", "sites", website.Alias) - fileOp := files.NewFileOp() - if !fileOp.Stat(siteFolder) { - if err := fileOp.CreateDir(siteFolder, 0755); err != nil { - return err - } - if err := fileOp.CreateDir(path.Join(siteFolder, "log"), 0755); err != nil { - return err - } - if err := fileOp.CreateFile(path.Join(siteFolder, "log", "access.log")); err != nil { - return err - } - if err := fileOp.CreateFile(path.Join(siteFolder, "log", "error.log")); err != nil { - return err - } - if err := fileOp.CreateDir(path.Join(siteFolder, "index"), 0775); err != nil { - return err - } - if err := fileOp.CreateDir(path.Join(siteFolder, "ssl"), 0755); err != nil { - return err - } - if website.Type == constant.Runtime { - if runtime.Type == constant.RuntimePHP && runtime.Resource == constant.ResourceLocal { - phpPoolDir := path.Join(siteFolder, "php-pool") - if err := fileOp.CreateDir(phpPoolDir, 0755); err != nil { - return err - } - if err := fileOp.CreateFile(path.Join(phpPoolDir, "php-fpm.sock")); err != nil { - return err - } - } - } - if website.Type == constant.Static || (website.Type == constant.Runtime && runtime.Type == constant.RuntimePHP) { - if err := createIndexFile(website, runtime); err != nil { - return err - } - } - if website.Type == constant.Proxy { - if err := createProxyFile(website); err != nil { - return err - } - } - } - return nil -} - -func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, appInstall *model.AppInstall, runtime *model.Runtime) error { - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return err - } - if err := createWebsiteFolder(nginxInstall, website, runtime); err != nil { - return err - } - - nginxFileName := website.Alias + ".conf" - configPath := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name, "conf", "conf.d", nginxFileName) - nginxContent := string(nginx_conf.WebsiteDefault) - config, err := parser.NewStringParser(nginxContent).Parse() - if err != nil { - return err - } - servers := config.FindServers() - if len(servers) == 0 { - return errors.New("nginx config is not valid") - } - server := servers[0] - server.DeleteListen("80") - var serverNames []string - for _, domain := range domains { - serverNames = append(serverNames, domain.Domain) - server.UpdateListen(strconv.Itoa(domain.Port), false) - if website.IPV6 { - server.UpdateListen("[::]:"+strconv.Itoa(domain.Port), false) - } - } - server.UpdateServerName(serverNames) - - siteFolder := path.Join("/www", "sites", website.Alias) - server.UpdateDirective("access_log", []string{path.Join(siteFolder, "log", "access.log"), "main"}) - server.UpdateDirective("error_log", []string{path.Join(siteFolder, "log", "error.log")}) - - rootIndex := path.Join("/www/sites", website.Alias, "index") - switch website.Type { - case constant.Deployment: - proxy := fmt.Sprintf("http://127.0.0.1:%d", appInstall.HttpPort) - server.UpdateRootProxy([]string{proxy}) - case constant.Static: - server.UpdateRoot(rootIndex) - server.UpdateDirective("error_page", []string{"404", "/404.html"}) - case constant.Proxy: - nginxInclude := fmt.Sprintf("/www/sites/%s/proxy/*.conf", website.Alias) - server.UpdateDirective("include", []string{nginxInclude}) - case constant.Runtime: - switch runtime.Type { - case constant.RuntimePHP: - server.UpdateDirective("error_page", []string{"404", "/404.html"}) - if runtime.Resource == constant.ResourceLocal { - switch runtime.Type { - case constant.RuntimePHP: - server.UpdateRoot(rootIndex) - localPath := path.Join(nginxInstall.GetPath(), rootIndex, "index.php") - server.UpdatePHPProxy([]string{website.Proxy}, localPath) - } - } else { - server.UpdateRoot(rootIndex) - server.UpdatePHPProxy([]string{website.Proxy}, "") - } - case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo: - proxy := fmt.Sprintf("http://127.0.0.1:%d", runtime.Port) - server.UpdateRootProxy([]string{proxy}) - } - } - - config.FilePath = configPath - if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { - return err - } - if err := opNginx(nginxInstall.ContainerName, constant.NginxCheck); err != nil { - _ = deleteWebsiteFolder(nginxInstall, website) - return err - } - if err := opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil { - _ = deleteWebsiteFolder(nginxInstall, website) - return err - } - return nil -} - -func createWafConfig(website *model.Website, domains []model.WebsiteDomain) error { - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return err - } - - if !common.CompareVersion(nginxInstall.Version, "1.21.4.3-2-0") { - return nil - } - wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data") - fileOp := files.NewFileOp() - if !fileOp.Stat(wafDataPath) { - return nil - } - websitesConfigPath := path.Join(wafDataPath, "conf", "sites.json") - content, err := fileOp.GetContent(websitesConfigPath) - if err != nil { - return err - } - var websitesArray []request.WafWebsite - if len(content) != 0 { - if err := json.Unmarshal(content, &websitesArray); err != nil { - return err - } - } - wafWebsite := request.WafWebsite{ - Key: website.Alias, - Domains: make([]string, 0), - Host: make([]string, 0), - } - - for _, domain := range domains { - wafWebsite.Domains = append(wafWebsite.Domains, domain.Domain) - wafWebsite.Host = append(wafWebsite.Host, domain.Domain+":"+strconv.Itoa(domain.Port)) - } - websitesArray = append(websitesArray, wafWebsite) - websitesContent, err := json.Marshal(websitesArray) - if err != nil { - return err - } - if err := fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, 0644); err != nil { - return err - } - - var ( - sitesDir = path.Join(wafDataPath, "sites") - defaultConfigPath = path.Join(wafDataPath, "conf", "siteConfig.json") - defaultRuleDir = path.Join(wafDataPath, "rules") - websiteDir = path.Join(sitesDir, website.Alias) - ) - - defaultConfigContent, err := fileOp.GetContent(defaultConfigPath) - if err != nil { - return err - } - - if !fileOp.Stat(websiteDir) { - if err = fileOp.CreateDir(websiteDir, 0755); err != nil { - return err - } - } - defer func() { - if err != nil { - _ = fileOp.DeleteDir(websiteDir) - } - }() - - if err = fileOp.SaveFileWithByte(path.Join(websiteDir, "config.json"), defaultConfigContent, 0644); err != nil { - return err - } - - websiteRuleDir := path.Join(websiteDir, "rules") - if !fileOp.Stat(websiteRuleDir) { - if err := fileOp.CreateDir(websiteRuleDir, 0755); err != nil { - return err - } - } - defaultRulesName := []string{"acl", "args", "cookie", "defaultUaBlack", "defaultUrlBlack", "fileExt", "header", "methodWhite", "cdn"} - for _, ruleName := range defaultRulesName { - srcPath := path.Join(defaultRuleDir, ruleName+".json") - if fileOp.Stat(srcPath) { - _ = fileOp.Copy(srcPath, websiteRuleDir) - } - } - - if err = opNginx(nginxInstall.ContainerName, constant.NginxCheck); err != nil { - return err - } - if err = opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil { - return err - } - - return nil -} - -func delNginxConfig(website model.Website, force bool) error { - nginxApp, err := appRepo.GetFirst(appRepo.WithKey(constant.AppOpenresty)) - if err != nil { - return err - } - nginxInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithAppId(nginxApp.ID)) - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil - } - return err - } - - nginxFileName := website.Alias + ".conf" - configPath := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name, "conf", "conf.d", nginxFileName) - fileOp := files.NewFileOp() - - if !fileOp.Stat(configPath) { - return nil - } - if err := fileOp.DeleteFile(configPath); err != nil { - return err - } - sitePath := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name, "www", "sites", website.Alias) - if fileOp.Stat(sitePath) { - xpack.RemoveTamper(website.Alias) - _ = fileOp.DeleteDir(sitePath) - } - - if err := opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil { - if force { - return nil - } - return err - } - return nil -} - -func delWafConfig(website model.Website, force bool) error { - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return err - } - if !common.CompareVersion(nginxInstall.Version, "1.21.4.3-2-0") { - return nil - } - wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data") - fileOp := files.NewFileOp() - if !fileOp.Stat(wafDataPath) { - return nil - } - monitorDir := path.Join(wafDataPath, "db", "sites", website.Alias) - if fileOp.Stat(monitorDir) { - _ = fileOp.DeleteDir(monitorDir) - } - websitesConfigPath := path.Join(wafDataPath, "conf", "sites.json") - content, err := fileOp.GetContent(websitesConfigPath) - if err != nil { - return err - } - var websitesArray []request.WafWebsite - var newWebsiteArray []request.WafWebsite - if len(content) > 0 { - if err = json.Unmarshal(content, &websitesArray); err != nil { - return err - } - } - for _, wafWebsite := range websitesArray { - if wafWebsite.Key != website.Alias { - newWebsiteArray = append(newWebsiteArray, wafWebsite) - } - } - websitesContent, err := json.Marshal(newWebsiteArray) - if err != nil { - return err - } - if err := fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, 0644); err != nil { - return err - } - - _ = fileOp.DeleteDir(path.Join(wafDataPath, "sites", website.Alias)) - - if err := opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil { - if force { - return nil - } - return err - } - return nil -} - -func addListenAndServerName(website model.Website, ports []int, domains []string) error { - nginxFull, err := getNginxFull(&website) - if err != nil { - return nil - } - nginxConfig := nginxFull.SiteConfig - config := nginxFull.SiteConfig.Config - server := config.FindServers()[0] - for _, port := range ports { - server.AddListen(strconv.Itoa(port), false) - if website.IPV6 { - server.UpdateListen("[::]:"+strconv.Itoa(port), false) - } - } - for _, domain := range domains { - server.AddServerName(domain) - } - if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { - return err - } - return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxFull.Install.ContainerName) -} - -func deleteListenAndServerName(website model.Website, binds []string, domains []string) error { - nginxFull, err := getNginxFull(&website) - if err != nil { - return nil - } - nginxConfig := nginxFull.SiteConfig - config := nginxFull.SiteConfig.Config - server := config.FindServers()[0] - for _, bind := range binds { - server.DeleteListen(bind) - server.DeleteListen("[::]:" + bind) - } - for _, domain := range domains { - server.DeleteServerName(domain) - } - - if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { - return err - } - return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxFull.Install.ContainerName) -} - -func createPemFile(website model.Website, websiteSSL model.WebsiteSSL) error { - nginxApp, err := appRepo.GetFirst(appRepo.WithKey(constant.AppOpenresty)) - if err != nil { - return err - } - nginxInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithAppId(nginxApp.ID)) - if err != nil { - return err - } - - configDir := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name, "www", "sites", website.Alias, "ssl") - fileOp := files.NewFileOp() - - if !fileOp.Stat(configDir) { - if err := fileOp.CreateDir(configDir, 0775); err != nil { - return err - } - } - - fullChainFile := path.Join(configDir, "fullchain.pem") - privatePemFile := path.Join(configDir, "privkey.pem") - - if !fileOp.Stat(fullChainFile) { - if err := fileOp.CreateFile(fullChainFile); err != nil { - return err - } - } - if !fileOp.Stat(privatePemFile) { - if err := fileOp.CreateFile(privatePemFile); err != nil { - return err - } - } - - if err := fileOp.WriteFile(fullChainFile, strings.NewReader(websiteSSL.Pem), 0644); err != nil { - return err - } - if err := fileOp.WriteFile(privatePemFile, strings.NewReader(websiteSSL.PrivateKey), 0644); err != nil { - return err - } - return nil -} - -func applySSL(website model.Website, websiteSSL model.WebsiteSSL, req request.WebsiteHTTPSOp) error { - nginxFull, err := getNginxFull(&website) - if err != nil { - return nil - } - domains, err := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(website.ID)) - if err != nil { - return nil - } - noDefaultPort := true - for _, domain := range domains { - if domain.Port == 80 { - noDefaultPort = false - } - } - config := nginxFull.SiteConfig.Config - server := config.FindServers()[0] - - httpPort := strconv.Itoa(nginxFull.Install.HttpPort) - httpsPort := strconv.Itoa(nginxFull.Install.HttpsPort) - httpPortIPV6 := "[::]:" + httpPort - httpsPortIPV6 := "[::]:" + httpsPort - - server.UpdateListen(httpsPort, website.DefaultServer, "ssl", "http2") - if website.IPV6 { - server.UpdateListen(httpsPortIPV6, website.DefaultServer, "ssl", "http2") - } - - switch req.HttpConfig { - case constant.HTTPSOnly: - server.RemoveListenByBind(httpPort) - server.RemoveListenByBind(httpPortIPV6) - server.RemoveDirective("if", []string{"($scheme"}) - case constant.HTTPToHTTPS: - if !noDefaultPort { - server.UpdateListen(httpPort, website.DefaultServer) - } - if website.IPV6 { - server.UpdateListen(httpPortIPV6, website.DefaultServer) - } - server.AddHTTP2HTTPS() - case constant.HTTPAlso: - if !noDefaultPort { - server.UpdateListen(httpPort, website.DefaultServer) - } - server.RemoveDirective("if", []string{"($scheme"}) - if website.IPV6 { - server.UpdateListen(httpPortIPV6, website.DefaultServer) - } - } - - if !req.Hsts { - server.RemoveDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000\""}) - } - - if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { - return err - } - if err := createPemFile(website, websiteSSL); err != nil { - return err - } - nginxParams := getNginxParamsFromStaticFile(dto.SSL, []dto.NginxParam{}) - for i, param := range nginxParams { - if param.Name == "ssl_certificate" { - nginxParams[i].Params = []string{path.Join("/www", "sites", website.Alias, "ssl", "fullchain.pem")} - } - if param.Name == "ssl_certificate_key" { - nginxParams[i].Params = []string{path.Join("/www", "sites", website.Alias, "ssl", "privkey.pem")} - } - if param.Name == "ssl_protocols" { - nginxParams[i].Params = req.SSLProtocol - } - if param.Name == "ssl_ciphers" { - nginxParams[i].Params = []string{req.Algorithm} - } - } - if req.Hsts { - nginxParams = append(nginxParams, dto.NginxParam{ - Name: "add_header", - Params: []string{"Strict-Transport-Security", "\"max-age=31536000\""}, - }) - } - - if err := updateNginxConfig(constant.NginxScopeServer, nginxParams, &website); err != nil { - return err - } - return nil -} - -func getParamArray(key string, param interface{}) []string { - var res []string - switch p := param.(type) { - case string: - if key == "index" { - res = strings.Split(p, "\n") - return res - } - - res = strings.Split(p, " ") - return res - } - return res -} - -func handleParamMap(paramMap map[string]string, keys []string) []dto.NginxParam { - var nginxParams []dto.NginxParam - for k, v := range paramMap { - for _, name := range keys { - if name == k { - param := dto.NginxParam{ - Name: k, - Params: getParamArray(k, v), - } - nginxParams = append(nginxParams, param) - } - } - } - return nginxParams -} - -func getNginxParams(params interface{}, keys []string) []dto.NginxParam { - var nginxParams []dto.NginxParam - - switch p := params.(type) { - case map[string]interface{}: - return handleParamMap(toMapStr(p), keys) - case []interface{}: - for _, mA := range p { - if m, ok := mA.(map[string]interface{}); ok { - nginxParams = append(nginxParams, handleParamMap(toMapStr(m), keys)...) - } - } - } - return nginxParams -} - -func toMapStr(m map[string]interface{}) map[string]string { - ret := make(map[string]string, len(m)) - for k, v := range m { - ret[k] = fmt.Sprint(v) - } - return ret -} - -func deleteWebsiteFolder(nginxInstall model.AppInstall, website *model.Website) error { - nginxFolder := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name) - siteFolder := path.Join(nginxFolder, "www", "sites", website.Alias) - fileOp := files.NewFileOp() - if fileOp.Stat(siteFolder) { - _ = fileOp.DeleteDir(siteFolder) - } - nginxFilePath := path.Join(nginxFolder, "conf", "conf.d", website.PrimaryDomain+".conf") - if fileOp.Stat(nginxFilePath) { - _ = fileOp.DeleteFile(nginxFilePath) - } - return nil -} - -func opWebsite(website *model.Website, operate string) error { - nginxInstall, err := getNginxFull(website) - if err != nil { - return err - } - config := nginxInstall.SiteConfig.Config - servers := config.FindServers() - if len(servers) == 0 { - return errors.New("nginx config is not valid") - } - server := servers[0] - if operate == constant.StopWeb { - proxyInclude := fmt.Sprintf("/www/sites/%s/proxy/*.conf", website.Alias) - server.RemoveDirective("include", []string{proxyInclude}) - rewriteInclude := fmt.Sprintf("/www/sites/%s/rewrite/%s.conf", website.Alias, website.Alias) - server.RemoveDirective("include", []string{rewriteInclude}) - - switch website.Type { - case constant.Deployment: - server.RemoveDirective("location", []string{"/"}) - case constant.Runtime: - runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID)) - if err != nil { - return err - } - if runtime.Type == constant.RuntimePHP { - server.RemoveDirective("location", []string{"~", "[^/]\\.php(/|$)"}) - } else { - server.RemoveDirective("location", []string{"/"}) - } - } - server.UpdateRoot("/usr/share/nginx/html/stop") - website.Status = constant.WebStopped - } - if operate == constant.StartWeb { - absoluteIncludeDir := path.Join(nginxInstall.Install.GetPath(), fmt.Sprintf("/www/sites/%s/proxy", website.Alias)) - fileOp := files.NewFileOp() - if fileOp.Stat(absoluteIncludeDir) && !files.IsEmptyDir(absoluteIncludeDir) { - proxyInclude := fmt.Sprintf("/www/sites/%s/proxy/*.conf", website.Alias) - server.UpdateDirective("include", []string{proxyInclude}) - } - rewriteInclude := fmt.Sprintf("/www/sites/%s/rewrite/%s.conf", website.Alias, website.Alias) - absoluteRewritePath := path.Join(nginxInstall.Install.GetPath(), rewriteInclude) - if fileOp.Stat(absoluteRewritePath) { - server.UpdateDirective("include", []string{rewriteInclude}) - } - rootIndex := path.Join("/www/sites", website.Alias, "index") - if website.SiteDir != "/" { - rootIndex = path.Join(rootIndex, website.SiteDir) - } - switch website.Type { - case constant.Deployment: - server.RemoveDirective("root", nil) - appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) - if err != nil { - return err - } - proxy := fmt.Sprintf("http://127.0.0.1:%d", appInstall.HttpPort) - server.UpdateRootProxy([]string{proxy}) - case constant.Static: - server.UpdateRoot(rootIndex) - server.UpdateRootLocation() - case constant.Proxy: - server.RemoveDirective("root", nil) - case constant.Runtime: - server.UpdateRoot(rootIndex) - localPath := "" - runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID)) - if err != nil { - return err - } - if runtime.Type == constant.RuntimePHP { - if website.ProxyType == constant.RuntimeProxyUnix || website.ProxyType == constant.RuntimeProxyTcp { - localPath = path.Join(nginxInstall.Install.GetPath(), rootIndex, "index.php") - } - server.UpdatePHPProxy([]string{website.Proxy}, localPath) - } else { - proxy := fmt.Sprintf("http://127.0.0.1:%d", runtime.Port) - server.UpdateRootProxy([]string{proxy}) - } - } - website.Status = constant.WebRunning - now := time.Now() - if website.ExpireDate.Before(now) { - defaultDate, _ := time.Parse(constant.DateLayout, constant.DefaultDate) - website.ExpireDate = defaultDate - } - } - - if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { - return err - } - return nginxCheckAndReload(nginxInstall.SiteConfig.OldContent, config.FilePath, nginxInstall.Install.ContainerName) -} - -func changeIPV6(website model.Website, enable bool) error { - nginxFull, err := getNginxFull(&website) - if err != nil { - return nil - } - config := nginxFull.SiteConfig.Config - server := config.FindServers()[0] - listens := server.Listens - if enable { - for _, listen := range listens { - if strings.HasPrefix(listen.Bind, "[::]:") { - continue - } - exist := false - ipv6Bind := fmt.Sprintf("[::]:%s", listen.Bind) - for _, li := range listens { - if li.Bind == ipv6Bind { - exist = true - break - } - } - if !exist { - server.UpdateListen(ipv6Bind, false, listen.GetParameters()[1:]...) - } - } - } else { - for _, listen := range listens { - if strings.HasPrefix(listen.Bind, "[::]:") { - server.RemoveListenByBind(listen.Bind) - } - } - } - if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { - return err - } - return nginxCheckAndReload(nginxFull.SiteConfig.OldContent, config.FilePath, nginxFull.Install.ContainerName) -} - -func checkIsLinkApp(website model.Website) bool { - if website.Type == constant.Deployment { - return true - } - if website.Type == constant.Runtime { - runtime, _ := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID)) - return runtime.Resource == constant.ResourceAppstore - } - return false -} - -func chownRootDir(path string) error { - _, err := cmd.ExecWithTimeOut(fmt.Sprintf(`chown -R 1000:1000 "%s"`, path), 1*time.Second) - if err != nil { - return err - } - return nil -} - -func changeServiceName(newComposeContent, newServiceName string) (composeByte []byte, err error) { - composeMap := make(map[string]interface{}) - if err = yaml.Unmarshal([]byte(newComposeContent), &composeMap); err != nil { - return - } - value, ok := composeMap["services"] - if !ok || value == nil { - err = buserr.New(constant.ErrFileParse) - return - } - servicesMap := value.(map[string]interface{}) - - index := 0 - serviceName := "" - for k := range servicesMap { - serviceName = k - if index > 0 { - continue - } - index++ - } - if newServiceName != serviceName { - servicesMap[newServiceName] = servicesMap[serviceName] - delete(servicesMap, serviceName) - } - - return yaml.Marshal(composeMap) -} - -func getWebsiteDomains(domains string, defaultPort int, websiteID uint) (domainModels []model.WebsiteDomain, addPorts []int, addDomains []string, err error) { - var ( - ports = make(map[int]struct{}) - ) - domainArray := strings.Split(domains, "\n") - for _, domain := range domainArray { - if domain == "" { - continue - } - if !common.IsValidDomain(domain) { - err = buserr.WithName("ErrDomainFormat", domain) - return - } - var domainModel model.WebsiteDomain - domainModel, err = getDomain(domain, defaultPort) - if err != nil { - return - } - if reflect.DeepEqual(domainModel, model.WebsiteDomain{}) { - continue - } - domainModel.WebsiteID = websiteID - domainModels = append(domainModels, domainModel) - if domainModel.Port != defaultPort { - ports[domainModel.Port] = struct{}{} - } - if exist, _ := websiteDomainRepo.GetFirst(websiteDomainRepo.WithDomain(domainModel.Domain), websiteDomainRepo.WithWebsiteId(websiteID)); exist.ID == 0 { - addDomains = append(addDomains, domainModel.Domain) - } - } - for _, domain := range domainModels { - if exist, _ := websiteDomainRepo.GetFirst(websiteDomainRepo.WithDomain(domain.Domain), websiteDomainRepo.WithPort(domain.Port)); exist.ID > 0 { - website, _ := websiteRepo.GetFirst(commonRepo.WithByID(exist.WebsiteID)) - err = buserr.WithName(constant.ErrDomainIsUsed, website.PrimaryDomain) - return - } - } - - for port := range ports { - if existPorts, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithPort(port)); len(existPorts) == 0 { - errMap := make(map[string]interface{}) - errMap["port"] = port - appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port)) - if appInstall.ID > 0 { - errMap["type"] = i18n.GetMsgByKey("TYPE_APP") - errMap["name"] = appInstall.Name - err = buserr.WithMap("ErrPortExist", errMap, nil) - return - } - runtime, _ := runtimeRepo.GetFirst(runtimeRepo.WithPort(port)) - if runtime != nil { - errMap["type"] = i18n.GetMsgByKey("TYPE_RUNTIME") - errMap["name"] = runtime.Name - err = buserr.WithMap("ErrPortExist", errMap, nil) - return - } - if common.ScanPort(port) { - err = buserr.WithDetail(constant.ErrPortInUsed, port, nil) - return - } - } - if existPorts, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(websiteID), websiteDomainRepo.WithPort(port)); len(existPorts) == 0 { - addPorts = append(addPorts, port) - } - } - - return -} - -func saveCertificateFile(websiteSSL *model.WebsiteSSL, logger *log.Logger) { - if websiteSSL.PushDir { - fileOp := files.NewFileOp() - var ( - pushErr error - MsgMap = map[string]interface{}{"path": websiteSSL.Dir, "status": i18n.GetMsgByKey("Success")} - ) - if pushErr = fileOp.SaveFile(path.Join(websiteSSL.Dir, "privkey.pem"), websiteSSL.PrivateKey, 0666); pushErr != nil { - MsgMap["status"] = i18n.GetMsgByKey("Failed") - logger.Println(i18n.GetMsgWithMap("PushDirLog", MsgMap)) - logger.Println("Push dir failed:" + pushErr.Error()) - } - if pushErr = fileOp.SaveFile(path.Join(websiteSSL.Dir, "fullchain.pem"), websiteSSL.Pem, 0666); pushErr != nil { - MsgMap["status"] = i18n.GetMsgByKey("Failed") - logger.Println(i18n.GetMsgWithMap("PushDirLog", MsgMap)) - logger.Println("Push dir failed:" + pushErr.Error()) - } - if pushErr == nil { - logger.Println(i18n.GetMsgWithMap("PushDirLog", MsgMap)) - } - } -} - -func GetSystemSSL() (bool, uint) { - sslSetting, err := settingRepo.Get(settingRepo.WithByKey("SSL")) - if err != nil { - global.LOG.Errorf("load service ssl from setting failed, err: %v", err) - return false, 0 - } - if sslSetting.Value == "enable" { - sslID, _ := settingRepo.Get(settingRepo.WithByKey("SSLID")) - idValue, _ := strconv.Atoi(sslID.Value) - if idValue > 0 { - return true, uint(idValue) - } - } - return false, 0 -} - -func UpdateSSLConfig(websiteSSL model.WebsiteSSL) error { - websites, _ := websiteRepo.GetBy(websiteRepo.WithWebsiteSSLID(websiteSSL.ID)) - if len(websites) > 0 { - for _, website := range websites { - if err := createPemFile(website, websiteSSL); err != nil { - return buserr.WithMap("ErrUpdateWebsiteSSL", map[string]interface{}{"name": website.PrimaryDomain, "err": err.Error()}, err) - } - } - nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) - if err != nil { - return err - } - if err := opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil { - return buserr.WithErr(constant.ErrSSLApply, err) - } - } - enable, sslID := GetSystemSSL() - if enable && sslID == websiteSSL.ID { - fileOp := files.NewFileOp() - secretDir := path.Join(global.CONF.System.BaseDir, "1panel/secret") - if err := fileOp.WriteFile(path.Join(secretDir, "server.crt"), strings.NewReader(websiteSSL.Pem), 0600); err != nil { - global.LOG.Errorf("Failed to update the SSL certificate File for 1Panel System domain [%s] , err:%s", websiteSSL.PrimaryDomain, err.Error()) - return err - } - if err := fileOp.WriteFile(path.Join(secretDir, "server.key"), strings.NewReader(websiteSSL.PrivateKey), 0600); err != nil { - global.LOG.Errorf("Failed to update the SSL certificate for 1Panel System domain [%s] , err:%s", websiteSSL.PrimaryDomain, err.Error()) - return err - } - } - return nil -} - -func ChangeHSTSConfig(enable bool, nginxInstall model.AppInstall, website model.Website) error { - includeDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "proxy") - fileOp := files.NewFileOp() - if !fileOp.Stat(includeDir) { - return nil - } - err := filepath.Walk(includeDir, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if !info.IsDir() { - if filepath.Ext(path) == ".conf" { - par, err := parser.NewParser(path) - if err != nil { - return err - } - config, err := par.Parse() - if err != nil { - return err - } - config.FilePath = path - directives := config.Directives - location, ok := directives[0].(*components.Location) - if !ok { - return nil - } - if enable { - location.UpdateDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000\""}) - } else { - location.RemoveDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000\""}) - } - if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { - return buserr.WithErr(constant.ErrUpdateBuWebsite, err) - } - } - } - return nil - }) - if err != nil { - return err - } - return nil -} - -func checkSSLStatus(expireDate time.Time) string { - now := time.Now() - daysUntilExpiry := int(expireDate.Sub(now).Hours() / 24) - - if daysUntilExpiry < 0 { - return "danger" - } else if daysUntilExpiry <= 10 { - return "warning" - } - return "success" -} - -func getResourceContent(fileOp files.FileOp, resourcePath string) (string, error) { - if fileOp.Stat(resourcePath) { - content, err := fileOp.GetContent(resourcePath) - if err != nil { - return "", err - } - return string(content), nil - } - return "", nil -} diff --git a/backend/app/task/task.go b/backend/app/task/task.go deleted file mode 100644 index 121d14904..000000000 --- a/backend/app/task/task.go +++ /dev/null @@ -1,115 +0,0 @@ -package task - -import ( - "context" - "fmt" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/i18n" - "log" - "os" - "path" - "strconv" - "time" -) - -type ActionFunc func() error -type RollbackFunc func() - -type Task struct { - Name string - Logger *log.Logger - SubTasks []*SubTask - Rollbacks []RollbackFunc - logFile *os.File -} - -type SubTask struct { - Name string - Retry int - Timeout time.Duration - Action ActionFunc - Rollback RollbackFunc - Error error -} - -func NewTask(name string, taskType string) (*Task, error) { - logPath := path.Join(constant.LogDir, taskType) - //TODO 增加插入到日志表的逻辑 - file, err := os.OpenFile(logPath, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0666) - if err != nil { - return nil, fmt.Errorf("failed to open log file: %w", err) - } - logger := log.New(file, "", log.LstdFlags) - return &Task{Name: name, logFile: file, Logger: logger}, nil -} - -func (t *Task) AddSubTask(name string, action ActionFunc, rollback RollbackFunc) { - subTask := &SubTask{Name: name, Retry: 0, Timeout: 10 * time.Minute, Action: action, Rollback: rollback} - t.SubTasks = append(t.SubTasks, subTask) -} - -func (t *Task) AddSubTaskWithOps(name string, action ActionFunc, rollback RollbackFunc, retry int, timeout time.Duration) { - subTask := &SubTask{Name: name, Retry: retry, Timeout: timeout, Action: action, Rollback: rollback} - t.SubTasks = append(t.SubTasks, subTask) -} - -func (s *SubTask) Execute(logger *log.Logger) bool { - logger.Printf(i18n.GetWithName("SubTaskStart", s.Name)) - for i := 0; i < s.Retry+1; i++ { - if i > 0 { - logger.Printf(i18n.GetWithName("TaskRetry", strconv.Itoa(i))) - } - ctx, cancel := context.WithTimeout(context.Background(), s.Timeout) - defer cancel() - - done := make(chan error) - go func() { - done <- s.Action() - }() - - select { - case <-ctx.Done(): - logger.Printf(i18n.GetWithName("TaskTimeout", s.Name)) - case err := <-done: - if err != nil { - s.Error = err - logger.Printf(i18n.GetWithNameAndErr("TaskFailed", s.Name, err)) - } else { - logger.Printf(i18n.GetWithName("TaskSuccess", s.Name)) - return true - } - } - - if i == s.Retry { - if s.Rollback != nil { - s.Rollback() - } - } - time.Sleep(1 * time.Second) - } - if s.Error != nil { - s.Error = fmt.Errorf(i18n.GetWithName("TaskFailed", s.Name)) - } - return false -} - -func (t *Task) Execute() error { - t.Logger.Printf(i18n.GetWithName("TaskStart", t.Name)) - var err error - for _, subTask := range t.SubTasks { - if subTask.Execute(t.Logger) { - if subTask.Rollback != nil { - t.Rollbacks = append(t.Rollbacks, subTask.Rollback) - } - } else { - err = subTask.Error - for _, rollback := range t.Rollbacks { - rollback() - } - break - } - } - t.Logger.Printf(i18n.GetWithName("TaskEnd", t.Name)) - _ = t.logFile.Close() - return err -} diff --git a/backend/buserr/errors.go b/backend/buserr/errors.go deleted file mode 100644 index ad3fe1152..000000000 --- a/backend/buserr/errors.go +++ /dev/null @@ -1,93 +0,0 @@ -package buserr - -import ( - "github.com/1Panel-dev/1Panel/backend/i18n" - "github.com/pkg/errors" -) - -type BusinessError struct { - Msg string - Detail interface{} - Map map[string]interface{} - Err error -} - -func (e BusinessError) Error() string { - content := "" - if e.Detail != nil { - content = i18n.GetErrMsg(e.Msg, map[string]interface{}{"detail": e.Detail}) - } else if e.Map != nil { - content = i18n.GetErrMsg(e.Msg, e.Map) - } else { - content = i18n.GetErrMsg(e.Msg, nil) - } - if content == "" { - if e.Err != nil { - return e.Err.Error() - } - return errors.New(e.Msg).Error() - } - return content -} - -func New(Key string) BusinessError { - return BusinessError{ - Msg: Key, - Detail: nil, - Err: nil, - } -} - -func WithDetail(Key string, detail interface{}, err error) BusinessError { - return BusinessError{ - Msg: Key, - Detail: detail, - Err: err, - } -} - -func WithErr(Key string, err error) BusinessError { - paramMap := map[string]interface{}{} - if err != nil { - paramMap["err"] = err - } - return BusinessError{ - Msg: Key, - Map: paramMap, - Err: err, - } -} - -func WithMap(Key string, maps map[string]interface{}, err error) BusinessError { - return BusinessError{ - Msg: Key, - Map: maps, - Err: err, - } -} - -func WithNameAndErr(Key string, name string, err error) BusinessError { - paramMap := map[string]interface{}{} - if name != "" { - paramMap["name"] = name - } - if err != nil { - paramMap["err"] = err.Error() - } - return BusinessError{ - Msg: Key, - Map: paramMap, - Err: err, - } -} - -func WithName(Key string, name string) BusinessError { - paramMap := map[string]interface{}{} - if name != "" { - paramMap["name"] = name - } - return BusinessError{ - Msg: Key, - Map: paramMap, - } -} diff --git a/backend/buserr/multi_err.go b/backend/buserr/multi_err.go deleted file mode 100644 index bf0c875ce..000000000 --- a/backend/buserr/multi_err.go +++ /dev/null @@ -1,23 +0,0 @@ -package buserr - -import ( - "bytes" - "fmt" - "sort" -) - -type MultiErr map[string]error - -func (e MultiErr) Error() string { - var keys []string - for key := range e { - keys = append(keys, key) - } - sort.Strings(keys) - - buffer := bytes.NewBufferString("") - for _, key := range keys { - buffer.WriteString(fmt.Sprintf("[%s] %s\n", key, e[key])) - } - return buffer.String() -} diff --git a/backend/configs/config.go b/backend/configs/config.go deleted file mode 100644 index 7d8116b68..000000000 --- a/backend/configs/config.go +++ /dev/null @@ -1,6 +0,0 @@ -package configs - -type ServerConfig struct { - System System `mapstructure:"system"` - LogConfig LogConfig `mapstructure:"log"` -} diff --git a/backend/configs/log.go b/backend/configs/log.go deleted file mode 100644 index 8fe60a91d..000000000 --- a/backend/configs/log.go +++ /dev/null @@ -1,9 +0,0 @@ -package configs - -type LogConfig struct { - Level string `mapstructure:"level"` - TimeZone string `mapstructure:"timeZone"` - LogName string `mapstructure:"log_name"` - LogSuffix string `mapstructure:"log_suffix"` - MaxBackup int `mapstructure:"max_backup"` -} diff --git a/backend/configs/system.go b/backend/configs/system.go deleted file mode 100644 index d6e7c87c9..000000000 --- a/backend/configs/system.go +++ /dev/null @@ -1,20 +0,0 @@ -package configs - -type System struct { - DbFile string `mapstructure:"db_file"` - DbPath string `mapstructure:"db_path"` - LogPath string `mapstructure:"log_path"` - DataDir string `mapstructure:"data_dir"` - TmpDir string `mapstructure:"tmp_dir"` - Cache string `mapstructure:"cache"` - Backup string `mapstructure:"backup"` - EncryptKey string `mapstructure:"encrypt_key"` - BaseDir string `mapstructure:"base_dir"` - Mode string `mapstructure:"mode"` - RepoUrl string `mapstructure:"repo_url"` - Version string `mapstructure:"version"` - IsDemo bool `mapstructure:"is_demo"` - AppRepo string `mapstructure:"app_repo"` - OneDriveID string `mapstructure:"one_drive_id"` - OneDriveSc string `mapstructure:"one_drive_sc"` -} diff --git a/backend/constant/app.go b/backend/constant/app.go deleted file mode 100644 index 9a6f5c825..000000000 --- a/backend/constant/app.go +++ /dev/null @@ -1,54 +0,0 @@ -package constant - -const ( - Running = "Running" - UnHealthy = "UnHealthy" - Error = "Error" - Stopped = "Stopped" - Installing = "Installing" - DownloadErr = "DownloadErr" - Upgrading = "Upgrading" - UpgradeErr = "UpgradeErr" - Rebuilding = "Rebuilding" - Syncing = "Syncing" - SyncSuccess = "SyncSuccess" - Paused = "Paused" - UpErr = "UpErr" - - ContainerPrefix = "1Panel-" - - AppNormal = "Normal" - AppTakeDown = "TakeDown" - - AppOpenresty = "openresty" - AppMysql = "mysql" - AppMariaDB = "mariadb" - AppPostgresql = "postgresql" - AppRedis = "redis" - AppPostgres = "postgres" - AppMongodb = "mongodb" - AppMemcached = "memcached" - - AppResourceLocal = "local" - AppResourceRemote = "remote" - - CPUS = "CPUS" - MemoryLimit = "MEMORY_LIMIT" - HostIP = "HOST_IP" - ContainerName = "CONTAINER_NAME" -) - -type AppOperate string - -var ( - Start AppOperate = "start" - Stop AppOperate = "stop" - Restart AppOperate = "restart" - Delete AppOperate = "delete" - Sync AppOperate = "sync" - Backup AppOperate = "backup" - Update AppOperate = "update" - Rebuild AppOperate = "rebuild" - Upgrade AppOperate = "upgrade" - Reload AppOperate = "reload" -) diff --git a/backend/constant/backup.go b/backend/constant/backup.go deleted file mode 100644 index 37baa994e..000000000 --- a/backend/constant/backup.go +++ /dev/null @@ -1,18 +0,0 @@ -package constant - -const ( - Valid = "VALID" - DisConnect = "DISCONNECT" - VerifyFailed = "VERIFYFAILED" - S3 = "S3" - OSS = "OSS" - Sftp = "SFTP" - OneDrive = "OneDrive" - MinIo = "MINIO" - Cos = "COS" - Kodo = "KODO" - WebDAV = "WebDAV" - Local = "LOCAL" - - OneDriveRedirectURI = "http://localhost/login/authorized" -) diff --git a/backend/constant/common.go b/backend/constant/common.go deleted file mode 100644 index cca64e21a..000000000 --- a/backend/constant/common.go +++ /dev/null @@ -1,25 +0,0 @@ -package constant - -type DBContext string - -const ( - DB DBContext = "db" - - SystemRestart = "systemRestart" - - TypeWebsite = "website" - TypePhp = "php" - TypeSSL = "ssl" - TypeSystem = "system" -) - -const ( - TimeOut5s = 5 - TimeOut20s = 20 - TimeOut5m = 300 - - DateLayout = "2006-01-02" // or use time.DateOnly while go version >= 1.20 - DefaultDate = "1970-01-01" - DateTimeLayout = "2006-01-02 15:04:05" // or use time.DateTime while go version >= 1.20 - DateTimeSlimLayout = "20060102150405" -) diff --git a/backend/constant/container.go b/backend/constant/container.go deleted file mode 100644 index 98853664c..000000000 --- a/backend/constant/container.go +++ /dev/null @@ -1,18 +0,0 @@ -package constant - -const ( - ContainerOpStart = "start" - ContainerOpStop = "stop" - ContainerOpRestart = "restart" - ContainerOpKill = "kill" - ContainerOpPause = "pause" - ContainerOpUnpause = "unpause" - ContainerOpRename = "rename" - ContainerOpRemove = "remove" - - ComposeOpStop = "stop" - ComposeOpRestart = "restart" - ComposeOpRemove = "remove" - - DaemonJsonPath = "/etc/docker/daemon.json" -) diff --git a/backend/constant/dir.go b/backend/constant/dir.go deleted file mode 100644 index addcf40be..000000000 --- a/backend/constant/dir.go +++ /dev/null @@ -1,21 +0,0 @@ -package constant - -import ( - "path" - - "github.com/1Panel-dev/1Panel/backend/global" -) - -var ( - DataDir = global.CONF.System.DataDir - ResourceDir = path.Join(DataDir, "resource") - AppResourceDir = path.Join(ResourceDir, "apps") - AppInstallDir = path.Join(DataDir, "apps") - LocalAppResourceDir = path.Join(AppResourceDir, "local") - LocalAppInstallDir = path.Join(AppInstallDir, "local") - RemoteAppResourceDir = path.Join(AppResourceDir, "remote") - RuntimeDir = path.Join(DataDir, "runtime") - RecycleBinDir = "/.1panel_clash" - SSLLogDir = path.Join(global.CONF.System.DataDir, "log", "ssl") - LogDir = path.Join(global.CONF.System.DataDir, "log") -) diff --git a/backend/constant/errs.go b/backend/constant/errs.go deleted file mode 100644 index 411387d3d..000000000 --- a/backend/constant/errs.go +++ /dev/null @@ -1,164 +0,0 @@ -package constant - -import ( - "errors" -) - -const ( - CodeSuccess = 200 - CodeErrBadRequest = 400 - CodeErrUnauthorized = 401 - CodeErrNotFound = 404 - CodeAuth = 406 - CodeGlobalLoading = 407 - CodeErrInternalServer = 500 - - CodeErrIP = 310 - CodeErrDomain = 311 - CodeErrEntrance = 312 - CodePasswordExpired = 313 - - CodeErrXpack = 410 -) - -// internal -var ( - ErrCaptchaCode = errors.New("ErrCaptchaCode") - ErrAuth = errors.New("ErrAuth") - ErrRecordExist = errors.New("ErrRecordExist") - ErrRecordNotFound = errors.New("ErrRecordNotFound") - ErrStructTransform = errors.New("ErrStructTransform") - ErrInitialPassword = errors.New("ErrInitialPassword") - ErrNotSupportType = errors.New("ErrNotSupportType") - ErrInvalidParams = errors.New("ErrInvalidParams") - - ErrTokenParse = errors.New("ErrTokenParse") -) - -// api -var ( - ErrTypeInternalServer = "ErrInternalServer" - ErrTypeInvalidParams = "ErrInvalidParams" - ErrTypeNotLogin = "ErrNotLogin" - ErrTypePasswordExpired = "ErrPasswordExpired" - ErrNameIsExist = "ErrNameIsExist" - ErrDemoEnvironment = "ErrDemoEnvironment" - ErrCmdIllegal = "ErrCmdIllegal" - ErrXpackNotFound = "ErrXpackNotFound" - ErrXpackNotActive = "ErrXpackNotActive" - ErrXpackOutOfDate = "ErrXpackOutOfDate" -) - -// app -var ( - ErrPortInUsed = "ErrPortInUsed" - ErrAppLimit = "ErrAppLimit" - ErrFileCanNotRead = "ErrFileCanNotRead" - ErrNotInstall = "ErrNotInstall" - ErrPortInOtherApp = "ErrPortInOtherApp" - ErrDbUserNotValid = "ErrDbUserNotValid" - ErrUpdateBuWebsite = "ErrUpdateBuWebsite" - Err1PanelNetworkFailed = "Err1PanelNetworkFailed" - ErrCmdTimeout = "ErrCmdTimeout" - ErrFileParse = "ErrFileParse" - ErrInstallDirNotFound = "ErrInstallDirNotFound" - ErrContainerName = "ErrContainerName" - ErrAppNameExist = "ErrAppNameExist" - ErrFileNotFound = "ErrFileNotFound" - ErrFileParseApp = "ErrFileParseApp" - ErrAppParamKey = "ErrAppParamKey" -) - -// website -var ( - ErrDomainIsExist = "ErrDomainIsExist" - ErrAliasIsExist = "ErrAliasIsExist" - ErrGroupIsUsed = "ErrGroupIsUsed" - ErrUsernameIsExist = "ErrUsernameIsExist" - ErrUsernameIsNotExist = "ErrUsernameIsNotExist" - ErrBackupMatch = "ErrBackupMatch" - ErrBackupExist = "ErrBackupExist" - ErrDomainIsUsed = "ErrDomainIsUsed" -) - -// ssl -var ( - ErrSSLCannotDelete = "ErrSSLCannotDelete" - ErrAccountCannotDelete = "ErrAccountCannotDelete" - ErrSSLApply = "ErrSSLApply" - ErrEmailIsExist = "ErrEmailIsExist" - ErrEabKidOrEabHmacKeyCannotBlank = "ErrEabKidOrEabHmacKeyCannotBlank" -) - -// file -var ( - ErrPathNotFound = "ErrPathNotFound" - ErrMovePathFailed = "ErrMovePathFailed" - ErrLinkPathNotFound = "ErrLinkPathNotFound" - ErrFileIsExist = "ErrFileIsExist" - ErrFileUpload = "ErrFileUpload" - ErrFileDownloadDir = "ErrFileDownloadDir" - ErrCmdNotFound = "ErrCmdNotFound" - ErrFavoriteExist = "ErrFavoriteExist" -) - -// mysql -var ( - ErrUserIsExist = "ErrUserIsExist" - ErrDatabaseIsExist = "ErrDatabaseIsExist" - ErrExecTimeOut = "ErrExecTimeOut" - ErrRemoteExist = "ErrRemoteExist" - ErrLocalExist = "ErrLocalExist" -) - -// redis -var ( - ErrTypeOfRedis = "ErrTypeOfRedis" -) - -// container -var ( - ErrInUsed = "ErrInUsed" - ErrObjectInUsed = "ErrObjectInUsed" - ErrPortRules = "ErrPortRules" - ErrPgImagePull = "ErrPgImagePull" -) - -// runtime -var ( - ErrDirNotFound = "ErrDirNotFound" - ErrFileNotExist = "ErrFileNotExist" - ErrImageBuildErr = "ErrImageBuildErr" - ErrImageExist = "ErrImageExist" - ErrDelWithWebsite = "ErrDelWithWebsite" - ErrRuntimeStart = "ErrRuntimeStart" - ErrPackageJsonNotFound = "ErrPackageJsonNotFound" - ErrScriptsNotFound = "ErrScriptsNotFound" -) - -var ( - ErrBackupInUsed = "ErrBackupInUsed" - ErrOSSConn = "ErrOSSConn" - ErrEntrance = "ErrEntrance" -) - -var ( - ErrFirewall = "ErrFirewall" -) - -// cronjob -var ( - ErrBashExecute = "ErrBashExecute" -) - -var ( - ErrNotExistUser = "ErrNotExistUser" -) - -// license -var ( - ErrLicense = "ErrLicense" - ErrLicenseCheck = "ErrLicenseCheck" - ErrLicenseSave = "ErrLicenseSave" - ErrLicenseSync = "ErrLicenseSync" -) diff --git a/backend/constant/host_tool.go b/backend/constant/host_tool.go deleted file mode 100644 index 60f483b02..000000000 --- a/backend/constant/host_tool.go +++ /dev/null @@ -1,8 +0,0 @@ -package constant - -const ( - Supervisord = "supervisord" - Supervisor = "supervisor" - SupervisorConfigPath = "SupervisorConfigPath" - SupervisorServiceName = "SupervisorServiceName" -) diff --git a/backend/constant/nginx.go b/backend/constant/nginx.go deleted file mode 100644 index 93b46b868..000000000 --- a/backend/constant/nginx.go +++ /dev/null @@ -1,15 +0,0 @@ -package constant - -const ( - NginxScopeServer = "server" - NginxScopeHttp = "http" - NginxScopeOut = "out" - - NginxReload = "reload" - NginxCheck = "check" - NginxRestart = "restart" - - ConfigNew = "add" - ConfigUpdate = "update" - ConfigDel = "delete" -) diff --git a/backend/constant/runtime.go b/backend/constant/runtime.go deleted file mode 100644 index 55a524983..000000000 --- a/backend/constant/runtime.go +++ /dev/null @@ -1,35 +0,0 @@ -package constant - -const ( - ResourceLocal = "local" - ResourceAppstore = "appstore" - - RuntimeNormal = "normal" - RuntimeError = "error" - RuntimeBuildIng = "building" - RuntimeStarting = "starting" - RuntimeRunning = "running" - RuntimeReCreating = "recreating" - RuntimeStopped = "stopped" - RuntimeUnhealthy = "unhealthy" - RuntimeCreating = "creating" - - RuntimePHP = "php" - RuntimeNode = "node" - RuntimeJava = "java" - RuntimeGo = "go" - - RuntimeProxyUnix = "unix" - RuntimeProxyTcp = "tcp" - - RuntimeUp = "up" - RuntimeDown = "down" - RuntimeRestart = "restart" - - RuntimeInstall = "install" - RuntimeUninstall = "uninstall" - RuntimeUpdate = "update" - - RuntimeNpm = "npm" - RuntimeYarn = "yarn" -) diff --git a/backend/constant/session.go b/backend/constant/session.go deleted file mode 100644 index 94fdf462d..000000000 --- a/backend/constant/session.go +++ /dev/null @@ -1,13 +0,0 @@ -package constant - -const ( - AuthMethodSession = "session" - SessionName = "psession" - - AuthMethodJWT = "jwt" - JWTHeaderName = "PanelAuthorization" - JWTBufferTime = 3600 - JWTIssuer = "1Panel" - - PasswordExpiredName = "expired" -) diff --git a/backend/constant/status.go b/backend/constant/status.go deleted file mode 100644 index 161b50e00..000000000 --- a/backend/constant/status.go +++ /dev/null @@ -1,16 +0,0 @@ -package constant - -const ( - StatusRunning = "Running" - StatusDone = "Done" - StatusWaiting = "Waiting" - StatusSuccess = "Success" - StatusFailed = "Failed" - StatusUploading = "Uploading" - StatusEnable = "Enable" - StatusDisable = "Disable" - StatusNone = "None" - - OrderDesc = "descending" - OrderAsc = "ascending" -) diff --git a/backend/constant/website.go b/backend/constant/website.go deleted file mode 100644 index a236fc6a8..000000000 --- a/backend/constant/website.go +++ /dev/null @@ -1,51 +0,0 @@ -package constant - -const ( - WebRunning = "Running" - WebStopped = "Stopped" - - ProtocolHTTP = "HTTP" - ProtocolHTTPS = "HTTPS" - - NewApp = "new" - InstalledApp = "installed" - - Deployment = "deployment" - Static = "static" - Proxy = "proxy" - Runtime = "runtime" - - SSLExisted = "existed" - SSLAuto = "auto" - SSLManual = "manual" - - DNSAccount = "dnsAccount" - DnsManual = "dnsManual" - Http = "http" - Manual = "manual" - SelfSigned = "selfSigned" - - StartWeb = "start" - StopWeb = "stop" - - HTTPSOnly = "HTTPSOnly" - HTTPAlso = "HTTPAlso" - HTTPToHTTPS = "HTTPToHTTPS" - - GetLog = "get" - DisableLog = "disable" - EnableLog = "enable" - DeleteLog = "delete" - - AccessLog = "access.log" - ErrorLog = "error.log" - - ConfigPHP = "php" - ConfigFPM = "fpm" - - SSLInit = "init" - SSLError = "error" - SSLReady = "ready" - SSLApply = "applying" - SSLApplyError = "applyError" -) diff --git a/backend/cron/cron.go b/backend/cron/cron.go deleted file mode 100644 index ec9f6d9d5..000000000 --- a/backend/cron/cron.go +++ /dev/null @@ -1,102 +0,0 @@ -package cron - -import ( - "fmt" - mathRand "math/rand" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/app/repo" - "github.com/1Panel-dev/1Panel/backend/app/service" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/cron/job" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/ntp" - "github.com/robfig/cron/v3" -) - -func Run() { - nyc, _ := time.LoadLocation(common.LoadTimeZone()) - global.Cron = cron.New(cron.WithLocation(nyc), cron.WithChain(cron.Recover(cron.DefaultLogger)), cron.WithChain(cron.DelayIfStillRunning(cron.DefaultLogger))) - - var ( - interval model.Setting - status model.Setting - ) - syncBeforeStart() - if err := global.DB.Where("key = ?", "MonitorStatus").Find(&status).Error; err != nil { - global.LOG.Errorf("load monitor status from db failed, err: %v", err) - } - if status.Value == "enable" { - if err := global.DB.Where("key = ?", "MonitorInterval").Find(&interval).Error; err != nil { - global.LOG.Errorf("load monitor interval from db failed, err: %v", err) - } - if err := service.StartMonitor(false, interval.Value); err != nil { - global.LOG.Errorf("can not add monitor corn job: %s", err.Error()) - } - } - - if _, err := global.Cron.AddJob("@daily", job.NewWebsiteJob()); err != nil { - global.LOG.Errorf("can not add website corn job: %s", err.Error()) - } - if _, err := global.Cron.AddJob("@daily", job.NewSSLJob()); err != nil { - global.LOG.Errorf("can not add ssl corn job: %s", err.Error()) - } - if _, err := global.Cron.AddJob(fmt.Sprintf("%v %v * * *", mathRand.Intn(60), mathRand.Intn(3)), job.NewAppStoreJob()); err != nil { - global.LOG.Errorf("can not add appstore corn job: %s", err.Error()) - } - if _, err := global.Cron.AddJob("@daily", job.NewCacheJob()); err != nil { - global.LOG.Errorf("can not add cache corn job: %s", err.Error()) - } - - var backup model.BackupAccount - _ = global.DB.Where("type = ?", "OneDrive").Find(&backup).Error - if backup.ID != 0 { - service.StartRefreshOneDriveToken() - } - global.Cron.Start() - - var cronJobs []model.Cronjob - if err := global.DB.Where("status = ?", constant.StatusEnable).Find(&cronJobs).Error; err != nil { - global.LOG.Errorf("start my cronjob failed, err: %v", err) - } - if err := global.DB.Model(&model.JobRecords{}). - Where("status = ?", constant.StatusRunning). - Updates(map[string]interface{}{ - "status": constant.StatusFailed, - "message": "Task Cancel", - "records": "errHandle", - }).Error; err != nil { - global.LOG.Errorf("start my cronjob failed, err: %v", err) - } - for i := 0; i < len(cronJobs); i++ { - entryIDs, err := service.NewICronjobService().StartJob(&cronJobs[i], false) - if err != nil { - global.LOG.Errorf("start %s job %s failed, err: %v", cronJobs[i].Type, cronJobs[i].Name, err) - } - if err := repo.NewICronjobRepo().Update(cronJobs[i].ID, map[string]interface{}{"entry_ids": entryIDs}); err != nil { - global.LOG.Errorf("update cronjob %s %s failed, err: %v", cronJobs[i].Type, cronJobs[i].Name, err) - } - } -} - -func syncBeforeStart() { - var ntpSite model.Setting - if err := global.DB.Where("key = ?", "NtpSite").Find(&ntpSite).Error; err != nil { - global.LOG.Errorf("load ntp serve from db failed, err: %v", err) - } - if len(ntpSite.Value) == 0 { - ntpSite.Value = "pool.ntp.org" - } - ntime, err := ntp.GetRemoteTime(ntpSite.Value) - if err != nil { - global.LOG.Errorf("load remote time with [%s] failed, err: %v", ntpSite.Value, err) - return - } - ts := ntime.Format(constant.DateTimeLayout) - if err := ntp.UpdateSystemTime(ts); err != nil { - global.LOG.Errorf("failed to synchronize system time with [%s], err: %v", ntpSite.Value, err) - } - global.LOG.Debugf("synchronize system time with [%s] successful!", ntpSite.Value) -} diff --git a/backend/cron/job/app.go b/backend/cron/job/app.go deleted file mode 100644 index 92142f021..000000000 --- a/backend/cron/job/app.go +++ /dev/null @@ -1,20 +0,0 @@ -package job - -import ( - "github.com/1Panel-dev/1Panel/backend/app/service" - "github.com/1Panel-dev/1Panel/backend/global" -) - -type app struct{} - -func NewAppStoreJob() *app { - return &app{} -} - -func (a *app) Run() { - global.LOG.Info("AppStore scheduled task in progress ...") - if err := service.NewIAppService().SyncAppListFromRemote(); err != nil { - global.LOG.Errorf("AppStore sync failed %s", err.Error()) - } - global.LOG.Info("AppStore scheduled task has completed") -} diff --git a/backend/cron/job/cache.go b/backend/cron/job/cache.go deleted file mode 100644 index 2fb3cd643..000000000 --- a/backend/cron/job/cache.go +++ /dev/null @@ -1,26 +0,0 @@ -package job - -import ( - "github.com/1Panel-dev/1Panel/backend/global" - "time" -) - -type Cache struct{} - -func NewCacheJob() *Cache { - return &Cache{} -} - -func (c *Cache) Run() { - global.LOG.Info("run cache gc start ...") - ticker := time.NewTicker(5 * time.Minute) - defer ticker.Stop() - for range ticker.C { - again: - err := global.CacheDb.RunValueLogGC(0.7) - if err == nil { - goto again - } - } - global.LOG.Info("run cache gc end ...") -} diff --git a/backend/cron/job/ssl.go b/backend/cron/job/ssl.go deleted file mode 100644 index 374d45664..000000000 --- a/backend/cron/job/ssl.go +++ /dev/null @@ -1,76 +0,0 @@ -package job - -import ( - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/repo" - "github.com/1Panel-dev/1Panel/backend/app/service" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "path" - "strings" - "time" -) - -type ssl struct { -} - -func NewSSLJob() *ssl { - return &ssl{} -} - -func (ssl *ssl) Run() { - systemSSLEnable, sslID := service.GetSystemSSL() - sslRepo := repo.NewISSLRepo() - sslService := service.NewIWebsiteSSLService() - sslList, _ := sslRepo.List() - nyc, _ := time.LoadLocation(common.LoadTimeZone()) - global.LOG.Info("The scheduled certificate update task is currently in progress ...") - now := time.Now().Add(10 * time.Second) - for _, s := range sslList { - if !s.AutoRenew || s.Provider == "manual" || s.Provider == "dnsManual" || s.Status == "applying" { - continue - } - expireDate := s.ExpireDate.In(nyc) - sub := expireDate.Sub(now) - if sub.Hours() < 720 { - global.LOG.Infof("Update the SSL certificate for the [%s] domain", s.PrimaryDomain) - if s.Provider == constant.SelfSigned { - caService := service.NewIWebsiteCAService() - if _, err := caService.ObtainSSL(request.WebsiteCAObtain{ - ID: s.CaID, - SSLID: s.ID, - Renew: true, - Unit: "year", - Time: 10, - }); err != nil { - global.LOG.Errorf("Failed to update the SSL certificate for the [%s] domain , err:%s", s.PrimaryDomain, err.Error()) - continue - } - } else { - if err := sslService.ObtainSSL(request.WebsiteSSLApply{ - ID: s.ID, - }); err != nil { - global.LOG.Errorf("Failed to update the SSL certificate for the [%s] domain , err:%s", s.PrimaryDomain, err.Error()) - continue - } - } - if systemSSLEnable && sslID == s.ID { - websiteSSL, _ := sslRepo.GetFirst(repo.NewCommonRepo().WithByID(s.ID)) - fileOp := files.NewFileOp() - secretDir := path.Join(global.CONF.System.BaseDir, "1panel/secret") - if err := fileOp.WriteFile(path.Join(secretDir, "server.crt"), strings.NewReader(websiteSSL.Pem), 0600); err != nil { - global.LOG.Errorf("Failed to update the SSL certificate File for 1Panel System domain [%s] , err:%s", s.PrimaryDomain, err.Error()) - continue - } - if err := fileOp.WriteFile(path.Join(secretDir, "server.key"), strings.NewReader(websiteSSL.PrivateKey), 0600); err != nil { - global.LOG.Errorf("Failed to update the SSL certificate for 1Panel System domain [%s] , err:%s", s.PrimaryDomain, err.Error()) - continue - } - } - global.LOG.Infof("The SSL certificate for the [%s] domain has been successfully updated", s.PrimaryDomain) - } - } - global.LOG.Info("The scheduled certificate update task has completed") -} diff --git a/backend/cron/job/website.go b/backend/cron/job/website.go deleted file mode 100644 index 4eb91373b..000000000 --- a/backend/cron/job/website.go +++ /dev/null @@ -1,62 +0,0 @@ -package job - -import ( - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/app/repo" - "github.com/1Panel-dev/1Panel/backend/app/service" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/common" - "sync" - "time" -) - -type website struct{} - -func NewWebsiteJob() *website { - return &website{} -} - -func (w *website) Run() { - nyc, _ := time.LoadLocation(common.LoadTimeZone()) - websites, _ := repo.NewIWebsiteRepo().List() - global.LOG.Info("Website scheduled task in progress ...") - now := time.Now().Add(10 * time.Minute) - if len(websites) > 0 { - neverExpireDate, _ := time.Parse(constant.DateLayout, constant.DefaultDate) - var wg sync.WaitGroup - for _, site := range websites { - if site.Status != constant.WebRunning || neverExpireDate.Equal(site.ExpireDate) { - continue - } - expireDate, err := time.ParseInLocation(constant.DateLayout, site.ExpireDate.Format(constant.DateLayout), nyc) - if err != nil { - global.LOG.Errorf("time parse err %v", err) - continue - } - if expireDate.Before(now) { - wg.Add(1) - go func(ws model.Website) { - stopWebsite(ws.ID, ws.PrimaryDomain, &wg) - }(site) - } - } - wg.Wait() - } - global.LOG.Info("Website scheduled task has completed") -} - -func stopWebsite(websiteId uint, websiteName string, wg *sync.WaitGroup) { - websiteService := service.NewIWebsiteService() - req := request.WebsiteOp{ - ID: websiteId, - Operate: constant.StopWeb, - } - if err := websiteService.OpWebsite(req); err != nil { - global.LOG.Errorf("Website [%s] seop failed err %v", websiteName, err) - } else { - global.LOG.Infof("Website [%s] stopped successfully", websiteName) - } - wg.Done() -} diff --git a/backend/global/global.go b/backend/global/global.go deleted file mode 100644 index cf92a8fc0..000000000 --- a/backend/global/global.go +++ /dev/null @@ -1,30 +0,0 @@ -package global - -import ( - "github.com/1Panel-dev/1Panel/backend/configs" - "github.com/1Panel-dev/1Panel/backend/init/cache/badger_db" - "github.com/dgraph-io/badger/v4" - "github.com/go-playground/validator/v10" - "github.com/nicksnyder/go-i18n/v2/i18n" - "github.com/robfig/cron/v3" - "github.com/sirupsen/logrus" - "github.com/spf13/viper" - "gorm.io/gorm" -) - -var ( - DB *gorm.DB - MonitorDB *gorm.DB - LOG *logrus.Logger - CONF configs.ServerConfig - VALID *validator.Validate - CACHE *badger_db.Cache - CacheDb *badger.DB - Viper *viper.Viper - - Cron *cron.Cron - MonitorCronID cron.EntryID - OneDriveCronID cron.EntryID - - I18n *i18n.Localizer -) diff --git a/backend/i18n/i18n.go b/backend/i18n/i18n.go deleted file mode 100644 index 2cc7d4802..000000000 --- a/backend/i18n/i18n.go +++ /dev/null @@ -1,130 +0,0 @@ -package i18n - -import ( - "embed" - "github.com/1Panel-dev/1Panel/backend/global" - "strings" - - "github.com/gin-gonic/gin" - "github.com/nicksnyder/go-i18n/v2/i18n" - "golang.org/x/text/language" - "gopkg.in/yaml.v3" -) - -func GetMsgWithMap(key string, maps map[string]interface{}) string { - var content string - if maps == nil { - content, _ = global.I18n.Localize(&i18n.LocalizeConfig{ - MessageID: key, - }) - } else { - content, _ = global.I18n.Localize(&i18n.LocalizeConfig{ - MessageID: key, - TemplateData: maps, - }) - } - content = strings.ReplaceAll(content, ": ", "") - if content == "" { - return key - } else { - return content - } -} - -func GetMsgWithName(key string, name string, err error) string { - var ( - content string - dataMap = make(map[string]interface{}) - ) - dataMap["name"] = name - if err != nil { - dataMap["err"] = err.Error() - } - content, _ = global.I18n.Localize(&i18n.LocalizeConfig{ - MessageID: key, - TemplateData: dataMap, - }) - content = strings.ReplaceAll(content, "", "") - if content == "" { - return key - } else { - return content - } -} - -func GetErrMsg(key string, maps map[string]interface{}) string { - var content string - if maps == nil { - content, _ = global.I18n.Localize(&i18n.LocalizeConfig{ - MessageID: key, - }) - } else { - content, _ = global.I18n.Localize(&i18n.LocalizeConfig{ - MessageID: key, - TemplateData: maps, - }) - } - return content -} - -func GetMsgByKey(key string) string { - content, _ := global.I18n.Localize(&i18n.LocalizeConfig{ - MessageID: key, - }) - return content -} - -func GetWithName(key string, name string) string { - var ( - dataMap = make(map[string]interface{}) - ) - dataMap["name"] = name - content, _ := global.I18n.Localize(&i18n.LocalizeConfig{ - MessageID: key, - TemplateData: dataMap, - }) - return content -} - -func GetWithMap(key string, dataMap map[string]string) string { - content, _ := global.I18n.Localize(&i18n.LocalizeConfig{ - MessageID: key, - TemplateData: dataMap, - }) - return content -} - -func GetWithNameAndErr(key string, name string, err error) string { - var ( - dataMap = make(map[string]interface{}) - ) - dataMap["name"] = name - dataMap["err"] = err.Error() - content, _ := global.I18n.Localize(&i18n.LocalizeConfig{ - MessageID: key, - TemplateData: dataMap, - }) - return content -} - -//go:embed lang/* -var fs embed.FS -var bundle *i18n.Bundle - -func UseI18n() gin.HandlerFunc { - return func(context *gin.Context) { - lang := context.GetHeader("Accept-Language") - if lang == "" { - lang = "zh" - } - global.I18n = i18n.NewLocalizer(bundle, lang) - } -} - -func Init() { - bundle = i18n.NewBundle(language.Chinese) - bundle.RegisterUnmarshalFunc("yaml", yaml.Unmarshal) - _, _ = bundle.LoadMessageFileFS(fs, "lang/zh.yaml") - _, _ = bundle.LoadMessageFileFS(fs, "lang/en.yaml") - _, _ = bundle.LoadMessageFileFS(fs, "lang/zh-Hant.yaml") -} diff --git a/backend/i18n/lang/en.yaml b/backend/i18n/lang/en.yaml deleted file mode 100644 index 69b99e474..000000000 --- a/backend/i18n/lang/en.yaml +++ /dev/null @@ -1,207 +0,0 @@ -ErrInvalidParams: "Request parameter error: {{ .detail }}" -ErrTokenParse: "Token generation error: {{ .detail }}" -ErrInitialPassword: "Initial password error" -ErrInternalServer: "Service internal error: {{ .detail }}" -ErrRecordExist: "Record already exists" -ErrRecordNotFound: "Records not found" -ErrStructTransform: "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 }}" - -#common -ErrNameIsExist: "Name is already exist" -ErrDemoEnvironment: "Demo server, prohibit this operation!" -ErrCmdTimeout: "Command execution timed out!" -ErrCmdIllegal: "The command contains illegal characters. Please modify and try again!" -ErrPortExist: '{{ .port }} port is already occupied by {{ .type }} [{{ .name }}]' -TYPE_APP: "Application" -TYPE_RUNTIME: "Runtime environment" -TYPE_DOMAIN: "Domain name" -ErrTypePort: 'Port {{ .name }} format error' -ErrTypePortRange: 'Port range needs to be between 1-65535' -Success: "Success" -Failed: "Failed" -SystemRestart: "System restart causes task interruption" - -#app -ErrPortInUsed: "{{ .detail }} port already in use" -ErrAppLimit: "App exceeds install limit" -ErrAppRequired: "{{ .detail }} app is required" -ErrNotInstall: "App not installed" -ErrPortInOtherApp: "{{ .port }} port already in use by app {{ .apps }}" -ErrDbUserNotValid: "Stock database, username and password do not match!" -ErrDockerComposeNotValid: "docker-compose file format error!" -ErrUpdateBuWebsite: 'The application was updated successfully, but the modification of the website configuration file failed, please check the configuration!' -Err1PanelNetworkFailed: 'Default container network creation failed! {{ .detail }}' -ErrFileParse: 'Application docker-compose file parsing failed!' -ErrInstallDirNotFound: 'installation directory does not exist' -AppStoreIsUpToDate: 'The app store is already up to date!' -LocalAppVersionNull: 'The {{.name}} app is not synced to version! Could not add to application list' -LocalAppVersionErr: '{{.name}} failed to sync version {{.version}}! {{.err}}' -ErrFileNotFound: '{{.name}} file does not exist' -ErrFileParseApp: 'Failed to parse {{.name}} file {{.err}}' -ErrAppDirNull: 'version folder does not exist' -LocalAppErr: "App {{.name}} sync failed! {{.err}}" -ErrContainerName: "ContainerName is already exist" -ErrAppSystemRestart: "1Panel restart causes the task to terminate" -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" -ErrImagePullTimeOut: 'Image pull timeout' -ErrContainerNotFound: '{{ .name }} container does not exist' -ErrContainerMsg: '{{ .name }} container is abnormal, please check the log on the container page for details' -ErrAppBackup: '{{ .name }} application backup failed err {{.err}}' -ErrImagePull: '{{ .name }} image pull failed err {{.err}}' -ErrVersionTooLow: 'The current 1Panel version is too low to update the app store, please upgrade the version' -ErrAppNameExist: 'App name is already exist' -AppStoreIsSyncing: 'The App Store is syncing, please try again later' -ErrGetCompose: "Failed to obtain docker-compose.yml file! {{ .detail }}" -ErrAppWarn: "Abnormal status, please check the log" -ErrAppParamKey: "Parameter {{ .name }} field exception" -ErrAppUpgrade: "Failed to upgrade application {{ .name }} {{ .err }}" -AppRecover: "App {{ .name }} rolled back " -PullImageStart: "Start pulling image {{ .name }}" -PullImageSuccess: "Image pulled successfully" -UpgradeAppStart: "Start upgrading application {{ .name }}" -UpgradeAppSuccess: "App {{ .name }} upgraded successfully" - -#file -ErrFileCanNotRead: "File can not read" -ErrFileToLarge: "file is too large" -ErrPathNotFound: "Path is not found" -ErrMovePathFailed: "The target path cannot contain the original path!" -ErrLinkPathNotFound: "Target path does not exist!" -ErrFileIsExist: "File or directory already exists!" -ErrFileUpload: "Failed to upload file {{.name}} {{.detail}}" -ErrFileDownloadDir: "Download folder not supported" -ErrCmdNotFound: "{{ .name}} command does not exist, please install this command on the host first" -ErrSourcePathNotFound: "Source directory does not exist" -ErrFavoriteExist: "This path has been collected" -ErrInvalidChar: "Illegal characters are prohibited" - -#website -ErrDomainIsExist: "Domain is already exist" -ErrAliasIsExist: "Alias is already exist" -ErrAppDelete: 'Other Website use this App' -ErrGroupIsUsed: 'The group is in use and cannot be deleted' -ErrBackupMatch: 'the backup file does not match the current partial data of the website: {{ .detail}}' -ErrBackupExist: 'the backup file corresponds to a portion of the original data that does not exist: {{ .detail}}' -ErrPHPResource: 'The local runtime does not support switching!' -ErrPathPermission: 'A folder with non-1000:1000 permissions was detected in the index directory, which may cause an Access denied error when accessing the website. Please click the save button above' -ErrDomainIsUsed: "Domain is already used by website {{ .name }}" -ErrDomainFormat: "{{ .name }} domain format error" -ErrDefaultAlias: "default is a reserved code name, please use another code name" - -#ssl -ErrSSLCannotDelete: "The certificate {{ .name }} is being used by the website and cannot be removed" -ErrAccountCannotDelete: "The certificate associated with the account cannot be deleted" -ErrSSLApply: "The certificate continues to be signed successfully, but openresty reload fails, please check the configuration!" -ErrEmailIsExist: 'Email is already exist' -ErrSSLKeyNotFound: 'The private key file does not exist' -ErrSSLCertificateNotFound: 'The certificate file does not exist' -ErrSSLKeyFormat: 'Private key file verification error' -ErrSSLCertificateFormat: 'Certificate file format error, please use pem format' -ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid or EabHmacKey cannot be empty' -ErrOpenrestyNotFound: 'Http mode requires Openresty to be installed first' -ApplySSLStart: 'Start applying for certificate, domain name [{{ .domain }}] application method [{{ .type }}] ' -dnsAccount: "DNS Automatic" -dnsManual: "DNS Manual" -http: "HTTP" -ApplySSLFailed: 'Application for [{{ .domain }}] certificate failed, {{.detail}} ' -ApplySSLSuccess: 'Application for [{{ .domain }}] certificate successful! ! ' -DNSAccountName: 'DNS account [{{ .name }}] manufacturer [{{.type}}]' -PushDirLog: 'Certificate pushed to directory [{{ .path }}] {{ .status }}' -ErrDeleteCAWithSSL: "There is an issued certificate under the current organization and cannot be deleted" -ErrDeleteWithPanelSSL: "Panel SSL configuration uses this certificate and cannot be deleted" -ErrDefaultCA: "The default organization cannot be deleted" -ApplyWebSiteSSLLog: "Start updating {{ .name }} website certificate" -ErrUpdateWebsiteSSL: "{{ .name }} website failed to update certificate: {{ .err }}" -ApplyWebSiteSSLSuccess: "Update website certificate successfully" - -#mysql -ErrUserIsExist: "The current user already exists. Please enter a new user" -ErrDatabaseIsExist: "The current database already exists. Please enter a new database" -ErrExecTimeOut: "SQL execution timed out, please check the database" -ErrRemoteExist: "The remote database already exists with that name, please modify it and try again" -ErrLocalExist: "The local database already exists with that name, please modify it and try again" - -#redis -ErrTypeOfRedis: "The recovery file type does not match the current persistence mode. Modify the file type and try again" - -#container -ErrInUsed: "{{ .detail }} is in use and cannot be deleted" -ErrObjectInUsed: "This object is in use and cannot be deleted" -ErrPortRules: "The number of ports does not match, please re-enter!" -ErrPgImagePull: "Image pull timeout. Please configure image acceleration or manually pull the postgres:16.0-alpine image and try again" - -#runtime -ErrDirNotFound: "The build folder does not exist! Please check file integrity!" -ErrFileNotExist: "{{ .detail }} file does not exist! Please check source file integrity!" -ErrImageBuildErr: "Image build failed" -ErrImageExist: "Image is already exist!" -ErrDelWithWebsite: "The operating environment has been associated with a website and cannot be deleted" -ErrRuntimeStart: "Failed to start" -ErrPackageJsonNotFound: "package.json file does not exist" -ErrScriptsNotFound: "No scripts configuration item was found in package.json" -ErrContainerNameNotFound: "Unable to get container name, please check .env file" -ErrNodeModulesNotFound: "The node_modules folder does not exist! Please edit the running environment or wait for the running environment to start successfully" - -#setting -ErrBackupInUsed: "The backup account is already being used in a cronjob and cannot be deleted." -ErrBackupCheck: "Backup account test connection failed {{ .err}}" -ErrOSSConn: "Unable to retrieve the latest version, please check if the server can connect to the external network." -ErrEntrance: "Security entrance information error. Please check and try again!" - -#tool -ErrConfigNotFound: "Configuration file does not exist" -ErrConfigParse: "Configuration file format error" -ErrConfigIsNull: "The configuration file is not allowed to be empty" -ErrConfigDirNotFound: "The running directory does not exist" -ErrConfigAlreadyExist: "A configuration file with the same name already exists" -ErrUserFindErr: "Failed to find user {{ .name }} {{ .err }}" - -#ssh -ErrFirewall: "No firewalld or ufw service is detected. Please check and try again!" - -#cronjob -ErrBashExecute: "Script execution error, please check the specific information in the task output text area." -ErrCutWebsiteLog: "{{ .name }} website log cutting failed, error {{ .err }}" -CutWebsiteLogSuccess: "{{ .name }} website log cut successfully, backup path {{ .path }}" - -#toolbox -ErrNotExistUser: "The current user does not exist. Please modify and retry!" -ErrBanAction: "Setting failed, the current {{ .name }} service is unavailable, please check and try again!" -ErrClamdscanNotFound: "The clamdscan command was not detected, please refer to the documentation to install it!" - -#waf -ErrScope: "Modification of this configuration is not supported" -ErrStateChange: "State modification failed" -ErrRuleExist: "Rule is Exist" -ErrRuleNotExist: "Rule is not Exist" -ErrParseIP: "IP format error" -ErrDefaultIP: "default is a reserved name, please change it to another name" -ErrGroupInUse: "The IP group is used by the black/white list and cannot be deleted" -ErrGroupExist: "IP group name already exists" -ErrIPRange: "Wrong IP range" -ErrIPExist: "IP is exit" - -#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" -ErrXpackNotActive: "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" - -#task -TaskStart: "{{.name}} started [START]" -TaskEnd: "{{.name}} ended [COMPLETED]" -TaskFailed: "{{.name}} failed: {{.err}}" -TaskTimeout: "{{.name}} timed out" -TaskSuccess: "{{.name}} succeeded" -TaskRetry: "Start {{.name}} retry" -SubTaskStart: "Start {{.name}}" diff --git a/backend/i18n/lang/zh-Hant.yaml b/backend/i18n/lang/zh-Hant.yaml deleted file mode 100644 index 817f38e23..000000000 --- a/backend/i18n/lang/zh-Hant.yaml +++ /dev/null @@ -1,209 +0,0 @@ -ErrInvalidParams: "請求參數錯誤: {{ .detail }}" -ErrTokenParse: "Token 產生錯誤: {{ .detail }}" -ErrInitialPassword: "原密碼錯誤" -ErrInternalServer: "伺服器內部錯誤: {{ .detail }}" -ErrRecordExist: "記錄已存在" -ErrRecordNotFound: "記錄未找到" -ErrStructTransform: "類型轉換失敗: {{ .detail }}" -ErrNotLogin: "用戶未登入: {{ .detail }}" -ErrPasswordExpired: "當前密碼已過期: {{ .detail }}" -ErrNotSupportType: "系統暫不支持當前類型: {{ .detail }}" - -#common -ErrNameIsExist: "名稱已存在" -ErrDemoEnvironment: "演示伺服器,禁止此操作!" -ErrCmdTimeout: "指令執行超時!" -ErrCmdIllegal: "執行命令中存在不合法字符,請修改後重試!" -ErrPortExist: '{{ .port }} 埠已被 {{ .type }} [{{ .name }}] 佔用' -TYPE_APP: "應用" -TYPE_RUNTIME: "運作環境" -TYPE_DOMAIN: "網域名稱" -ErrTypePort: '埠 {{ .name }} 格式錯誤' -ErrTypePortRange: '連接埠範圍需要在 1-65535 之間' -Success: "成功" -Failed: "失敗" -SystemRestart: "系統重啟導致任務中斷" -ErrInvalidChar: "禁止使用非法字元" - -#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 {{.err}}' -ErrImagePull: '{{ .name }} 鏡像拉取失敗 err {{.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: "文件超過10M,無法打開" -ErrPathNotFound: "目錄不存在" -ErrMovePathFailed: "目標路徑不能包含原路徑!" -ErrLinkPathNotFound: "目標路徑不存在!" -ErrFileIsExist: "文件或文件夾已存在!" -ErrFileUpload: "{{ .name }} 上傳文件失敗 {{ .detail}}" -ErrFileDownloadDir: "不支持下載文件夾" -ErrCmdNotFound: "{{ .name}} 命令不存在,請先在宿主機安裝此命令" -ErrSourcePathNotFound: "源目錄不存在" -ErrFavoriteExist: "已收藏此路徑" - -#website -ErrDomainIsExist: "域名已存在" -ErrAliasIsExist: "代號已存在" -ErrAppDelete: '其他網站使用此應用,無法刪除' -ErrGroupIsUsed: '分組正在使用中,無法刪除' -ErrBackupMatch: '該備份文件與當前網站部分數據不匹配: {{ .detail}}' -ErrBackupExist: '該備份文件對應部分原數據不存在: {{ .detail}}' -ErrPHPResource: '本地運行環境不支持切換!' -ErrPathPermission: 'index 目錄下偵測到非 1000:1000 權限資料夾,可能導致網站存取 Access denied 錯誤,請點擊上方儲存按鈕' -ErrDomainIsUsed: "域名已被網站【{{ .name }}】使用" -ErrDomainFormat: "{{ .name }} 域名格式不正確" -ErrDefaultAlias: "default 為保留代號,請使用其他代號" - -#ssl -ErrSSLCannotDelete: "{{ .name }} 證書正在被網站使用,無法刪除" -ErrAccountCannotDelete: "帳號關聯證書,無法刪除" -ErrSSLApply: "證書續簽成功,openresty reload失敗,請檢查配置!" -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: "更新網站憑證成功" - - -#mysql -ErrUserIsExist: "當前用戶已存在,請重新輸入" -ErrDatabaseIsExist: "當前資料庫已存在,請重新輸入" -ErrExecTimeOut: "SQL 執行超時,請檢查數據庫" -ErrRemoteExist: "遠程數據庫已存在該名稱,請修改後重試" -ErrLocalExist: "本地數據庫已存在該名稱,請修改後重試" - -#redis -ErrTypeOfRedis: "恢復文件類型與當前持久化方式不符,請修改後重試" - -#container -ErrInUsed: "{{ .detail }} 正被使用,無法刪除" -ErrObjectInUsed: "該對象正被使用,無法刪除" -ErrPortRules: "端口數目不匹配,請重新輸入!" -ErrPgImagePull: "鏡像拉取超時,請配置鏡像加速或手動拉取 postgres:16.0-alpine 鏡像後重試" - -#runtime -ErrDirNotFound: "build 文件夾不存在!請檢查文件完整性!" -ErrFileNotExist: "{{ .detail }} 文件不存在!請檢查源文件完整性!" -ErrImageBuildErr: "鏡像 build 失敗" -ErrImageExist: "鏡像已存在!" -ErrDelWithWebsite: "運行環境已經關聯網站,無法刪除" -ErrRuntimeStart: "啟動失敗" -ErrPackageJsonNotFound: "package.json 文件不存在" -ErrScriptsNotFound: "沒有在 package.json 中找到 scripts 配置項" -ErrContainerNameNotFound: "無法取得容器名稱,請檢查 .env 文件" -ErrNodeModulesNotFound: "node_modules 文件夾不存在!請編輯運行環境或者等待運行環境啟動成功" - -#setting -ErrBackupInUsed: "該備份帳號已在計劃任務中使用,無法刪除" -ErrBackupCheck: "備份帳號測試連接失敗 {{ .err}}" -ErrOSSConn: "無法獲取最新版本,請確認伺服器是否能夠連接外部網路。" -ErrEntrance: "安全入口信息錯誤,請檢查後重試!" - -#tool -ErrConfigNotFound: "配置文件不存在" -ErrConfigParse: "配置文件格式有誤" -ErrConfigIsNull: "配置文件不允許為空" -ErrConfigDirNotFound: "運行目錄不存在" -ErrConfigAlreadyExist: "已存在同名配置文件" -ErrUserFindErr: "用戶 {{ .name }} 查找失敗 {{ .err }}" - -#ssh -ErrFirewall: "當前未檢測到系統 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: "許可證校驗失敗,請檢查後重試!" -ErrLicenseSave: "許可證信息保存失敗,錯誤 {{ .err }}, 請重試!" -ErrLicenseSync: "許可證信息同步失敗,資料庫中未檢測到許可證信息!" -ErrXpackNotFound: "該部分為專業版功能,請先在 面板設置-許可證 界面導入許可證" -ErrXpackNotActive: "該部分為專業版功能,請先在 面板設置-許可證 界面同步許可證狀態" -ErrXpackOutOfDate: "當前許可證已過期,請重新在 面板設置-許可證 界面導入許可證" - -#task -TaskStart: "{{.name}} 開始 [START]" -TaskEnd: "{{.name}} 結束 [COMPLETED]" -TaskFailed: "{{.name}} 失敗: {{.err}}" -TaskTimeout: "{{.name}} 逾時" -TaskSuccess: "{{.name}} 成功" -TaskRetry: "開始第 {{.name}} 次重試" -SubTaskStart: "開始 {{.name}}" diff --git a/backend/i18n/lang/zh.yaml b/backend/i18n/lang/zh.yaml deleted file mode 100644 index ff3bb1346..000000000 --- a/backend/i18n/lang/zh.yaml +++ /dev/null @@ -1,210 +0,0 @@ -ErrInvalidParams: "请求参数错误: {{ .detail }}" -ErrTokenParse: "Token 生成错误: {{ .detail }}" -ErrInitialPassword: "原密码错误" -ErrInternalServer: "服务内部错误: {{ .detail }}" -ErrRecordExist: "记录已存在" -ErrRecordNotFound: "记录未能找到" -ErrStructTransform: "类型转换失败: {{ .detail }}" -ErrNotLogin: "用户未登录: {{ .detail }}" -ErrPasswordExpired: "当前密码已过期: {{ .detail }}" -ErrNotSupportType: "系统暂不支持当前类型: {{ .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 {{.err}}' -ErrImagePull: '镜像拉取失败 {{.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: "文件超过10M,无法打开" -ErrPathNotFound: "目录不存在" -ErrMovePathFailed: "目标路径不能包含原路径!" -ErrLinkPathNotFound: "目标路径不存在!" -ErrFileIsExist: "文件或文件夹已存在!" -ErrFileUpload: "{{ .name }} 上传文件失败 {{ .detail}}" -ErrFileDownloadDir: "不支持下载文件夹" -ErrCmdNotFound: "{{ .name}} 命令不存在,请先在宿主机安装此命令" -ErrSourcePathNotFound: "源目录不存在" -ErrFavoriteExist: "已收藏此路径" -ErrInvalidChar: "禁止使用非法字符" - -#website -ErrDomainIsExist: "域名已存在" -ErrAliasIsExist: "代号已存在" -ErrAppDelete: '其他网站使用此应用,无法删除' -ErrGroupIsUsed: '分组正在使用中,无法删除' -ErrBackupMatch: '该备份文件与当前网站部分数据不匹配 {{ .detail}}' -ErrBackupExist: '该备份文件对应部分源数据不存在 {{ .detail}}' -ErrPHPResource: '本地运行环境不支持切换!' -ErrPathPermission: 'index 目录下检测到非 1000:1000 权限文件夹,可能导致网站访问 Access denied 错误,请点击上方保存按钮' -ErrDomainIsUsed: "域名已被网站【{{ .name }}】使用" -ErrDomainFormat: "{{ .name }} 域名格式不正确" -ErrDefaultAlias: "default 为保留代号,请使用其他代号" - -#ssl -ErrSSLCannotDelete: "{{ .name }} 证书正在被网站使用,无法删除" -ErrAccountCannotDelete: "账号关联证书,无法删除" -ErrSSLApply: "证书续签成功,openresty reload失败,请检查配置!" -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: "脚本执行成功" - -#mysql -ErrUserIsExist: "当前用户已存在,请重新输入" -ErrDatabaseIsExist: "当前数据库已存在,请重新输入" -ErrExecTimeOut: "SQL 执行超时,请检查数据库" -ErrRemoteExist: "远程数据库已存在该名称,请修改后重试" -ErrLocalExist: "本地数据库已存在该名称,请修改后重试" - -#redis -ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后重试" - -#container -ErrInUsed: "{{ .detail }} 正被使用,无法删除" -ErrObjectInUsed: "该对象正被使用,无法删除" -ErrPortRules: "端口数目不匹配,请重新输入!" -ErrPgImagePull: "镜像拉取超时,请配置镜像加速或手动拉取 postgres:16.0-alpine 镜像后重试" - -#runtime -ErrDirNotFound: "build 文件夹不存在!请检查文件完整性!" -ErrFileNotExist: "{{ .detail }} 文件不存在!请检查源文件完整性!" -ErrImageBuildErr: "镜像 build 失败" -ErrImageExist: "镜像已存在!" -ErrDelWithWebsite: "运行环境已经关联网站,无法删除" -ErrRuntimeStart: "启动失败" -ErrPackageJsonNotFound: "package.json 文件不存在" -ErrScriptsNotFound: "没有在 package.json 中找到 scripts 配置项" -ErrContainerNameNotFound: "无法获取容器名称,请检查 .env 文件" -ErrNodeModulesNotFound: "node_modules 文件夹不存在!请编辑运行环境或者等待运行环境启动成功" - -#setting -ErrBackupInUsed: "该备份账号已在计划任务中使用,无法删除" -ErrBackupCheck: "备份账号测试连接失败 {{ .err}}" -ErrOSSConn: "无法获取最新版本,请确认服务器是否能够连接外部网络。" -ErrEntrance: "安全入口信息错误,请检查后重试!" - -#tool -ErrConfigNotFound: "配置文件不存在" -ErrConfigParse: "配置文件格式有误" -ErrConfigIsNull: "配置文件不允许为空" -ErrConfigDirNotFound: "运行目录不存在" -ErrConfigAlreadyExist: "已存在同名配置文件" -ErrUserFindErr: "用户 {{ .name }} 查找失败 {{ .err }}" - -#ssh -ErrFirewall: "当前未检测到系统 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: "许可证校验失败,请检查后重试!" -ErrLicenseSave: "许可证信息保存失败,错误 {{ .err }},请重试!" -ErrLicenseSync: "许可证信息同步失败,数据库中未检测到许可证信息!" -ErrXpackNotFound: "该部分为专业版功能,请先在 面板设置-许可证 界面导入许可证" -ErrXpackNotActive: "该部分为专业版功能,请先在 面板设置-许可证 界面同步许可证状态" -ErrXpackOutOfDate: "当前许可证已过期,请重新在 面板设置-许可证 界面导入许可证" - -#task -TaskStart: "{{.name}} 开始 [START]" -TaskEnd: "{{.name}} 结束 [COMPLETED]" -TaskFailed: "{{.name}} 失败: {{.err}}" -TaskTimeout: "{{.name}} 超时" -TaskSuccess: "{{.name}} 成功" -TaskRetry: "开始第 {{.name}} 次重试" -SubTaskStart: "开始 {{.name}}" diff --git a/backend/init/app/app.go b/backend/init/app/app.go deleted file mode 100644 index 51cc8c46d..000000000 --- a/backend/init/app/app.go +++ /dev/null @@ -1,46 +0,0 @@ -package app - -import ( - "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/1Panel-dev/1Panel/backend/utils/firewall" - "path" - - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/files" -) - -func Init() { - constant.DataDir = global.CONF.System.DataDir - constant.ResourceDir = path.Join(constant.DataDir, "resource") - constant.AppResourceDir = path.Join(constant.ResourceDir, "apps") - constant.AppInstallDir = path.Join(constant.DataDir, "apps") - constant.RuntimeDir = path.Join(constant.DataDir, "runtime") - - constant.LocalAppResourceDir = path.Join(constant.AppResourceDir, "local") - constant.LocalAppInstallDir = path.Join(constant.AppInstallDir, "local") - constant.RemoteAppResourceDir = path.Join(constant.AppResourceDir, "remote") - - constant.LogDir = path.Join(global.CONF.System.DataDir, "log") - constant.SSLLogDir = path.Join(constant.LogDir, "ssl") - - dirs := []string{constant.DataDir, constant.ResourceDir, constant.AppResourceDir, constant.AppInstallDir, - global.CONF.System.Backup, constant.RuntimeDir, constant.LocalAppResourceDir, constant.RemoteAppResourceDir, constant.SSLLogDir} - - fileOp := files.NewFileOp() - for _, dir := range dirs { - createDir(fileOp, dir) - } - - _ = docker.CreateDefaultDockerNetwork() - - if f, err := firewall.NewFirewallClient(); err == nil { - _ = f.EnableForward() - } -} - -func createDir(fileOp files.FileOp, dirPath string) { - if !fileOp.Stat(dirPath) { - _ = fileOp.CreateDir(dirPath, 0755) - } -} diff --git a/backend/init/business/business.go b/backend/init/business/business.go deleted file mode 100644 index 4a544b5da..000000000 --- a/backend/init/business/business.go +++ /dev/null @@ -1,40 +0,0 @@ -package business - -import ( - "github.com/1Panel-dev/1Panel/backend/app/service" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" -) - -func Init() { - go syncApp() - go syncInstalledApp() - go syncRuntime() - go syncSSL() -} - -func syncApp() { - _ = service.NewISettingService().Update("AppStoreSyncStatus", constant.SyncSuccess) - if err := service.NewIAppService().SyncAppListFromRemote(); err != nil { - global.LOG.Errorf("App Store synchronization failed") - return - } -} - -func syncInstalledApp() { - if err := service.NewIAppInstalledService().SyncAll(true); err != nil { - global.LOG.Errorf("sync installed app error: %s", err.Error()) - } -} - -func syncRuntime() { - if err := service.NewRuntimeService().SyncForRestart(); err != nil { - global.LOG.Errorf("sync runtime status error : %s", err.Error()) - } -} - -func syncSSL() { - if err := service.NewIWebsiteSSLService().SyncForRestart(); err != nil { - global.LOG.Errorf("sync ssl status error : %s", err.Error()) - } -} diff --git a/backend/init/cache/badger_db/badger_db.go b/backend/init/cache/badger_db/badger_db.go deleted file mode 100644 index a1508503a..000000000 --- a/backend/init/cache/badger_db/badger_db.go +++ /dev/null @@ -1,79 +0,0 @@ -package badger_db - -import ( - "fmt" - "time" - - "github.com/dgraph-io/badger/v4" -) - -type Cache struct { - db *badger.DB -} - -func NewCacheDB(db *badger.DB) *Cache { - return &Cache{ - db: db, - } -} - -func (c *Cache) Set(key string, value interface{}) error { - err := c.db.Update(func(txn *badger.Txn) error { - v := []byte(fmt.Sprintf("%v", value)) - return txn.Set([]byte(key), v) - }) - return err -} - -func (c *Cache) Del(key string) error { - err := c.db.Update(func(txn *badger.Txn) error { - return txn.Delete([]byte(key)) - }) - return err -} - -func (c *Cache) Clean() error { - return c.db.DropAll() -} - -func (c *Cache) Get(key string) ([]byte, error) { - var result []byte - err := c.db.View(func(txn *badger.Txn) error { - item, err := txn.Get([]byte(key)) - if err != nil { - return err - } - err = item.Value(func(val []byte) error { - result = append([]byte{}, val...) - return nil - }) - return err - }) - return result, err -} - -func (c *Cache) SetWithTTL(key string, value interface{}, duration time.Duration) error { - err := c.db.Update(func(txn *badger.Txn) error { - v := []byte(fmt.Sprintf("%v", value)) - e := badger.NewEntry([]byte(key), v).WithTTL(duration) - return txn.SetEntry(e) - }) - return err -} - -func (c *Cache) PrefixScanKey(prefixStr string) ([]string, error) { - var res []string - err := c.db.View(func(txn *badger.Txn) error { - it := txn.NewIterator(badger.DefaultIteratorOptions) - defer it.Close() - prefix := []byte(prefixStr) - for it.Seek(prefix); it.ValidForPrefix(prefix); it.Next() { - item := it.Item() - k := item.Key() - res = append(res, string(k)) - return nil - } - return nil - }) - return res, err -} diff --git a/backend/init/cache/cache.go b/backend/init/cache/cache.go deleted file mode 100644 index 1b64e1f72..000000000 --- a/backend/init/cache/cache.go +++ /dev/null @@ -1,56 +0,0 @@ -package cache - -import ( - "time" - - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/init/cache/badger_db" - "github.com/dgraph-io/badger/v4" -) - -func Init() { - c := global.CONF.System.Cache - - options := badger.Options{ - Dir: c, - ValueDir: c, - ValueLogFileSize: 64 << 20, - ValueLogMaxEntries: 10 << 20, - VLogPercentile: 0.1, - - MemTableSize: 32 << 20, - BaseTableSize: 2 << 20, - BaseLevelSize: 10 << 20, - TableSizeMultiplier: 2, - LevelSizeMultiplier: 10, - MaxLevels: 7, - NumGoroutines: 4, - MetricsEnabled: true, - NumCompactors: 2, - NumLevelZeroTables: 5, - NumLevelZeroTablesStall: 15, - NumMemtables: 1, - BloomFalsePositive: 0.01, - BlockSize: 2 * 1024, - SyncWrites: false, - NumVersionsToKeep: 1, - CompactL0OnClose: false, - VerifyValueChecksum: false, - BlockCacheSize: 32 << 20, - IndexCacheSize: 0, - ZSTDCompressionLevel: 1, - EncryptionKey: []byte{}, - EncryptionKeyRotationDuration: 10 * 24 * time.Hour, // Default 10 days. - DetectConflicts: true, - NamespaceOffset: -1, - } - - cache, err := badger.Open(options) - if err != nil { - panic(err) - } - _ = cache.DropAll() - global.CacheDb = cache - global.CACHE = badger_db.NewCacheDB(cache) - global.LOG.Info("init cache successfully") -} diff --git a/backend/init/db/db.go b/backend/init/db/db.go deleted file mode 100644 index e0cd1bc8b..000000000 --- a/backend/init/db/db.go +++ /dev/null @@ -1,94 +0,0 @@ -package db - -import ( - "fmt" - "log" - "os" - "path" - "time" - - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/glebarez/sqlite" - "gorm.io/gorm" - "gorm.io/gorm/logger" -) - -func Init() { - if _, err := os.Stat(global.CONF.System.DbPath); err != nil { - if err := os.MkdirAll(global.CONF.System.DbPath, os.ModePerm); err != nil { - panic(fmt.Errorf("init db dir failed, err: %v", err)) - } - } - fullPath := global.CONF.System.DbPath + "/" + global.CONF.System.DbFile - if _, err := os.Stat(fullPath); err != nil { - f, err := os.Create(fullPath) - if err != nil { - panic(fmt.Errorf("init db file failed, err: %v", err)) - } - _ = f.Close() - } - - newLogger := logger.New( - log.New(os.Stdout, "\r\n", log.LstdFlags), - logger.Config{ - SlowThreshold: time.Second, - LogLevel: logger.Silent, - IgnoreRecordNotFoundError: true, - Colorful: false, - }, - ) - initMonitorDB(newLogger) - - db, err := gorm.Open(sqlite.Open(fullPath), &gorm.Config{ - DisableForeignKeyConstraintWhenMigrating: true, - Logger: newLogger, - }) - if err != nil { - panic(err) - } - _ = db.Exec("PRAGMA journal_mode = WAL;") - sqlDB, dbError := db.DB() - if dbError != nil { - panic(dbError) - } - sqlDB.SetConnMaxIdleTime(10) - sqlDB.SetMaxOpenConns(100) - sqlDB.SetConnMaxLifetime(time.Hour) - - global.DB = db - global.LOG.Info("init db successfully") -} - -func initMonitorDB(newLogger logger.Interface) { - if _, err := os.Stat(global.CONF.System.DbPath); err != nil { - if err := os.MkdirAll(global.CONF.System.DbPath, os.ModePerm); err != nil { - panic(fmt.Errorf("init db dir failed, err: %v", err)) - } - } - fullPath := path.Join(global.CONF.System.DbPath, "monitor.db") - if _, err := os.Stat(fullPath); err != nil { - f, err := os.Create(fullPath) - if err != nil { - panic(fmt.Errorf("init db file failed, err: %v", err)) - } - _ = f.Close() - } - - db, err := gorm.Open(sqlite.Open(fullPath), &gorm.Config{ - DisableForeignKeyConstraintWhenMigrating: true, - Logger: newLogger, - }) - if err != nil { - panic(err) - } - sqlDB, dbError := db.DB() - if dbError != nil { - panic(dbError) - } - sqlDB.SetConnMaxIdleTime(10) - sqlDB.SetMaxOpenConns(100) - sqlDB.SetConnMaxLifetime(time.Hour) - - global.MonitorDB = db - global.LOG.Info("init monitor db successfully") -} diff --git a/backend/init/hook/hook.go b/backend/init/hook/hook.go deleted file mode 100644 index 8f02d4a79..000000000 --- a/backend/init/hook/hook.go +++ /dev/null @@ -1,147 +0,0 @@ -package hook - -import ( - "encoding/base64" - "encoding/json" - "os" - "path" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/app/repo" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" -) - -func Init() { - settingRepo := repo.NewISettingRepo() - OneDriveID, err := settingRepo.Get(settingRepo.WithByKey("OneDriveID")) - if err != nil { - global.LOG.Errorf("load onedrive info from setting failed, err: %v", err) - } - idItem, _ := base64.StdEncoding.DecodeString(OneDriveID.Value) - global.CONF.System.OneDriveID = string(idItem) - OneDriveSc, err := settingRepo.Get(settingRepo.WithByKey("OneDriveSc")) - if err != nil { - global.LOG.Errorf("load onedrive info from setting failed, err: %v", err) - } - scItem, _ := base64.StdEncoding.DecodeString(OneDriveSc.Value) - global.CONF.System.OneDriveSc = string(scItem) - - if _, err := settingRepo.Get(settingRepo.WithByKey("SystemStatus")); err != nil { - _ = settingRepo.Create("SystemStatus", "Free") - } - if err := settingRepo.Update("SystemStatus", "Free"); err != nil { - global.LOG.Fatalf("init service before start failed, err: %v", err) - } - - handleCronjobStatus() - handleSnapStatus() - loadLocalDir() - initDir() -} - -func handleSnapStatus() { - msgFailed := "the task was interrupted due to the restart of the 1panel service" - _ = global.DB.Model(&model.Snapshot{}).Where("status = ?", "OnSaveData"). - Updates(map[string]interface{}{"status": constant.StatusSuccess}).Error - - _ = global.DB.Model(&model.Snapshot{}).Where("status = ?", constant.StatusWaiting). - Updates(map[string]interface{}{ - "status": constant.StatusFailed, - "message": msgFailed, - }).Error - - _ = global.DB.Model(&model.Snapshot{}).Where("recover_status = ?", constant.StatusWaiting). - Updates(map[string]interface{}{ - "recover_status": constant.StatusFailed, - "recover_message": msgFailed, - }).Error - - _ = global.DB.Model(&model.Snapshot{}).Where("rollback_status = ?", constant.StatusWaiting). - Updates(map[string]interface{}{ - "rollback_status": constant.StatusFailed, - "rollback_message": msgFailed, - }).Error - - snapRepo := repo.NewISnapshotRepo() - - status, _ := snapRepo.GetStatusList() - for _, item := range status { - updates := make(map[string]interface{}) - if item.Panel == constant.StatusRunning { - updates["panel"] = constant.StatusFailed - } - if item.PanelInfo == constant.StatusRunning { - updates["panel_info"] = constant.StatusFailed - } - if item.DaemonJson == constant.StatusRunning { - updates["daemon_json"] = constant.StatusFailed - } - if item.AppData == constant.StatusRunning { - updates["app_data"] = constant.StatusFailed - } - if item.PanelData == constant.StatusRunning { - updates["panel_data"] = constant.StatusFailed - } - if item.BackupData == constant.StatusRunning { - updates["backup_data"] = constant.StatusFailed - } - if item.Compress == constant.StatusRunning { - updates["compress"] = constant.StatusFailed - } - if item.Upload == constant.StatusUploading { - updates["upload"] = constant.StatusFailed - } - if len(updates) != 0 { - _ = snapRepo.UpdateStatus(item.ID, updates) - } - } -} - -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 -} - -func loadLocalDir() { - var backup model.BackupAccount - _ = global.DB.Where("type = ?", "LOCAL").First(&backup).Error - if backup.ID == 0 { - global.LOG.Errorf("no such backup account `%s` in db", "LOCAL") - return - } - varMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil { - global.LOG.Errorf("json unmarshal backup.Vars: %v failed, err: %v", backup.Vars, err) - return - } - if _, ok := varMap["dir"]; !ok { - global.LOG.Error("load local backup dir failed") - return - } - baseDir, ok := varMap["dir"].(string) - if ok { - if _, err := os.Stat(baseDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(baseDir, os.ModePerm); err != nil { - global.LOG.Errorf("mkdir %s failed, err: %v", baseDir, err) - return - } - } - global.CONF.System.Backup = baseDir - return - } - global.LOG.Errorf("error type dir: %T", varMap["dir"]) -} - -func initDir() { - composePath := path.Join(global.CONF.System.BaseDir, "1panel/docker/compose/") - if _, err := os.Stat(composePath); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(composePath, os.ModePerm); err != nil { - global.LOG.Errorf("mkdir %s failed, err: %v", composePath, err) - return - } - } -} diff --git a/backend/init/log/log.go b/backend/init/log/log.go deleted file mode 100644 index 9e1128e2d..000000000 --- a/backend/init/log/log.go +++ /dev/null @@ -1,68 +0,0 @@ -package log - -import ( - "fmt" - "io" - "os" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/log" - - "github.com/1Panel-dev/1Panel/backend/configs" - "github.com/1Panel-dev/1Panel/backend/global" - - "github.com/sirupsen/logrus" -) - -const ( - TimeFormat = "2006-01-02 15:04:05" - FileTImeFormat = "2006-01-02" - RollingTimePattern = "0 0 * * *" -) - -func Init() { - l := logrus.New() - setOutput(l, global.CONF.LogConfig) - global.LOG = l - global.LOG.Info("init logger successfully") -} - -func setOutput(logger *logrus.Logger, config configs.LogConfig) { - writer, err := log.NewWriterFromConfig(&log.Config{ - LogPath: global.CONF.System.LogPath, - FileName: config.LogName, - TimeTagFormat: FileTImeFormat, - MaxRemain: config.MaxBackup, - RollingTimePattern: RollingTimePattern, - LogSuffix: config.LogSuffix, - }) - if err != nil { - panic(err) - } - level, err := logrus.ParseLevel(config.Level) - if err != nil { - panic(err) - } - fileAndStdoutWriter := io.MultiWriter(writer, os.Stdout) - - logger.SetOutput(fileAndStdoutWriter) - logger.SetLevel(level) - logger.SetFormatter(new(MineFormatter)) -} - -type MineFormatter struct{} - -func (s *MineFormatter) Format(entry *logrus.Entry) ([]byte, error) { - detailInfo := "" - if entry.Caller != nil { - function := strings.ReplaceAll(entry.Caller.Function, "github.com/1Panel-dev/1Panel/backend/", "") - detailInfo = fmt.Sprintf("(%s: %d)", function, entry.Caller.Line) - } - if len(entry.Data) == 0 { - msg := fmt.Sprintf("[%s] [%s] %s %s \n", time.Now().Format(TimeFormat), strings.ToUpper(entry.Level.String()), entry.Message, detailInfo) - return []byte(msg), nil - } - msg := fmt.Sprintf("[%s] [%s] %s %s {%v} \n", time.Now().Format(TimeFormat), strings.ToUpper(entry.Level.String()), entry.Message, detailInfo, entry.Data) - return []byte(msg), nil -} diff --git a/backend/init/migration/migrate.go b/backend/init/migration/migrate.go deleted file mode 100644 index 773f0f299..000000000 --- a/backend/init/migration/migrate.go +++ /dev/null @@ -1,26 +0,0 @@ -package migration - -import ( - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/init/migration/migrations" - - "github.com/go-gormigrate/gormigrate/v2" -) - -func Init() { - m := gormigrate.New(global.DB, gormigrate.DefaultOptions, []*gormigrate.Migration{ - migrations.AddTable, - migrations.InitHost, - migrations.InitSetting, - migrations.InitBackupAccount, - migrations.InitImageRepo, - migrations.InitDefaultGroup, - migrations.InitDefaultCA, - migrations.InitPHPExtensions, - }) - if err := m.Migrate(); err != nil { - global.LOG.Error(err) - panic(err) - } - global.LOG.Info("Migration run successfully") -} diff --git a/backend/init/migration/migrations/init.go b/backend/init/migration/migrations/init.go deleted file mode 100644 index 9a3d96822..000000000 --- a/backend/init/migration/migrations/init.go +++ /dev/null @@ -1,249 +0,0 @@ -package migrations - -import ( - "fmt" - - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/app/service" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/common" - - "github.com/go-gormigrate/gormigrate/v2" - "gorm.io/gorm" -) - -var AddTable = &gormigrate.Migration{ - ID: "20240722-add-table", - Migrate: func(tx *gorm.DB) error { - return tx.AutoMigrate( - &model.AppDetail{}, - &model.AppInstallResource{}, - &model.AppInstall{}, - &model.AppTag{}, - &model.Tag{}, - &model.App{}, - &model.BackupAccount{}, - &model.BackupRecord{}, - &model.Clam{}, - &model.Command{}, - &model.ComposeTemplate{}, - &model.Compose{}, - &model.Cronjob{}, - &model.Database{}, - &model.DatabaseMysql{}, - &model.DatabasePostgresql{}, - &model.Favorite{}, - &model.Forward{}, - &model.Firewall{}, - &model.Ftp{}, - &model.Group{}, - &model.Host{}, - &model.ImageRepo{}, - &model.JobRecords{}, - &model.MonitorBase{}, - &model.MonitorIO{}, - &model.MonitorNetwork{}, - &model.PHPExtensions{}, - &model.RedisCommand{}, - &model.Runtime{}, - &model.Setting{}, - &model.Snapshot{}, - &model.SnapshotStatus{}, - &model.Tag{}, - &model.Website{}, - &model.WebsiteAcmeAccount{}, - &model.WebsiteCA{}, - &model.WebsiteDnsAccount{}, - &model.WebsiteDomain{}, - &model.WebsiteSSL{}, - ) - }, -} - -var InitHost = &gormigrate.Migration{ - ID: "20240722-init-host", - Migrate: func(tx *gorm.DB) error { - group := model.Group{ - Name: "default", Type: "host", IsDefault: true, - } - if err := tx.Create(&group).Error; err != nil { - return err - } - host := model.Host{ - Name: "localhost", Addr: "127.0.0.1", User: "root", Port: 22, AuthMode: "password", GroupID: group.ID, - } - if err := tx.Create(&host).Error; err != nil { - return err - } - return nil - }, -} - -var InitSetting = &gormigrate.Migration{ - ID: "20240722-init-setting", - Migrate: func(tx *gorm.DB) error { - if err := tx.Create(&model.Setting{Key: "SystemIP", Value: ""}).Error; err != nil { - return err - } - if err := tx.Create(&model.Setting{Key: "DockerSockPath", Value: "unix:///var/run/docker.sock"}).Error; err != nil { - return err - } - if err := tx.Create(&model.Setting{Key: "SystemVersion", Value: global.CONF.System.Version}).Error; err != nil { - return err - } - if err := tx.Create(&model.Setting{Key: "SystemStatus", Value: "Free"}).Error; err != nil { - return err - } - - if err := tx.Create(&model.Setting{Key: "LocalTime", Value: ""}).Error; err != nil { - return err - } - if err := tx.Create(&model.Setting{Key: "TimeZone", Value: common.LoadTimeZoneByCmd()}).Error; err != nil { - return err - } - if err := tx.Create(&model.Setting{Key: "NtpSite", Value: "pool.ntp.org"}).Error; err != nil { - return err - } - - if err := tx.Create(&model.Setting{Key: "DefaultNetwork", Value: "all"}).Error; err != nil { - return err - } - if err := tx.Create(&model.Setting{Key: "LastCleanTime", Value: ""}).Error; err != nil { - return err - } - if err := tx.Create(&model.Setting{Key: "LastCleanSize", Value: ""}).Error; err != nil { - return err - } - if err := tx.Create(&model.Setting{Key: "LastCleanData", Value: ""}).Error; err != nil { - return err - } - - if err := tx.Create(&model.Setting{Key: "MonitorStatus", Value: "enable"}).Error; err != nil { - return err - } - if err := tx.Create(&model.Setting{Key: "MonitorStoreDays", Value: "7"}).Error; err != nil { - return err - } - if err := tx.Create(&model.Setting{Key: "MonitorInterval", Value: "5"}).Error; err != nil { - return err - } - - if err := tx.Create(&model.Setting{Key: "AppStoreVersion", Value: ""}).Error; err != nil { - return err - } - if err := tx.Create(&model.Setting{Key: "AppStoreSyncStatus", Value: "SyncSuccess"}).Error; err != nil { - return err - } - if err := tx.Create(&model.Setting{Key: "AppStoreLastModified", Value: "0"}).Error; err != nil { - return err - } - - if err := tx.Create(&model.Setting{Key: "OneDriveID", Value: "MDEwOTM1YTktMWFhOS00ODU0LWExZGMtNmU0NWZlNjI4YzZi"}).Error; err != nil { - return err - } - if err := tx.Create(&model.Setting{Key: "OneDriveSc", Value: "akpuOFF+YkNXOU1OLWRzS1ZSRDdOcG1LT2ZRM0RLNmdvS1RkVWNGRA=="}).Error; err != nil { - return err - } - - if err := tx.Create(&model.Setting{Key: "FileRecycleBin", Value: "enable"}).Error; err != nil { - return err - } - if err := tx.Create(&model.Setting{Key: "SnapshotIgnore", Value: "*.sock"}).Error; err != nil { - return err - } - return nil - }, -} - -var InitBackupAccount = &gormigrate.Migration{ - ID: "20240722-init-backup", - Migrate: func(tx *gorm.DB) error { - item := &model.BackupAccount{ - Type: "LOCAL", - Vars: fmt.Sprintf("{\"dir\":\"%s\"}", global.CONF.System.Backup), - } - if err := tx.Create(item).Error; err != nil { - return err - } - return nil - }, -} - -var InitImageRepo = &gormigrate.Migration{ - ID: "20240722-init-imagerepo", - Migrate: func(tx *gorm.DB) error { - item := &model.ImageRepo{ - Name: "Docker Hub", - Protocol: "https", - DownloadUrl: "docker.io", - Status: constant.StatusSuccess, - } - if err := tx.Create(item).Error; err != nil { - return err - } - return nil - }, -} - -var InitDefaultGroup = &gormigrate.Migration{ - ID: "20240722-init-default-group", - Migrate: func(tx *gorm.DB) error { - websiteGroup := &model.Group{ - Name: "默认", - IsDefault: true, - Type: "website", - } - if err := tx.Create(websiteGroup).Error; err != nil { - return err - } - commandGroup := &model.Group{IsDefault: true, Name: "默认", Type: "command"} - if err := tx.Create(commandGroup).Error; err != nil { - return err - } - return nil - }, -} - -var InitDefaultCA = &gormigrate.Migration{ - ID: "20240722-init-default-ca", - Migrate: func(tx *gorm.DB) error { - caService := service.NewIWebsiteCAService() - if _, err := caService.Create(request.WebsiteCACreate{ - CommonName: "1Panel-CA", - Country: "CN", - KeyType: "P256", - Name: "1Panel", - Organization: "FIT2CLOUD", - OrganizationUint: "1Panel", - Province: "Beijing", - City: "Beijing", - }); err != nil { - return err - } - return nil - }, -} - -var InitPHPExtensions = &gormigrate.Migration{ - ID: "20240722-add-php-extensions", - Migrate: func(tx *gorm.DB) error { - if err := tx.Create(&model.PHPExtensions{Name: "默认", Extensions: "bcmath,gd,gettext,intl,pcntl,shmop,soap,sockets,sysvsem,xmlrpc,zip"}).Error; err != nil { - return err - } - if err := tx.Create(&model.PHPExtensions{Name: "WordPress", Extensions: "exif,igbinary,imagick,intl,zip,apcu,memcached,opcache,redis,bc,image,shmop,mysqli,pdo_mysql,gd"}).Error; err != nil { - return err - } - if err := tx.Create(&model.PHPExtensions{Name: "Flarum", Extensions: "curl,gd,pdo_mysql,mysqli,bz2,exif,yaf,imap"}).Error; err != nil { - return err - } - if err := tx.Create(&model.PHPExtensions{Name: "苹果CMS-V10", Extensions: "mysqli,pdo_mysql,zip,gd,redis,memcache,memcached"}).Error; err != nil { - return err - } - if err := tx.Create(&model.PHPExtensions{Name: "SeaCMS", Extensions: "mysqli,pdo_mysql,gd,curl"}).Error; err != nil { - return err - } - return nil - }, -} diff --git a/backend/init/router/router.go b/backend/init/router/router.go deleted file mode 100644 index 217e65be0..000000000 --- a/backend/init/router/router.go +++ /dev/null @@ -1,41 +0,0 @@ -package router - -import ( - "github.com/1Panel-dev/1Panel/backend/i18n" - "github.com/1Panel-dev/1Panel/backend/middleware" - rou "github.com/1Panel-dev/1Panel/backend/router" - "github.com/gin-contrib/gzip" - "github.com/gin-gonic/gin" -) - -var ( - Router *gin.Engine -) - -func setWebStatic(rootRouter *gin.RouterGroup) { - rootRouter.Static("/api/v1/images", "./uploads") - rootRouter.Use(func(c *gin.Context) { - c.Next() - }) -} - -func Routers() *gin.Engine { - Router = gin.Default() - Router.Use(i18n.UseI18n()) - - PublicGroup := Router.Group("") - { - PublicGroup.GET("/health", func(c *gin.Context) { - c.JSON(200, "ok") - }) - PublicGroup.Use(gzip.Gzip(gzip.DefaultCompression)) - setWebStatic(PublicGroup) - } - PrivateGroup := Router.Group("/api/v1") - PrivateGroup.Use(middleware.GlobalLoading()) - for _, router := range rou.RouterGroupApp { - router.InitRouter(PrivateGroup) - } - - return Router -} diff --git a/backend/init/validator/validator.go b/backend/init/validator/validator.go deleted file mode 100644 index d840383bd..000000000 --- a/backend/init/validator/validator.go +++ /dev/null @@ -1,65 +0,0 @@ -package validator - -import ( - "regexp" - "unicode" - - "github.com/1Panel-dev/1Panel/backend/global" - - "github.com/go-playground/validator/v10" -) - -func Init() { - validator := validator.New() - if err := validator.RegisterValidation("name", checkNamePattern); err != nil { - panic(err) - } - if err := validator.RegisterValidation("ip", checkIpPattern); err != nil { - panic(err) - } - if err := validator.RegisterValidation("password", checkPasswordPattern); err != nil { - panic(err) - } - global.VALID = validator -} - -func checkNamePattern(fl validator.FieldLevel) bool { - value := fl.Field().String() - result, err := regexp.MatchString("^[a-zA-Z\u4e00-\u9fa5]{1}[a-zA-Z0-9_\u4e00-\u9fa5]{0,30}$", value) - if err != nil { - global.LOG.Errorf("regexp matchString failed, %v", err) - } - return result -} - -func checkIpPattern(fl validator.FieldLevel) bool { - value := fl.Field().String() - result, err := regexp.MatchString(`^((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}$`, value) - if err != nil { - global.LOG.Errorf("regexp check ip matchString failed, %v", err) - } - return result -} - -func checkPasswordPattern(fl validator.FieldLevel) bool { - value := fl.Field().String() - if len(value) < 8 || len(value) > 30 { - return false - } - - hasNum := false - hasLetter := false - for _, r := range value { - if unicode.IsLetter(r) && !hasLetter { - hasLetter = true - } - if unicode.IsNumber(r) && !hasNum { - hasNum = true - } - if hasLetter && hasNum { - return true - } - } - - return false -} diff --git a/backend/init/viper/viper.go b/backend/init/viper/viper.go deleted file mode 100644 index 084a7d84d..000000000 --- a/backend/init/viper/viper.go +++ /dev/null @@ -1,90 +0,0 @@ -package viper - -import ( - "bytes" - "fmt" - "path" - "strings" - - "github.com/1Panel-dev/1Panel/backend/configs" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/1Panel-dev/1Panel/cmd/server/conf" - "github.com/fsnotify/fsnotify" - "github.com/spf13/viper" - "gopkg.in/yaml.v3" -) - -func Init() { - baseDir := "/opt" - mode := "" - version := "v1.0.0" - fileOp := files.NewFileOp() - v := viper.NewWithOptions() - v.SetConfigType("yaml") - - config := configs.ServerConfig{} - if err := yaml.Unmarshal(conf.AppYaml, &config); err != nil { - panic(err) - } - if config.System.Mode != "" { - mode = config.System.Mode - } - if mode == "dev" && fileOp.Stat("/opt/1panel/conf/app.yaml") { - v.SetConfigName("app") - v.AddConfigPath(path.Join("/opt/1panel/conf")) - if err := v.ReadInConfig(); err != nil { - panic(fmt.Errorf("Fatal error config file: %s \n", err)) - } - } else { - baseDir = loadParams("BASE_DIR") - version = loadParams("ORIGINAL_VERSION") - - reader := bytes.NewReader(conf.AppYaml) - if err := v.ReadConfig(reader); err != nil { - panic(fmt.Errorf("Fatal error config file: %s \n", err)) - } - } - v.OnConfigChange(func(e fsnotify.Event) { - if err := v.Unmarshal(&global.CONF); err != nil { - panic(err) - } - }) - serverConfig := configs.ServerConfig{} - if err := v.Unmarshal(&serverConfig); err != nil { - panic(err) - } - if mode == "dev" && fileOp.Stat("/opt/1panel/conf/app.yaml") { - if serverConfig.System.BaseDir != "" { - baseDir = serverConfig.System.BaseDir - } - if serverConfig.System.Version != "" { - version = serverConfig.System.Version - } - } - - global.CONF = serverConfig - global.CONF.System.BaseDir = baseDir - global.CONF.System.IsDemo = v.GetBool("system.is_demo") - global.CONF.System.DataDir = path.Join(global.CONF.System.BaseDir, "1panel") - global.CONF.System.Cache = path.Join(global.CONF.System.DataDir, "cache") - global.CONF.System.Backup = path.Join(global.CONF.System.DataDir, "backup") - global.CONF.System.DbPath = path.Join(global.CONF.System.DataDir, "db") - global.CONF.System.LogPath = path.Join(global.CONF.System.DataDir, "log") - global.CONF.System.TmpDir = path.Join(global.CONF.System.DataDir, "tmp") - global.CONF.System.Version = version - global.Viper = v -} - -func loadParams(param string) string { - stdout, err := cmd.Execf("grep '^%s=' /usr/local/bin/1pctl | cut -d'=' -f2", param) - if err != nil { - panic(err) - } - info := strings.ReplaceAll(stdout, "\n", "") - if len(info) == 0 || info == `""` { - panic(fmt.Sprintf("error `%s` find in /usr/local/bin/1pctl", param)) - } - return info -} diff --git a/backend/log/config.go b/backend/log/config.go deleted file mode 100644 index 08c1d6173..000000000 --- a/backend/log/config.go +++ /dev/null @@ -1,41 +0,0 @@ -package log - -import ( - "errors" - "io" - "os" - "path" -) - -var ( - BufferSize = 0x100000 - DefaultFileMode = os.FileMode(0644) - DefaultFileFlag = os.O_RDWR | os.O_CREATE | os.O_APPEND - ErrInvalidArgument = errors.New("error argument invalid") - QueueSize = 1024 - ErrClosed = errors.New("error write on close") -) - -type Config struct { - TimeTagFormat string - LogPath string - FileName string - LogSuffix string - MaxRemain int - RollingTimePattern string -} - -type Manager interface { - Fire() chan string - Close() -} - -type RollingWriter interface { - io.Writer - Close() error -} - -func FilePath(c *Config) (filepath string) { - filepath = path.Join(c.LogPath, c.FileName) + c.LogSuffix - return -} diff --git a/backend/log/dup_write_darwin.go b/backend/log/dup_write_darwin.go deleted file mode 100644 index 822d24e82..000000000 --- a/backend/log/dup_write_darwin.go +++ /dev/null @@ -1,20 +0,0 @@ -package log - -import ( - "golang.org/x/sys/unix" - "os" - "runtime" -) - -var stdErrFileHandler *os.File - -func dupWrite(file *os.File) error { - stdErrFileHandler = file - if err := unix.Dup2(int(file.Fd()), int(os.Stderr.Fd())); err != nil { - return err - } - runtime.SetFinalizer(stdErrFileHandler, func(fd *os.File) { - fd.Close() - }) - return nil -} diff --git a/backend/log/dup_write_linux.go b/backend/log/dup_write_linux.go deleted file mode 100644 index 822d24e82..000000000 --- a/backend/log/dup_write_linux.go +++ /dev/null @@ -1,20 +0,0 @@ -package log - -import ( - "golang.org/x/sys/unix" - "os" - "runtime" -) - -var stdErrFileHandler *os.File - -func dupWrite(file *os.File) error { - stdErrFileHandler = file - if err := unix.Dup2(int(file.Fd()), int(os.Stderr.Fd())); err != nil { - return err - } - runtime.SetFinalizer(stdErrFileHandler, func(fd *os.File) { - fd.Close() - }) - return nil -} diff --git a/backend/log/dup_write_windows.go b/backend/log/dup_write_windows.go deleted file mode 100644 index 4996cc12d..000000000 --- a/backend/log/dup_write_windows.go +++ /dev/null @@ -1,9 +0,0 @@ -package log - -import ( - "os" -) - -func dupWrite(file *os.File) error { - return nil -} diff --git a/backend/log/manager.go b/backend/log/manager.go deleted file mode 100644 index 1f4f94546..000000000 --- a/backend/log/manager.go +++ /dev/null @@ -1,53 +0,0 @@ -package log - -import ( - "github.com/robfig/cron/v3" - "path" - "sync" - "time" -) - -type manager struct { - startAt time.Time - fire chan string - cr *cron.Cron - context chan int - wg sync.WaitGroup - lock sync.Mutex -} - -func (m *manager) Fire() chan string { - return m.fire -} - -func (m *manager) Close() { - close(m.context) - m.cr.Stop() -} - -func NewManager(c *Config) (Manager, error) { - m := &manager{ - startAt: time.Now(), - cr: cron.New(), - fire: make(chan string), - context: make(chan int), - wg: sync.WaitGroup{}, - } - - if _, err := m.cr.AddFunc(c.RollingTimePattern, func() { - m.fire <- m.GenLogFileName(c) - }); err != nil { - return nil, err - } - m.cr.Start() - - return m, nil -} - -func (m *manager) GenLogFileName(c *Config) (filename string) { - m.lock.Lock() - filename = path.Join(c.LogPath, c.FileName+"-"+m.startAt.Format(c.TimeTagFormat)) + c.LogSuffix - m.startAt = time.Now() - m.lock.Unlock() - return -} diff --git a/backend/log/writer.go b/backend/log/writer.go deleted file mode 100644 index 74d7a1959..000000000 --- a/backend/log/writer.go +++ /dev/null @@ -1,250 +0,0 @@ -package log - -import ( - "log" - "os" - "path" - "sort" - "strings" - "sync" - "sync/atomic" - "time" - "unsafe" - - "github.com/1Panel-dev/1Panel/backend/global" -) - -type Writer struct { - m Manager - file *os.File - absPath string - fire chan string - cf *Config - rollingfilech chan string -} - -type AsynchronousWriter struct { - Writer - ctx chan int - queue chan []byte - errChan chan error - closed int32 - wg sync.WaitGroup -} - -func (w *AsynchronousWriter) Close() error { - if atomic.CompareAndSwapInt32(&w.closed, 0, 1) { - close(w.ctx) - w.onClose() - - func() { - defer func() { - if r := recover(); r != nil { - global.LOG.Error(r) - } - }() - w.m.Close() - }() - return w.file.Close() - } - return ErrClosed -} - -func (w *AsynchronousWriter) onClose() { - var err error - for { - select { - case b := <-w.queue: - if _, err = w.file.Write(b); err != nil { - select { - case w.errChan <- err: - default: - _asyncBufferPool.Put(&b) - return - } - } - _asyncBufferPool.Put(&b) - default: - return - } - } -} - -var _asyncBufferPool = sync.Pool{ - New: func() interface{} { - return make([]byte, BufferSize) - }, -} - -func NewWriterFromConfig(c *Config) (RollingWriter, error) { - if c.LogPath == "" || c.FileName == "" { - return nil, ErrInvalidArgument - } - if err := os.MkdirAll(c.LogPath, 0700); err != nil { - return nil, err - } - filepath := FilePath(c) - file, err := os.OpenFile(filepath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644) - if err != nil { - return nil, err - } - if err := dupWrite(file); err != nil { - return nil, err - } - mng, err := NewManager(c) - if err != nil { - return nil, err - } - - var rollingWriter RollingWriter - writer := Writer{ - m: mng, - file: file, - absPath: filepath, - fire: mng.Fire(), - cf: c, - } - if c.MaxRemain > 0 { - writer.rollingfilech = make(chan string, c.MaxRemain) - dir, err := os.ReadDir(c.LogPath) - if err != nil { - mng.Close() - return nil, err - } - - files := make([]string, 0, 10) - for _, fi := range dir { - if fi.IsDir() { - continue - } - - fileName := c.FileName - if strings.Contains(fi.Name(), fileName) && strings.Contains(fi.Name(), c.LogSuffix) { - start := strings.Index(fi.Name(), "-") - end := strings.Index(fi.Name(), c.LogSuffix) - name := fi.Name() - if start > 0 && end > 0 { - _, err := time.Parse(c.TimeTagFormat, name[start+1:end]) - if err == nil { - files = append(files, fi.Name()) - } - } - } - } - sort.Slice(files, func(i, j int) bool { - t1Start := strings.Index(files[i], "-") - t1End := strings.Index(files[i], c.LogSuffix) - t2Start := strings.Index(files[i], "-") - t2End := strings.Index(files[i], c.LogSuffix) - t1, _ := time.Parse(c.TimeTagFormat, files[i][t1Start+1:t1End]) - t2, _ := time.Parse(c.TimeTagFormat, files[j][t2Start+1:t2End]) - return t1.Before(t2) - }) - - for _, file := range files { - retry: - select { - case writer.rollingfilech <- path.Join(c.LogPath, file): - default: - writer.DoRemove() - goto retry - } - } - } - - wr := &AsynchronousWriter{ - ctx: make(chan int), - queue: make(chan []byte, QueueSize), - errChan: make(chan error, QueueSize), - wg: sync.WaitGroup{}, - closed: 0, - Writer: writer, - } - - wr.wg.Add(1) - go wr.writer() - wr.wg.Wait() - rollingWriter = wr - - return rollingWriter, nil -} - -func (w *AsynchronousWriter) writer() { - var err error - w.wg.Done() - for { - select { - case filename := <-w.fire: - if err = w.Reopen(filename); err != nil && len(w.errChan) < cap(w.errChan) { - w.errChan <- err - } - case b := <-w.queue: - if _, err = w.file.Write(b); err != nil && len(w.errChan) < cap(w.errChan) { - w.errChan <- err - } - _asyncBufferPool.Put(&b) - case <-w.ctx: - return - } - } -} - -func (w *Writer) DoRemove() { - file := <-w.rollingfilech - if err := os.Remove(file); err != nil { - log.Println("error in remove log file", file, err) - } -} - -func (w *Writer) Write(b []byte) (int, error) { - var ok = false - for !ok { - select { - case filename := <-w.fire: - if err := w.Reopen(filename); err != nil { - return 0, err - } - default: - ok = true - } - } - - fp := atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&w.file))) - file := (*os.File)(fp) - return file.Write(b) -} - -func (w *Writer) Reopen(file string) error { - fileInfo, err := w.file.Stat() - if err != nil { - return err - } - - if fileInfo.Size() == 0 { - return nil - } - - w.file.Close() - if err := os.Rename(w.absPath, file); err != nil { - return err - } - newFile, err := os.OpenFile(w.absPath, DefaultFileFlag, DefaultFileMode) - if err != nil { - return err - } - - w.file = newFile - - go func() { - if w.cf.MaxRemain > 0 { - retry: - select { - case w.rollingfilech <- file: - default: - w.DoRemove() - goto retry - } - } - }() - return nil -} diff --git a/backend/middleware/demo_handle.go b/backend/middleware/demo_handle.go deleted file mode 100644 index b18240ec2..000000000 --- a/backend/middleware/demo_handle.go +++ /dev/null @@ -1,57 +0,0 @@ -package middleware - -import ( - "net/http" - "strings" - - "github.com/1Panel-dev/1Panel/backend/app/dto" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -var whiteUrlList = map[string]struct{}{ - "/api/v1/auth/login": {}, - "/api/v1/websites/config": {}, - "/api/v1/websites/waf/config": {}, - "/api/v1/files/loadfile": {}, - "/api/v1/files/size": {}, - "/api/v1/logs/operation": {}, - "/api/v1/logs/login": {}, - "/api/v1/auth/logout": {}, - - "/api/v1/apps/installed/loadport": {}, - "/api/v1/apps/installed/check": {}, - "/api/v1/apps/installed/conninfo": {}, - "/api/v1/databases/load/file": {}, - "/api/v1/databases/variables": {}, - "/api/v1/databases/status": {}, - "/api/v1/databases/baseinfo": {}, - - "/api/v1/waf/attack/stat": {}, - "/api/v1/waf/config/website": {}, - - "/api/v1/monitor/stat": {}, - "/api/v1/monitor/visitors": {}, - "/api/v1/monitor/visitors/loc": {}, - "/api/v1/monitor/qps": {}, -} - -func DemoHandle() gin.HandlerFunc { - return func(c *gin.Context) { - if strings.Contains(c.Request.URL.Path, "search") || c.Request.Method == http.MethodGet { - c.Next() - return - } - if _, ok := whiteUrlList[c.Request.URL.Path]; ok { - c.Next() - return - } - - c.JSON(http.StatusInternalServerError, dto.Response{ - Code: http.StatusInternalServerError, - Message: buserr.New(constant.ErrDemoEnvironment).Error(), - }) - c.Abort() - } -} diff --git a/backend/middleware/helper.go b/backend/middleware/helper.go deleted file mode 100644 index b25c99907..000000000 --- a/backend/middleware/helper.go +++ /dev/null @@ -1,32 +0,0 @@ -package middleware - -import ( - "net/http" - - "github.com/1Panel-dev/1Panel/backend/app/repo" -) - -func LoadErrCode(errInfo string) int { - settingRepo := repo.NewISettingRepo() - codeVal, err := settingRepo.Get(settingRepo.WithByKey("NoAuthSetting")) - if err != nil { - return 500 - } - - switch codeVal.Value { - case "400": - return http.StatusBadRequest - case "401": - return http.StatusUnauthorized - case "403": - return http.StatusForbidden - case "404": - return http.StatusNotFound - case "408": - return http.StatusRequestTimeout - case "416": - return http.StatusRequestedRangeNotSatisfiable - default: - return http.StatusOK - } -} diff --git a/backend/middleware/loading.go b/backend/middleware/loading.go deleted file mode 100644 index eccb30931..000000000 --- a/backend/middleware/loading.go +++ /dev/null @@ -1,24 +0,0 @@ -package middleware - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/repo" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -func GlobalLoading() gin.HandlerFunc { - return func(c *gin.Context) { - settingRepo := repo.NewISettingRepo() - status, err := settingRepo.Get(settingRepo.WithByKey("SystemStatus")) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - if status.Value != "Free" { - helper.ErrorWithDetail(c, constant.CodeGlobalLoading, status.Value, err) - return - } - c.Next() - } -} diff --git a/backend/router/common.go b/backend/router/common.go deleted file mode 100644 index b96153767..000000000 --- a/backend/router/common.go +++ /dev/null @@ -1,26 +0,0 @@ -package router - -func commonGroups() []CommonRouter { - return []CommonRouter{ - &DashboardRouter{}, - &HostRouter{}, - &ContainerRouter{}, - &LogRouter{}, - &FileRouter{}, - &ToolboxRouter{}, - &TerminalRouter{}, - &CronjobRouter{}, - &SettingRouter{}, - &AppRouter{}, - &WebsiteRouter{}, - &WebsiteGroupRouter{}, - &WebsiteDnsAccountRouter{}, - &WebsiteAcmeAccountRouter{}, - &WebsiteSSLRouter{}, - &DatabaseRouter{}, - &NginxRouter{}, - &RuntimeRouter{}, - &ProcessRouter{}, - &WebsiteCARouter{}, - } -} diff --git a/backend/router/entry.go b/backend/router/entry.go deleted file mode 100644 index 49ed25fd1..000000000 --- a/backend/router/entry.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build !xpack - -package router - -func RouterGroups() []CommonRouter { - return commonGroups() -} - -var RouterGroupApp = RouterGroups() diff --git a/backend/router/ro_app.go b/backend/router/ro_app.go deleted file mode 100644 index 12877f54c..000000000 --- a/backend/router/ro_app.go +++ /dev/null @@ -1,41 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - "github.com/gin-gonic/gin" -) - -type AppRouter struct { -} - -func (a *AppRouter) InitRouter(Router *gin.RouterGroup) { - appRouter := Router.Group("apps") - - baseApi := v1.ApiGroupApp.BaseApi - { - appRouter.POST("/sync", baseApi.SyncApp) - appRouter.GET("/checkupdate", baseApi.GetAppListUpdate) - appRouter.POST("/search", baseApi.SearchApp) - appRouter.GET("/:key", baseApi.GetApp) - appRouter.GET("/detail/:appId/:version/:type", baseApi.GetAppDetail) - appRouter.GET("/details/:id", baseApi.GetAppDetailByID) - appRouter.POST("/install", baseApi.InstallApp) - appRouter.GET("/tags", baseApi.GetAppTags) - appRouter.POST("/installed/check", baseApi.CheckAppInstalled) - appRouter.POST("/installed/loadport", baseApi.LoadPort) - appRouter.POST("/installed/conninfo", baseApi.LoadConnInfo) - appRouter.GET("/installed/delete/check/:appInstallId", baseApi.DeleteCheck) - appRouter.POST("/installed/search", baseApi.SearchAppInstalled) - appRouter.GET("/installed/list", baseApi.ListAppInstalled) - appRouter.POST("/installed/op", baseApi.OperateInstalled) - appRouter.POST("/installed/sync", baseApi.SyncInstalled) - appRouter.POST("/installed/port/change", baseApi.ChangeAppPort) - appRouter.GET("/services/:key", baseApi.GetServices) - appRouter.POST("/installed/conf", baseApi.GetDefaultConfig) - appRouter.GET("/installed/params/:appInstallId", baseApi.GetParams) - appRouter.POST("/installed/params/update", baseApi.UpdateInstalled) - appRouter.POST("/installed/ignore", baseApi.IgnoreUpgrade) - appRouter.GET("/ignored/detail", baseApi.GetIgnoredApp) - appRouter.POST("/installed/update/versions", baseApi.GetUpdateVersions) - } -} diff --git a/backend/router/ro_container.go b/backend/router/ro_container.go deleted file mode 100644 index 33e591851..000000000 --- a/backend/router/ro_container.go +++ /dev/null @@ -1,84 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - "github.com/gin-gonic/gin" -) - -type ContainerRouter struct{} - -func (s *ContainerRouter) InitRouter(Router *gin.RouterGroup) { - baRouter := Router.Group("containers") - baseApi := v1.ApiGroupApp.BaseApi - { - baRouter.GET("/exec", baseApi.ContainerWsSsh) - baRouter.GET("/stats/:id", baseApi.ContainerStats) - - baRouter.POST("", baseApi.ContainerCreate) - baRouter.POST("/update", baseApi.ContainerUpdate) - baRouter.POST("/upgrade", baseApi.ContainerUpgrade) - baRouter.POST("/info", baseApi.ContainerInfo) - baRouter.POST("/search", baseApi.SearchContainer) - baRouter.POST("/list", baseApi.ListContainer) - baRouter.GET("/list/stats", baseApi.ContainerListStats) - baRouter.GET("/search/log", baseApi.ContainerLogs) - baRouter.POST("/download/log", baseApi.DownloadContainerLogs) - baRouter.GET("/limit", baseApi.LoadResourceLimit) - baRouter.POST("/clean/log", baseApi.CleanContainerLog) - baRouter.POST("/load/log", baseApi.LoadContainerLog) - baRouter.POST("/inspect", baseApi.Inspect) - baRouter.POST("/rename", baseApi.ContainerRename) - baRouter.POST("/commit", baseApi.ContainerCommit) - baRouter.POST("/operate", baseApi.ContainerOperation) - baRouter.POST("/prune", baseApi.ContainerPrune) - - baRouter.GET("/repo", baseApi.ListRepo) - baRouter.POST("/repo/status", baseApi.CheckRepoStatus) - baRouter.POST("/repo/search", baseApi.SearchRepo) - baRouter.POST("/repo/update", baseApi.UpdateRepo) - baRouter.POST("/repo", baseApi.CreateRepo) - baRouter.POST("/repo/del", baseApi.DeleteRepo) - - baRouter.POST("/compose/search", baseApi.SearchCompose) - baRouter.POST("/compose", baseApi.CreateCompose) - baRouter.POST("/compose/test", baseApi.TestCompose) - baRouter.POST("/compose/operate", baseApi.OperatorCompose) - baRouter.POST("/compose/update", baseApi.ComposeUpdate) - baRouter.GET("/compose/search/log", baseApi.ComposeLogs) - - baRouter.GET("/template", baseApi.ListComposeTemplate) - baRouter.POST("/template/search", baseApi.SearchComposeTemplate) - baRouter.POST("/template/update", baseApi.UpdateComposeTemplate) - baRouter.POST("/template", baseApi.CreateComposeTemplate) - baRouter.POST("/template/del", baseApi.DeleteComposeTemplate) - - baRouter.GET("/image", baseApi.ListImage) - baRouter.GET("/image/all", baseApi.ListAllImage) - baRouter.POST("/image/search", baseApi.SearchImage) - baRouter.POST("/image/pull", baseApi.ImagePull) - baRouter.POST("/image/push", baseApi.ImagePush) - baRouter.POST("/image/save", baseApi.ImageSave) - baRouter.POST("/image/load", baseApi.ImageLoad) - baRouter.POST("/image/remove", baseApi.ImageRemove) - baRouter.POST("/image/tag", baseApi.ImageTag) - baRouter.POST("/image/build", baseApi.ImageBuild) - - baRouter.GET("/network", baseApi.ListNetwork) - baRouter.POST("/network/del", baseApi.DeleteNetwork) - baRouter.POST("/network/search", baseApi.SearchNetwork) - baRouter.POST("/network", baseApi.CreateNetwork) - baRouter.GET("/volume", baseApi.ListVolume) - baRouter.POST("/volume/del", baseApi.DeleteVolume) - baRouter.POST("/volume/search", baseApi.SearchVolume) - baRouter.POST("/volume", baseApi.CreateVolume) - - baRouter.GET("/daemonjson", baseApi.LoadDaemonJson) - baRouter.GET("/daemonjson/file", baseApi.LoadDaemonJsonFile) - baRouter.GET("/docker/status", baseApi.LoadDockerStatus) - baRouter.POST("/docker/operate", baseApi.OperateDocker) - baRouter.POST("/daemonjson/update", baseApi.UpdateDaemonJson) - baRouter.POST("/logoption/update", baseApi.UpdateLogOption) - baRouter.POST("/ipv6option/update", baseApi.UpdateIpv6Option) - baRouter.POST("/daemonjson/update/byfile", baseApi.UpdateDaemonJsonByFile) - } -} diff --git a/backend/router/ro_cronjob.go b/backend/router/ro_cronjob.go deleted file mode 100644 index 672ff36a5..000000000 --- a/backend/router/ro_cronjob.go +++ /dev/null @@ -1,26 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - - "github.com/gin-gonic/gin" -) - -type CronjobRouter struct{} - -func (s *CronjobRouter) InitRouter(Router *gin.RouterGroup) { - cmdRouter := Router.Group("cronjobs") - baseApi := v1.ApiGroupApp.BaseApi - { - cmdRouter.POST("", baseApi.CreateCronjob) - cmdRouter.POST("/del", baseApi.DeleteCronjob) - cmdRouter.POST("/update", baseApi.UpdateCronjob) - cmdRouter.POST("/status", baseApi.UpdateCronjobStatus) - cmdRouter.POST("/handle", baseApi.HandleOnce) - cmdRouter.POST("/download", baseApi.TargetDownload) - cmdRouter.POST("/search", baseApi.SearchCronjob) - cmdRouter.POST("/search/records", baseApi.SearchJobRecords) - cmdRouter.POST("/records/log", baseApi.LoadRecordLog) - cmdRouter.POST("/records/clean", baseApi.CleanRecord) - } -} diff --git a/backend/router/ro_dashboard.go b/backend/router/ro_dashboard.go deleted file mode 100644 index 1445e6180..000000000 --- a/backend/router/ro_dashboard.go +++ /dev/null @@ -1,20 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - - "github.com/gin-gonic/gin" -) - -type DashboardRouter struct{} - -func (s *DashboardRouter) InitRouter(Router *gin.RouterGroup) { - cmdRouter := Router.Group("dashboard") - baseApi := v1.ApiGroupApp.BaseApi - { - cmdRouter.GET("/base/os", baseApi.LoadDashboardOsInfo) - cmdRouter.GET("/base/:ioOption/:netOption", baseApi.LoadDashboardBaseInfo) - cmdRouter.GET("/current/:ioOption/:netOption", baseApi.LoadDashboardCurrentInfo) - cmdRouter.POST("/system/restart/:operation", baseApi.SystemRestart) - } -} diff --git a/backend/router/ro_database.go b/backend/router/ro_database.go deleted file mode 100644 index e2dd4e016..000000000 --- a/backend/router/ro_database.go +++ /dev/null @@ -1,64 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - - "github.com/gin-gonic/gin" -) - -type DatabaseRouter struct{} - -func (s *DatabaseRouter) InitRouter(Router *gin.RouterGroup) { - cmdRouter := Router.Group("databases") - baseApi := v1.ApiGroupApp.BaseApi - { - cmdRouter.POST("/common/info", baseApi.LoadDBBaseInfo) - cmdRouter.POST("/common/load/file", baseApi.LoadDBFile) - cmdRouter.POST("/common/update/conf", baseApi.UpdateDBConfByFile) - - cmdRouter.POST("", baseApi.CreateMysql) - cmdRouter.POST("/bind", baseApi.BindUser) - cmdRouter.POST("load", baseApi.LoadDBFromRemote) - cmdRouter.POST("/change/access", baseApi.ChangeMysqlAccess) - cmdRouter.POST("/change/password", baseApi.ChangeMysqlPassword) - cmdRouter.POST("/del/check", baseApi.DeleteCheckMysql) - cmdRouter.POST("/del", baseApi.DeleteMysql) - cmdRouter.POST("/description/update", baseApi.UpdateMysqlDescription) - cmdRouter.POST("/variables/update", baseApi.UpdateMysqlVariables) - cmdRouter.POST("/search", baseApi.SearchMysql) - cmdRouter.POST("/variables", baseApi.LoadVariables) - cmdRouter.POST("/status", baseApi.LoadStatus) - cmdRouter.POST("/remote", baseApi.LoadRemoteAccess) - cmdRouter.GET("/options", baseApi.ListDBName) - - cmdRouter.POST("/redis/persistence/conf", baseApi.LoadPersistenceConf) - cmdRouter.POST("/redis/status", baseApi.LoadRedisStatus) - cmdRouter.POST("/redis/conf", baseApi.LoadRedisConf) - cmdRouter.GET("/redis/exec", baseApi.RedisWsSsh) - cmdRouter.GET("/redis/check", baseApi.CheckHasCli) - cmdRouter.POST("/redis/install/cli", baseApi.InstallCli) - cmdRouter.POST("/redis/password", baseApi.ChangeRedisPassword) - cmdRouter.POST("/redis/conf/update", baseApi.UpdateRedisConf) - cmdRouter.POST("/redis/persistence/update", baseApi.UpdateRedisPersistenceConf) - - cmdRouter.POST("/db/check", baseApi.CheckDatabase) - cmdRouter.POST("/db", baseApi.CreateDatabase) - cmdRouter.GET("/db/:name", baseApi.GetDatabase) - cmdRouter.GET("/db/list/:type", baseApi.ListDatabase) - cmdRouter.GET("/db/item/:type", baseApi.LoadDatabaseItems) - cmdRouter.POST("/db/update", baseApi.UpdateDatabase) - cmdRouter.POST("/db/search", baseApi.SearchDatabase) - cmdRouter.POST("/db/del/check", baseApi.DeleteCheckDatabase) - cmdRouter.POST("/db/del", baseApi.DeleteDatabase) - - cmdRouter.POST("/pg", baseApi.CreatePostgresql) - cmdRouter.POST("/pg/search", baseApi.SearchPostgresql) - cmdRouter.POST("/pg/:database/load", baseApi.LoadPostgresqlDBFromRemote) - cmdRouter.POST("/pg/bind", baseApi.BindPostgresqlUser) - cmdRouter.POST("/pg/del/check", baseApi.DeleteCheckPostgresql) - cmdRouter.POST("/pg/del", baseApi.DeletePostgresql) - cmdRouter.POST("/pg/privileges", baseApi.ChangePostgresqlPrivileges) - cmdRouter.POST("/pg/password", baseApi.ChangePostgresqlPassword) - cmdRouter.POST("/pg/description", baseApi.UpdatePostgresqlDescription) - } -} diff --git a/backend/router/ro_file.go b/backend/router/ro_file.go deleted file mode 100644 index 78fba28ce..000000000 --- a/backend/router/ro_file.go +++ /dev/null @@ -1,51 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - "github.com/gin-gonic/gin" -) - -type FileRouter struct { -} - -func (f *FileRouter) InitRouter(Router *gin.RouterGroup) { - fileRouter := Router.Group("files") - baseApi := v1.ApiGroupApp.BaseApi - { - fileRouter.POST("/search", baseApi.ListFiles) - fileRouter.POST("/upload/search", baseApi.SearchUploadWithPage) - fileRouter.POST("/tree", baseApi.GetFileTree) - fileRouter.POST("", baseApi.CreateFile) - fileRouter.POST("/del", baseApi.DeleteFile) - fileRouter.POST("/batch/del", baseApi.BatchDeleteFile) - fileRouter.POST("/mode", baseApi.ChangeFileMode) - fileRouter.POST("/owner", baseApi.ChangeFileOwner) - fileRouter.POST("/compress", baseApi.CompressFile) - fileRouter.POST("/decompress", baseApi.DeCompressFile) - fileRouter.POST("/content", baseApi.GetContent) - fileRouter.POST("/save", baseApi.SaveContent) - fileRouter.POST("/check", baseApi.CheckFile) - fileRouter.POST("/upload", baseApi.UploadFiles) - fileRouter.POST("/chunkupload", baseApi.UploadChunkFiles) - fileRouter.POST("/rename", baseApi.ChangeFileName) - fileRouter.POST("/wget", baseApi.WgetFile) - fileRouter.POST("/move", baseApi.MoveFile) - fileRouter.GET("/download", baseApi.Download) - fileRouter.POST("/chunkdownload", baseApi.DownloadChunkFiles) - fileRouter.POST("/size", baseApi.Size) - fileRouter.GET("/ws", baseApi.Ws) - fileRouter.GET("/keys", baseApi.Keys) - fileRouter.POST("/read", baseApi.ReadFileByLine) - fileRouter.POST("/batch/role", baseApi.BatchChangeModeAndOwner) - - fileRouter.POST("/recycle/search", baseApi.SearchRecycleBinFile) - fileRouter.POST("/recycle/reduce", baseApi.ReduceRecycleBinFile) - fileRouter.POST("/recycle/clear", baseApi.ClearRecycleBinFile) - fileRouter.GET("/recycle/status", baseApi.GetRecycleStatus) - - fileRouter.POST("/favorite/search", baseApi.SearchFavorite) - fileRouter.POST("/favorite", baseApi.CreateFavorite) - fileRouter.POST("/favorite/del", baseApi.DeleteFavorite) - - } -} diff --git a/backend/router/ro_group.go b/backend/router/ro_group.go deleted file mode 100644 index aefcdee40..000000000 --- a/backend/router/ro_group.go +++ /dev/null @@ -1,21 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - "github.com/gin-gonic/gin" -) - -type WebsiteGroupRouter struct { -} - -func (a *WebsiteGroupRouter) InitRouter(Router *gin.RouterGroup) { - groupRouter := Router.Group("groups") - - baseApi := v1.ApiGroupApp.BaseApi - { - groupRouter.POST("", baseApi.CreateGroup) - groupRouter.POST("/del", baseApi.DeleteGroup) - groupRouter.POST("/update", baseApi.UpdateGroup) - groupRouter.POST("/search", baseApi.ListGroup) - } -} diff --git a/backend/router/ro_host.go b/backend/router/ro_host.go deleted file mode 100644 index 1405b2014..000000000 --- a/backend/router/ro_host.go +++ /dev/null @@ -1,70 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - - "github.com/gin-gonic/gin" -) - -type HostRouter struct{} - -func (s *HostRouter) InitRouter(Router *gin.RouterGroup) { - hostRouter := Router.Group("hosts") - baseApi := v1.ApiGroupApp.BaseApi - { - hostRouter.POST("", baseApi.CreateHost) - hostRouter.POST("/del", baseApi.DeleteHost) - hostRouter.POST("/update", baseApi.UpdateHost) - hostRouter.POST("/update/group", baseApi.UpdateHostGroup) - hostRouter.POST("/search", baseApi.SearchHost) - hostRouter.POST("/tree", baseApi.HostTree) - hostRouter.POST("/test/byinfo", baseApi.TestByInfo) - hostRouter.POST("/test/byid/:id", baseApi.TestByID) - - hostRouter.GET("/firewall/base", baseApi.LoadFirewallBaseInfo) - hostRouter.POST("/firewall/search", baseApi.SearchFirewallRule) - hostRouter.POST("/firewall/operate", baseApi.OperateFirewall) - hostRouter.POST("/firewall/port", baseApi.OperatePortRule) - hostRouter.POST("/firewall/forward", baseApi.OperateForwardRule) - hostRouter.POST("/firewall/ip", baseApi.OperateIPRule) - hostRouter.POST("/firewall/batch", baseApi.BatchOperateRule) - hostRouter.POST("/firewall/update/port", baseApi.UpdatePortRule) - hostRouter.POST("/firewall/update/addr", baseApi.UpdateAddrRule) - hostRouter.POST("/firewall/update/description", baseApi.UpdateFirewallDescription) - - hostRouter.POST("/monitor/search", baseApi.LoadMonitor) - hostRouter.POST("/monitor/clean", baseApi.CleanMonitor) - hostRouter.GET("/monitor/netoptions", baseApi.GetNetworkOptions) - hostRouter.GET("/monitor/iooptions", baseApi.GetIOOptions) - - hostRouter.GET("/ssh/conf", baseApi.LoadSSHConf) - hostRouter.POST("/ssh/search", baseApi.GetSSHInfo) - hostRouter.POST("/ssh/update", baseApi.UpdateSSH) - hostRouter.POST("/ssh/generate", baseApi.GenerateSSH) - hostRouter.POST("/ssh/secret", baseApi.LoadSSHSecret) - hostRouter.POST("/ssh/log", baseApi.LoadSSHLogs) - hostRouter.POST("/ssh/conffile/update", baseApi.UpdateSSHByfile) - hostRouter.POST("/ssh/operate", baseApi.OperateSSH) - - hostRouter.GET("/command", baseApi.ListCommand) - hostRouter.POST("/command", baseApi.CreateCommand) - hostRouter.POST("/command/del", baseApi.DeleteCommand) - hostRouter.POST("/command/search", baseApi.SearchCommand) - hostRouter.GET("/command/tree", baseApi.SearchCommandTree) - hostRouter.POST("/command/update", baseApi.UpdateCommand) - - hostRouter.GET("/command/redis", baseApi.ListRedisCommand) - hostRouter.POST("/command/redis", baseApi.SaveRedisCommand) - hostRouter.POST("/command/redis/search", baseApi.SearchRedisCommand) - hostRouter.POST("/command/redis/del", baseApi.DeleteRedisCommand) - - hostRouter.POST("/tool", baseApi.GetToolStatus) - hostRouter.POST("/tool/init", baseApi.InitToolConfig) - hostRouter.POST("/tool/operate", baseApi.OperateTool) - hostRouter.POST("/tool/config", baseApi.OperateToolConfig) - hostRouter.POST("/tool/log", baseApi.GetToolLog) - hostRouter.POST("/tool/supervisor/process", baseApi.OperateProcess) - hostRouter.GET("/tool/supervisor/process", baseApi.GetProcess) - hostRouter.POST("/tool/supervisor/process/file", baseApi.GetProcessFile) - } -} diff --git a/backend/router/ro_log.go b/backend/router/ro_log.go deleted file mode 100644 index 1bb372ad7..000000000 --- a/backend/router/ro_log.go +++ /dev/null @@ -1,18 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - - "github.com/gin-gonic/gin" -) - -type LogRouter struct{} - -func (s *LogRouter) InitRouter(Router *gin.RouterGroup) { - operationRouter := Router.Group("logs") - baseApi := v1.ApiGroupApp.BaseApi - { - operationRouter.GET("/system/files", baseApi.GetSystemFiles) - operationRouter.POST("/system", baseApi.GetSystemLogs) - } -} diff --git a/backend/router/ro_nginx.go b/backend/router/ro_nginx.go deleted file mode 100644 index 38bf3825a..000000000 --- a/backend/router/ro_nginx.go +++ /dev/null @@ -1,23 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - "github.com/gin-gonic/gin" -) - -type NginxRouter struct { -} - -func (a *NginxRouter) InitRouter(Router *gin.RouterGroup) { - groupRouter := Router.Group("openresty") - - baseApi := v1.ApiGroupApp.BaseApi - { - groupRouter.GET("", baseApi.GetNginx) - groupRouter.POST("/scope", baseApi.GetNginxConfigByScope) - groupRouter.POST("/update", baseApi.UpdateNginxConfigByScope) - groupRouter.GET("/status", baseApi.GetNginxStatus) - groupRouter.POST("/file", baseApi.UpdateNginxFile) - groupRouter.POST("/clear", baseApi.ClearNginxProxyCache) - } -} diff --git a/backend/router/ro_process.go b/backend/router/ro_process.go deleted file mode 100644 index d077ff8ae..000000000 --- a/backend/router/ro_process.go +++ /dev/null @@ -1,18 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - "github.com/gin-gonic/gin" -) - -type ProcessRouter struct { -} - -func (f *ProcessRouter) InitRouter(Router *gin.RouterGroup) { - processRouter := Router.Group("process") - baseApi := v1.ApiGroupApp.BaseApi - { - processRouter.GET("/ws", baseApi.ProcessWs) - processRouter.POST("/stop", baseApi.StopProcess) - } -} diff --git a/backend/router/ro_router.go b/backend/router/ro_router.go deleted file mode 100644 index 58a52dce0..000000000 --- a/backend/router/ro_router.go +++ /dev/null @@ -1,7 +0,0 @@ -package router - -import "github.com/gin-gonic/gin" - -type CommonRouter interface { - InitRouter(Router *gin.RouterGroup) -} diff --git a/backend/router/ro_runtime.go b/backend/router/ro_runtime.go deleted file mode 100644 index 6e35b89ff..000000000 --- a/backend/router/ro_runtime.go +++ /dev/null @@ -1,35 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - "github.com/gin-gonic/gin" -) - -type RuntimeRouter struct { -} - -func (r *RuntimeRouter) InitRouter(Router *gin.RouterGroup) { - groupRouter := Router.Group("runtimes") - - baseApi := v1.ApiGroupApp.BaseApi - { - groupRouter.GET("/installed/delete/check/:runTimeId", baseApi.DeleteRuntimeCheck) - groupRouter.POST("/search", baseApi.SearchRuntimes) - groupRouter.POST("", baseApi.CreateRuntime) - groupRouter.POST("/del", baseApi.DeleteRuntime) - groupRouter.POST("/update", baseApi.UpdateRuntime) - groupRouter.GET("/:id", baseApi.GetRuntime) - groupRouter.POST("/sync", baseApi.SyncStatus) - - groupRouter.POST("/node/package", baseApi.GetNodePackageRunScript) - groupRouter.POST("/operate", baseApi.OperateRuntime) - groupRouter.POST("/node/modules", baseApi.GetNodeModules) - groupRouter.POST("/node/modules/operate", baseApi.OperateNodeModules) - - groupRouter.POST("/php/extensions/search", baseApi.PagePHPExtensions) - groupRouter.POST("/php/extensions", baseApi.CreatePHPExtensions) - groupRouter.POST("/php/extensions/update", baseApi.UpdatePHPExtensions) - groupRouter.POST("/php/extensions/del", baseApi.DeletePHPExtensions) - } - -} diff --git a/backend/router/ro_setting.go b/backend/router/ro_setting.go deleted file mode 100644 index dcb3c1eab..000000000 --- a/backend/router/ro_setting.go +++ /dev/null @@ -1,45 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - "github.com/gin-gonic/gin" -) - -type SettingRouter struct{} - -func (s *SettingRouter) InitRouter(Router *gin.RouterGroup) { - settingRouter := Router.Group("settings") - baseApi := v1.ApiGroupApp.BaseApi - { - settingRouter.POST("/search", baseApi.GetSettingInfo) - settingRouter.GET("/search/available", baseApi.GetSystemAvailable) - settingRouter.POST("/update", baseApi.UpdateSetting) - - settingRouter.POST("/snapshot", baseApi.CreateSnapshot) - settingRouter.POST("/snapshot/status", baseApi.LoadSnapShotStatus) - settingRouter.POST("/snapshot/search", baseApi.SearchSnapshot) - settingRouter.POST("/snapshot/import", baseApi.ImportSnapshot) - settingRouter.POST("/snapshot/del", baseApi.DeleteSnapshot) - settingRouter.POST("/snapshot/recover", baseApi.RecoverSnapshot) - settingRouter.POST("/snapshot/rollback", baseApi.RollbackSnapshot) - settingRouter.POST("/snapshot/description/update", baseApi.UpdateSnapDescription) - - settingRouter.GET("/backup/search", baseApi.ListBackup) - settingRouter.GET("/backup/onedrive", baseApi.LoadOneDriveInfo) - settingRouter.POST("/backup/backup", baseApi.Backup) - settingRouter.POST("/backup/refresh/onedrive", baseApi.RefreshOneDriveToken) - settingRouter.POST("/backup/recover", baseApi.Recover) - settingRouter.POST("/backup/recover/byupload", baseApi.RecoverByUpload) - settingRouter.POST("/backup/search/files", baseApi.LoadFilesFromBackup) - settingRouter.POST("/backup/buckets", baseApi.ListBuckets) - settingRouter.POST("/backup", baseApi.CreateBackup) - settingRouter.POST("/backup/del", baseApi.DeleteBackup) - settingRouter.POST("/backup/update", baseApi.UpdateBackup) - settingRouter.POST("/backup/record/search", baseApi.SearchBackupRecords) - settingRouter.POST("/backup/record/search/bycronjob", baseApi.SearchBackupRecordsByCronjob) - settingRouter.POST("/backup/record/download", baseApi.DownloadRecord) - settingRouter.POST("/backup/record/del", baseApi.DeleteBackupRecord) - - settingRouter.GET("/basedir", baseApi.LoadBaseDir) - } -} diff --git a/backend/router/ro_terminal.go b/backend/router/ro_terminal.go deleted file mode 100644 index d263c70e4..000000000 --- a/backend/router/ro_terminal.go +++ /dev/null @@ -1,17 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - - "github.com/gin-gonic/gin" -) - -type TerminalRouter struct{} - -func (s *TerminalRouter) InitRouter(Router *gin.RouterGroup) { - terminalRouter := Router.Group("terminals") - baseApi := v1.ApiGroupApp.BaseApi - { - terminalRouter.GET("", baseApi.WsSsh) - } -} diff --git a/backend/router/ro_toolbox.go b/backend/router/ro_toolbox.go deleted file mode 100644 index 8487d43dd..000000000 --- a/backend/router/ro_toolbox.go +++ /dev/null @@ -1,59 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - - "github.com/gin-gonic/gin" -) - -type ToolboxRouter struct{} - -func (s *ToolboxRouter) InitRouter(Router *gin.RouterGroup) { - toolboxRouter := Router.Group("toolbox") - baseApi := v1.ApiGroupApp.BaseApi - { - toolboxRouter.POST("/device/base", baseApi.LoadDeviceBaseInfo) - toolboxRouter.GET("/device/zone/options", baseApi.LoadTimeOption) - toolboxRouter.POST("/device/update/conf", baseApi.UpdateDeviceConf) - toolboxRouter.POST("/device/update/host", baseApi.UpdateDeviceHost) - toolboxRouter.POST("/device/update/passwd", baseApi.UpdateDevicePasswd) - toolboxRouter.POST("/device/update/swap", baseApi.UpdateDeviceSwap) - toolboxRouter.POST("/device/update/byconf", baseApi.UpdateDeviceByFile) - toolboxRouter.POST("/device/check/dns", baseApi.CheckDNS) - toolboxRouter.POST("/device/conf", baseApi.LoadDeviceConf) - - toolboxRouter.POST("/scan", baseApi.ScanSystem) - toolboxRouter.POST("/clean", baseApi.SystemClean) - - toolboxRouter.GET("/fail2ban/base", baseApi.LoadFail2BanBaseInfo) - toolboxRouter.GET("/fail2ban/load/conf", baseApi.LoadFail2BanConf) - toolboxRouter.POST("/fail2ban/search", baseApi.SearchFail2Ban) - toolboxRouter.POST("/fail2ban/operate", baseApi.OperateFail2Ban) - toolboxRouter.POST("/fail2ban/operate/sshd", baseApi.OperateSSHD) - toolboxRouter.POST("/fail2ban/update", baseApi.UpdateFail2BanConf) - toolboxRouter.POST("/fail2ban/update/byconf", baseApi.UpdateFail2BanConfByFile) - - toolboxRouter.GET("/ftp/base", baseApi.LoadFtpBaseInfo) - toolboxRouter.POST("/ftp/log/search", baseApi.LoadFtpLogInfo) - toolboxRouter.POST("/ftp/operate", baseApi.OperateFtp) - toolboxRouter.POST("/ftp/search", baseApi.SearchFtp) - toolboxRouter.POST("/ftp", baseApi.CreateFtp) - toolboxRouter.POST("/ftp/update", baseApi.UpdateFtp) - toolboxRouter.POST("/ftp/del", baseApi.DeleteFtp) - toolboxRouter.POST("/ftp/sync", baseApi.SyncFtp) - - toolboxRouter.POST("/clam/search", baseApi.SearchClam) - toolboxRouter.POST("/clam/record/search", baseApi.SearchClamRecord) - toolboxRouter.POST("/clam/record/clean", baseApi.CleanClamRecord) - toolboxRouter.POST("/clam/record/log", baseApi.LoadClamRecordLog) - toolboxRouter.POST("/clam/file/search", baseApi.SearchClamFile) - toolboxRouter.POST("/clam/file/update", baseApi.UpdateFile) - toolboxRouter.POST("/clam", baseApi.CreateClam) - toolboxRouter.POST("/clam/base", baseApi.LoadClamBaseInfo) - toolboxRouter.POST("/clam/operate", baseApi.OperateClam) - toolboxRouter.POST("/clam/update", baseApi.UpdateClam) - toolboxRouter.POST("/clam/status/update", baseApi.UpdateClamStatus) - toolboxRouter.POST("/clam/del", baseApi.DeleteClam) - toolboxRouter.POST("/clam/handle", baseApi.HandleClamScan) - } -} diff --git a/backend/router/ro_website.go b/backend/router/ro_website.go deleted file mode 100644 index 0c91907b2..000000000 --- a/backend/router/ro_website.go +++ /dev/null @@ -1,69 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - "github.com/gin-gonic/gin" -) - -type WebsiteRouter struct { -} - -func (a *WebsiteRouter) InitRouter(Router *gin.RouterGroup) { - websiteRouter := Router.Group("websites") - - baseApi := v1.ApiGroupApp.BaseApi - { - websiteRouter.POST("/search", baseApi.PageWebsite) - websiteRouter.GET("/list", baseApi.GetWebsites) - websiteRouter.POST("", baseApi.CreateWebsite) - websiteRouter.POST("/operate", baseApi.OpWebsite) - websiteRouter.POST("/log", baseApi.OpWebsiteLog) - websiteRouter.POST("/check", baseApi.CreateWebsiteCheck) - websiteRouter.GET("/options", baseApi.GetWebsiteOptions) - websiteRouter.POST("/update", baseApi.UpdateWebsite) - websiteRouter.GET("/:id", baseApi.GetWebsite) - websiteRouter.POST("/del", baseApi.DeleteWebsite) - websiteRouter.POST("/default/server", baseApi.ChangeDefaultServer) - - websiteRouter.GET("/domains/:websiteId", baseApi.GetWebDomains) - websiteRouter.POST("/domains/del", baseApi.DeleteWebDomain) - websiteRouter.POST("/domains", baseApi.CreateWebDomain) - - websiteRouter.GET("/:id/config/:type", baseApi.GetWebsiteNginx) - websiteRouter.POST("/config", baseApi.GetNginxConfig) - websiteRouter.POST("/config/update", baseApi.UpdateNginxConfig) - websiteRouter.POST("/nginx/update", baseApi.UpdateWebsiteNginxConfig) - - websiteRouter.GET("/:id/https", baseApi.GetHTTPSConfig) - websiteRouter.POST("/:id/https", baseApi.UpdateHTTPSConfig) - - websiteRouter.GET("/php/config/:id", baseApi.GetWebsitePHPConfig) - websiteRouter.POST("/php/config", baseApi.UpdateWebsitePHPConfig) - websiteRouter.POST("/php/update", baseApi.UpdatePHPFile) - websiteRouter.POST("/php/version", baseApi.ChangePHPVersion) - - websiteRouter.POST("/rewrite", baseApi.GetRewriteConfig) - websiteRouter.POST("/rewrite/update", baseApi.UpdateRewriteConfig) - - websiteRouter.POST("/dir/update", baseApi.UpdateSiteDir) - websiteRouter.POST("/dir/permission", baseApi.UpdateSiteDirPermission) - websiteRouter.POST("/dir", baseApi.GetDirConfig) - - websiteRouter.POST("/proxies", baseApi.GetProxyConfig) - websiteRouter.POST("/proxies/update", baseApi.UpdateProxyConfig) - websiteRouter.POST("/proxies/file", baseApi.UpdateProxyConfigFile) - - websiteRouter.POST("/auths", baseApi.GetAuthConfig) - websiteRouter.POST("/auths/update", baseApi.UpdateAuthConfig) - - websiteRouter.POST("/leech", baseApi.GetAntiLeech) - websiteRouter.POST("/leech/update", baseApi.UpdateAntiLeech) - - websiteRouter.POST("/redirect/update", baseApi.UpdateRedirectConfig) - websiteRouter.POST("/redirect", baseApi.GetRedirectConfig) - websiteRouter.POST("/redirect/file", baseApi.UpdateRedirectConfigFile) - - websiteRouter.GET("/default/html/:type", baseApi.GetDefaultHtml) - websiteRouter.POST("/default/html/update", baseApi.UpdateDefaultHtml) - } -} diff --git a/backend/router/ro_website_acme_account.go b/backend/router/ro_website_acme_account.go deleted file mode 100644 index f620d32d8..000000000 --- a/backend/router/ro_website_acme_account.go +++ /dev/null @@ -1,20 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - "github.com/gin-gonic/gin" -) - -type WebsiteAcmeAccountRouter struct { -} - -func (a *WebsiteAcmeAccountRouter) InitRouter(Router *gin.RouterGroup) { - groupRouter := Router.Group("websites/acme") - - baseApi := v1.ApiGroupApp.BaseApi - { - groupRouter.POST("/search", baseApi.PageWebsiteAcmeAccount) - groupRouter.POST("", baseApi.CreateWebsiteAcmeAccount) - groupRouter.POST("/del", baseApi.DeleteWebsiteAcmeAccount) - } -} diff --git a/backend/router/ro_website_ca.go b/backend/router/ro_website_ca.go deleted file mode 100644 index 5fbcc9f9c..000000000 --- a/backend/router/ro_website_ca.go +++ /dev/null @@ -1,24 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - "github.com/gin-gonic/gin" -) - -type WebsiteCARouter struct { -} - -func (a *WebsiteCARouter) InitRouter(Router *gin.RouterGroup) { - groupRouter := Router.Group("websites/ca") - - baseApi := v1.ApiGroupApp.BaseApi - { - groupRouter.POST("/search", baseApi.PageWebsiteCA) - groupRouter.POST("", baseApi.CreateWebsiteCA) - groupRouter.POST("/del", baseApi.DeleteWebsiteCA) - groupRouter.POST("/obtain", baseApi.ObtainWebsiteCA) - groupRouter.POST("/renew", baseApi.RenewWebsiteCA) - groupRouter.GET("/:id", baseApi.GetWebsiteCA) - groupRouter.POST("/download", baseApi.DownloadCAFile) - } -} diff --git a/backend/router/ro_website_dns_account.go b/backend/router/ro_website_dns_account.go deleted file mode 100644 index 8416df5c2..000000000 --- a/backend/router/ro_website_dns_account.go +++ /dev/null @@ -1,21 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - "github.com/gin-gonic/gin" -) - -type WebsiteDnsAccountRouter struct { -} - -func (a *WebsiteDnsAccountRouter) InitRouter(Router *gin.RouterGroup) { - groupRouter := Router.Group("websites/dns") - - baseApi := v1.ApiGroupApp.BaseApi - { - groupRouter.POST("/search", baseApi.PageWebsiteDnsAccount) - groupRouter.POST("", baseApi.CreateWebsiteDnsAccount) - groupRouter.POST("/update", baseApi.UpdateWebsiteDnsAccount) - groupRouter.POST("/del", baseApi.DeleteWebsiteDnsAccount) - } -} diff --git a/backend/router/ro_website_ssl.go b/backend/router/ro_website_ssl.go deleted file mode 100644 index 5664d39e0..000000000 --- a/backend/router/ro_website_ssl.go +++ /dev/null @@ -1,27 +0,0 @@ -package router - -import ( - v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" - "github.com/gin-gonic/gin" -) - -type WebsiteSSLRouter struct { -} - -func (a *WebsiteSSLRouter) InitRouter(Router *gin.RouterGroup) { - groupRouter := Router.Group("websites/ssl") - - baseApi := v1.ApiGroupApp.BaseApi - { - groupRouter.POST("/search", baseApi.PageWebsiteSSL) - groupRouter.POST("", baseApi.CreateWebsiteSSL) - groupRouter.POST("/resolve", baseApi.GetDNSResolve) - groupRouter.POST("/del", baseApi.DeleteWebsiteSSL) - groupRouter.GET("/website/:websiteId", baseApi.GetWebsiteSSLByWebsiteId) - groupRouter.GET("/:id", baseApi.GetWebsiteSSLById) - groupRouter.POST("/update", baseApi.UpdateWebsiteSSL) - groupRouter.POST("/upload", baseApi.UploadWebsiteSSL) - groupRouter.POST("/obtain", baseApi.ApplyWebsiteSSL) - groupRouter.POST("/download", baseApi.DownloadWebsiteSSL) - } -} diff --git a/backend/server/init.go b/backend/server/init.go deleted file mode 100644 index b8ed30b47..000000000 --- a/backend/server/init.go +++ /dev/null @@ -1,6 +0,0 @@ -//go:build !xpack - -package server - -func InitOthers() { -} diff --git a/backend/server/server.go b/backend/server/server.go deleted file mode 100644 index 988949dd2..000000000 --- a/backend/server/server.go +++ /dev/null @@ -1,55 +0,0 @@ -package server - -import ( - "net" - "net/http" - - "github.com/1Panel-dev/1Panel/backend/cron" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/i18n" - "github.com/1Panel-dev/1Panel/backend/init/app" - "github.com/1Panel-dev/1Panel/backend/init/business" - "github.com/1Panel-dev/1Panel/backend/init/db" - "github.com/1Panel-dev/1Panel/backend/init/hook" - "github.com/1Panel-dev/1Panel/backend/init/log" - "github.com/1Panel-dev/1Panel/backend/init/migration" - "github.com/1Panel-dev/1Panel/backend/init/router" - "github.com/1Panel-dev/1Panel/backend/init/validator" - "github.com/1Panel-dev/1Panel/backend/init/viper" - - "github.com/gin-gonic/gin" -) - -func Start() { - viper.Init() - i18n.Init() - log.Init() - db.Init() - migration.Init() - app.Init() - validator.Init() - gin.SetMode("debug") - cron.Run() - InitOthers() - business.Init() - hook.Init() - - rootRouter := router.Routers() - - server := &http.Server{ - Addr: "0.0.0.0:9998", - Handler: rootRouter, - } - ln, err := net.Listen("tcp4", "0.0.0.0:9998") - if err != nil { - panic(err) - } - type tcpKeepAliveListener struct { - *net.TCPListener - } - - global.LOG.Info("listen at http://0.0.0.0:9998") - if err := server.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)}); err != nil { - panic(err) - } -} diff --git a/backend/utils/cloud_storage/client/cos.go b/backend/utils/cloud_storage/client/cos.go deleted file mode 100644 index 0184c8ed4..000000000 --- a/backend/utils/cloud_storage/client/cos.go +++ /dev/null @@ -1,142 +0,0 @@ -package client - -import ( - "context" - "fmt" - "net/http" - "net/url" - "os" - - cosSDK "github.com/tencentyun/cos-go-sdk-v5" -) - -type cosClient struct { - scType string - client *cosSDK.Client - clientWithBucket *cosSDK.Client -} - -func NewCosClient(vars map[string]interface{}) (*cosClient, error) { - region := loadParamFromVars("region", vars) - accessKey := loadParamFromVars("accessKey", vars) - secretKey := loadParamFromVars("secretKey", vars) - bucket := loadParamFromVars("bucket", vars) - scType := loadParamFromVars("scType", vars) - if len(scType) == 0 { - scType = "Standard" - } - - u, _ := url.Parse(fmt.Sprintf("https://cos.%s.myqcloud.com", region)) - b := &cosSDK.BaseURL{BucketURL: u} - client := cosSDK.NewClient(b, &http.Client{ - Transport: &cosSDK.AuthorizationTransport{ - SecretID: accessKey, - SecretKey: secretKey, - }, - }) - - if len(bucket) != 0 { - u2, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", bucket, region)) - b2 := &cosSDK.BaseURL{BucketURL: u2} - clientWithBucket := cosSDK.NewClient(b2, &http.Client{ - Transport: &cosSDK.AuthorizationTransport{ - SecretID: accessKey, - SecretKey: secretKey, - }, - }) - return &cosClient{client: client, clientWithBucket: clientWithBucket, scType: scType}, nil - } - - return &cosClient{client: client, clientWithBucket: nil, scType: scType}, nil -} - -func (c cosClient) ListBuckets() ([]interface{}, error) { - buckets, _, err := c.client.Service.Get(context.Background()) - if err != nil { - return nil, err - } - var datas []interface{} - for _, bucket := range buckets.Buckets { - datas = append(datas, bucket.Name) - } - return datas, nil -} - -func (c cosClient) Exist(path string) (bool, error) { - exist, err := c.clientWithBucket.Object.IsExist(context.Background(), path) - if err != nil { - return false, err - } - return exist, nil -} - -func (c cosClient) Size(path string) (int64, error) { - data, _, err := c.clientWithBucket.Bucket.Get(context.Background(), &cosSDK.BucketGetOptions{Prefix: path}) - if err != nil { - return 0, err - } - if len(data.Contents) == 0 { - return 0, fmt.Errorf("no such file %s", path) - } - return data.Contents[0].Size, nil -} - -func (c cosClient) Delete(path string) (bool, error) { - if _, err := c.clientWithBucket.Object.Delete(context.Background(), path); err != nil { - return false, err - } - return true, nil -} - -func (c cosClient) Upload(src, target string) (bool, error) { - fileInfo, err := os.Stat(src) - if err != nil { - return false, err - } - if fileInfo.Size() > 5368709120 { - opt := &cosSDK.MultiUploadOptions{ - OptIni: &cosSDK.InitiateMultipartUploadOptions{ - ACLHeaderOptions: nil, - ObjectPutHeaderOptions: &cosSDK.ObjectPutHeaderOptions{ - XCosStorageClass: c.scType, - }, - }, - PartSize: 200, - } - if _, _, err := c.clientWithBucket.Object.MultiUpload( - context.Background(), target, src, opt, - ); err != nil { - return false, err - } - return true, nil - } - if _, err := c.clientWithBucket.Object.PutFromFile(context.Background(), target, src, &cosSDK.ObjectPutOptions{ - ACLHeaderOptions: nil, - ObjectPutHeaderOptions: &cosSDK.ObjectPutHeaderOptions{ - XCosStorageClass: c.scType, - }, - }); err != nil { - return false, err - } - return true, nil -} - -func (c cosClient) Download(src, target string) (bool, error) { - if _, err := c.clientWithBucket.Object.Download(context.Background(), src, target, &cosSDK.MultiDownloadOptions{}); err != nil { - return false, err - } - return true, nil -} - -func (c cosClient) ListObjects(prefix string) ([]string, error) { - datas, _, err := c.clientWithBucket.Bucket.Get(context.Background(), &cosSDK.BucketGetOptions{Prefix: prefix}) - if err != nil { - return nil, err - } - - var result []string - for _, item := range datas.Contents { - result = append(result, item.Key) - } - return result, nil -} diff --git a/backend/utils/cloud_storage/client/helper.go b/backend/utils/cloud_storage/client/helper.go deleted file mode 100644 index 37ebdb359..000000000 --- a/backend/utils/cloud_storage/client/helper.go +++ /dev/null @@ -1,18 +0,0 @@ -package client - -import ( - "fmt" - - "github.com/1Panel-dev/1Panel/backend/global" -) - -func loadParamFromVars(key string, vars map[string]interface{}) string { - if _, ok := vars[key]; !ok { - if key != "bucket" && key != "port" { - global.LOG.Errorf("load param %s from vars failed, err: not exist!", key) - } - return "" - } - - return fmt.Sprintf("%v", vars[key]) -} diff --git a/backend/utils/cloud_storage/client/kodo.go b/backend/utils/cloud_storage/client/kodo.go deleted file mode 100644 index d1fcf28eb..000000000 --- a/backend/utils/cloud_storage/client/kodo.go +++ /dev/null @@ -1,122 +0,0 @@ -package client - -import ( - "context" - "strconv" - "time" - - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/qiniu/go-sdk/v7/auth" - "github.com/qiniu/go-sdk/v7/storage" -) - -type kodoClient struct { - bucket string - domain string - timeout string - auth *auth.Credentials - client *storage.BucketManager -} - -func NewKodoClient(vars map[string]interface{}) (*kodoClient, error) { - accessKey := loadParamFromVars("accessKey", vars) - secretKey := loadParamFromVars("secretKey", vars) - bucket := loadParamFromVars("bucket", vars) - domain := loadParamFromVars("domain", vars) - timeout := loadParamFromVars("timeout", vars) - if timeout == "" { - timeout = "1" - } - conn := auth.New(accessKey, secretKey) - cfg := storage.Config{ - UseHTTPS: false, - } - bucketManager := storage.NewBucketManager(conn, &cfg) - - return &kodoClient{client: bucketManager, auth: conn, bucket: bucket, domain: domain, timeout: timeout}, nil -} - -func (k kodoClient) ListBuckets() ([]interface{}, error) { - buckets, err := k.client.Buckets(true) - if err != nil { - return nil, err - } - var datas []interface{} - for _, bucket := range buckets { - datas = append(datas, bucket) - } - return datas, nil -} - -func (k kodoClient) Exist(path string) (bool, error) { - if _, err := k.client.Stat(k.bucket, path); err != nil { - return false, err - } - return true, nil -} - -func (k kodoClient) Size(path string) (int64, error) { - file, err := k.client.Stat(k.bucket, path) - if err != nil { - return 0, err - } - return file.Fsize, nil -} - -func (k kodoClient) Delete(path string) (bool, error) { - if err := k.client.Delete(k.bucket, path); err != nil { - return false, err - } - return true, nil -} - -func (k kodoClient) Upload(src, target string) (bool, error) { - - int64Value, _ := strconv.ParseInt(k.timeout, 10, 64) - unixTimestamp := int64Value * 3600 - - putPolicy := storage.PutPolicy{ - Scope: k.bucket, - Expires: uint64(unixTimestamp), - } - upToken := putPolicy.UploadToken(k.auth) - cfg := storage.Config{UseHTTPS: true, UseCdnDomains: false} - resumeUploader := storage.NewResumeUploaderV2(&cfg) - ret := storage.PutRet{} - putExtra := storage.RputV2Extra{} - if err := resumeUploader.PutFile(context.Background(), &ret, upToken, target, src, &putExtra); err != nil { - return false, err - } - return true, nil -} - -func (k kodoClient) Download(src, target string) (bool, error) { - deadline := time.Now().Add(time.Second * 3600).Unix() - privateAccessURL := storage.MakePrivateURL(k.auth, k.domain, src, deadline) - - fo := files.NewFileOp() - if err := fo.DownloadFile(privateAccessURL, target); err != nil { - return false, err - } - return true, nil -} - -func (k kodoClient) ListObjects(prefix string) ([]string, error) { - var result []string - marker := "" - for { - entries, _, nextMarker, hashNext, err := k.client.ListFiles(k.bucket, prefix, "", marker, 1000) - if err != nil { - return nil, err - } - for _, entry := range entries { - result = append(result, entry.Key) - } - if hashNext { - marker = nextMarker - } else { - break - } - } - return result, nil -} diff --git a/backend/utils/cloud_storage/client/local.go b/backend/utils/cloud_storage/client/local.go deleted file mode 100644 index 80f3e51e2..000000000 --- a/backend/utils/cloud_storage/client/local.go +++ /dev/null @@ -1,97 +0,0 @@ -package client - -import ( - "fmt" - "os" - "path" - "path/filepath" - - "github.com/1Panel-dev/1Panel/backend/utils/common" -) - -type localClient struct { - dir string -} - -func NewLocalClient(vars map[string]interface{}) (*localClient, error) { - dir := loadParamFromVars("dir", vars) - return &localClient{dir: dir}, nil -} - -func (c localClient) ListBuckets() ([]interface{}, error) { - return nil, nil -} - -func (c localClient) Exist(file string) (bool, error) { - _, err := os.Stat(path.Join(c.dir, file)) - return err == nil, err -} - -func (c localClient) Size(file string) (int64, error) { - fileInfo, err := os.Stat(path.Join(c.dir, file)) - if err != nil { - return 0, err - } - return fileInfo.Size(), nil -} - -func (c localClient) Delete(file string) (bool, error) { - if err := os.RemoveAll(path.Join(c.dir, file)); err != nil { - return false, err - } - return true, nil -} - -func (c localClient) Upload(src, target string) (bool, error) { - targetFilePath := path.Join(c.dir, target) - if _, err := os.Stat(path.Dir(targetFilePath)); err != nil { - if os.IsNotExist(err) { - if err = os.MkdirAll(path.Dir(targetFilePath), os.ModePerm); err != nil { - return false, err - } - } else { - return false, err - } - } - - if err := common.CopyFile(src, targetFilePath); err != nil { - return false, fmt.Errorf("cp file failed, err: %v", err) - } - return true, nil -} - -func (c localClient) Download(src, target string) (bool, error) { - localPath := path.Join(c.dir, src) - if _, err := os.Stat(path.Dir(target)); err != nil { - if os.IsNotExist(err) { - if err = os.MkdirAll(path.Dir(target), os.ModePerm); err != nil { - return false, err - } - } else { - return false, err - } - } - - if err := common.CopyFile(localPath, target); err != nil { - return false, fmt.Errorf("cp file failed, err: %v", err) - } - return true, nil -} - -func (c localClient) ListObjects(prefix string) ([]string, error) { - var files []string - itemPath := path.Join(c.dir, prefix) - if _, err := os.Stat(itemPath); err != nil { - return files, nil - } - if err := filepath.Walk(itemPath, func(path string, info os.FileInfo, err error) error { - if !info.IsDir() { - files = append(files, info.Name()) - } - return nil - }); err != nil { - return nil, err - } - - return files, nil -} diff --git a/backend/utils/cloud_storage/client/minio.go b/backend/utils/cloud_storage/client/minio.go deleted file mode 100644 index bedae3cfa..000000000 --- a/backend/utils/cloud_storage/client/minio.go +++ /dev/null @@ -1,149 +0,0 @@ -package client - -import ( - "context" - "crypto/tls" - "io" - "net/http" - "os" - "strings" - - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/minio/minio-go/v7" - "github.com/minio/minio-go/v7/pkg/credentials" -) - -type minIoClient struct { - bucket string - client *minio.Client -} - -func NewMinIoClient(vars map[string]interface{}) (*minIoClient, error) { - endpoint := loadParamFromVars("endpoint", vars) - accessKeyID := loadParamFromVars("accessKey", vars) - secretAccessKey := loadParamFromVars("secretKey", vars) - bucket := loadParamFromVars("bucket", vars) - ssl := strings.Split(endpoint, ":")[0] - if len(ssl) == 0 || (ssl != "https" && ssl != "http") { - return nil, constant.ErrInvalidParams - } - - secure := false - tlsConfig := &tls.Config{} - if ssl == "https" { - secure = true - tlsConfig.InsecureSkipVerify = true - } - var transport http.RoundTripper = &http.Transport{ - TLSClientConfig: tlsConfig, - } - client, err := minio.New(strings.ReplaceAll(endpoint, ssl+"://", ""), &minio.Options{ - Creds: credentials.NewStaticV4(accessKeyID, secretAccessKey, ""), - Secure: secure, - Transport: transport, - }) - if err != nil { - return nil, err - } - return &minIoClient{bucket: bucket, client: client}, nil -} - -func (m minIoClient) ListBuckets() ([]interface{}, error) { - buckets, err := m.client.ListBuckets(context.Background()) - if err != nil { - return nil, err - } - var result []interface{} - for _, bucket := range buckets { - result = append(result, bucket.Name) - } - return result, err -} - -func (m minIoClient) Exist(path string) (bool, error) { - if _, err := m.client.GetObject(context.Background(), m.bucket, path, minio.GetObjectOptions{}); err != nil { - return false, err - } - return true, nil -} - -func (m minIoClient) Size(path string) (int64, error) { - obj, err := m.client.GetObject(context.Background(), m.bucket, path, minio.GetObjectOptions{}) - if err != nil { - return 0, err - } - file, err := obj.Stat() - if err != nil { - return 0, err - } - return file.Size, nil -} - -func (m minIoClient) Delete(path string) (bool, error) { - object, err := m.client.GetObject(context.Background(), m.bucket, path, minio.GetObjectOptions{}) - if err != nil { - return false, err - } - info, err := object.Stat() - if err != nil { - return false, err - } - if err = m.client.RemoveObject(context.Background(), m.bucket, path, minio.RemoveObjectOptions{ - GovernanceBypass: true, - VersionID: info.VersionID, - }); err != nil { - return false, err - } - return true, nil -} - -func (m minIoClient) Upload(src, target string) (bool, error) { - file, err := os.Open(src) - if err != nil { - return false, err - } - defer file.Close() - - fileStat, err := file.Stat() - if err != nil { - return false, err - } - _, err = m.client.PutObject(context.Background(), m.bucket, target, file, fileStat.Size(), minio.PutObjectOptions{ContentType: "application/octet-stream"}) - if err != nil { - return false, err - } - return true, nil -} - -func (m minIoClient) Download(src, target string) (bool, error) { - object, err := m.client.GetObject(context.Background(), m.bucket, src, minio.GetObjectOptions{}) - if err != nil { - return false, err - } - defer object.Close() - localFile, err := os.Create(target) - if err != nil { - return false, err - } - defer localFile.Close() - if _, err = io.Copy(localFile, object); err != nil { - return false, err - } - return true, nil -} - -func (m minIoClient) ListObjects(prefix string) ([]string, error) { - opts := minio.ListObjectsOptions{ - Recursive: true, - Prefix: prefix, - } - - var result []string - for object := range m.client.ListObjects(context.Background(), m.bucket, opts) { - if object.Err != nil { - continue - } - result = append(result, object.Key) - } - return result, nil -} diff --git a/backend/utils/cloud_storage/client/onedrive.go b/backend/utils/cloud_storage/client/onedrive.go deleted file mode 100644 index 7ad0177d7..000000000 --- a/backend/utils/cloud_storage/client/onedrive.go +++ /dev/null @@ -1,405 +0,0 @@ -package client - -import ( - "bufio" - "bytes" - "context" - "crypto/tls" - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - "net/url" - "os" - "path" - "strconv" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/utils/files" - odsdk "github.com/goh-chunlin/go-onedrive/onedrive" - "golang.org/x/oauth2" -) - -type oneDriveClient struct { - client odsdk.Client -} - -func NewOneDriveClient(vars map[string]interface{}) (*oneDriveClient, error) { - token, err := RefreshToken("refresh_token", "accessToken", vars) - if err != nil { - return nil, err - } - isCN := loadParamFromVars("isCN", vars) - ctx := context.Background() - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: token}, - ) - tc := oauth2.NewClient(ctx, ts) - - client := odsdk.NewClient(tc) - if isCN == "true" { - client.BaseURL, _ = url.Parse("https://microsoftgraph.chinacloudapi.cn/v1.0/") - } - return &oneDriveClient{client: *client}, nil -} - -func (o oneDriveClient) ListBuckets() ([]interface{}, error) { - return nil, nil -} - -func (o oneDriveClient) Exist(path string) (bool, error) { - path = "/" + strings.TrimPrefix(path, "/") - fileID, err := o.loadIDByPath(path) - if err != nil { - return false, err - } - - return len(fileID) != 0, nil -} - -func (o oneDriveClient) Size(path string) (int64, error) { - path = "/" + strings.TrimPrefix(path, "/") - pathItem := "root:" + path - if path == "/" { - pathItem = "root" - } - req, err := o.client.NewRequest("GET", fmt.Sprintf("me/drive/%s", pathItem), nil) - if err != nil { - return 0, fmt.Errorf("new request for file id failed, err: %v", err) - } - var driveItem myDriverItem - if err := o.client.Do(context.Background(), req, false, &driveItem); err != nil { - return 0, fmt.Errorf("do request for file id failed, err: %v", err) - } - - return driveItem.Size, nil -} - -type myDriverItem struct { - Name string `json:"name"` - Id string `json:"id"` - Size int64 `json:"size"` -} - -func (o oneDriveClient) Delete(path string) (bool, error) { - path = "/" + strings.TrimPrefix(path, "/") - req, err := o.client.NewRequest("DELETE", fmt.Sprintf("me/drive/root:%s", path), nil) - if err != nil { - return false, fmt.Errorf("new request for delete file failed, err: %v \n", err) - } - if err := o.client.Do(context.Background(), req, false, nil); err != nil { - return false, fmt.Errorf("do request for delete file failed, err: %v \n", err) - } - - return true, nil -} - -func (o oneDriveClient) Upload(src, target string) (bool, error) { - target = "/" + strings.TrimPrefix(target, "/") - if _, err := o.loadIDByPath(path.Dir(target)); err != nil { - if !strings.Contains(err.Error(), "itemNotFound") { - return false, err - } - if err := o.createFolder(path.Dir(target)); err != nil { - return false, fmt.Errorf("create dir before upload failed, err: %v", err) - } - } - - ctx := context.Background() - folderID, err := o.loadIDByPath(path.Dir(target)) - if err != nil { - return false, err - } - fileInfo, err := os.Stat(src) - if err != nil { - return false, err - } - if fileInfo.IsDir() { - return false, errors.New("only file is allowed to be uploaded here") - } - var isOk bool - if fileInfo.Size() < 4*1024*1024 { - isOk, err = o.upSmall(src, folderID, fileInfo.Size()) - } else { - isOk, err = o.upBig(ctx, src, folderID, fileInfo.Size()) - } - return isOk, err -} - -func (o oneDriveClient) Download(src, target string) (bool, error) { - src = "/" + strings.TrimPrefix(src, "/") - req, err := o.client.NewRequest("GET", fmt.Sprintf("me/drive/root:%s", src), nil) - if err != nil { - return false, fmt.Errorf("new request for file id failed, err: %v", err) - } - var driveItem *odsdk.DriveItem - if err := o.client.Do(context.Background(), req, false, &driveItem); err != nil { - return false, fmt.Errorf("do request for file id failed, err: %v", err) - } - - resp, err := http.Get(driveItem.DownloadURL) - if err != nil { - return false, err - } - defer resp.Body.Close() - - out, err := os.Create(target) - if err != nil { - return false, err - } - defer out.Close() - buffer := make([]byte, 2*1024*1024) - - _, err = io.CopyBuffer(out, resp.Body, buffer) - if err != nil { - return false, err - } - - return true, nil -} - -func (o *oneDriveClient) ListObjects(prefix string) ([]string, error) { - prefix = "/" + strings.TrimPrefix(prefix, "/") - folderID, err := o.loadIDByPath(prefix) - if err != nil { - return nil, err - } - - req, err := o.client.NewRequest("GET", fmt.Sprintf("me/drive/items/%s/children", folderID), nil) - if err != nil { - return nil, fmt.Errorf("new request for list failed, err: %v", err) - } - var driveItems *odsdk.OneDriveDriveItemsResponse - if err := o.client.Do(context.Background(), req, false, &driveItems); err != nil { - return nil, fmt.Errorf("do request for list failed, err: %v", err) - } - - var itemList []string - for _, item := range driveItems.DriveItems { - itemList = append(itemList, item.Name) - } - return itemList, nil -} - -func (o *oneDriveClient) loadIDByPath(path string) (string, error) { - pathItem := "root:" + path - if path == "/" { - pathItem = "root" - } - req, err := o.client.NewRequest("GET", fmt.Sprintf("me/drive/%s", pathItem), nil) - if err != nil { - return "", fmt.Errorf("new request for file id failed, err: %v", err) - } - var driveItem *odsdk.DriveItem - if err := o.client.Do(context.Background(), req, false, &driveItem); err != nil { - return "", fmt.Errorf("do request for file id failed, err: %v", err) - } - return driveItem.Id, nil -} - -func RefreshToken(grantType string, tokenType string, varMap map[string]interface{}) (string, error) { - data := url.Values{} - isCN := loadParamFromVars("isCN", varMap) - data.Set("client_id", loadParamFromVars("client_id", varMap)) - data.Set("client_secret", loadParamFromVars("client_secret", varMap)) - if grantType == "refresh_token" { - data.Set("grant_type", "refresh_token") - data.Set("refresh_token", loadParamFromVars("refresh_token", varMap)) - } else { - data.Set("grant_type", "authorization_code") - data.Set("code", loadParamFromVars("code", varMap)) - } - data.Set("redirect_uri", loadParamFromVars("redirect_uri", varMap)) - client := &http.Client{} - url := "https://login.microsoftonline.com/common/oauth2/v2.0/token" - if isCN == "true" { - url = "https://login.chinacloudapi.cn/common/oauth2/v2.0/token" - } - req, err := http.NewRequest("POST", url, strings.NewReader(data.Encode())) - if err != nil { - return "", fmt.Errorf("new http post client for access token failed, err: %v", err) - } - req.Header.Add("Content-Type", "application/x-www-form-urlencoded") - resp, err := client.Do(req) - if err != nil { - return "", fmt.Errorf("request for access token failed, err: %v", err) - } - defer resp.Body.Close() - respBody, err := io.ReadAll(resp.Body) - if err != nil { - return "", fmt.Errorf("read data from response body failed, err: %v", err) - } - - tokenMap := map[string]interface{}{} - if err := json.Unmarshal(respBody, &tokenMap); err != nil { - return "", fmt.Errorf("unmarshal data from response body failed, err: %v", err) - } - if tokenType == "accessToken" { - accessToken, ok := tokenMap["access_token"].(string) - if !ok { - return "", errors.New("no such access token in response") - } - tokenMap = nil - return accessToken, nil - } - refreshToken, ok := tokenMap["refresh_token"].(string) - if !ok { - return "", errors.New("no such access token in response") - } - tokenMap = nil - return refreshToken, nil -} - -func (o *oneDriveClient) createFolder(parent string) error { - if _, err := o.loadIDByPath(path.Dir(parent)); err != nil { - if !strings.Contains(err.Error(), "itemNotFound") { - return err - } - _ = o.createFolder(path.Dir(parent)) - } - item2, err := o.loadIDByPath(path.Dir(parent)) - if err != nil { - return err - } - if _, err := o.client.DriveItems.CreateNewFolder(context.Background(), "", item2, path.Base(parent)); err != nil { - return err - } - return nil -} - -type NewUploadSessionCreationRequest struct { - ConflictBehavior string `json:"@microsoft.graph.conflictBehavior,omitempty"` -} -type NewUploadSessionCreationResponse struct { - UploadURL string `json:"uploadUrl"` - ExpirationDateTime string `json:"expirationDateTime"` -} -type UploadSessionUploadResponse struct { - ExpirationDateTime string `json:"expirationDateTime"` - NextExpectedRanges []string `json:"nextExpectedRanges"` - DriveItem -} -type DriveItem struct { - Name string `json:"name"` - Id string `json:"id"` - DownloadURL string `json:"@microsoft.graph.downloadUrl"` - Description string `json:"description"` - Size int64 `json:"size"` - WebURL string `json:"webUrl"` -} - -func (o *oneDriveClient) NewSessionFileUploadRequest(absoluteUrl string, grandOffset, grandTotalSize int64, byteReader *bytes.Reader) (*http.Request, error) { - apiUrl, err := o.client.BaseURL.Parse(absoluteUrl) - if err != nil { - return nil, err - } - absoluteUrl = apiUrl.String() - contentLength := byteReader.Size() - req, err := http.NewRequest("PUT", absoluteUrl, byteReader) - req.Header.Set("Content-Length", strconv.FormatInt(contentLength, 10)) - preliminaryLength := grandOffset - preliminaryRange := grandOffset + contentLength - 1 - if preliminaryRange >= grandTotalSize { - preliminaryRange = grandTotalSize - 1 - preliminaryLength = preliminaryRange - grandOffset + 1 - } - req.Header.Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", preliminaryLength, preliminaryRange, grandTotalSize)) - - return req, err -} - -func (o *oneDriveClient) upSmall(srcPath, folderID string, fileSize int64) (bool, error) { - file, err := os.Open(srcPath) - if err != nil { - return false, err - } - defer file.Close() - - buffer := make([]byte, fileSize) - _, _ = file.Read(buffer) - fileReader := bytes.NewReader(buffer) - apiURL := fmt.Sprintf("me/drive/items/%s:/%s:/content?@microsoft.graph.conflictBehavior=rename", url.PathEscape(folderID), path.Base(srcPath)) - - mimeType := files.GetMimeType(srcPath) - req, err := o.client.NewFileUploadRequest(apiURL, mimeType, fileReader) - if err != nil { - return false, err - } - var response *DriveItem - if err := o.client.Do(context.Background(), req, false, &response); err != nil { - return false, fmt.Errorf("do request for list failed, err: %v", err) - } - return true, nil -} - -func (o *oneDriveClient) upBig(ctx context.Context, srcPath, folderID string, fileSize int64) (bool, error) { - file, err := os.Open(srcPath) - if err != nil { - return false, err - } - defer file.Close() - - apiURL := fmt.Sprintf("me/drive/items/%s:/%s:/createUploadSession", url.PathEscape(folderID), path.Base(srcPath)) - sessionCreationRequestInside := NewUploadSessionCreationRequest{ - ConflictBehavior: "rename", - } - - sessionCreationRequest := struct { - Item NewUploadSessionCreationRequest `json:"item"` - DeferCommit bool `json:"deferCommit"` - }{sessionCreationRequestInside, false} - - sessionCreationReq, err := o.client.NewRequest("POST", apiURL, sessionCreationRequest) - if err != nil { - return false, err - } - - var sessionCreationResp *NewUploadSessionCreationResponse - err = o.client.Do(ctx, sessionCreationReq, false, &sessionCreationResp) - if err != nil { - return false, fmt.Errorf("session creation failed %w", err) - } - - fileSessionUploadUrl := sessionCreationResp.UploadURL - - sizePerSplit := int64(5 * 1024 * 1024) - buffer := make([]byte, 5*1024*1024) - splitCount := fileSize / sizePerSplit - if fileSize%sizePerSplit != 0 { - splitCount += 1 - } - bfReader := bufio.NewReader(file) - httpClient := http.Client{ - Timeout: time.Minute * 10, - Transport: &http.Transport{ - Proxy: http.ProxyFromEnvironment, - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - }, - } - for splitNow := int64(0); splitNow < splitCount; splitNow++ { - length, err := bfReader.Read(buffer) - if err != nil { - return false, err - } - if int64(length) < sizePerSplit { - bufferLast := buffer[:length] - buffer = bufferLast - } - sessionFileUploadReq, err := o.NewSessionFileUploadRequest(fileSessionUploadUrl, splitNow*sizePerSplit, fileSize, bytes.NewReader(buffer)) - if err != nil { - return false, err - } - res, err := httpClient.Do(sessionFileUploadReq) - if err != nil { - return false, err - } - res.Body.Close() - if res.StatusCode != 201 && res.StatusCode != 202 && res.StatusCode != 200 { - data, _ := io.ReadAll(res.Body) - return false, errors.New(string(data)) - } - } - return true, nil -} diff --git a/backend/utils/cloud_storage/client/oss.go b/backend/utils/cloud_storage/client/oss.go deleted file mode 100644 index e4fed15d7..000000000 --- a/backend/utils/cloud_storage/client/oss.go +++ /dev/null @@ -1,118 +0,0 @@ -package client - -import ( - "fmt" - - osssdk "github.com/aliyun/aliyun-oss-go-sdk/oss" -) - -type ossClient struct { - scType string - bucketStr string - client osssdk.Client -} - -func NewOssClient(vars map[string]interface{}) (*ossClient, error) { - endpoint := loadParamFromVars("endpoint", vars) - accessKey := loadParamFromVars("accessKey", vars) - secretKey := loadParamFromVars("secretKey", vars) - bucketStr := loadParamFromVars("bucket", vars) - scType := loadParamFromVars("scType", vars) - if len(scType) == 0 { - scType = "Standard" - } - client, err := osssdk.New(endpoint, accessKey, secretKey) - if err != nil { - return nil, err - } - - return &ossClient{scType: scType, bucketStr: bucketStr, client: *client}, nil -} - -func (o ossClient) ListBuckets() ([]interface{}, error) { - response, err := o.client.ListBuckets() - if err != nil { - return nil, err - } - var result []interface{} - for _, bucket := range response.Buckets { - result = append(result, bucket.Name) - } - return result, err -} - -func (o ossClient) Exist(path string) (bool, error) { - bucket, err := o.client.Bucket(o.bucketStr) - if err != nil { - return false, err - } - return bucket.IsObjectExist(path) -} - -func (o ossClient) Size(path string) (int64, error) { - bucket, err := o.client.Bucket(o.bucketStr) - if err != nil { - return 0, err - } - lor, err := bucket.ListObjectsV2(osssdk.Prefix(path)) - if err != nil { - return 0, err - } - if len(lor.Objects) == 0 { - return 0, fmt.Errorf("no such file %s", path) - } - return lor.Objects[0].Size, nil -} - -func (o ossClient) Delete(path string) (bool, error) { - bucket, err := o.client.Bucket(o.bucketStr) - if err != nil { - return false, err - } - if err := bucket.DeleteObject(path); err != nil { - return false, err - } - return true, nil -} - -func (o ossClient) Upload(src, target string) (bool, error) { - bucket, err := o.client.Bucket(o.bucketStr) - if err != nil { - return false, err - } - if err := bucket.UploadFile(target, src, - 200*1024*1024, - osssdk.Routines(5), - osssdk.Checkpoint(true, ""), - osssdk.ObjectStorageClass(osssdk.StorageClassType(o.scType))); err != nil { - return false, err - } - return true, nil -} - -func (o ossClient) Download(src, target string) (bool, error) { - bucket, err := o.client.Bucket(o.bucketStr) - if err != nil { - return false, err - } - if err := bucket.DownloadFile(src, target, 200*1024*1024, osssdk.Routines(5), osssdk.Checkpoint(true, "")); err != nil { - return false, err - } - return true, nil -} - -func (o *ossClient) ListObjects(prefix string) ([]string, error) { - bucket, err := o.client.Bucket(o.bucketStr) - if err != nil { - return nil, err - } - lor, err := bucket.ListObjectsV2(osssdk.Prefix(prefix)) - if err != nil { - return nil, err - } - var result []string - for _, obj := range lor.Objects { - result = append(result, obj.Key) - } - return result, nil -} diff --git a/backend/utils/cloud_storage/client/s3.go b/backend/utils/cloud_storage/client/s3.go deleted file mode 100644 index 9fc7ebadd..000000000 --- a/backend/utils/cloud_storage/client/s3.go +++ /dev/null @@ -1,163 +0,0 @@ -package client - -import ( - "os" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/s3" - "github.com/aws/aws-sdk-go/service/s3/s3manager" -) - -type s3Client struct { - scType string - bucket string - Sess session.Session -} - -func NewS3Client(vars map[string]interface{}) (*s3Client, error) { - accessKey := loadParamFromVars("accessKey", vars) - secretKey := loadParamFromVars("secretKey", vars) - endpoint := loadParamFromVars("endpoint", vars) - region := loadParamFromVars("region", vars) - bucket := loadParamFromVars("bucket", vars) - scType := loadParamFromVars("scType", vars) - if len(scType) == 0 { - scType = "Standard" - } - sess, err := session.NewSession(&aws.Config{ - Credentials: credentials.NewStaticCredentials(accessKey, secretKey, ""), - Endpoint: aws.String(endpoint), - Region: aws.String(region), - DisableSSL: aws.Bool(true), - S3ForcePathStyle: aws.Bool(false), - }) - if err != nil { - return nil, err - } - return &s3Client{scType: scType, bucket: bucket, Sess: *sess}, nil -} - -func (s s3Client) ListBuckets() ([]interface{}, error) { - var result []interface{} - svc := s3.New(&s.Sess) - res, err := svc.ListBuckets(nil) - if err != nil { - return nil, err - } - for _, b := range res.Buckets { - result = append(result, b.Name) - } - return result, nil -} - -func (s s3Client) Exist(path string) (bool, error) { - svc := s3.New(&s.Sess) - if _, err := svc.HeadObject(&s3.HeadObjectInput{ - Bucket: &s.bucket, - Key: &path, - }); err != nil { - if aerr, ok := err.(awserr.RequestFailure); ok { - if aerr.StatusCode() == 404 { - return false, nil - } - } else { - return false, aerr - } - } - return true, nil -} - -func (s *s3Client) Size(path string) (int64, error) { - svc := s3.New(&s.Sess) - file, err := svc.GetObject(&s3.GetObjectInput{ - Bucket: &s.bucket, - Key: &path, - }) - if err != nil { - return 0, err - } - return *file.ContentLength, nil -} - -func (s s3Client) Delete(path string) (bool, error) { - svc := s3.New(&s.Sess) - if _, err := svc.DeleteObject(&s3.DeleteObjectInput{Bucket: aws.String(s.bucket), Key: aws.String(path)}); err != nil { - return false, err - } - if err := svc.WaitUntilObjectNotExists(&s3.HeadObjectInput{ - Bucket: aws.String(s.bucket), - Key: aws.String(path), - }); err != nil { - return false, err - } - return true, nil -} - -func (s s3Client) Upload(src, target string) (bool, error) { - fileInfo, err := os.Stat(src) - if err != nil { - return false, err - } - file, err := os.Open(src) - if err != nil { - return false, err - } - defer file.Close() - - uploader := s3manager.NewUploader(&s.Sess) - if fileInfo.Size() > s3manager.MaxUploadParts*s3manager.DefaultUploadPartSize { - uploader.PartSize = fileInfo.Size() / (s3manager.MaxUploadParts - 1) - } - if _, err := uploader.Upload(&s3manager.UploadInput{ - Bucket: aws.String(s.bucket), - Key: aws.String(target), - Body: file, - StorageClass: &s.scType, - }); err != nil { - return false, err - } - return true, nil -} - -func (s s3Client) Download(src, target string) (bool, error) { - if _, err := os.Stat(target); err != nil { - if os.IsNotExist(err) { - os.Remove(target) - } else { - return false, err - } - } - file, err := os.Create(target) - if err != nil { - return false, err - } - defer file.Close() - downloader := s3manager.NewDownloader(&s.Sess) - if _, err = downloader.Download(file, &s3.GetObjectInput{ - Bucket: aws.String(s.bucket), - Key: aws.String(src), - }); err != nil { - os.Remove(target) - return false, err - } - return true, nil -} - -func (s *s3Client) ListObjects(prefix string) ([]string, error) { - svc := s3.New(&s.Sess) - var result []string - outputs, err := svc.ListObjects(&s3.ListObjectsInput{ - Bucket: &s.bucket, - Prefix: &prefix, - }) - if err != nil { - return result, err - } - for _, item := range outputs.Contents { - result = append(result, *item.Key) - } - return result, nil -} diff --git a/backend/utils/cloud_storage/client/sftp.go b/backend/utils/cloud_storage/client/sftp.go deleted file mode 100644 index d544315bf..000000000 --- a/backend/utils/cloud_storage/client/sftp.go +++ /dev/null @@ -1,206 +0,0 @@ -package client - -import ( - "fmt" - "io" - "net" - "os" - "path" - "time" - - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/pkg/sftp" - "golang.org/x/crypto/ssh" -) - -type sftpClient struct { - bucket string - connInfo string - config *ssh.ClientConfig -} - -func NewSftpClient(vars map[string]interface{}) (*sftpClient, error) { - address := loadParamFromVars("address", vars) - port := loadParamFromVars("port", vars) - if len(port) == 0 { - global.LOG.Errorf("load param port from vars failed, err: not exist!") - } - password := loadParamFromVars("password", vars) - username := loadParamFromVars("username", vars) - bucket := loadParamFromVars("bucket", vars) - - auth := []ssh.AuthMethod{ssh.Password(password)} - clientConfig := &ssh.ClientConfig{ - User: username, - Auth: auth, - Timeout: 30 * time.Second, - HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error { - return nil - }, - } - if _, err := ssh.Dial("tcp", fmt.Sprintf("%s:%s", address, port), clientConfig); err != nil { - return nil, err - } - - return &sftpClient{bucket: bucket, connInfo: fmt.Sprintf("%s:%s", address, port), config: clientConfig}, nil -} - -func (s sftpClient) Upload(src, target string) (bool, error) { - sshClient, err := ssh.Dial("tcp", s.connInfo, s.config) - if err != nil { - return false, err - } - defer sshClient.Close() - client, err := sftp.NewClient(sshClient) - if err != nil { - return false, err - } - defer client.Close() - - srcFile, err := os.Open(src) - if err != nil { - return false, err - } - defer srcFile.Close() - - targetFilePath := path.Join(s.bucket, target) - targetDir, _ := path.Split(targetFilePath) - if _, err = client.Stat(targetDir); err != nil { - if os.IsNotExist(err) { - if err = client.MkdirAll(targetDir); err != nil { - return false, err - } - } else { - return false, err - } - } - dstFile, err := client.Create(path.Join(s.bucket, target)) - if err != nil { - return false, err - } - defer dstFile.Close() - - if _, err := io.Copy(dstFile, srcFile); err != nil { - return false, err - } - return true, nil -} - -func (s sftpClient) ListBuckets() ([]interface{}, error) { - var result []interface{} - return result, nil -} - -func (s sftpClient) Download(src, target string) (bool, error) { - sshClient, err := ssh.Dial("tcp", s.connInfo, s.config) - if err != nil { - return false, err - } - client, err := sftp.NewClient(sshClient) - if err != nil { - return false, err - } - defer client.Close() - defer sshClient.Close() - - srcFile, err := client.Open(s.bucket + "/" + src) - if err != nil { - return false, err - } - defer srcFile.Close() - - dstFile, err := os.Create(target) - if err != nil { - return false, err - } - defer dstFile.Close() - - if _, err = io.Copy(dstFile, srcFile); err != nil { - return false, err - } - return true, err -} - -func (s sftpClient) Exist(filePath string) (bool, error) { - sshClient, err := ssh.Dial("tcp", s.connInfo, s.config) - if err != nil { - return false, err - } - client, err := sftp.NewClient(sshClient) - if err != nil { - return false, err - } - defer client.Close() - defer sshClient.Close() - - srcFile, err := client.Open(path.Join(s.bucket, filePath)) - if err != nil { - if os.IsNotExist(err) { - return false, nil - } else { - return false, err - } - } - defer srcFile.Close() - return true, err -} - -func (s sftpClient) Size(filePath string) (int64, error) { - sshClient, err := ssh.Dial("tcp", s.connInfo, s.config) - if err != nil { - return 0, err - } - client, err := sftp.NewClient(sshClient) - if err != nil { - return 0, err - } - defer client.Close() - defer sshClient.Close() - - files, err := client.Stat(path.Join(s.bucket, filePath)) - if err != nil { - return 0, err - } - return files.Size(), nil -} - -func (s sftpClient) Delete(filePath string) (bool, error) { - sshClient, err := ssh.Dial("tcp", s.connInfo, s.config) - if err != nil { - return false, err - } - client, err := sftp.NewClient(sshClient) - if err != nil { - return false, err - } - defer client.Close() - defer sshClient.Close() - - if err := client.Remove(path.Join(s.bucket, filePath)); err != nil { - return false, err - } - return true, nil -} - -func (s sftpClient) ListObjects(prefix string) ([]string, error) { - sshClient, err := ssh.Dial("tcp", s.connInfo, s.config) - if err != nil { - return nil, err - } - client, err := sftp.NewClient(sshClient) - if err != nil { - return nil, err - } - defer client.Close() - defer sshClient.Close() - - files, err := client.ReadDir(path.Join(s.bucket, prefix)) - if err != nil { - return nil, err - } - var result []string - for _, file := range files { - result = append(result, file.Name()) - } - return result, nil -} diff --git a/backend/utils/cloud_storage/client/webdav.go b/backend/utils/cloud_storage/client/webdav.go deleted file mode 100644 index c1013357c..000000000 --- a/backend/utils/cloud_storage/client/webdav.go +++ /dev/null @@ -1,121 +0,0 @@ -package client - -import ( - "crypto/tls" - "fmt" - "io" - "net/http" - "os" - "path" - "strings" - - "github.com/studio-b12/gowebdav" -) - -type webDAVClient struct { - Bucket string - client *gowebdav.Client -} - -func NewWebDAVClient(vars map[string]interface{}) (*webDAVClient, error) { - address := loadParamFromVars("address", vars) - port := loadParamFromVars("port", vars) - password := loadParamFromVars("password", vars) - username := loadParamFromVars("username", vars) - bucket := loadParamFromVars("bucket", vars) - - url := fmt.Sprintf("%s:%s", address, port) - if len(port) == 0 { - url = address - } - client := gowebdav.NewClient(url, username, password) - tlsConfig := &tls.Config{} - if strings.HasPrefix(address, "https") { - tlsConfig.InsecureSkipVerify = true - } - var transport http.RoundTripper = &http.Transport{ - TLSClientConfig: tlsConfig, - } - client.SetTransport(transport) - if err := client.Connect(); err != nil { - return nil, err - } - return &webDAVClient{Bucket: bucket, client: client}, nil -} - -func (s webDAVClient) Upload(src, target string) (bool, error) { - targetFilePath := path.Join(s.Bucket, target) - srcFile, err := os.Open(src) - if err != nil { - return false, err - } - defer srcFile.Close() - - if err := s.client.WriteStream(targetFilePath, srcFile, 0644); err != nil { - return false, err - } - return true, nil -} - -func (s webDAVClient) ListBuckets() ([]interface{}, error) { - var result []interface{} - return result, nil -} - -func (s webDAVClient) Download(src, target string) (bool, error) { - srcPath := path.Join(s.Bucket, src) - info, err := s.client.Stat(srcPath) - if err != nil { - return false, err - } - targetStat, err := os.Stat(target) - if err == nil { - if info.Size() == targetStat.Size() { - return true, nil - } - } - file, err := os.Create(target) - if err != nil { - return false, err - } - defer file.Close() - reader, _ := s.client.ReadStream(srcPath) - if _, err := io.Copy(file, reader); err != nil { - return false, err - } - return true, err -} - -func (s webDAVClient) Exist(pathItem string) (bool, error) { - if _, err := s.client.Stat(path.Join(s.Bucket, pathItem)); err != nil { - return false, err - } - return true, nil -} - -func (s webDAVClient) Size(pathItem string) (int64, error) { - file, err := s.client.Stat(path.Join(s.Bucket, pathItem)) - if err != nil { - return 0, err - } - return file.Size(), nil -} - -func (s webDAVClient) Delete(pathItem string) (bool, error) { - if err := s.client.Remove(path.Join(s.Bucket, pathItem)); err != nil { - return false, err - } - return true, nil -} - -func (s webDAVClient) ListObjects(prefix string) ([]string, error) { - files, err := s.client.ReadDir(path.Join(s.Bucket, prefix)) - if err != nil { - return nil, err - } - var result []string - for _, file := range files { - result = append(result, file.Name()) - } - return result, nil -} diff --git a/backend/utils/cloud_storage/cloud_storage_client.go b/backend/utils/cloud_storage/cloud_storage_client.go deleted file mode 100644 index 44412e7ba..000000000 --- a/backend/utils/cloud_storage/cloud_storage_client.go +++ /dev/null @@ -1,42 +0,0 @@ -package cloud_storage - -import ( - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/cloud_storage/client" -) - -type CloudStorageClient interface { - ListBuckets() ([]interface{}, error) - ListObjects(prefix string) ([]string, error) - Exist(path string) (bool, error) - Delete(path string) (bool, error) - Upload(src, target string) (bool, error) - Download(src, target string) (bool, error) - - Size(path string) (int64, error) -} - -func NewCloudStorageClient(backupType string, vars map[string]interface{}) (CloudStorageClient, error) { - switch backupType { - case constant.Local: - return client.NewLocalClient(vars) - case constant.S3: - return client.NewS3Client(vars) - case constant.OSS: - return client.NewOssClient(vars) - case constant.Sftp: - return client.NewSftpClient(vars) - case constant.WebDAV: - return client.NewWebDAVClient(vars) - case constant.MinIo: - return client.NewMinIoClient(vars) - case constant.Cos: - return client.NewCosClient(vars) - case constant.Kodo: - return client.NewKodoClient(vars) - case constant.OneDrive: - return client.NewOneDriveClient(vars) - default: - return nil, constant.ErrNotSupportType - } -} diff --git a/backend/utils/cmd/cmd.go b/backend/utils/cmd/cmd.go deleted file mode 100644 index 46b20fc1f..000000000 --- a/backend/utils/cmd/cmd.go +++ /dev/null @@ -1,229 +0,0 @@ -package cmd - -import ( - "bytes" - "context" - "errors" - "fmt" - "log" - "os" - "os/exec" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" -) - -func Exec(cmdStr string) (string, error) { - return ExecWithTimeOut(cmdStr, 20*time.Second) -} - -func handleErr(stdout, stderr bytes.Buffer, err error) (string, error) { - errMsg := "" - if len(stderr.String()) != 0 { - errMsg = fmt.Sprintf("stderr: %s", stderr.String()) - } - if len(stdout.String()) != 0 { - if len(errMsg) != 0 { - errMsg = fmt.Sprintf("%s; stdout: %s", errMsg, stdout.String()) - } else { - errMsg = fmt.Sprintf("stdout: %s", stdout.String()) - } - } - return errMsg, err -} - -func ExecWithTimeOut(cmdStr string, timeout time.Duration) (string, error) { - cmd := exec.Command("bash", "-c", cmdStr) - var stdout, stderr bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stderr - if err := cmd.Start(); err != nil { - return "", err - } - done := make(chan error, 1) - go func() { - done <- cmd.Wait() - }() - after := time.After(timeout) - select { - case <-after: - _ = cmd.Process.Kill() - return "", buserr.New(constant.ErrCmdTimeout) - case err := <-done: - if err != nil { - return handleErr(stdout, stderr, err) - } - } - - return stdout.String(), nil -} - -func ExecContainerScript(containerName, cmdStr string, timeout time.Duration) error { - cmdStr = fmt.Sprintf("docker exec -i %s bash -c '%s'", containerName, cmdStr) - out, err := ExecWithTimeOut(cmdStr, timeout) - if err != nil { - if out != "" { - return fmt.Errorf("%s; err: %v", out, err) - } - return err - } - return nil -} - -func ExecCronjobWithTimeOut(cmdStr, workdir, outPath string, timeout time.Duration) error { - file, err := os.OpenFile(outPath, os.O_WRONLY|os.O_CREATE, 0666) - if err != nil { - return err - } - defer file.Close() - - cmd := exec.Command("bash", "-c", cmdStr) - cmd.Dir = workdir - cmd.Stdout = file - cmd.Stderr = file - if err := cmd.Start(); err != nil { - return err - } - done := make(chan error, 1) - go func() { - done <- cmd.Wait() - }() - after := time.After(timeout) - select { - case <-after: - _ = cmd.Process.Kill() - return buserr.New(constant.ErrCmdTimeout) - case err := <-done: - if err != nil { - return err - } - } - return nil -} - -func Execf(cmdStr string, a ...interface{}) (string, error) { - cmd := exec.Command("bash", "-c", fmt.Sprintf(cmdStr, a...)) - var stdout, stderr bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stderr - err := cmd.Run() - if err != nil { - return handleErr(stdout, stderr, err) - } - return stdout.String(), nil -} - -func ExecWithCheck(name string, a ...string) (string, error) { - cmd := exec.Command(name, a...) - var stdout, stderr bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stderr - err := cmd.Run() - if err != nil { - return handleErr(stdout, stderr, err) - } - return stdout.String(), nil -} - -func ExecScript(scriptPath, workDir string) (string, error) { - cmd := exec.Command("bash", scriptPath) - var stdout, stderr bytes.Buffer - cmd.Dir = workDir - cmd.Stdout = &stdout - cmd.Stderr = &stderr - if err := cmd.Start(); err != nil { - return "", err - } - done := make(chan error, 1) - go func() { - done <- cmd.Wait() - }() - after := time.After(10 * time.Minute) - select { - case <-after: - _ = cmd.Process.Kill() - return "", buserr.New(constant.ErrCmdTimeout) - case err := <-done: - if err != nil { - return handleErr(stdout, stderr, err) - } - } - - return stdout.String(), nil -} - -func ExecCmd(cmdStr string) error { - cmd := exec.Command("bash", "-c", cmdStr) - output, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("error : %v, output: %s", err, output) - } - return nil -} - -func ExecCmdWithDir(cmdStr, workDir string) error { - cmd := exec.Command("bash", "-c", cmdStr) - cmd.Dir = workDir - output, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("error : %v, output: %s", err, output) - } - return nil -} - -func CheckIllegal(args ...string) bool { - if args == nil { - return false - } - for _, arg := range args { - if strings.Contains(arg, "&") || strings.Contains(arg, "|") || strings.Contains(arg, ";") || - strings.Contains(arg, "$") || strings.Contains(arg, "'") || strings.Contains(arg, "`") || - strings.Contains(arg, "(") || strings.Contains(arg, ")") || strings.Contains(arg, "\"") || - strings.Contains(arg, "\n") || strings.Contains(arg, "\r") || strings.Contains(arg, ">") || strings.Contains(arg, "<") { - return true - } - } - return false -} - -func HasNoPasswordSudo() bool { - cmd2 := exec.Command("sudo", "-n", "ls") - err2 := cmd2.Run() - return err2 == nil -} - -func SudoHandleCmd() string { - cmd := exec.Command("sudo", "-n", "ls") - if err := cmd.Run(); err == nil { - return "sudo " - } - return "" -} - -func Which(name string) bool { - stdout, err := Execf("which %s", name) - if err != nil || (len(strings.ReplaceAll(stdout, "\n", "")) == 0 && strings.HasPrefix(stdout, "/")) { - return false - } - return true -} - -func ExecShellWithTimeOut(cmdStr, workdir string, logger *log.Logger, timeout time.Duration) error { - ctx, cancel := context.WithTimeout(context.Background(), timeout) - defer cancel() - - cmd := exec.CommandContext(ctx, "bash", "-c", cmdStr) - cmd.Dir = workdir - cmd.Stdout = logger.Writer() - cmd.Stderr = logger.Writer() - if err := cmd.Start(); err != nil { - return err - } - err := cmd.Wait() - if errors.Is(ctx.Err(), context.DeadlineExceeded) { - return buserr.New(constant.ErrCmdTimeout) - } - return err -} diff --git a/backend/utils/common/common.go b/backend/utils/common/common.go deleted file mode 100644 index d0def7382..000000000 --- a/backend/utils/common/common.go +++ /dev/null @@ -1,327 +0,0 @@ -package common - -import ( - "crypto/rand" - "fmt" - "io" - mathRand "math/rand" - "net" - "os" - "path" - "reflect" - "regexp" - "sort" - "strconv" - "strings" - "time" - "unicode" - - "golang.org/x/net/idna" - - "github.com/1Panel-dev/1Panel/backend/utils/cmd" -) - -func CompareVersion(version1, version2 string) bool { - v1s := extractNumbers(version1) - v2s := extractNumbers(version2) - - maxLen := max(len(v1s), len(v2s)) - v1s = append(v1s, make([]string, maxLen-len(v1s))...) - v2s = append(v2s, make([]string, maxLen-len(v2s))...) - - for i := 0; i < maxLen; i++ { - v1, err1 := strconv.Atoi(v1s[i]) - v2, err2 := strconv.Atoi(v2s[i]) - if err1 != nil { - v1 = 0 - } - if err2 != nil { - v2 = 0 - } - if v1 != v2 { - return v1 > v2 - } - } - return false -} - -func ComparePanelVersion(version1, version2 string) bool { - if version1 == version2 { - return false - } - version1s := SplitStr(version1, ".", "-") - version2s := SplitStr(version2, ".", "-") - - if len(version2s) > len(version1s) { - for i := 0; i < len(version2s)-len(version1s); i++ { - version1s = append(version1s, "0") - } - } - if len(version1s) > len(version2s) { - for i := 0; i < len(version1s)-len(version2s); i++ { - version2s = append(version2s, "0") - } - } - - n := min(len(version1s), len(version2s)) - for i := 0; i < n; i++ { - if version1s[i] == version2s[i] { - continue - } else { - v1, err1 := strconv.Atoi(version1s[i]) - if err1 != nil { - return version1s[i] > version2s[i] - } - v2, err2 := strconv.Atoi(version2s[i]) - if err2 != nil { - return version1s[i] > version2s[i] - } - return v1 > v2 - } - } - return true -} - -func extractNumbers(version string) []string { - var numbers []string - start := -1 - for i, r := range version { - if isDigit(r) { - if start == -1 { - start = i - } - } else { - if start != -1 { - numbers = append(numbers, version[start:i]) - start = -1 - } - } - } - if start != -1 { - numbers = append(numbers, version[start:]) - } - return numbers -} - -func isDigit(r rune) bool { - return r >= '0' && r <= '9' -} - -func max(x, y int) int { - if x > y { - return x - } - return y -} - -func GetSortedVersions(versions []string) []string { - sort.Slice(versions, func(i, j int) bool { - return CompareVersion(versions[i], versions[j]) - }) - return versions -} - -func CopyFile(src, dst string) error { - source, err := os.Open(src) - if err != nil { - return err - } - defer source.Close() - - if path.Base(src) != path.Base(dst) { - dst = path.Join(dst, path.Base(src)) - } - if _, err := os.Stat(path.Dir(dst)); err != nil { - if os.IsNotExist(err) { - _ = os.MkdirAll(path.Dir(dst), os.ModePerm) - } - } - target, err := os.OpenFile(dst+"_temp", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) - if err != nil { - return err - } - defer target.Close() - - if _, err = io.Copy(target, source); err != nil { - return err - } - if err = os.Rename(dst+"_temp", dst); err != nil { - return err - } - return nil -} - -func IsCrossVersion(version1, version2 string) bool { - version1s := strings.Split(version1, ".") - version2s := strings.Split(version2, ".") - v1num, _ := strconv.Atoi(version1s[0]) - v2num, _ := strconv.Atoi(version2s[0]) - return v2num > v1num -} - -func GetUuid() string { - b := make([]byte, 16) - _, _ = io.ReadFull(rand.Reader, b) - b[6] = (b[6] & 0x0f) | 0x40 - b[8] = (b[8] & 0x3f) | 0x80 - return fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) -} - -var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") - -func RandStr(n int) string { - b := make([]rune, n) - for i := range b { - b[i] = letters[mathRand.Intn(len(letters))] - } - return string(b) -} - -func RandStrAndNum(n int) string { - source := mathRand.NewSource(time.Now().UnixNano()) - randGen := mathRand.New(source) - const charset = "abcdefghijklmnopqrstuvwxyz0123456789" - b := make([]byte, n) - for i := range b { - b[i] = charset[randGen.Intn(len(charset)-1)] - } - return (string(b)) -} - -func ScanPort(port int) bool { - ln, err := net.Listen("tcp", ":"+strconv.Itoa(port)) - if err != nil { - return true - } - defer ln.Close() - return false -} - -func ScanUDPPort(port int) bool { - ln, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: port}) - if err != nil { - return true - } - defer ln.Close() - return false -} - -func ScanPortWithProto(port int, proto string) bool { - if proto == "udp" { - return ScanUDPPort(port) - } - return ScanPort(port) -} - -func IsNum(s string) bool { - _, err := strconv.ParseFloat(s, 64) - return err == nil -} - -func RemoveRepeatElement(a interface{}) (ret []interface{}) { - va := reflect.ValueOf(a) - for i := 0; i < va.Len(); i++ { - if i > 0 && reflect.DeepEqual(va.Index(i-1).Interface(), va.Index(i).Interface()) { - continue - } - ret = append(ret, va.Index(i).Interface()) - } - return ret -} - -func LoadSizeUnit(value float64) string { - val := int64(value) - if val%1024 != 0 { - return fmt.Sprintf("%v", val) - } - if val > 1048576 { - return fmt.Sprintf("%vM", val/1048576) - } - if val > 1024 { - return fmt.Sprintf("%vK", val/1024) - } - return fmt.Sprintf("%v", val) -} - -func LoadSizeUnit2F(value float64) string { - if value > 1073741824 { - return fmt.Sprintf("%.2fG", value/1073741824) - } - if value > 1048576 { - return fmt.Sprintf("%.2fM", value/1048576) - } - if value > 1024 { - return fmt.Sprintf("%.2fK", value/1024) - } - return fmt.Sprintf("%.2f", value) -} - -func LoadTimeZone() string { - loc := time.Now().Location() - if _, err := time.LoadLocation(loc.String()); err != nil { - return "Asia/Shanghai" - } - return loc.String() -} -func LoadTimeZoneByCmd() string { - loc := time.Now().Location().String() - if _, err := time.LoadLocation(loc); err != nil { - loc = "Asia/Shanghai" - } - std, err := cmd.Exec("timedatectl | grep 'Time zone'") - if err != nil { - return loc - } - fields := strings.Fields(string(std)) - if len(fields) != 5 { - return loc - } - if _, err := time.LoadLocation(fields[2]); err != nil { - return loc - } - return fields[2] -} - -func IsValidDomain(domain string) bool { - pattern := `^([\w\p{Han}\-\*]{1,100}\.){1,10}([\w\p{Han}\-]{1,24}|[\w\p{Han}\-]{1,24}\.[\w\p{Han}\-]{1,24})(:\d{1,5})?$` - match, err := regexp.MatchString(pattern, domain) - if err != nil { - return false - } - return match -} - -func ContainsChinese(text string) bool { - for _, char := range text { - if unicode.Is(unicode.Han, char) { - return true - } - } - return false -} - -func PunycodeEncode(text string) (string, error) { - encoder := idna.New() - ascii, err := encoder.ToASCII(text) - if err != nil { - return "", err - } - return ascii, nil -} - -func SplitStr(str string, spi ...string) []string { - lists := []string{str} - var results []string - for _, s := range spi { - results = []string{} - for _, list := range lists { - results = append(results, strings.Split(list, s)...) - } - lists = results - } - return results -} - -func IsValidIP(ip string) bool { - return net.ParseIP(ip) != nil -} diff --git a/backend/utils/compose/compose.go b/backend/utils/compose/compose.go deleted file mode 100644 index 08ade3bba..000000000 --- a/backend/utils/compose/compose.go +++ /dev/null @@ -1,40 +0,0 @@ -package compose - -import ( - "github.com/1Panel-dev/1Panel/backend/utils/cmd" -) - -func Pull(filePath string) (string, error) { - stdout, err := cmd.Execf("docker-compose -f %s pull", filePath) - return stdout, err -} - -func Up(filePath string) (string, error) { - stdout, err := cmd.Execf("docker-compose -f %s up -d", filePath) - return stdout, err -} - -func Down(filePath string) (string, error) { - stdout, err := cmd.Execf("docker-compose -f %s down --remove-orphans", filePath) - return stdout, err -} - -func Start(filePath string) (string, error) { - stdout, err := cmd.Execf("docker-compose -f %s start", filePath) - return stdout, err -} - -func Stop(filePath string) (string, error) { - stdout, err := cmd.Execf("docker-compose -f %s stop", filePath) - return stdout, err -} - -func Restart(filePath string) (string, error) { - stdout, err := cmd.Execf("docker-compose -f %s restart", filePath) - return stdout, err -} - -func Operate(filePath, operation string) (string, error) { - stdout, err := cmd.Execf("docker-compose -f %s %s", filePath, operation) - return stdout, err -} diff --git a/backend/utils/copier/copier.go b/backend/utils/copier/copier.go deleted file mode 100644 index bfc684ce9..000000000 --- a/backend/utils/copier/copier.go +++ /dev/null @@ -1,18 +0,0 @@ -package copier - -import ( - "encoding/json" - - "github.com/pkg/errors" -) - -func Copy(to, from interface{}) error { - b, err := json.Marshal(from) - if err != nil { - return errors.Wrap(err, "marshal from data err") - } - if err = json.Unmarshal(b, to); err != nil { - return errors.Wrap(err, "unmarshal to data err") - } - return nil -} diff --git a/backend/utils/docker/compose.go b/backend/utils/docker/compose.go deleted file mode 100644 index 6b78c59a0..000000000 --- a/backend/utils/docker/compose.go +++ /dev/null @@ -1,87 +0,0 @@ -package docker - -import ( - "context" - "github.com/compose-spec/compose-go/v2/loader" - "github.com/compose-spec/compose-go/v2/types" - "github.com/docker/compose/v2/pkg/api" - "github.com/joho/godotenv" - "path" - "regexp" - "strings" -) - -type ComposeService struct { - api.Service - project *types.Project -} - -func GetComposeProject(projectName, workDir string, yml []byte, env []byte, skipNormalization bool) (*types.Project, error) { - var configFiles []types.ConfigFile - configFiles = append(configFiles, types.ConfigFile{ - Filename: "docker-compose.yml", - Content: yml}, - ) - envMap, err := godotenv.UnmarshalBytes(env) - if err != nil { - return nil, err - } - details := types.ConfigDetails{ - WorkingDir: workDir, - ConfigFiles: configFiles, - Environment: envMap, - } - projectName = strings.ToLower(projectName) - reg, _ := regexp.Compile(`[^a-z0-9_-]+`) - projectName = reg.ReplaceAllString(projectName, "") - project, err := loader.LoadWithContext(context.Background(), details, func(options *loader.Options) { - options.SetProjectName(projectName, true) - options.ResolvePaths = true - options.SkipNormalization = skipNormalization - }) - if err != nil { - return nil, err - } - project.ComposeFiles = []string{path.Join(workDir, "docker-compose.yml")} - return project, nil -} - -type ComposeProject struct { - Version string - Services map[string]Service `yaml:"services"` -} - -type Service struct { - Image string `yaml:"image"` -} - -func GetDockerComposeImages(projectName string, env, yml []byte) ([]string, error) { - var ( - configFiles []types.ConfigFile - images []string - ) - configFiles = append(configFiles, types.ConfigFile{ - Filename: "docker-compose.yml", - Content: yml}, - ) - envMap, err := godotenv.UnmarshalBytes(env) - if err != nil { - return nil, err - } - details := types.ConfigDetails{ - ConfigFiles: configFiles, - Environment: envMap, - } - - project, err := loader.LoadWithContext(context.Background(), details, func(options *loader.Options) { - options.SetProjectName(projectName, true) - options.ResolvePaths = true - }) - if err != nil { - return nil, err - } - for _, service := range project.AllServices() { - images = append(images, service.Image) - } - return images, nil -} diff --git a/backend/utils/docker/docker.go b/backend/utils/docker/docker.go deleted file mode 100644 index e11e42e1d..000000000 --- a/backend/utils/docker/docker.go +++ /dev/null @@ -1,177 +0,0 @@ -package docker - -import ( - "context" - - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/image" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/client" -) - -type Client struct { - cli *client.Client -} - -func NewClient() (Client, error) { - var settingItem model.Setting - _ = global.DB.Where("key = ?", "DockerSockPath").First(&settingItem).Error - if len(settingItem.Value) == 0 { - settingItem.Value = "unix:///var/run/docker.sock" - } - cli, err := client.NewClientWithOpts(client.FromEnv, client.WithHost(settingItem.Value), client.WithAPIVersionNegotiation()) - if err != nil { - return Client{}, err - } - - return Client{ - cli: cli, - }, nil -} - -func (c Client) Close() { - _ = c.cli.Close() -} - -func NewDockerClient() (*client.Client, error) { - var settingItem model.Setting - _ = global.DB.Where("key = ?", "DockerSockPath").First(&settingItem).Error - if len(settingItem.Value) == 0 { - settingItem.Value = "unix:///var/run/docker.sock" - } - cli, err := client.NewClientWithOpts(client.FromEnv, client.WithHost(settingItem.Value), client.WithAPIVersionNegotiation()) - if err != nil { - return nil, err - } - return cli, nil -} - -func (c Client) ListContainersByName(names []string) ([]types.Container, error) { - var ( - options container.ListOptions - namesMap = make(map[string]bool) - res []types.Container - ) - options.All = true - if len(names) > 0 { - var array []filters.KeyValuePair - for _, n := range names { - namesMap["/"+n] = true - array = append(array, filters.Arg("name", n)) - } - options.Filters = filters.NewArgs(array...) - } - containers, err := c.cli.ContainerList(context.Background(), options) - if err != nil { - return nil, err - } - for _, con := range containers { - if _, ok := namesMap[con.Names[0]]; ok { - res = append(res, con) - } - } - return res, nil -} -func (c Client) ListAllContainers() ([]types.Container, error) { - var ( - options container.ListOptions - ) - options.All = true - containers, err := c.cli.ContainerList(context.Background(), options) - if err != nil { - return nil, err - } - return containers, nil -} - -func (c Client) CreateNetwork(name string) error { - _, err := c.cli.NetworkCreate(context.Background(), name, types.NetworkCreate{ - Driver: "bridge", - }) - return err -} - -func (c Client) DeleteImage(imageID string) error { - if _, err := c.cli.ImageRemove(context.Background(), imageID, image.RemoveOptions{Force: true}); err != nil { - return err - } - return nil -} - -func (c Client) InspectContainer(containerID string) (types.ContainerJSON, error) { - return c.cli.ContainerInspect(context.Background(), containerID) -} - -func (c Client) PullImage(imageName string, force bool) error { - if !force { - exist, err := c.CheckImageExist(imageName) - if err != nil { - return err - } - if exist { - return nil - } - } - if _, err := c.cli.ImagePull(context.Background(), imageName, image.PullOptions{}); err != nil { - return err - } - return nil -} - -func (c Client) GetImageIDByName(imageName string) (string, error) { - filter := filters.NewArgs() - filter.Add("reference", imageName) - list, err := c.cli.ImageList(context.Background(), image.ListOptions{ - Filters: filter, - }) - if err != nil { - return "", err - } - if len(list) > 0 { - return list[0].ID, nil - } - return "", nil -} - -func (c Client) CheckImageExist(imageName string) (bool, error) { - filter := filters.NewArgs() - filter.Add("reference", imageName) - list, err := c.cli.ImageList(context.Background(), image.ListOptions{ - Filters: filter, - }) - if err != nil { - return false, err - } - return len(list) > 0, nil -} - -func (c Client) NetworkExist(name string) bool { - var options types.NetworkListOptions - options.Filters = filters.NewArgs(filters.Arg("name", name)) - networks, err := c.cli.NetworkList(context.Background(), options) - if err != nil { - return false - } - return len(networks) > 0 -} - -func CreateDefaultDockerNetwork() error { - cli, err := NewClient() - if err != nil { - global.LOG.Errorf("init docker client error %s", err.Error()) - return err - } - defer cli.Close() - if !cli.NetworkExist("1panel-network") { - if err := cli.CreateNetwork("1panel-network"); err != nil { - global.LOG.Errorf("create default docker network error %s", err.Error()) - return err - } - } - return nil -} diff --git a/backend/utils/encrypt/encrypt.go b/backend/utils/encrypt/encrypt.go deleted file mode 100644 index 62d4e1cde..000000000 --- a/backend/utils/encrypt/encrypt.go +++ /dev/null @@ -1,104 +0,0 @@ -package encrypt - -import ( - "bytes" - "crypto/aes" - "crypto/cipher" - "crypto/rand" - "encoding/base64" - "fmt" - "io" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" -) - -func StringEncrypt(text string) (string, error) { - if len(text) == 0 { - return "", nil - } - if len(global.CONF.System.EncryptKey) == 0 { - var encryptSetting model.Setting - if err := global.DB.Where("key = ?", "EncryptKey").First(&encryptSetting).Error; err != nil { - return "", err - } - global.CONF.System.EncryptKey = encryptSetting.Value - } - key := global.CONF.System.EncryptKey - pass := []byte(text) - xpass, err := aesEncryptWithSalt([]byte(key), pass) - if err == nil { - pass64 := base64.StdEncoding.EncodeToString(xpass) - return pass64, err - } - return "", err -} - -func StringDecrypt(text string) (string, error) { - if len(text) == 0 { - return "", nil - } - if len(global.CONF.System.EncryptKey) == 0 { - var encryptSetting model.Setting - if err := global.DB.Where("key = ?", "EncryptKey").First(&encryptSetting).Error; err != nil { - return "", err - } - global.CONF.System.EncryptKey = encryptSetting.Value - } - key := global.CONF.System.EncryptKey - bytesPass, err := base64.StdEncoding.DecodeString(text) - if err != nil { - return "", err - } - var tpass []byte - tpass, err = aesDecryptWithSalt([]byte(key), bytesPass) - if err == nil { - result := string(tpass[:]) - return result, err - } - return "", err -} - -func padding(plaintext []byte, blockSize int) []byte { - padding := blockSize - len(plaintext)%blockSize - padtext := bytes.Repeat([]byte{byte(padding)}, padding) - return append(plaintext, padtext...) -} - -func unPadding(origData []byte) []byte { - length := len(origData) - unpadding := int(origData[length-1]) - return origData[:(length - unpadding)] -} - -func aesEncryptWithSalt(key, plaintext []byte) ([]byte, error) { - plaintext = padding(plaintext, aes.BlockSize) - block, err := aes.NewCipher(key) - if err != nil { - return nil, err - } - ciphertext := make([]byte, aes.BlockSize+len(plaintext)) - iv := ciphertext[0:aes.BlockSize] - if _, err := io.ReadFull(rand.Reader, iv); err != nil { - return nil, err - } - cbc := cipher.NewCBCEncrypter(block, iv) - cbc.CryptBlocks(ciphertext[aes.BlockSize:], plaintext) - return ciphertext, nil -} -func aesDecryptWithSalt(key, ciphertext []byte) ([]byte, error) { - var block cipher.Block - block, err := aes.NewCipher(key) - if err != nil { - return nil, err - } - if len(ciphertext) < aes.BlockSize { - return nil, fmt.Errorf("iciphertext too short") - } - iv := ciphertext[:aes.BlockSize] - ciphertext = ciphertext[aes.BlockSize:] - cbc := cipher.NewCBCDecrypter(block, iv) - cbc.CryptBlocks(ciphertext, ciphertext) - ciphertext = unPadding(ciphertext) - return ciphertext, nil -} diff --git a/backend/utils/env/env.go b/backend/utils/env/env.go deleted file mode 100644 index 630511618..000000000 --- a/backend/utils/env/env.go +++ /dev/null @@ -1,52 +0,0 @@ -package env - -import ( - "fmt" - "github.com/joho/godotenv" - "os" - "sort" - "strconv" - "strings" -) - -func Write(envMap map[string]string, filename string) error { - content, err := Marshal(envMap) - if err != nil { - return err - } - file, err := os.Create(filename) - if err != nil { - return err - } - defer file.Close() - _, err = file.WriteString(content + "\n") - if err != nil { - return err - } - return file.Sync() -} - -func Marshal(envMap map[string]string) (string, error) { - lines := make([]string, 0, len(envMap)) - for k, v := range envMap { - if d, err := strconv.Atoi(v); err == nil { - lines = append(lines, fmt.Sprintf(`%s=%d`, k, d)) - } else { - lines = append(lines, fmt.Sprintf(`%s="%s"`, k, v)) - } - } - sort.Strings(lines) - return strings.Join(lines, "\n"), nil -} - -func GetEnvValueByKey(envPath, key string) (string, error) { - envMap, err := godotenv.Read(envPath) - if err != nil { - return "", err - } - value, ok := envMap[key] - if !ok { - return "", fmt.Errorf("key %s not found in %s", key, envPath) - } - return value, nil -} diff --git a/backend/utils/files/archiver.go b/backend/utils/files/archiver.go deleted file mode 100644 index 374b500e7..000000000 --- a/backend/utils/files/archiver.go +++ /dev/null @@ -1,38 +0,0 @@ -package files - -import ( - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" -) - -type ShellArchiver interface { - Extract(filePath, dstDir string, secret string) error - Compress(sourcePaths []string, dstFile string, secret string) error -} - -func NewShellArchiver(compressType CompressType) (ShellArchiver, error) { - switch compressType { - case Tar: - if err := checkCmdAvailability("tar"); err != nil { - return nil, err - } - return NewTarArchiver(compressType), nil - case TarGz: - return NewTarGzArchiver(), nil - case Zip: - if err := checkCmdAvailability("zip"); err != nil { - return nil, err - } - return NewZipArchiver(), nil - default: - return nil, buserr.New("unsupported compress type") - } -} - -func checkCmdAvailability(cmdStr string) error { - if cmd.Which(cmdStr) { - return nil - } - return buserr.WithName(constant.ErrCmdNotFound, cmdStr) -} diff --git a/backend/utils/files/file_op.go b/backend/utils/files/file_op.go deleted file mode 100644 index 913a65d37..000000000 --- a/backend/utils/files/file_op.go +++ /dev/null @@ -1,666 +0,0 @@ -package files - -import ( - "archive/zip" - "bufio" - "bytes" - "context" - "crypto/tls" - "encoding/json" - "fmt" - "io" - "io/fs" - "net/http" - "os" - "path" - "path/filepath" - "strconv" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - http2 "github.com/1Panel-dev/1Panel/backend/utils/http" - cZip "github.com/klauspost/compress/zip" - "golang.org/x/text/encoding/simplifiedchinese" - "golang.org/x/text/transform" - - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/mholt/archiver/v4" - "github.com/pkg/errors" - "github.com/spf13/afero" -) - -type FileOp struct { - Fs afero.Fs -} - -func NewFileOp() FileOp { - return FileOp{ - Fs: afero.NewOsFs(), - } -} - -func (f FileOp) OpenFile(dst string) (fs.File, error) { - return f.Fs.Open(dst) -} - -func (f FileOp) GetContent(dst string) ([]byte, error) { - afs := &afero.Afero{Fs: f.Fs} - cByte, err := afs.ReadFile(dst) - if err != nil { - return nil, err - } - return cByte, nil -} - -func (f FileOp) CreateDir(dst string, mode fs.FileMode) error { - return f.Fs.MkdirAll(dst, mode) -} - -func (f FileOp) CreateDirWithMode(dst string, mode fs.FileMode) error { - if err := f.Fs.MkdirAll(dst, mode); err != nil { - return err - } - return f.ChmodRWithMode(dst, mode, true) -} - -func (f FileOp) CreateFile(dst string) error { - if _, err := f.Fs.Create(dst); err != nil { - return err - } - return nil -} - -func (f FileOp) CreateFileWithMode(dst string, mode fs.FileMode) error { - file, err := f.Fs.OpenFile(dst, os.O_CREATE, mode) - if err != nil { - return err - } - return file.Close() -} - -func (f FileOp) LinkFile(source string, dst string, isSymlink bool) error { - if isSymlink { - osFs := afero.OsFs{} - return osFs.SymlinkIfPossible(source, dst) - } else { - return os.Link(source, dst) - } -} - -func (f FileOp) DeleteDir(dst string) error { - return f.Fs.RemoveAll(dst) -} - -func (f FileOp) Stat(dst string) bool { - info, _ := f.Fs.Stat(dst) - return info != nil -} - -func (f FileOp) DeleteFile(dst string) error { - return f.Fs.Remove(dst) -} - -func (f FileOp) CleanDir(dst string) error { - return cmd.ExecCmd(fmt.Sprintf("rm -rf %s/*", dst)) -} - -func (f FileOp) RmRf(dst string) error { - return cmd.ExecCmd(fmt.Sprintf("rm -rf %s", dst)) -} - -func (f FileOp) WriteFile(dst string, in io.Reader, mode fs.FileMode) error { - file, err := f.Fs.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode) - if err != nil { - return err - } - defer file.Close() - - if _, err = io.Copy(file, in); err != nil { - return err - } - - if _, err = file.Stat(); err != nil { - return err - } - return nil -} - -func (f FileOp) SaveFile(dst string, content string, mode fs.FileMode) error { - if !f.Stat(path.Dir(dst)) { - _ = f.CreateDir(path.Dir(dst), mode.Perm()) - } - file, err := f.Fs.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode) - if err != nil { - return err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(content) - write.Flush() - return nil -} - -func (f FileOp) SaveFileWithByte(dst string, content []byte, mode fs.FileMode) error { - if !f.Stat(path.Dir(dst)) { - _ = f.CreateDir(path.Dir(dst), mode.Perm()) - } - file, err := f.Fs.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode) - if err != nil { - return err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.Write(content) - write.Flush() - return nil -} - -func (f FileOp) ChownR(dst string, uid string, gid string, sub bool) error { - cmdStr := fmt.Sprintf(`chown %s:%s "%s"`, uid, gid, dst) - if sub { - cmdStr = fmt.Sprintf(`chown -R %s:%s "%s"`, uid, gid, dst) - } - if cmd.HasNoPasswordSudo() { - cmdStr = fmt.Sprintf("sudo %s", cmdStr) - } - if msg, err := cmd.ExecWithTimeOut(cmdStr, 10*time.Second); err != nil { - if msg != "" { - return errors.New(msg) - } - return err - } - return nil -} - -func (f FileOp) ChmodR(dst string, mode int64, sub bool) error { - cmdStr := fmt.Sprintf(`chmod %v "%s"`, fmt.Sprintf("%04o", mode), dst) - if sub { - cmdStr = fmt.Sprintf(`chmod -R %v "%s"`, fmt.Sprintf("%04o", mode), dst) - } - if cmd.HasNoPasswordSudo() { - cmdStr = fmt.Sprintf("sudo %s", cmdStr) - } - if msg, err := cmd.ExecWithTimeOut(cmdStr, 10*time.Second); err != nil { - if msg != "" { - return errors.New(msg) - } - return err - } - return nil -} - -func (f FileOp) ChmodRWithMode(dst string, mode fs.FileMode, sub bool) error { - cmdStr := fmt.Sprintf(`chmod %v "%s"`, fmt.Sprintf("%o", mode.Perm()), dst) - if sub { - cmdStr = fmt.Sprintf(`chmod -R %v "%s"`, fmt.Sprintf("%o", mode.Perm()), dst) - } - if cmd.HasNoPasswordSudo() { - cmdStr = fmt.Sprintf("sudo %s", cmdStr) - } - if msg, err := cmd.ExecWithTimeOut(cmdStr, 10*time.Second); err != nil { - if msg != "" { - return errors.New(msg) - } - return err - } - return nil -} - -func (f FileOp) Rename(oldName string, newName string) error { - return f.Fs.Rename(oldName, newName) -} - -type WriteCounter struct { - Total uint64 - Written uint64 - Key string - Name string -} - -type Process struct { - Total uint64 `json:"total"` - Written uint64 `json:"written"` - Percent float64 `json:"percent"` - Name string `json:"name"` -} - -func (w *WriteCounter) Write(p []byte) (n int, err error) { - n = len(p) - w.Written += uint64(n) - w.SaveProcess() - return n, nil -} - -func (w *WriteCounter) SaveProcess() { - percentValue := 0.0 - if w.Total > 0 { - percent := float64(w.Written) / float64(w.Total) * 100 - percentValue, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", percent), 64) - } - process := Process{ - Total: w.Total, - Written: w.Written, - Percent: percentValue, - Name: w.Name, - } - by, _ := json.Marshal(process) - if percentValue < 100 { - if err := global.CACHE.Set(w.Key, string(by)); err != nil { - global.LOG.Errorf("save cache error, err %s", err.Error()) - } - } else { - if err := global.CACHE.SetWithTTL(w.Key, string(by), time.Second*time.Duration(10)); err != nil { - global.LOG.Errorf("save cache error, err %s", err.Error()) - } - } -} - -func (f FileOp) DownloadFileWithProcess(url, dst, key string, ignoreCertificate bool) error { - client := &http.Client{} - if ignoreCertificate { - client.Transport = &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - } - } - request, err := http.NewRequest("GET", url, nil) - if err != nil { - return nil - } - request.Header.Set("Accept-Encoding", "identity") - resp, err := client.Do(request) - if err != nil { - global.LOG.Errorf("get download file [%s] error, err %s", dst, err.Error()) - return err - } - out, err := os.Create(dst) - if err != nil { - global.LOG.Errorf("create download file [%s] error, err %s", dst, err.Error()) - return err - } - go func() { - counter := &WriteCounter{} - counter.Key = key - if resp.ContentLength > 0 { - counter.Total = uint64(resp.ContentLength) - } - counter.Name = filepath.Base(dst) - if _, err = io.Copy(out, io.TeeReader(resp.Body, counter)); err != nil { - global.LOG.Errorf("save download file [%s] error, err %s", dst, err.Error()) - } - out.Close() - resp.Body.Close() - - value, err := global.CACHE.Get(counter.Key) - if err != nil { - global.LOG.Errorf("get cache error,err %s", err.Error()) - return - } - process := &Process{} - _ = json.Unmarshal(value, process) - process.Percent = 100 - process.Name = counter.Name - process.Total = process.Written - by, _ := json.Marshal(process) - if err := global.CACHE.SetWithTTL(counter.Key, string(by), time.Second*time.Duration(10)); err != nil { - global.LOG.Errorf("save cache error, err %s", err.Error()) - } - }() - return nil -} - -func (f FileOp) DownloadFile(url, dst string) error { - resp, err := http2.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 (f FileOp) DownloadFileWithProxy(url, dst string) error { - _, resp, err := http2.HandleGet(url, http.MethodGet, constant.TimeOut5m) - if err != nil { - return err - } - - out, err := os.Create(dst) - if err != nil { - return fmt.Errorf("create download file [%s] error, err %s", dst, err.Error()) - } - defer out.Close() - - reader := bytes.NewReader(resp) - if _, err = io.Copy(out, reader); err != nil { - return fmt.Errorf("save download file [%s] error, err %s", dst, err.Error()) - } - return nil -} - -func (f FileOp) Cut(oldPaths []string, dst, name string, cover bool) error { - for _, p := range oldPaths { - var dstPath string - if name != "" { - dstPath = filepath.Join(dst, name) - if f.Stat(dstPath) { - dstPath = dst - } - } else { - base := filepath.Base(p) - dstPath = filepath.Join(dst, base) - } - coverFlag := "" - if cover { - coverFlag = "-f" - } - - cmdStr := fmt.Sprintf(`mv %s '%s' '%s'`, coverFlag, p, dstPath) - if err := cmd.ExecCmd(cmdStr); err != nil { - return err - } - } - return nil -} - -func (f FileOp) Mv(oldPath, dstPath string) error { - cmdStr := fmt.Sprintf(`mv '%s' '%s'`, oldPath, dstPath) - if err := cmd.ExecCmd(cmdStr); err != nil { - return err - } - return nil -} - -func (f FileOp) Copy(src, dst string) error { - if src = path.Clean("/" + src); src == "" { - return os.ErrNotExist - } - if dst = path.Clean("/" + dst); dst == "" { - return os.ErrNotExist - } - if src == "/" || dst == "/" { - return os.ErrInvalid - } - if dst == src { - return os.ErrInvalid - } - info, err := f.Fs.Stat(src) - if err != nil { - return err - } - if info.IsDir() { - return f.CopyDir(src, dst) - } - return f.CopyFile(src, dst) -} - -func (f FileOp) CopyAndReName(src, dst, name string, cover bool) error { - if src = path.Clean("/" + src); src == "" { - return os.ErrNotExist - } - if dst = path.Clean("/" + dst); dst == "" { - return os.ErrNotExist - } - if src == "/" || dst == "/" { - return os.ErrInvalid - } - if dst == src { - return os.ErrInvalid - } - - srcInfo, err := f.Fs.Stat(src) - if err != nil { - return err - } - - if srcInfo.IsDir() { - dstPath := dst - if name != "" && !cover { - dstPath = filepath.Join(dst, name) - } - return cmd.ExecCmd(fmt.Sprintf(`cp -rf '%s' '%s'`, src, dstPath)) - } else { - dstPath := filepath.Join(dst, name) - if cover { - dstPath = dst - } - return cmd.ExecCmd(fmt.Sprintf(`cp -f '%s' '%s'`, src, dstPath)) - } -} - -func (f FileOp) CopyDir(src, dst string) error { - srcInfo, err := f.Fs.Stat(src) - if err != nil { - return err - } - dstDir := filepath.Join(dst, srcInfo.Name()) - if err = f.Fs.MkdirAll(dstDir, srcInfo.Mode()); err != nil { - return err - } - return cmd.ExecCmd(fmt.Sprintf(`cp -rf '%s' '%s'`, src, dst+"/")) -} - -func (f FileOp) CopyFile(src, dst string) error { - dst = filepath.Clean(dst) + string(filepath.Separator) - return cmd.ExecCmd(fmt.Sprintf(`cp -f '%s' '%s'`, src, dst+"/")) -} - -func (f FileOp) GetDirSize(path string) (float64, error) { - var size int64 - err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if !info.IsDir() { - size += info.Size() - } - return nil - }) - if err != nil { - return 0, err - } - return float64(size), nil -} - -func getFormat(cType CompressType) archiver.CompressedArchive { - format := archiver.CompressedArchive{} - switch cType { - case Tar: - format.Archival = archiver.Tar{} - case TarGz, Gz: - format.Compression = archiver.Gz{} - format.Archival = archiver.Tar{} - case SdkTarGz: - format.Compression = archiver.Gz{} - format.Archival = archiver.Tar{} - case SdkZip, Zip: - format.Archival = archiver.Zip{ - Compression: zip.Deflate, - } - case Bz2: - format.Compression = archiver.Bz2{} - format.Archival = archiver.Tar{} - case Xz: - format.Compression = archiver.Xz{} - format.Archival = archiver.Tar{} - } - return format -} - -func (f FileOp) Compress(srcRiles []string, dst string, name string, cType CompressType, secret string) error { - format := getFormat(cType) - - fileMaps := make(map[string]string, len(srcRiles)) - for _, s := range srcRiles { - base := filepath.Base(s) - fileMaps[s] = base - } - - if !f.Stat(dst) { - _ = f.CreateDir(dst, 0755) - } - - files, err := archiver.FilesFromDisk(nil, fileMaps) - if err != nil { - return err - } - dstFile := filepath.Join(dst, name) - out, err := f.Fs.Create(dstFile) - if err != nil { - return err - } - - switch cType { - case Zip: - if err := ZipFile(files, out); err == nil { - return nil - } - _ = f.DeleteFile(dstFile) - return NewZipArchiver().Compress(srcRiles, dstFile, "") - case TarGz: - err = NewTarGzArchiver().Compress(srcRiles, dstFile, secret) - if err != nil { - _ = f.DeleteFile(dstFile) - return err - } - default: - err = format.Archive(context.Background(), out, files) - if err != nil { - _ = f.DeleteFile(dstFile) - return err - } - } - return nil -} - -func isIgnoreFile(name string) bool { - return strings.HasPrefix(name, "__MACOSX") || strings.HasSuffix(name, ".DS_Store") || strings.HasPrefix(name, "._") -} - -func decodeGBK(input string) (string, error) { - decoder := simplifiedchinese.GBK.NewDecoder() - decoded, _, err := transform.String(decoder, input) - if err != nil { - return "", err - } - return decoded, nil -} - -func (f FileOp) decompressWithSDK(srcFile string, dst string, cType CompressType) error { - format := getFormat(cType) - handler := func(ctx context.Context, archFile archiver.File) error { - info := archFile.FileInfo - if isIgnoreFile(archFile.Name()) { - return nil - } - fileName := archFile.NameInArchive - var err error - if header, ok := archFile.Header.(cZip.FileHeader); ok { - if header.NonUTF8 && header.Flags == 0 { - fileName, err = decodeGBK(fileName) - if err != nil { - return err - } - } - } - filePath := filepath.Join(dst, fileName) - if archFile.FileInfo.IsDir() { - if err := f.Fs.MkdirAll(filePath, info.Mode()); err != nil { - return err - } - return nil - } else { - parentDir := path.Dir(filePath) - if !f.Stat(parentDir) { - if err := f.Fs.MkdirAll(parentDir, info.Mode()); err != nil { - return err - } - } - } - fr, err := archFile.Open() - if err != nil { - return err - } - defer fr.Close() - fw, err := f.Fs.OpenFile(filePath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, info.Mode()) - if err != nil { - return err - } - defer fw.Close() - if _, err := io.Copy(fw, fr); err != nil { - return err - } - - return nil - } - input, err := f.Fs.Open(srcFile) - if err != nil { - return err - } - return format.Extract(context.Background(), input, nil, handler) -} - -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 err == nil { - if err = shellArchiver.Extract(srcFile, dst, secret); err == nil { - return nil - } - } - } - return f.decompressWithSDK(srcFile, dst, cType) -} - -func ZipFile(files []archiver.File, dst afero.File) error { - zw := zip.NewWriter(dst) - defer zw.Close() - - for _, file := range files { - hdr, err := zip.FileInfoHeader(file) - if err != nil { - return err - } - hdr.Method = zip.Deflate - hdr.Name = file.NameInArchive - if file.IsDir() { - if !strings.HasSuffix(hdr.Name, "/") { - hdr.Name += "/" - } - } - w, err := zw.CreateHeader(hdr) - if err != nil { - return err - } - if file.IsDir() { - continue - } - - if file.LinkTarget != "" { - _, err = w.Write([]byte(filepath.ToSlash(file.LinkTarget))) - if err != nil { - return err - } - } else { - fileReader, err := file.Open() - if err != nil { - return err - } - _, err = io.Copy(w, fileReader) - if err != nil { - return err - } - } - } - return nil -} diff --git a/backend/utils/files/fileinfo.go b/backend/utils/files/fileinfo.go deleted file mode 100644 index 660d20fe6..000000000 --- a/backend/utils/files/fileinfo.go +++ /dev/null @@ -1,425 +0,0 @@ -package files - -import ( - "bufio" - "fmt" - "github.com/1Panel-dev/1Panel/backend/app/repo" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "io/fs" - "net/http" - "os" - "os/exec" - "path" - "path/filepath" - "sort" - "strconv" - "strings" - "syscall" - "time" - - "github.com/spf13/afero" -) - -type FileInfo struct { - Fs afero.Fs `json:"-"` - Path string `json:"path"` - Name string `json:"name"` - User string `json:"user"` - Group string `json:"group"` - Uid string `json:"uid"` - Gid string `json:"gid"` - Extension string `json:"extension"` - Content string `json:"content"` - Size int64 `json:"size"` - IsDir bool `json:"isDir"` - IsSymlink bool `json:"isSymlink"` - IsHidden bool `json:"isHidden"` - LinkPath string `json:"linkPath"` - Type string `json:"type"` - Mode string `json:"mode"` - MimeType string `json:"mimeType"` - UpdateTime time.Time `json:"updateTime"` - ModTime time.Time `json:"modTime"` - FileMode os.FileMode `json:"-"` - Items []*FileInfo `json:"items"` - ItemTotal int `json:"itemTotal"` - FavoriteID uint `json:"favoriteID"` - IsDetail bool `json:"isDetail"` -} - -type FileOption struct { - Path string `json:"path"` - Search string `json:"search"` - ContainSub bool `json:"containSub"` - Expand bool `json:"expand"` - Dir bool `json:"dir"` - ShowHidden bool `json:"showHidden"` - Page int `json:"page"` - PageSize int `json:"pageSize"` - SortBy string `json:"sortBy"` - SortOrder string `json:"sortOrder"` - IsDetail bool `json:"isDetail"` -} - -type FileSearchInfo struct { - Path string `json:"path"` - fs.FileInfo -} - -func NewFileInfo(op FileOption) (*FileInfo, error) { - var appFs = afero.NewOsFs() - - info, err := appFs.Stat(op.Path) - if err != nil { - return nil, err - } - - file := &FileInfo{ - Fs: appFs, - Path: op.Path, - Name: info.Name(), - IsDir: info.IsDir(), - FileMode: info.Mode(), - ModTime: info.ModTime(), - Size: info.Size(), - IsSymlink: IsSymlink(info.Mode()), - Extension: filepath.Ext(info.Name()), - IsHidden: IsHidden(op.Path), - Mode: fmt.Sprintf("%04o", info.Mode().Perm()), - User: GetUsername(info.Sys().(*syscall.Stat_t).Uid), - Uid: strconv.FormatUint(uint64(info.Sys().(*syscall.Stat_t).Uid), 10), - Gid: strconv.FormatUint(uint64(info.Sys().(*syscall.Stat_t).Gid), 10), - Group: GetGroup(info.Sys().(*syscall.Stat_t).Gid), - MimeType: GetMimeType(op.Path), - IsDetail: op.IsDetail, - } - favoriteRepo := repo.NewIFavoriteRepo() - favorite, _ := favoriteRepo.GetFirst(favoriteRepo.WithByPath(op.Path)) - if favorite.ID > 0 { - file.FavoriteID = favorite.ID - } - - if file.IsSymlink { - file.LinkPath = GetSymlink(op.Path) - } - if op.Expand { - if err := handleExpansion(file, op); err != nil { - return nil, err - } - } - return file, nil -} - -func handleExpansion(file *FileInfo, op FileOption) error { - if file.IsDir { - return file.listChildren(op) - } - - if !file.IsDetail { - return file.getContent() - } - - return nil -} - -func (f *FileInfo) search(search string, count int) (files []FileSearchInfo, total int, err error) { - cmd := exec.Command("find", f.Path, "-name", fmt.Sprintf("*%s*", search)) - output, err := cmd.StdoutPipe() - if err != nil { - return - } - if err = cmd.Start(); err != nil { - return - } - defer func() { - _ = cmd.Wait() - _ = cmd.Process.Kill() - }() - - scanner := bufio.NewScanner(output) - for scanner.Scan() { - line := scanner.Text() - info, err := os.Stat(line) - if err != nil { - continue - } - total++ - if total > count { - continue - } - files = append(files, FileSearchInfo{ - Path: line, - FileInfo: info, - }) - } - if err = scanner.Err(); err != nil { - return - } - return -} - -func sortFileList(list []FileSearchInfo, sortBy, sortOrder string) { - switch sortBy { - case "name": - if sortOrder == "ascending" { - sort.Slice(list, func(i, j int) bool { - return list[i].Name() < list[j].Name() - }) - } else { - sort.Slice(list, func(i, j int) bool { - return list[i].Name() > list[j].Name() - }) - } - case "size": - if sortOrder == "ascending" { - sort.Slice(list, func(i, j int) bool { - return list[i].Size() < list[j].Size() - }) - } else { - sort.Slice(list, func(i, j int) bool { - return list[i].Size() > list[j].Size() - }) - } - case "modTime": - if sortOrder == "ascending" { - sort.Slice(list, func(i, j int) bool { - return list[i].ModTime().Before(list[j].ModTime()) - }) - } else { - sort.Slice(list, func(i, j int) bool { - return list[i].ModTime().After(list[j].ModTime()) - }) - } - } -} - -func (f *FileInfo) listChildren(option FileOption) error { - afs := &afero.Afero{Fs: f.Fs} - var ( - files []FileSearchInfo - err error - total int - ) - - if option.Search != "" && option.ContainSub { - files, total, err = f.search(option.Search, option.Page*option.PageSize) - if err != nil { - return err - } - } else { - files, err = f.getFiles(afs, option) - if err != nil { - return err - } - } - - items, err := f.processFiles(files, option) - if err != nil { - return err - } - - if option.ContainSub { - f.ItemTotal = total - } - start := (option.Page - 1) * option.PageSize - end := option.PageSize + start - var result []*FileInfo - if start < 0 || start > f.ItemTotal || end < 0 || start > end { - result = items - } else { - if end > f.ItemTotal { - result = items[start:] - } else { - result = items[start:end] - } - } - - f.Items = result - return nil -} - -func (f *FileInfo) getFiles(afs *afero.Afero, option FileOption) ([]FileSearchInfo, error) { - dirFiles, err := afs.ReadDir(f.Path) - if err != nil { - return nil, err - } - - var ( - dirs []FileSearchInfo - fileList []FileSearchInfo - ) - - for _, file := range dirFiles { - info := FileSearchInfo{ - Path: f.Path, - FileInfo: file, - } - if file.IsDir() { - dirs = append(dirs, info) - } else { - fileList = append(fileList, info) - } - } - - sortFileList(dirs, option.SortBy, option.SortOrder) - sortFileList(fileList, option.SortBy, option.SortOrder) - - return append(dirs, fileList...), nil -} - -func (f *FileInfo) processFiles(files []FileSearchInfo, option FileOption) ([]*FileInfo, error) { - var items []*FileInfo - - for _, df := range files { - if shouldSkipFile(df, option) { - continue - } - - name, fPath := f.getFilePathAndName(option, df) - - if !option.ShowHidden && IsHidden(name) { - continue - } - f.ItemTotal++ - - isSymlink, isInvalidLink := f.checkSymlink(df) - - file := &FileInfo{ - Fs: f.Fs, - Name: name, - Size: df.Size(), - ModTime: df.ModTime(), - FileMode: df.Mode(), - IsDir: df.IsDir(), - IsSymlink: isSymlink, - IsHidden: IsHidden(fPath), - Extension: filepath.Ext(name), - Path: fPath, - Mode: fmt.Sprintf("%04o", df.Mode().Perm()), - User: GetUsername(df.Sys().(*syscall.Stat_t).Uid), - Group: GetGroup(df.Sys().(*syscall.Stat_t).Gid), - Uid: strconv.FormatUint(uint64(df.Sys().(*syscall.Stat_t).Uid), 10), - Gid: strconv.FormatUint(uint64(df.Sys().(*syscall.Stat_t).Gid), 10), - } - favoriteRepo := repo.NewIFavoriteRepo() - favorite, _ := favoriteRepo.GetFirst(favoriteRepo.WithByPath(fPath)) - if favorite.ID > 0 { - file.FavoriteID = favorite.ID - } - if isSymlink { - file.LinkPath = GetSymlink(fPath) - } - if df.Size() > 0 { - file.MimeType = GetMimeType(fPath) - } - if isInvalidLink { - file.Type = "invalid_link" - } - items = append(items, file) - } - - return items, nil -} - -func shouldSkipFile(df FileSearchInfo, option FileOption) bool { - if option.Dir && !df.IsDir() { - return true - } - - if option.Search != "" && !option.ContainSub { - lowerName := strings.ToLower(df.Name()) - lowerSearch := strings.ToLower(option.Search) - if !strings.Contains(lowerName, lowerSearch) { - return true - } - } - - return false -} - -func (f *FileInfo) getFilePathAndName(option FileOption, df FileSearchInfo) (string, string) { - name := df.Name() - fPath := path.Join(df.Path, df.Name()) - - if option.Search != "" && option.ContainSub { - fPath = df.Path - name = strings.TrimPrefix(strings.TrimPrefix(fPath, f.Path), "/") - } - - return name, fPath -} - -func (f *FileInfo) checkSymlink(df FileSearchInfo) (bool, bool) { - isSymlink := false - isInvalidLink := false - - if IsSymlink(df.Mode()) { - isSymlink = true - info, err := f.Fs.Stat(path.Join(df.Path, df.Name())) - if err == nil { - df.FileInfo = info - } else { - isInvalidLink = true - } - } - - return isSymlink, isInvalidLink -} - -func (f *FileInfo) getContent() error { - if IsBlockDevice(f.FileMode) { - return buserr.New(constant.ErrFileCanNotRead) - } - if f.Size > 10*1024*1024 { - return buserr.New("ErrFileToLarge") - } - afs := &afero.Afero{Fs: f.Fs} - cByte, err := afs.ReadFile(f.Path) - if err != nil { - return nil - } - if len(cByte) > 0 && DetectBinary(cByte) { - return buserr.New(constant.ErrFileCanNotRead) - } - f.Content = string(cByte) - return nil -} - -func DetectBinary(buf []byte) bool { - mimeType := http.DetectContentType(buf) - if !strings.HasPrefix(mimeType, "text/") { - whiteByte := 0 - n := min(1024, len(buf)) - for i := 0; i < n; i++ { - if (buf[i] >= 0x20) || buf[i] == 9 || buf[i] == 10 || buf[i] == 13 { - whiteByte++ - } else if buf[i] <= 6 || (buf[i] >= 14 && buf[i] <= 31) { - return true - } - } - return whiteByte < 1 - } - return false - -} - -func min(x, y int) int { - if x < y { - return x - } - return y -} - -type CompressType string - -const ( - Zip CompressType = "zip" - Gz CompressType = "gz" - Bz2 CompressType = "bz2" - Tar CompressType = "tar" - TarGz CompressType = "tar.gz" - Xz CompressType = "xz" - SdkZip CompressType = "sdkZip" - SdkTarGz CompressType = "sdkTarGz" -) diff --git a/backend/utils/files/tar.go b/backend/utils/files/tar.go deleted file mode 100644 index 6aaa1f035..000000000 --- a/backend/utils/files/tar.go +++ /dev/null @@ -1,38 +0,0 @@ -package files - -import ( - "fmt" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" -) - -type TarArchiver struct { - Cmd string - CompressType CompressType -} - -func NewTarArchiver(compressType CompressType) ShellArchiver { - return &TarArchiver{ - Cmd: "tar", - CompressType: compressType, - } -} - -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)) -} - -func (t TarArchiver) Compress(sourcePaths []string, dstFile string, secret string) error { - return nil -} - -func (t TarArchiver) getOptionStr(Option string) string { - switch t.CompressType { - case Tar: - if Option == "compress" { - return "cvf" - } else { - return "xf" - } - } - return "" -} diff --git a/backend/utils/files/tar_gz.go b/backend/utils/files/tar_gz.go deleted file mode 100644 index 8a1691abf..000000000 --- a/backend/utils/files/tar_gz.go +++ /dev/null @@ -1,61 +0,0 @@ -package files - -import ( - "fmt" - "path/filepath" - "strings" - - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" -) - -type TarGzArchiver struct { -} - -func NewTarGzArchiver() ShellArchiver { - return &TarGzArchiver{} -} - -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") - 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") - global.LOG.Debug(commands) - } - if err = cmd.ExecCmd(commands); err != nil { - return err - } - return nil -} - -func (t TarGzArchiver) Compress(sourcePaths []string, dstFile string, secret string) error { - var err error - path := "" - itemDir := "" - for _, item := range sourcePaths { - itemDir += filepath.Base(item) + " " - } - aheadDir := dstFile[:strings.LastIndex(dstFile, "/")] - if len(aheadDir) == 0 { - aheadDir = "/" - } - path += fmt.Sprintf("- -C %s %s", aheadDir, itemDir) - commands := "" - if len(secret) != 0 { - extraCmd := "| openssl enc -aes-256-cbc -salt -k '" + secret + "' -out" - commands = fmt.Sprintf("tar -zcf %s %s %s", path, extraCmd, dstFile) - global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" %s ", secret), "******")) - } else { - commands = fmt.Sprintf("tar -zcf %s -C %s %s", dstFile, aheadDir, itemDir) - global.LOG.Debug(commands) - } - if err = cmd.ExecCmd(commands); err != nil { - return err - } - return nil -} diff --git a/backend/utils/files/utils.go b/backend/utils/files/utils.go deleted file mode 100644 index 76ba78156..000000000 --- a/backend/utils/files/utils.go +++ /dev/null @@ -1,164 +0,0 @@ -package files - -import ( - "bufio" - "fmt" - "io" - "net/http" - "os" - "os/user" - "path/filepath" - "strconv" - "strings" -) - -func IsSymlink(mode os.FileMode) bool { - return mode&os.ModeSymlink != 0 -} - -func IsBlockDevice(mode os.FileMode) bool { - return mode&os.ModeDevice != 0 && mode&os.ModeCharDevice == 0 -} - -func GetMimeType(path string) string { - file, err := os.Open(path) - if err != nil { - return "" - } - defer file.Close() - - buffer := make([]byte, 512) - _, err = file.Read(buffer) - if err != nil { - return "" - } - mimeType := http.DetectContentType(buffer) - return mimeType -} - -func GetSymlink(path string) string { - linkPath, err := os.Readlink(path) - if err != nil { - return "" - } - return linkPath -} - -func GetUsername(uid uint32) string { - usr, err := user.LookupId(strconv.Itoa(int(uid))) - if err != nil { - return "" - } - return usr.Username -} - -func GetGroup(gid uint32) string { - usr, err := user.LookupGroupId(strconv.Itoa(int(gid))) - if err != nil { - return "" - } - return usr.Name -} - -const dotCharacter = 46 - -func IsHidden(path string) bool { - return path[0] == dotCharacter -} - -func countLines(path string) (int, error) { - file, err := os.Open(path) - if err != nil { - return 0, err - } - defer file.Close() - - scanner := bufio.NewScanner(file) - lineCount := 0 - for scanner.Scan() { - lineCount++ - } - if err := scanner.Err(); err != nil { - return 0, err - } - return lineCount, nil -} - -func ReadFileByLine(filename string, page, pageSize int, latest bool) (lines []string, isEndOfFile bool, total int, err error) { - if !NewFileOp().Stat(filename) { - return - } - file, err := os.Open(filename) - if err != nil { - return - } - defer file.Close() - - totalLines, err := countLines(filename) - if err != nil { - return - } - total = (totalLines + pageSize - 1) / pageSize - reader := bufio.NewReaderSize(file, 8192) - - if latest { - page = total - } - currentLine := 0 - startLine := (page - 1) * pageSize - endLine := startLine + pageSize - - for { - line, _, err := reader.ReadLine() - if err == io.EOF { - break - } - if currentLine >= startLine && currentLine < endLine { - lines = append(lines, string(line)) - } - currentLine++ - if currentLine >= endLine { - break - } - } - - isEndOfFile = currentLine < endLine - return -} - -func GetParentMode(path string) (os.FileMode, error) { - absPath, err := filepath.Abs(path) - if err != nil { - return 0, err - } - - for { - fileInfo, err := os.Stat(absPath) - if err == nil { - return fileInfo.Mode() & os.ModePerm, nil - } - if !os.IsNotExist(err) { - return 0, err - } - - parentDir := filepath.Dir(absPath) - if parentDir == absPath { - return 0, fmt.Errorf("no existing directory found in the path: %s", path) - } - absPath = parentDir - } -} - -func IsInvalidChar(name string) bool { - return strings.Contains(name, "&") -} - -func IsEmptyDir(dir string) bool { - f, err := os.Open(dir) - if err != nil { - return false - } - defer f.Close() - _, err = f.Readdirnames(1) - return err == io.EOF -} diff --git a/backend/utils/files/zip.go b/backend/utils/files/zip.go deleted file mode 100644 index 0d2896811..000000000 --- a/backend/utils/files/zip.go +++ /dev/null @@ -1,52 +0,0 @@ -package files - -import ( - "fmt" - "path" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/common" -) - -type ZipArchiver struct { -} - -func NewZipArchiver() ShellArchiver { - return &ZipArchiver{} -} - -func (z ZipArchiver) Extract(filePath, dstDir string, secret string) error { - if err := checkCmdAvailability("unzip"); err != nil { - return err - } - return cmd.ExecCmd(fmt.Sprintf("unzip -qo %s -d %s", filePath, dstDir)) -} - -func (z ZipArchiver) Compress(sourcePaths []string, dstFile string, _ string) error { - var err error - tmpFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("%s%s.zip", common.RandStr(50), time.Now().Format(constant.DateTimeSlimLayout))) - op := NewFileOp() - defer func() { - _ = op.DeleteFile(tmpFile) - if err != nil { - _ = op.DeleteFile(dstFile) - } - }() - baseDir := path.Dir(sourcePaths[0]) - relativePaths := make([]string, len(sourcePaths)) - for i, sp := range sourcePaths { - relativePaths[i] = path.Base(sp) - } - cmdStr := fmt.Sprintf("zip -qr %s %s", tmpFile, strings.Join(relativePaths, " ")) - if err = cmd.ExecCmdWithDir(cmdStr, baseDir); err != nil { - return err - } - if err = op.Mv(tmpFile, dstFile); err != nil { - return err - } - return nil -} diff --git a/backend/utils/firewall/client.go b/backend/utils/firewall/client.go deleted file mode 100644 index de88fca35..000000000 --- a/backend/utils/firewall/client.go +++ /dev/null @@ -1,39 +0,0 @@ -package firewall - -import ( - "os" - - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/firewall/client" -) - -type FirewallClient interface { - Name() string // ufw firewalld - Start() error - Stop() error - Restart() error - Reload() error - Status() (string, error) // running not running - Version() (string, error) - - ListPort() ([]client.FireInfo, error) - ListForward() ([]client.FireInfo, error) - ListAddress() ([]client.FireInfo, error) - - Port(port client.FireInfo, operation string) error - RichRules(rule client.FireInfo, operation string) error - PortForward(info client.Forward, operation string) error - - EnableForward() error -} - -func NewFirewallClient() (FirewallClient, error) { - if _, err := os.Stat("/usr/sbin/firewalld"); err == nil { - return client.NewFirewalld() - } - if _, err := os.Stat("/usr/sbin/ufw"); err == nil { - return client.NewUfw() - } - return nil, buserr.New(constant.ErrFirewall) -} diff --git a/backend/utils/firewall/client/firewalld.go b/backend/utils/firewall/client/firewalld.go deleted file mode 100644 index e0cd33e24..000000000 --- a/backend/utils/firewall/client/firewalld.go +++ /dev/null @@ -1,263 +0,0 @@ -package client - -import ( - "fmt" - "regexp" - "strings" - "sync" - - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" -) - -var ForwardListRegex = regexp.MustCompile(`^port=(\d{1,5}):proto=(.+?):toport=(\d{1,5}):toaddr=(.*)$`) - -type Firewall struct{} - -func NewFirewalld() (*Firewall, error) { - return &Firewall{}, nil -} - -func (f *Firewall) Name() string { - return "firewalld" -} - -func (f *Firewall) Status() (string, error) { - stdout, _ := cmd.Exec("firewall-cmd --state") - if stdout == "running\n" { - return "running", nil - } - return "not running", nil -} - -func (f *Firewall) Version() (string, error) { - stdout, err := cmd.Exec("firewall-cmd --version") - if err != nil { - return "", fmt.Errorf("load the firewall version failed, err: %s", stdout) - } - return strings.ReplaceAll(stdout, "\n ", ""), nil -} - -func (f *Firewall) Start() error { - stdout, err := cmd.Exec("systemctl start firewalld") - if err != nil { - return fmt.Errorf("enable the firewall failed, err: %s", stdout) - } - return nil -} - -func (f *Firewall) Stop() error { - stdout, err := cmd.Exec("systemctl stop firewalld") - if err != nil { - return fmt.Errorf("stop the firewall failed, err: %s", stdout) - } - return nil -} - -func (f *Firewall) Restart() error { - stdout, err := cmd.Exec("systemctl restart firewalld") - if err != nil { - return fmt.Errorf("restart the firewall failed, err: %s", stdout) - } - return nil -} - -func (f *Firewall) Reload() error { - stdout, err := cmd.Exec("firewall-cmd --reload") - if err != nil { - return fmt.Errorf("reload firewall failed, err: %s", stdout) - } - return nil -} - -func (f *Firewall) ListPort() ([]FireInfo, error) { - var wg sync.WaitGroup - var datas []FireInfo - wg.Add(2) - go func() { - defer wg.Done() - stdout, err := cmd.Exec("firewall-cmd --zone=public --list-ports") - if err != nil { - return - } - ports := strings.Split(strings.ReplaceAll(stdout, "\n", ""), " ") - for _, port := range ports { - if len(port) == 0 { - continue - } - var itemPort FireInfo - if strings.Contains(port, "/") { - itemPort.Port = strings.Split(port, "/")[0] - itemPort.Protocol = strings.Split(port, "/")[1] - } - itemPort.Strategy = "accept" - datas = append(datas, itemPort) - } - }() - - go func() { - defer wg.Done() - stdout1, err := cmd.Exec("firewall-cmd --zone=public --list-rich-rules") - if err != nil { - return - } - rules := strings.Split(stdout1, "\n") - for _, rule := range rules { - if len(rule) == 0 { - continue - } - itemRule := f.loadInfo(rule) - if len(itemRule.Port) != 0 && (itemRule.Family == "ipv4" || (itemRule.Family == "ipv6" && len(itemRule.Address) != 0)) { - datas = append(datas, itemRule) - } - } - }() - wg.Wait() - return datas, nil -} - -func (f *Firewall) ListForward() ([]FireInfo, error) { - stdout, err := cmd.Exec("firewall-cmd --zone=public --list-forward-ports") - if err != nil { - return nil, err - } - var datas []FireInfo - for _, line := range strings.Split(stdout, "\n") { - line = strings.TrimFunc(line, func(r rune) bool { - return r <= 32 - }) - if ForwardListRegex.MatchString(line) { - match := ForwardListRegex.FindStringSubmatch(line) - if len(match) < 4 { - continue - } - if len(match[4]) == 0 { - match[4] = "127.0.0.1" - } - datas = append(datas, FireInfo{ - Port: match[1], - Protocol: match[2], - TargetIP: match[4], - TargetPort: match[3], - }) - } - } - return datas, nil -} - -func (f *Firewall) ListAddress() ([]FireInfo, error) { - stdout, err := cmd.Exec("firewall-cmd --zone=public --list-rich-rules") - if err != nil { - return nil, err - } - var datas []FireInfo - rules := strings.Split(stdout, "\n") - for _, rule := range rules { - if len(rule) == 0 { - continue - } - itemRule := f.loadInfo(rule) - if len(itemRule.Port) == 0 && len(itemRule.Address) != 0 { - datas = append(datas, itemRule) - } - } - return datas, nil -} - -func (f *Firewall) Port(port FireInfo, operation string) error { - if cmd.CheckIllegal(operation, port.Protocol, port.Port) { - return buserr.New(constant.ErrCmdIllegal) - } - - stdout, err := cmd.Execf("firewall-cmd --zone=public --%s-port=%s/%s --permanent", operation, port.Port, port.Protocol) - if err != nil { - return fmt.Errorf("%s (port: %s/%s strategy: %s) failed, err: %s", operation, port.Port, port.Protocol, port.Strategy, stdout) - } - return nil -} - -func (f *Firewall) RichRules(rule FireInfo, operation string) error { - if cmd.CheckIllegal(operation, rule.Address, rule.Protocol, rule.Port, rule.Strategy) { - return buserr.New(constant.ErrCmdIllegal) - } - ruleStr := "rule family=ipv4 " - if strings.Contains(rule.Address, ":") { - ruleStr = "rule family=ipv6 " - } - if len(rule.Address) != 0 { - ruleStr += fmt.Sprintf("source address=%s ", rule.Address) - } - if len(rule.Port) != 0 { - ruleStr += fmt.Sprintf("port port=%s ", rule.Port) - } - if len(rule.Protocol) != 0 { - ruleStr += fmt.Sprintf("protocol=%s ", rule.Protocol) - } - ruleStr += rule.Strategy - stdout, err := cmd.Execf("firewall-cmd --zone=public --%s-rich-rule '%s' --permanent", operation, ruleStr) - if err != nil { - return fmt.Errorf("%s rich rules (%s) failed, err: %s", operation, ruleStr, stdout) - } - if len(rule.Address) == 0 { - stdout1, err := cmd.Execf("firewall-cmd --zone=public --%s-rich-rule '%s' --permanent", operation, strings.ReplaceAll(ruleStr, "family=ipv4 ", "family=ipv6 ")) - if err != nil { - return fmt.Errorf("%s rich rules (%s) failed, err: %s", operation, strings.ReplaceAll(ruleStr, "family=ipv4 ", "family=ipv6 "), stdout1) - } - } - return nil -} - -func (f *Firewall) PortForward(info Forward, operation string) error { - ruleStr := fmt.Sprintf("firewall-cmd --zone=public --%s-forward-port=port=%s:proto=%s:toport=%s --permanent", operation, info.Port, info.Protocol, info.TargetPort) - if info.TargetIP != "" && info.TargetIP != "127.0.0.1" && info.TargetIP != "localhost" { - ruleStr = fmt.Sprintf("firewall-cmd --zone=public --%s-forward-port=port=%s:proto=%s:toaddr=%s:toport=%s --permanent", operation, info.Port, info.Protocol, info.TargetIP, info.TargetPort) - } - - stdout, err := cmd.Exec(ruleStr) - if err != nil { - return fmt.Errorf("%s port forward failed, err: %s", operation, stdout) - } - if err = f.Reload(); err != nil { - return err - } - return nil -} - -func (f *Firewall) loadInfo(line string) FireInfo { - var itemRule FireInfo - ruleInfo := strings.Split(strings.ReplaceAll(line, "\"", ""), " ") - for _, item := range ruleInfo { - switch { - case strings.Contains(item, "family="): - itemRule.Family = strings.ReplaceAll(item, "family=", "") - case strings.Contains(item, "ipset="): - itemRule.Address = strings.ReplaceAll(item, "ipset=", "") - case strings.Contains(item, "address="): - itemRule.Address = strings.ReplaceAll(item, "address=", "") - case strings.Contains(item, "port="): - itemRule.Port = strings.ReplaceAll(item, "port=", "") - case strings.Contains(item, "protocol="): - itemRule.Protocol = strings.ReplaceAll(item, "protocol=", "") - case item == "accept" || item == "drop" || item == "reject": - itemRule.Strategy = item - } - } - return itemRule -} - -func (f *Firewall) EnableForward() error { - stdout, err := cmd.Exec("firewall-cmd --zone=public --query-masquerade") - if err != nil { - if strings.HasSuffix(strings.TrimSpace(stdout), "no") { - stdout, err = cmd.Exec("firewall-cmd --zone=public --add-masquerade --permanent") - if err != nil { - return fmt.Errorf("%s: %s", err, stdout) - } - return f.Reload() - } - return fmt.Errorf("%s: %s", err, stdout) - } - - return nil -} diff --git a/backend/utils/firewall/client/info.go b/backend/utils/firewall/client/info.go deleted file mode 100644 index 3503c25ed..000000000 --- a/backend/utils/firewall/client/info.go +++ /dev/null @@ -1,35 +0,0 @@ -package client - -type FireInfo struct { - Family string `json:"family"` // ipv4 ipv6 - Address string `json:"address"` // Anywhere - Port string `json:"port"` - Protocol string `json:"protocol"` // tcp udp tcp/udp - Strategy string `json:"strategy"` // accept drop - - Num string `json:"num"` - TargetIP string `json:"targetIP"` - TargetPort string `json:"targetPort"` - - UsedStatus string `json:"usedStatus"` - Description string `json:"description"` -} - -type Forward struct { - Num string `json:"num"` - Protocol string `json:"protocol"` - Port string `json:"port"` - TargetIP string `json:"targetIP"` - TargetPort string `json:"targetPort"` -} - -type IptablesNatInfo struct { - Num string `json:"num"` - Target string `json:"target"` - Protocol string `json:"protocol"` - Opt string `json:"opt"` - Source string `json:"source"` - Destination string `json:"destination"` - SrcPort string `json:"srcPort"` - DestPort string `json:"destPort"` -} diff --git a/backend/utils/firewall/client/iptables.go b/backend/utils/firewall/client/iptables.go deleted file mode 100644 index 8f8bf263a..000000000 --- a/backend/utils/firewall/client/iptables.go +++ /dev/null @@ -1,145 +0,0 @@ -package client - -import ( - "fmt" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "regexp" - "strings" -) - -const NatChain = "1PANEL" - -var NatListRegex = regexp.MustCompile(`^(\d+)\s+(.+?)\s+(.+?)\s+(.+?)\s+(.+?)\s+(.+?)(?:\s+(.+?) .+?:(\d{1,5}(?::\d+)?).+?[ :](.+-.+|(?:.+:)?\d{1,5}(?:-\d{1,5})?))?$`) - -type Iptables struct { - CmdStr string -} - -func NewIptables() (*Iptables, error) { - iptables := new(Iptables) - if cmd.HasNoPasswordSudo() { - iptables.CmdStr = "sudo" - } - - return iptables, nil -} - -func (iptables *Iptables) runf(rule string, a ...any) error { - stdout, err := cmd.Execf("%s iptables -t nat %s", iptables.CmdStr, fmt.Sprintf(rule, a...)) - if err != nil { - return fmt.Errorf("%s, %s", err, stdout) - } - if stdout != "" { - return fmt.Errorf("iptables error: %s", stdout) - } - - return nil -} - -func (iptables *Iptables) Check() error { - stdout, err := cmd.Exec("cat /proc/sys/net/ipv4/ip_forward") - if err != nil { - return fmt.Errorf("%s, %s", err, stdout) - } - if stdout == "0" { - return fmt.Errorf("disable") - } - - return nil -} - -func (iptables *Iptables) NatNewChain() error { - return iptables.runf("-N %s", NatChain) -} - -func (iptables *Iptables) NatAppendChain() error { - return iptables.runf("-A PREROUTING -j %s", NatChain) -} - -func (iptables *Iptables) NatList(chain ...string) ([]IptablesNatInfo, error) { - rule := fmt.Sprintf("%s iptables -t nat -nL %s --line", iptables.CmdStr, NatChain) - if len(chain) == 1 { - rule = fmt.Sprintf("%s iptables -t nat -nL %s --line", iptables.CmdStr, chain[0]) - } - stdout, err := cmd.Exec(rule) - if err != nil { - return nil, err - } - - var forwardList []IptablesNatInfo - for _, line := range strings.Split(stdout, "\n") { - line = strings.TrimFunc(line, func(r rune) bool { - return r <= 32 - }) - if NatListRegex.MatchString(line) { - match := NatListRegex.FindStringSubmatch(line) - if !strings.Contains(match[9], ":") { - match[9] = fmt.Sprintf(":%s", match[9]) - } - forwardList = append(forwardList, IptablesNatInfo{ - Num: match[1], - Target: match[2], - Protocol: match[7], - Opt: match[4], - Source: match[5], - Destination: match[6], - SrcPort: match[8], - DestPort: match[9], - }) - } - } - - return forwardList, nil -} - -func (iptables *Iptables) NatAdd(protocol, src, destIp, destPort string, save bool) error { - rule := fmt.Sprintf("-A %s -p %s --dport %s -j REDIRECT --to-port %s", NatChain, protocol, src, destPort) - if destIp != "" && destIp != "127.0.0.1" && destIp != "localhost" { - rule = fmt.Sprintf("-A %s -p %s --dport %s -j DNAT --to-destination %s:%s", NatChain, protocol, src, destIp, destPort) - } - if err := iptables.runf(rule); err != nil { - return err - } - - if save { - return global.DB.Save(&model.Forward{ - Protocol: protocol, - Port: src, - TargetIP: destIp, - TargetPort: destPort, - }).Error - } - return nil -} - -func (iptables *Iptables) NatRemove(num string, protocol, src, destIp, destPort string) error { - if err := iptables.runf("-D %s %s", NatChain, num); err != nil { - return err - } - - global.DB.Where( - "protocol = ? AND port = ? AND target_ip = ? AND target_port = ?", - protocol, - src, - destIp, - destPort, - ).Delete(&model.Forward{}) - return nil -} - -func (iptables *Iptables) Reload() error { - if err := iptables.runf("-F %s", NatChain); err != nil { - return err - } - - var rules []model.Forward - global.DB.Find(&rules) - for _, forward := range rules { - if err := iptables.NatAdd(forward.Protocol, forward.Port, forward.TargetIP, forward.TargetPort, false); err != nil { - return err - } - } - return nil -} diff --git a/backend/utils/firewall/client/ufw.go b/backend/utils/firewall/client/ufw.go deleted file mode 100644 index a43433263..000000000 --- a/backend/utils/firewall/client/ufw.go +++ /dev/null @@ -1,322 +0,0 @@ -package client - -import ( - "fmt" - "strings" - - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" -) - -type Ufw struct { - CmdStr string -} - -func NewUfw() (*Ufw, error) { - var ufw Ufw - if cmd.HasNoPasswordSudo() { - ufw.CmdStr = "sudo ufw" - } else { - ufw.CmdStr = "ufw" - } - return &ufw, nil -} - -func (f *Ufw) Name() string { - return "ufw" -} - -func (f *Ufw) Status() (string, error) { - stdout, _ := cmd.Execf("%s status | grep Status", f.CmdStr) - if stdout == "Status: active\n" { - return "running", nil - } - stdout1, _ := cmd.Execf("%s status | grep 状态", f.CmdStr) - if stdout1 == "状态: 激活\n" { - return "running", nil - } - return "not running", nil -} - -func (f *Ufw) Version() (string, error) { - stdout, err := cmd.Execf("%s version | grep ufw", f.CmdStr) - if err != nil { - return "", fmt.Errorf("load the firewall status failed, err: %s", stdout) - } - info := strings.ReplaceAll(stdout, "\n", "") - return strings.ReplaceAll(info, "ufw ", ""), nil -} - -func (f *Ufw) Start() error { - stdout, err := cmd.Execf("echo y | %s enable", f.CmdStr) - if err != nil { - return fmt.Errorf("enable the firewall failed, err: %s", stdout) - } - return nil -} - -func (f *Ufw) Stop() error { - stdout, err := cmd.Execf("%s disable", f.CmdStr) - if err != nil { - return fmt.Errorf("stop the firewall failed, err: %s", stdout) - } - return nil -} - -func (f *Ufw) Restart() error { - if err := f.Stop(); err != nil { - return err - } - if err := f.Start(); err != nil { - return err - } - return nil -} - -func (f *Ufw) Reload() error { - return nil -} - -func (f *Ufw) ListPort() ([]FireInfo, error) { - stdout, err := cmd.Execf("%s status verbose", f.CmdStr) - if err != nil { - return nil, err - } - portInfos := strings.Split(stdout, "\n") - var datas []FireInfo - isStart := false - for _, line := range portInfos { - if strings.HasPrefix(line, "-") { - isStart = true - continue - } - if !isStart { - continue - } - itemFire := f.loadInfo(line, "port") - if len(itemFire.Port) != 0 && itemFire.Port != "Anywhere" && !strings.Contains(itemFire.Port, ".") { - itemFire.Port = strings.ReplaceAll(itemFire.Port, ":", "-") - datas = append(datas, itemFire) - } - } - return datas, nil -} - -func (f *Ufw) ListForward() ([]FireInfo, error) { - iptables, err := NewIptables() - if err != nil { - return nil, err - } - rules, err := iptables.NatList() - if err != nil { - return nil, err - } - - var list []FireInfo - for _, rule := range rules { - dest := strings.Split(rule.DestPort, ":") - if len(dest) < 2 { - continue - } - if len(dest[0]) == 0 { - dest[0] = "127.0.0.1" - } - list = append(list, FireInfo{ - Num: rule.Num, - Protocol: rule.Protocol, - Port: rule.SrcPort, - TargetIP: dest[0], - TargetPort: dest[1], - }) - } - return list, nil -} - -func (f *Ufw) ListAddress() ([]FireInfo, error) { - stdout, err := cmd.Execf("%s status verbose", f.CmdStr) - if err != nil { - return nil, err - } - portInfos := strings.Split(stdout, "\n") - var datas []FireInfo - isStart := false - for _, line := range portInfos { - if strings.HasPrefix(line, "-") { - isStart = true - continue - } - if !isStart { - continue - } - if !strings.Contains(line, " IN") { - continue - } - itemFire := f.loadInfo(line, "address") - if strings.Contains(itemFire.Port, ".") { - itemFire.Address += ("-" + itemFire.Port) - itemFire.Port = "" - } - if len(itemFire.Port) == 0 && len(itemFire.Address) != 0 { - datas = append(datas, itemFire) - } - } - return datas, nil -} - -func (f *Ufw) Port(port FireInfo, operation string) error { - switch port.Strategy { - case "accept": - port.Strategy = "allow" - case "drop": - port.Strategy = "deny" - default: - return fmt.Errorf("unsupported strategy %s", port.Strategy) - } - if cmd.CheckIllegal(port.Protocol, port.Port) { - return buserr.New(constant.ErrCmdIllegal) - } - - command := fmt.Sprintf("%s %s %s", f.CmdStr, port.Strategy, port.Port) - if operation == "remove" { - command = fmt.Sprintf("%s delete %s %s", f.CmdStr, port.Strategy, port.Port) - } - if len(port.Protocol) != 0 { - command += fmt.Sprintf("/%s", port.Protocol) - } - stdout, err := cmd.Exec(command) - if err != nil { - return fmt.Errorf("%s (%s) failed, err: %s", operation, command, stdout) - } - return nil -} - -func (f *Ufw) RichRules(rule FireInfo, operation string) error { - switch rule.Strategy { - case "accept": - rule.Strategy = "allow" - case "drop": - rule.Strategy = "deny" - default: - return fmt.Errorf("unsupported strategy %s", rule.Strategy) - } - - if cmd.CheckIllegal(operation, rule.Protocol, rule.Address, rule.Port) { - return buserr.New(constant.ErrCmdIllegal) - } - - ruleStr := fmt.Sprintf("%s insert 1 %s ", f.CmdStr, rule.Strategy) - if operation == "remove" { - ruleStr = fmt.Sprintf("%s delete %s ", f.CmdStr, rule.Strategy) - } - if len(rule.Protocol) != 0 { - ruleStr += fmt.Sprintf("proto %s ", rule.Protocol) - } - if strings.Contains(rule.Address, "-") { - ruleStr += fmt.Sprintf("from %s to %s ", strings.Split(rule.Address, "-")[0], strings.Split(rule.Address, "-")[1]) - } else { - ruleStr += fmt.Sprintf("from %s ", rule.Address) - } - if len(rule.Port) != 0 { - ruleStr += fmt.Sprintf("to any port %s ", rule.Port) - } - - stdout, err := cmd.Exec(ruleStr) - if err != nil { - if strings.Contains(stdout, "ERROR: Invalid position") || strings.Contains(stdout, "ERROR: 无效位置") { - stdout, err := cmd.Exec(strings.ReplaceAll(ruleStr, "insert 1 ", "")) - if err != nil { - return fmt.Errorf("%s rich rules (%s), failed, err: %s", operation, ruleStr, stdout) - } - return nil - } - return fmt.Errorf("%s rich rules (%s), failed, err: %s", operation, ruleStr, stdout) - } - return nil -} - -func (f *Ufw) PortForward(info Forward, operation string) error { - iptables, err := NewIptables() - if err != nil { - return err - } - - if operation == "add" { - err = iptables.NatAdd(info.Protocol, info.Port, info.TargetIP, info.TargetPort, true) - } else { - err = iptables.NatRemove(info.Num, info.Protocol, info.Port, info.TargetIP, info.TargetPort) - } - if err != nil { - return fmt.Errorf("%s port forward failed, err: %s", operation, err) - } - return nil -} - -func (f *Ufw) loadInfo(line string, fireType string) FireInfo { - fields := strings.Fields(line) - var itemInfo FireInfo - if strings.Contains(line, "LIMIT") || strings.Contains(line, "ALLOW FWD") { - return itemInfo - } - if len(fields) < 4 { - return itemInfo - } - if fields[1] == "(v6)" && fireType == "port" { - return itemInfo - } - if fields[0] == "Anywhere" && fireType != "port" { - itemInfo.Strategy = "drop" - if fields[1] == "ALLOW" { - itemInfo.Strategy = "accept" - } - if fields[1] == "(v6)" { - if fields[2] == "ALLOW" { - itemInfo.Strategy = "accept" - } - itemInfo.Address = fields[4] - } else { - itemInfo.Address = fields[3] - } - return itemInfo - } - if strings.Contains(fields[0], "/") { - itemInfo.Port = strings.Split(fields[0], "/")[0] - itemInfo.Protocol = strings.Split(fields[0], "/")[1] - } else { - itemInfo.Port = fields[0] - itemInfo.Protocol = "tcp/udp" - } - itemInfo.Family = "ipv4" - if fields[1] == "ALLOW" { - itemInfo.Strategy = "accept" - } else { - itemInfo.Strategy = "drop" - } - itemInfo.Address = fields[3] - - return itemInfo -} - -func (f *Ufw) EnableForward() error { - iptables, err := NewIptables() - if err != nil { - return err - } - _ = iptables.NatNewChain() - - rules, err := iptables.NatList("PREROUTING") - if err != nil { - return err - } - for _, rule := range rules { - if rule.Target == NatChain { - goto reload - } - } - - if err = iptables.NatAppendChain(); err != nil { - return err - } -reload: - return iptables.Reload() -} diff --git a/backend/utils/http/get.go b/backend/utils/http/get.go deleted file mode 100644 index 4dd90da55..000000000 --- a/backend/utils/http/get.go +++ /dev/null @@ -1,42 +0,0 @@ -package http - -import ( - "context" - "errors" - "net/http" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/utils/xpack" -) - -func GetHttpRes(url string) (*http.Response, error) { - client := &http.Client{ - Timeout: time.Second * 300, - } - transport := xpack.LoadRequestTransport() - client.Transport = transport - - req, err := http.NewRequestWithContext(context.Background(), "GET", url, nil) - if err != nil { - return nil, buserr.WithMap("ErrCreateHttpClient", map[string]interface{}{"err": err.Error()}, err) - } - - resp, err := client.Do(req) - if err != nil { - if errors.Is(err, context.DeadlineExceeded) { - return nil, buserr.WithMap("ErrHttpReqTimeOut", map[string]interface{}{"err": err.Error()}, err) - } else { - if strings.Contains(err.Error(), "no such host") { - return nil, buserr.New("ErrNoSuchHost") - } - return nil, buserr.WithMap("ErrHttpReqFailed", map[string]interface{}{"err": err.Error()}, err) - } - } - if resp.StatusCode == 404 { - return nil, buserr.New("ErrHttpReqNotFound") - } - - return resp, nil -} diff --git a/backend/utils/http/request.go b/backend/utils/http/request.go deleted file mode 100644 index 6445ec8ef..000000000 --- a/backend/utils/http/request.go +++ /dev/null @@ -1,45 +0,0 @@ -package http - -import ( - "context" - "io" - "net/http" - "time" - - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/xpack" -) - -func HandleGet(url, method string, timeout int) (int, []byte, error) { - transport := xpack.LoadRequestTransport() - return HandleGetWithTransport(url, method, transport, timeout) -} - -func HandleGetWithTransport(url, method string, transport *http.Transport, timeout int) (int, []byte, error) { - defer func() { - if r := recover(); r != nil { - global.LOG.Errorf("handle request failed, error message: %v", r) - return - } - }() - - client := http.Client{Timeout: time.Duration(timeout) * time.Second, Transport: transport} - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) - defer cancel() - request, err := http.NewRequestWithContext(ctx, method, url, nil) - if err != nil { - return 0, nil, err - } - request.Header.Set("Content-Type", "application/json") - resp, err := client.Do(request) - if err != nil { - return 0, nil, err - } - body, err := io.ReadAll(resp.Body) - if err != nil { - return 0, nil, err - } - defer resp.Body.Close() - - return resp.StatusCode, body, nil -} diff --git a/backend/utils/ini_conf/ini.go b/backend/utils/ini_conf/ini.go deleted file mode 100644 index 4ea80a2a6..000000000 --- a/backend/utils/ini_conf/ini.go +++ /dev/null @@ -1,19 +0,0 @@ -package ini_conf - -import "gopkg.in/ini.v1" - -func GetIniValue(filePath, Group, Key string) (string, error) { - cfg, err := ini.Load(filePath) - if err != nil { - return "", err - } - service, err := cfg.GetSection(Group) - if err != nil { - return "", err - } - startKey, err := service.GetKey(Key) - if err != nil { - return "", err - } - return startKey.Value(), nil -} diff --git a/backend/utils/jwt/jwt.go b/backend/utils/jwt/jwt.go deleted file mode 100644 index f8c1c1529..000000000 --- a/backend/utils/jwt/jwt.go +++ /dev/null @@ -1,69 +0,0 @@ -package jwt - -import ( - "time" - - "github.com/1Panel-dev/1Panel/backend/app/repo" - "github.com/1Panel-dev/1Panel/backend/constant" - - "github.com/golang-jwt/jwt/v4" -) - -type JWT struct { - SigningKey []byte -} - -type JwtRequest struct { - BaseClaims - BufferTime int64 - jwt.RegisteredClaims -} - -type CustomClaims struct { - BaseClaims - BufferTime int64 - jwt.RegisteredClaims -} - -type BaseClaims struct { - ID uint - Name string -} - -func NewJWT() *JWT { - settingRepo := repo.NewISettingRepo() - jwtSign, _ := settingRepo.Get(settingRepo.WithByKey("JWTSigningKey")) - return &JWT{ - []byte(jwtSign.Value), - } -} - -func (j *JWT) CreateClaims(baseClaims BaseClaims) CustomClaims { - claims := CustomClaims{ - BaseClaims: baseClaims, - BufferTime: constant.JWTBufferTime, - RegisteredClaims: jwt.RegisteredClaims{ - ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Second * time.Duration(constant.JWTBufferTime))), - Issuer: constant.JWTIssuer, - }, - } - return claims -} - -func (j *JWT) CreateToken(request CustomClaims) (string, error) { - token := jwt.NewWithClaims(jwt.SigningMethodHS256, &request) - return token.SignedString(j.SigningKey) -} - -func (j *JWT) ParseToken(tokenStr string) (*JwtRequest, error) { - token, err := jwt.ParseWithClaims(tokenStr, &JwtRequest{}, func(token *jwt.Token) (interface{}, error) { - return j.SigningKey, nil - }) - if err != nil || token == nil { - return nil, constant.ErrTokenParse - } - if claims, ok := token.Claims.(*JwtRequest); ok && token.Valid { - return claims, nil - } - return nil, constant.ErrTokenParse -} diff --git a/backend/utils/mysql/client.go b/backend/utils/mysql/client.go deleted file mode 100644 index 364d0ea3e..000000000 --- a/backend/utils/mysql/client.go +++ /dev/null @@ -1,77 +0,0 @@ -package mysql - -import ( - "context" - "database/sql" - "errors" - "fmt" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/mysql/client" -) - -type MysqlClient interface { - Create(info client.CreateInfo) error - CreateUser(info client.CreateInfo, withDeleteDB bool) error - Delete(info client.DeleteInfo) error - - ChangePassword(info client.PasswordChangeInfo) error - ChangeAccess(info client.AccessChangeInfo) error - - Backup(info client.BackupInfo) error - Recover(info client.RecoverInfo) error - - SyncDB(version string) ([]client.SyncDBInfo, error) - Close() -} - -func NewMysqlClient(conn client.DBInfo) (MysqlClient, error) { - if conn.From == "local" { - connArgs := []string{"exec", conn.Address, conn.Type, "-u" + conn.Username, "-p" + conn.Password, "-e"} - return client.NewLocal(connArgs, conn.Type, conn.Address, conn.Password, conn.Database), nil - } - - if strings.Contains(conn.Address, ":") { - conn.Address = fmt.Sprintf("[%s]", conn.Address) - } - - tlsItem, err := client.ConnWithSSL(conn.SSL, conn.SkipVerify, conn.ClientKey, conn.ClientCert, conn.RootCert) - if err != nil { - return nil, err - } - connArgs := fmt.Sprintf("%s:%s@tcp(%s:%d)/?charset=utf8%s", conn.Username, conn.Password, conn.Address, conn.Port, tlsItem) - db, err := sql.Open("mysql", connArgs) - if err != nil { - return nil, err - } - - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(conn.Timeout)*time.Second) - defer cancel() - if err := db.PingContext(ctx); err != nil { - global.LOG.Errorf("test mysql conn failed, err: %v", err) - return nil, err - } - if errors.Is(ctx.Err(), context.DeadlineExceeded) { - return nil, buserr.New(constant.ErrExecTimeOut) - } - - return client.NewRemote(client.Remote{ - Type: conn.Type, - Client: db, - Database: conn.Database, - User: conn.Username, - Password: conn.Password, - Address: conn.Address, - Port: conn.Port, - - SSL: conn.SSL, - RootCert: conn.RootCert, - ClientKey: conn.ClientKey, - ClientCert: conn.ClientCert, - SkipVerify: conn.SkipVerify, - }), nil -} diff --git a/backend/utils/mysql/client/info.go b/backend/utils/mysql/client/info.go deleted file mode 100644 index 3c6c4c25b..000000000 --- a/backend/utils/mysql/client/info.go +++ /dev/null @@ -1,137 +0,0 @@ -package client - -import ( - "crypto/tls" - "crypto/x509" - "errors" - - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/go-sql-driver/mysql" -) - -type DBInfo struct { - Type string `json:"type"` - From string `json:"from"` - Database string `json:"database"` - Address string `json:"address"` - Port uint `json:"port"` - Username string `json:"userName"` - Password string `json:"password"` - - SSL bool `json:"ssl"` - RootCert string `json:"rootCert"` - ClientKey string `json:"clientKey"` - ClientCert string `json:"clientCert"` - SkipVerify bool `json:"skipVerify"` - - Timeout uint `json:"timeout"` // second -} - -type CreateInfo struct { - Name string `json:"name"` - Format string `json:"format"` - Version string `json:"version"` - Username string `json:"userName"` - Password string `json:"password"` - Permission string `json:"permission"` - - Timeout uint `json:"timeout"` // second -} - -type DeleteInfo struct { - Name string `json:"name"` - Version string `json:"version"` - Username string `json:"userName"` - Permission string `json:"permission"` - - ForceDelete bool `json:"forceDelete"` - Timeout uint `json:"timeout"` // second -} - -type PasswordChangeInfo struct { - Name string `json:"name"` - Version string `json:"version"` - Username string `json:"userName"` - Password string `json:"password"` - Permission string `json:"permission"` - - Timeout uint `json:"timeout"` // second -} - -type AccessChangeInfo struct { - Name string `json:"name"` - Version string `json:"version"` - Username string `json:"userName"` - Password string `json:"password"` - OldPermission string `json:"oldPermission"` - Permission string `json:"permission"` - - Timeout uint `json:"timeout"` // second -} - -type BackupInfo struct { - Name string `json:"name"` - Type string `json:"type"` - Version string `json:"version"` - Format string `json:"format"` - TargetDir string `json:"targetDir"` - FileName string `json:"fileName"` - - Timeout uint `json:"timeout"` // second -} - -type RecoverInfo struct { - Name string `json:"name"` - Type string `json:"type"` - Version string `json:"version"` - Format string `json:"format"` - SourceFile string `json:"sourceFile"` - - Timeout uint `json:"timeout"` // second -} - -type SyncDBInfo struct { - Name string `json:"name"` - From string `json:"from"` - MysqlName string `json:"mysqlName"` - Format string `json:"format"` - Username string `json:"username"` - Password string `json:"password"` - Permission string `json:"permission"` -} - -var formatMap = map[string]string{ - "utf8": "utf8_general_ci", - "utf8mb4": "utf8mb4_general_ci", - "gbk": "gbk_chinese_ci", - "big5": "big5_chinese_ci", -} - -func ConnWithSSL(ssl, skipVerify bool, clientKey, clientCert, rootCert string) (string, error) { - if !ssl { - return "", nil - } - tlsConfig := &tls.Config{ - InsecureSkipVerify: skipVerify, - } - if len(rootCert) != 0 { - pool := x509.NewCertPool() - if ok := pool.AppendCertsFromPEM([]byte(rootCert)); !ok { - global.LOG.Error("append certs from pem failed") - return "", errors.New("unable to append root cert to pool") - } - tlsConfig.RootCAs = pool - } - if len(clientCert) != 0 && len(clientKey) != 0 { - cert, err := tls.X509KeyPair([]byte(clientCert), []byte(clientKey)) - if err != nil { - return "", err - } - tlsConfig.Certificates = []tls.Certificate{cert} - } - if err := mysql.RegisterTLSConfig("cloudsql", tlsConfig); err != nil { - global.LOG.Errorf("register tls config failed, err: %v", err) - return "", err - } - return "&tls=cloudsql", nil -} diff --git a/backend/utils/mysql/client/local.go b/backend/utils/mysql/client/local.go deleted file mode 100644 index 3110e3f06..000000000 --- a/backend/utils/mysql/client/local.go +++ /dev/null @@ -1,381 +0,0 @@ -package client - -import ( - "bytes" - "compress/gzip" - "context" - "errors" - "fmt" - "os" - "os/exec" - "path" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/files" -) - -type Local struct { - Type string - PrefixCommand []string - Database string - Password string - ContainerName string -} - -func NewLocal(command []string, dbType, containerName, password, database string) *Local { - return &Local{Type: dbType, PrefixCommand: command, ContainerName: containerName, Password: password, Database: database} -} - -func (r *Local) Create(info CreateInfo) error { - createSql := fmt.Sprintf("create database `%s` default character set %s collate %s", info.Name, info.Format, formatMap[info.Format]) - if err := r.ExecSQL(createSql, info.Timeout); err != nil { - if strings.Contains(strings.ToLower(err.Error()), "error 1007") { - return buserr.New(constant.ErrDatabaseIsExist) - } - return err - } - - if err := r.CreateUser(info, true); err != nil { - _ = r.ExecSQL(fmt.Sprintf("drop database if exists `%s`", info.Name), info.Timeout) - return err - } - - return nil -} - -func (r *Local) CreateUser(info CreateInfo, withDeleteDB bool) error { - var userlist []string - if strings.Contains(info.Permission, ",") { - ips := strings.Split(info.Permission, ",") - for _, ip := range ips { - if len(ip) != 0 { - userlist = append(userlist, fmt.Sprintf("'%s'@'%s'", info.Username, ip)) - } - } - } else { - userlist = append(userlist, fmt.Sprintf("'%s'@'%s'", info.Username, info.Permission)) - } - - for _, user := range userlist { - if err := r.ExecSQL(fmt.Sprintf("create user %s identified by '%s';", user, info.Password), info.Timeout); err != nil { - if strings.Contains(strings.ToLower(err.Error()), "error 1396") { - return buserr.New(constant.ErrUserIsExist) - } - if withDeleteDB { - _ = r.Delete(DeleteInfo{ - Name: info.Name, - Version: info.Version, - Username: info.Username, - Permission: info.Permission, - ForceDelete: true, - Timeout: 300}) - } - return err - } - grantStr := fmt.Sprintf("grant all privileges on `%s`.* to %s", info.Name, user) - if info.Name == "*" { - grantStr = fmt.Sprintf("grant all privileges on *.* to %s", user) - } - if strings.HasPrefix(info.Version, "5.7") || strings.HasPrefix(info.Version, "5.6") { - grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, info.Password) - } else { - grantStr = grantStr + " with grant option;" - } - if err := r.ExecSQL(grantStr, info.Timeout); err != nil { - if withDeleteDB { - _ = r.Delete(DeleteInfo{ - Name: info.Name, - Version: info.Version, - Username: info.Username, - Permission: info.Permission, - ForceDelete: true, - Timeout: 300}) - } - return err - } - } - return nil -} - -func (r *Local) Delete(info DeleteInfo) error { - var userlist []string - if strings.Contains(info.Permission, ",") { - ips := strings.Split(info.Permission, ",") - for _, ip := range ips { - if len(ip) != 0 { - userlist = append(userlist, fmt.Sprintf("'%s'@'%s'", info.Username, ip)) - } - } - } else { - userlist = append(userlist, fmt.Sprintf("'%s'@'%s'", info.Username, info.Permission)) - } - - for _, user := range userlist { - if strings.HasPrefix(info.Version, "5.6") { - if err := r.ExecSQL(fmt.Sprintf("drop user %s", user), info.Timeout); err != nil && !info.ForceDelete { - return err - } - } else { - if err := r.ExecSQL(fmt.Sprintf("drop user if exists %s", user), info.Timeout); err != nil && !info.ForceDelete { - return err - } - } - } - if len(info.Name) != 0 { - if err := r.ExecSQL(fmt.Sprintf("drop database if exists `%s`", info.Name), info.Timeout); err != nil && !info.ForceDelete { - return err - } - } - if !info.ForceDelete { - global.LOG.Info("execute delete database sql successful, now start to drop uploads and records") - } - - return nil -} - -func (r *Local) ChangePassword(info PasswordChangeInfo) error { - if info.Username != "root" { - var userlist []string - if strings.Contains(info.Permission, ",") { - ips := strings.Split(info.Permission, ",") - for _, ip := range ips { - if len(ip) != 0 { - userlist = append(userlist, fmt.Sprintf("'%s'@'%s'", info.Username, ip)) - } - } - } else { - userlist = append(userlist, fmt.Sprintf("'%s'@'%s'", info.Username, info.Permission)) - } - - for _, user := range userlist { - passwordChangeSql := fmt.Sprintf("set password for %s = password('%s')", user, info.Password) - if !strings.HasPrefix(info.Version, "5.7") && !strings.HasPrefix(info.Version, "5.6") { - passwordChangeSql = fmt.Sprintf("ALTER USER %s IDENTIFIED BY '%s';", user, info.Password) - } - if err := r.ExecSQL(passwordChangeSql, info.Timeout); err != nil { - return err - } - } - return nil - } - - hosts, err := r.ExecSQLForRows("select host from mysql.user where user='root';", info.Timeout) - if err != nil { - return err - } - for _, host := range hosts { - if host == "%" || host == "localhost" { - passwordRootChangeCMD := fmt.Sprintf("set password for 'root'@'%s' = password('%s')", host, info.Password) - if !strings.HasPrefix(info.Version, "5.7") && !strings.HasPrefix(info.Version, "5.6") { - passwordRootChangeCMD = fmt.Sprintf("alter user 'root'@'%s' identified by '%s';", host, info.Password) - } - if err := r.ExecSQL(passwordRootChangeCMD, info.Timeout); err != nil { - return err - } - } - } - - return nil -} - -func (r *Local) ChangeAccess(info AccessChangeInfo) error { - if info.Username == "root" { - info.OldPermission = "%" - info.Name = "*" - info.Password = r.Password - } - if info.Permission != info.OldPermission { - if err := r.Delete(DeleteInfo{ - Version: info.Version, - Username: info.Username, - Permission: info.OldPermission, - ForceDelete: true, - Timeout: 300}); err != nil { - return err - } - if info.Username == "root" { - return nil - } - } - if err := r.CreateUser(CreateInfo{ - Name: info.Name, - Version: info.Version, - Username: info.Username, - Password: info.Password, - Permission: info.Permission, - Timeout: info.Timeout, - }, false); err != nil { - return err - } - if err := r.ExecSQL("flush privileges", 300); err != nil { - return err - } - return nil -} - -func (r *Local) Backup(info BackupInfo) error { - fileOp := files.NewFileOp() - if !fileOp.Stat(info.TargetDir) { - if err := os.MkdirAll(info.TargetDir, os.ModePerm); err != nil { - return fmt.Errorf("mkdir %s failed, err: %v", info.TargetDir, err) - } - } - outfile, err := os.OpenFile(path.Join(info.TargetDir, info.FileName), os.O_RDWR|os.O_CREATE, 0755) - if err != nil { - return fmt.Errorf("open file %s failed, err: %v", path.Join(info.TargetDir, info.FileName), err) - } - defer outfile.Close() - dumpCmd := "mysqldump" - if r.Type == constant.AppMariaDB { - dumpCmd = "mariadb-dump" - } - global.LOG.Infof("start to %s | gzip > %s.gzip", dumpCmd, info.TargetDir+"/"+info.FileName) - cmd := exec.Command("docker", "exec", r.ContainerName, dumpCmd, "-uroot", "-p"+r.Password, "--default-character-set="+info.Format, info.Name) - var stderr bytes.Buffer - cmd.Stderr = &stderr - - gzipCmd := exec.Command("gzip", "-cf") - gzipCmd.Stdin, _ = cmd.StdoutPipe() - gzipCmd.Stdout = outfile - _ = gzipCmd.Start() - - if err := cmd.Run(); err != nil { - return fmt.Errorf("handle backup database failed, err: %v", stderr.String()) - } - _ = gzipCmd.Wait() - return nil -} - -func (r *Local) Recover(info RecoverInfo) error { - fi, _ := os.Open(info.SourceFile) - defer fi.Close() - cmd := exec.Command("docker", "exec", "-i", r.ContainerName, r.Type, "-uroot", "-p"+r.Password, "--default-character-set="+info.Format, info.Name) - if strings.HasSuffix(info.SourceFile, ".gz") { - gzipFile, err := os.Open(info.SourceFile) - if err != nil { - return err - } - defer gzipFile.Close() - gzipReader, err := gzip.NewReader(gzipFile) - if err != nil { - return err - } - defer gzipReader.Close() - cmd.Stdin = gzipReader - } else { - cmd.Stdin = fi - } - stdout, err := cmd.CombinedOutput() - stdStr := strings.ReplaceAll(string(stdout), "mysql: [Warning] Using a password on the command line interface can be insecure.\n", "") - if err != nil || strings.HasPrefix(string(stdStr), "ERROR ") { - return errors.New(stdStr) - } - - return nil -} - -func (r *Local) SyncDB(version string) ([]SyncDBInfo, error) { - var datas []SyncDBInfo - lines, err := r.ExecSQLForRows("SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME FROM information_schema.SCHEMATA", 300) - if err != nil { - return datas, err - } - for _, line := range lines { - parts := strings.Fields(line) - if len(parts) != 2 { - continue - } - if parts[0] == "SCHEMA_NAME" || parts[0] == "information_schema" || parts[0] == "mysql" || parts[0] == "performance_schema" || parts[0] == "sys" || parts[0] == "__recycle_bin__" || parts[0] == "recycle_bin" { - continue - } - dataItem := SyncDBInfo{ - Name: parts[0], - From: "local", - MysqlName: r.Database, - Format: parts[1], - } - userLines, err := r.ExecSQLForRows(fmt.Sprintf("select user,host from mysql.db where db = '%s'", parts[0]), 300) - if err != nil { - global.LOG.Debugf("sync user of db %s failed, err: %v", parts[0], err) - dataItem.Permission = "%" - datas = append(datas, dataItem) - continue - } - - var permissionItem []string - isLocal := true - i := 0 - for _, userline := range userLines { - userparts := strings.Fields(userline) - if len(userparts) != 2 { - continue - } - if userparts[0] == "root" { - continue - } - if i == 0 { - dataItem.Username = userparts[0] - } - dataItem.Username = userparts[0] - if dataItem.Username == userparts[0] && userparts[1] == "%" { - isLocal = false - dataItem.Permission = "%" - } else if dataItem.Username == userparts[0] && userparts[1] != "localhost" { - isLocal = false - permissionItem = append(permissionItem, userparts[1]) - } - } - if len(dataItem.Username) == 0 { - dataItem.Permission = "%" - } else { - if isLocal { - dataItem.Permission = "localhost" - } - if len(dataItem.Permission) == 0 { - dataItem.Permission = strings.Join(permissionItem, ",") - } - } - datas = append(datas, dataItem) - } - return datas, nil -} - -func (r *Local) Close() {} - -func (r *Local) ExecSQL(command string, timeout uint) error { - itemCommand := r.PrefixCommand[:] - itemCommand = append(itemCommand, command) - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) - defer cancel() - cmd := exec.CommandContext(ctx, "docker", itemCommand...) - stdout, err := cmd.CombinedOutput() - if errors.Is(ctx.Err(), context.DeadlineExceeded) { - return buserr.New(constant.ErrExecTimeOut) - } - stdStr := strings.ReplaceAll(string(stdout), "mysql: [Warning] Using a password on the command line interface can be insecure.\n", "") - if err != nil || strings.HasPrefix(string(stdStr), "ERROR ") { - return errors.New(stdStr) - } - return nil -} - -func (r *Local) ExecSQLForRows(command string, timeout uint) ([]string, error) { - itemCommand := r.PrefixCommand[:] - itemCommand = append(itemCommand, command) - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) - defer cancel() - cmd := exec.CommandContext(ctx, "docker", itemCommand...) - stdout, err := cmd.CombinedOutput() - if errors.Is(ctx.Err(), context.DeadlineExceeded) { - return nil, buserr.New(constant.ErrExecTimeOut) - } - stdStr := strings.ReplaceAll(string(stdout), "mysql: [Warning] Using a password on the command line interface can be insecure.\n", "") - if err != nil || strings.HasPrefix(string(stdStr), "ERROR ") { - return nil, errors.New(stdStr) - } - return strings.Split(stdStr, "\n"), nil -} diff --git a/backend/utils/mysql/client/remote.go b/backend/utils/mysql/client/remote.go deleted file mode 100644 index 9596ba9de..000000000 --- a/backend/utils/mysql/client/remote.go +++ /dev/null @@ -1,472 +0,0 @@ -package client - -import ( - "bytes" - "compress/gzip" - "context" - "database/sql" - "errors" - "fmt" - "os" - "os/exec" - "path" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/client" -) - -type Remote struct { - Type string - Client *sql.DB - Database string - User string - Password string - Address string - Port uint - - SSL bool - RootCert string - ClientKey string - ClientCert string - SkipVerify bool -} - -func NewRemote(db Remote) *Remote { - return &db -} - -func (r *Remote) Create(info CreateInfo) error { - createSql := fmt.Sprintf("create database `%s` default character set %s collate %s", info.Name, info.Format, formatMap[info.Format]) - if err := r.ExecSQL(createSql, info.Timeout); err != nil { - if strings.Contains(strings.ToLower(err.Error()), "error 1007") { - return buserr.New(constant.ErrDatabaseIsExist) - } - return err - } - - if err := r.CreateUser(info, true); err != nil { - _ = r.ExecSQL(fmt.Sprintf("drop database if exists `%s`", info.Name), info.Timeout) - return err - } - - return nil -} - -func (r *Remote) CreateUser(info CreateInfo, withDeleteDB bool) error { - var userlist []string - if strings.Contains(info.Permission, ",") { - ips := strings.Split(info.Permission, ",") - for _, ip := range ips { - if len(ip) != 0 { - userlist = append(userlist, fmt.Sprintf("'%s'@'%s'", info.Username, ip)) - } - } - } else { - userlist = append(userlist, fmt.Sprintf("'%s'@'%s'", info.Username, info.Permission)) - } - - for _, user := range userlist { - if err := r.ExecSQL(fmt.Sprintf("create user %s identified by '%s';", user, info.Password), info.Timeout); err != nil { - if strings.Contains(strings.ToLower(err.Error()), "error 1396") { - return buserr.New(constant.ErrUserIsExist) - } - if withDeleteDB { - _ = r.Delete(DeleteInfo{ - Name: info.Name, - Version: info.Version, - Username: info.Username, - Permission: info.Permission, - ForceDelete: true, - Timeout: 300}) - } - return err - } - grantStr := fmt.Sprintf("grant all privileges on `%s`.* to %s", info.Name, user) - if info.Name == "*" { - grantStr = fmt.Sprintf("grant all privileges on *.* to %s", user) - } - if strings.HasPrefix(info.Version, "5.7") || strings.HasPrefix(info.Version, "5.6") { - grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, info.Password) - } else { - grantStr = grantStr + " with grant option;" - } - if err := r.ExecSQL(grantStr, info.Timeout); err != nil { - if withDeleteDB { - _ = r.Delete(DeleteInfo{ - Name: info.Name, - Version: info.Version, - Username: info.Username, - Permission: info.Permission, - ForceDelete: true, - Timeout: 300}) - } - return err - } - } - return nil -} - -func (r *Remote) Delete(info DeleteInfo) error { - var userlist []string - if strings.Contains(info.Permission, ",") { - ips := strings.Split(info.Permission, ",") - for _, ip := range ips { - if len(ip) != 0 { - userlist = append(userlist, fmt.Sprintf("'%s'@'%s'", info.Username, ip)) - } - } - } else { - userlist = append(userlist, fmt.Sprintf("'%s'@'%s'", info.Username, info.Permission)) - } - - for _, user := range userlist { - if strings.HasPrefix(info.Version, "5.6") { - if err := r.ExecSQL(fmt.Sprintf("drop user %s", user), info.Timeout); err != nil && !info.ForceDelete { - return err - } - } else { - if err := r.ExecSQL(fmt.Sprintf("drop user if exists %s", user), info.Timeout); err != nil && !info.ForceDelete { - return err - } - } - } - if len(info.Name) != 0 { - if err := r.ExecSQL(fmt.Sprintf("drop database if exists `%s`", info.Name), info.Timeout); err != nil && !info.ForceDelete { - return err - } - } - if !info.ForceDelete { - global.LOG.Info("execute delete database sql successful, now start to drop uploads and records") - } - - return nil -} - -func (r *Remote) ChangePassword(info PasswordChangeInfo) error { - if info.Username != "root" { - var userlist []string - if strings.Contains(info.Permission, ",") { - ips := strings.Split(info.Permission, ",") - for _, ip := range ips { - if len(ip) != 0 { - userlist = append(userlist, fmt.Sprintf("'%s'@'%s'", info.Username, ip)) - } - } - } else { - userlist = append(userlist, fmt.Sprintf("'%s'@'%s'", info.Username, info.Permission)) - } - - for _, user := range userlist { - passwordChangeSql := fmt.Sprintf("set password for %s = password('%s')", user, info.Password) - if !strings.HasPrefix(info.Version, "5.7") && !strings.HasPrefix(info.Version, "5.6") { - passwordChangeSql = fmt.Sprintf("ALTER USER %s IDENTIFIED BY '%s';", user, info.Password) - } - if err := r.ExecSQL(passwordChangeSql, info.Timeout); err != nil { - return err - } - } - return nil - } - - hosts, err := r.ExecSQLForHosts(info.Timeout) - if err != nil { - return err - } - for _, host := range hosts { - if host == "%" || host == "localhost" { - passwordRootChangeCMD := fmt.Sprintf("set password for 'root'@'%s' = password('%s')", host, info.Password) - if !strings.HasPrefix(info.Version, "5.7") && !strings.HasPrefix(info.Version, "5.6") { - passwordRootChangeCMD = fmt.Sprintf("alter user 'root'@'%s' identified by '%s';", host, info.Password) - } - if err := r.ExecSQL(passwordRootChangeCMD, info.Timeout); err != nil { - return err - } - } - } - - return nil -} - -func (r *Remote) ChangeAccess(info AccessChangeInfo) error { - if info.Username == "root" { - info.OldPermission = "%" - info.Name = "*" - info.Password = r.Password - } - if info.Permission != info.OldPermission { - if err := r.Delete(DeleteInfo{ - Version: info.Version, - Username: info.Username, - Permission: info.OldPermission, - ForceDelete: true, - Timeout: 300}); err != nil { - return err - } - if info.Username == "root" { - return nil - } - } - if err := r.CreateUser(CreateInfo{ - Name: info.Name, - Version: info.Version, - Username: info.Username, - Password: info.Password, - Permission: info.Permission, - Timeout: info.Timeout, - }, false); err != nil { - return err - } - if err := r.ExecSQL("flush privileges", 300); err != nil { - return err - } - return nil -} - -func (r *Remote) Backup(info BackupInfo) error { - fileOp := files.NewFileOp() - if !fileOp.Stat(info.TargetDir) { - if err := os.MkdirAll(info.TargetDir, os.ModePerm); err != nil { - return fmt.Errorf("mkdir %s failed, err: %v", info.TargetDir, err) - } - } - outfile, err := os.OpenFile(path.Join(info.TargetDir, info.FileName), os.O_RDWR|os.O_CREATE, 0755) - if err != nil { - return fmt.Errorf("open file %s failed, err: %v", path.Join(info.TargetDir, info.FileName), err) - } - defer outfile.Close() - dumpCmd := "mysqldump" - if r.Type == constant.AppMariaDB { - dumpCmd = "mariadb-dump" - } - global.LOG.Infof("start to %s | gzip > %s.gzip", dumpCmd, info.TargetDir+"/"+info.FileName) - image, err := loadImage(info.Type, info.Version) - if err != nil { - return err - } - backupCmd := fmt.Sprintf("docker run --rm --net=host -i %s /bin/bash -c '%s -h %s -P %d -u%s -p%s %s --default-character-set=%s %s'", - image, dumpCmd, r.Address, r.Port, r.User, r.Password, sslSkip(info.Version, r.Type), info.Format, info.Name) - - global.LOG.Debug(strings.ReplaceAll(backupCmd, r.Password, "******")) - cmd := exec.Command("bash", "-c", backupCmd) - var stderr bytes.Buffer - cmd.Stderr = &stderr - - gzipCmd := exec.Command("gzip", "-cf") - gzipCmd.Stdin, _ = cmd.StdoutPipe() - gzipCmd.Stdout = outfile - - _ = gzipCmd.Start() - if err := cmd.Run(); err != nil { - return fmt.Errorf("handle backup database failed, err: %v", stderr.String()) - } - _ = gzipCmd.Wait() - return nil -} - -func (r *Remote) Recover(info RecoverInfo) error { - fi, _ := os.Open(info.SourceFile) - defer fi.Close() - - image, err := loadImage(info.Type, info.Version) - if err != nil { - return err - } - - recoverCmd := fmt.Sprintf("docker run --rm --net=host -i %s /bin/bash -c '%s -h %s -P %d -u%s -p%s %s --default-character-set=%s %s'", - image, r.Type, r.Address, r.Port, r.User, r.Password, sslSkip(info.Version, r.Type), info.Format, info.Name) - - global.LOG.Debug(strings.ReplaceAll(recoverCmd, r.Password, "******")) - cmd := exec.Command("bash", "-c", recoverCmd) - - if strings.HasSuffix(info.SourceFile, ".gz") { - gzipFile, err := os.Open(info.SourceFile) - if err != nil { - return err - } - defer gzipFile.Close() - gzipReader, err := gzip.NewReader(gzipFile) - if err != nil { - return err - } - defer gzipReader.Close() - cmd.Stdin = gzipReader - } else { - cmd.Stdin = fi - } - stdout, err := cmd.CombinedOutput() - stdStr := strings.ReplaceAll(string(stdout), "mysql: [Warning] Using a password on the command line interface can be insecure.\n", "") - if err != nil || strings.HasPrefix(string(stdStr), "ERROR ") { - return errors.New(stdStr) - } - - return nil -} - -func (r *Remote) SyncDB(version string) ([]SyncDBInfo, error) { - var datas []SyncDBInfo - rows, err := r.Client.Query("select schema_name, default_character_set_name from information_schema.SCHEMATA") - if err != nil { - return datas, err - } - defer rows.Close() - - for rows.Next() { - var dbName, charsetName string - if err = rows.Scan(&dbName, &charsetName); err != nil { - return datas, err - } - if dbName == "information_schema" || dbName == "mysql" || dbName == "performance_schema" || dbName == "sys" || dbName == "__recycle_bin__" || dbName == "recycle_bin" { - continue - } - dataItem := SyncDBInfo{ - Name: dbName, - From: "remote", - MysqlName: r.Database, - Format: charsetName, - } - userRows, err := r.Client.Query("select user,host from mysql.db where db = ?", dbName) - if err != nil { - global.LOG.Debugf("sync user of db %s failed, err: %v", dbName, err) - dataItem.Permission = "%" - datas = append(datas, dataItem) - continue - } - - var permissionItem []string - isLocal := true - i := 0 - for userRows.Next() { - var user, host string - if err = userRows.Scan(&user, &host); err != nil { - return datas, err - } - if user == "root" { - continue - } - if i == 0 { - dataItem.Username = user - } - if dataItem.Username == user && host == "%" { - isLocal = false - dataItem.Permission = "%" - } else if dataItem.Username == user && host != "localhost" { - isLocal = false - permissionItem = append(permissionItem, host) - } - i++ - } - if len(dataItem.Username) == 0 { - dataItem.Permission = "%" - } else { - if isLocal { - dataItem.Permission = "localhost" - } - if len(dataItem.Permission) == 0 { - dataItem.Permission = strings.Join(permissionItem, ",") - } - } - datas = append(datas, dataItem) - } - if err = rows.Err(); err != nil { - return datas, err - } - return datas, nil -} - -func (r *Remote) Close() { - _ = r.Client.Close() -} - -func (r *Remote) ExecSQL(command string, timeout uint) error { - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) - defer cancel() - - if _, err := r.Client.ExecContext(ctx, command); err != nil { - return err - } - if errors.Is(ctx.Err(), context.DeadlineExceeded) { - return buserr.New(constant.ErrExecTimeOut) - } - - return nil -} - -func (r *Remote) ExecSQLForHosts(timeout uint) ([]string, error) { - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) - defer cancel() - - results, err := r.Client.QueryContext(ctx, "select host from mysql.user where user='root';") - if err != nil { - return nil, err - } - if errors.Is(ctx.Err(), context.DeadlineExceeded) { - return nil, buserr.New(constant.ErrExecTimeOut) - } - var rows []string - for results.Next() { - var host string - if err := results.Scan(&host); err != nil { - continue - } - rows = append(rows, host) - } - return rows, nil -} - -func loadImage(dbType, version string) (string, error) { - cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) - if err != nil { - return "", err - } - images, err := cli.ImageList(context.Background(), image.ListOptions{}) - if err != nil { - return "", err - } - - for _, image := range images { - for _, tag := range image.RepoTags { - if !strings.HasPrefix(tag, dbType+":") { - continue - } - if dbType == "mariadb" && strings.HasPrefix(tag, "mariadb:") { - return tag, nil - } - if strings.HasPrefix(version, "5.6") && strings.HasPrefix(tag, "mysql:5.6") { - return tag, nil - } - if strings.HasPrefix(version, "5.7") && strings.HasPrefix(tag, "mysql:5.7") { - return tag, nil - } - if strings.HasPrefix(version, "8.") && strings.HasPrefix(tag, "mysql:8.") { - return tag, nil - } - } - } - return loadVersion(dbType, version), nil -} - -func loadVersion(dbType string, version string) string { - if dbType == "mariadb" { - return "mariadb:11.3.2 " - } - if strings.HasPrefix(version, "5.6") { - return "mysql:5.6.51" - } - if strings.HasPrefix(version, "5.7") { - return "mysql:5.7.44" - } - return "mysql:8.2.0" -} - -func sslSkip(version, dbType string) string { - if dbType == constant.AppMariaDB || strings.HasPrefix(version, "5.6") || strings.HasPrefix(version, "5.7") { - return "--skip-ssl" - } - return "--ssl-mode=DISABLED" -} diff --git a/backend/utils/mysql/helper/dump.go b/backend/utils/mysql/helper/dump.go deleted file mode 100644 index df0144592..000000000 --- a/backend/utils/mysql/helper/dump.go +++ /dev/null @@ -1,303 +0,0 @@ -package helper - -import ( - "bufio" - "database/sql" - "fmt" - "io" - "os" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - _ "github.com/go-sql-driver/mysql" -) - -func init() {} - -type dumpOption struct { - isData bool - - tables []string - isAllTable bool - isDropTable bool - writer io.Writer -} - -type DumpOption func(*dumpOption) - -func WithDropTable() DumpOption { - return func(option *dumpOption) { - option.isDropTable = true - } -} - -func WithData() DumpOption { - return func(option *dumpOption) { - option.isData = true - } -} - -func WithWriter(writer io.Writer) DumpOption { - return func(option *dumpOption) { - option.writer = writer - } -} - -func Dump(dns string, opts ...DumpOption) error { - start := time.Now() - global.LOG.Infof("dump start at %s\n", start.Format(constant.DateTimeLayout)) - defer func() { - end := time.Now() - global.LOG.Infof("dump end at %s, cost %s\n", end.Format(constant.DateTimeLayout), end.Sub(start)) - }() - - var err error - - var o dumpOption - - for _, opt := range opts { - opt(&o) - } - - if len(o.tables) == 0 { - o.isAllTable = true - } - - if o.writer == nil { - o.writer = os.Stdout - } - - buf := bufio.NewWriter(o.writer) - defer buf.Flush() - - itemFile, lineNumber := "", 0 - - itemFile += "-- ----------------------------\n" - itemFile += "-- MySQL Database Dump\n" - itemFile += "-- Start Time: " + start.Format(constant.DateTimeLayout) + "\n" - itemFile += "-- ----------------------------\n\n\n" - - db, err := sql.Open("mysql", dns) - if err != nil { - global.LOG.Errorf("open mysql db failed, err: %v", err) - return err - } - defer db.Close() - - dbName, err := getDBNameFromDNS(dns) - if err != nil { - global.LOG.Errorf("get db name from dns failed, err: %v", err) - return err - } - _, err = db.Exec(fmt.Sprintf("USE `%s`", dbName)) - if err != nil { - global.LOG.Errorf("exec `use %s` failed, err: %v", dbName, err) - return err - } - - var tables []string - if o.isAllTable { - tmp, err := getAllTables(db) - if err != nil { - global.LOG.Errorf("get all tables failed, err: %v", err) - return err - } - tables = tmp - } else { - tables = o.tables - } - - for _, table := range tables { - if o.isDropTable { - itemFile += fmt.Sprintf("DROP TABLE IF EXISTS `%s`;\n", table) - } - - itemFile += "-- ----------------------------\n" - itemFile += fmt.Sprintf("-- Table structure for %s\n", table) - itemFile += "-- ----------------------------\n" - - createTableSQL, err := getCreateTableSQL(db, table) - if err != nil { - global.LOG.Errorf("get create table sql failed, err: %v", err) - return err - } - itemFile += createTableSQL - itemFile += ";\n\n\n\n" - - if o.isData { - itemFile += "-- ----------------------------\n" - itemFile += fmt.Sprintf("-- Records of %s\n", table) - itemFile += "-- ----------------------------\n" - - lineRows, err := db.Query(fmt.Sprintf("SELECT * FROM `%s`", table)) - if err != nil { - global.LOG.Errorf("exec `select * from %s` failed, err: %v", table, err) - return err - } - defer lineRows.Close() - - var columns []string - columns, err = lineRows.Columns() - if err != nil { - global.LOG.Errorf("get columes failed, err: %v", err) - return err - } - columnTypes, err := lineRows.ColumnTypes() - if err != nil { - global.LOG.Errorf("get colume types failed, err: %v", err) - return err - } - for lineRows.Next() { - row := make([]interface{}, len(columns)) - rowPointers := make([]interface{}, len(columns)) - for i := range columns { - rowPointers[i] = &row[i] - } - if err = lineRows.Scan(rowPointers...); err != nil { - global.LOG.Errorf("scan row data failed, err: %v", err) - return err - } - ssql := loadDataSql(row, columnTypes, table) - if len(ssql) != 0 { - itemFile += ssql - lineNumber++ - } - if lineNumber > 500 { - _, _ = buf.WriteString(itemFile) - itemFile = "" - lineNumber = 0 - } - } - - itemFile += "\n\n" - } - } - - itemFile += "-- ----------------------------\n" - itemFile += "-- Dumped by mysqldump\n" - itemFile += "-- Cost Time: " + time.Since(start).String() + "\n" - itemFile += "-- ----------------------------\n" - - _, _ = buf.WriteString(itemFile) - _ = buf.Flush() - - return nil -} - -func getCreateTableSQL(db *sql.DB, table string) (string, error) { - var createTableSQL string - err := db.QueryRow(fmt.Sprintf("SHOW CREATE TABLE `%s`", table)).Scan(&table, &createTableSQL) - if err != nil { - return "", err - } - createTableSQL = strings.Replace(createTableSQL, "CREATE TABLE", "CREATE TABLE IF NOT EXISTS", 1) - return createTableSQL, nil -} - -func getAllTables(db *sql.DB) ([]string, error) { - var tables []string - rows, err := db.Query("SHOW TABLES") - if err != nil { - return nil, err - } - defer rows.Close() - - for rows.Next() { - var table string - err = rows.Scan(&table) - if err != nil { - return nil, err - } - tables = append(tables, table) - } - return tables, nil -} - -func loadDataSql(row []interface{}, columnTypes []*sql.ColumnType, table string) string { - ssql := "INSERT INTO `" + table + "` VALUES (" - for i, col := range row { - if col == nil { - ssql += "NULL" - } else { - Type := columnTypes[i].DatabaseTypeName() - Type = strings.Replace(Type, "UNSIGNED", "", -1) - Type = strings.Replace(Type, " ", "", -1) - switch Type { - case "TINYINT", "SMALLINT", "MEDIUMINT", "INT", "INTEGER", "BIGINT": - if bs, ok := col.([]byte); ok { - ssql += string(bs) - } else { - ssql += fmt.Sprintf("%d", col) - } - case "FLOAT", "DOUBLE": - if bs, ok := col.([]byte); ok { - ssql += string(bs) - } else { - ssql += fmt.Sprintf("%f", col) - } - case "DECIMAL", "DEC": - ssql += fmt.Sprintf("%s", col) - - case "DATE": - t, ok := col.(time.Time) - if !ok { - global.LOG.Errorf("the DATE type conversion failed, err value: %v", col) - return "" - } - ssql += fmt.Sprintf("'%s'", t.Format("2006-01-02")) - case "DATETIME": - t, ok := col.(time.Time) - if !ok { - global.LOG.Errorf("the DATETIME type conversion failed, err value: %v", col) - return "" - } - ssql += fmt.Sprintf("'%s'", t.Format(constant.DateTimeLayout)) - case "TIMESTAMP": - t, ok := col.(time.Time) - if !ok { - global.LOG.Errorf("the TIMESTAMP type conversion failed, err value: %v", col) - return "" - } - ssql += fmt.Sprintf("'%s'", t.Format(constant.DateTimeLayout)) - case "TIME": - t, ok := col.([]byte) - if !ok { - global.LOG.Errorf("the TIME type conversion failed, err value: %v", col) - return "" - } - ssql += fmt.Sprintf("'%s'", string(t)) - case "YEAR": - t, ok := col.([]byte) - if !ok { - global.LOG.Errorf("the YEAR type conversion failed, err value: %v", col) - return "" - } - ssql += string(t) - case "CHAR", "VARCHAR", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT": - ssql += fmt.Sprintf("'%s'", strings.Replace(fmt.Sprintf("%s", col), "'", "''", -1)) - case "BIT", "BINARY", "VARBINARY", "TINYBLOB", "BLOB", "MEDIUMBLOB", "LONGBLOB": - ssql += fmt.Sprintf("0x%X", col) - case "ENUM", "SET": - ssql += fmt.Sprintf("'%s'", col) - case "BOOL", "BOOLEAN": - if col.(bool) { - ssql += "true" - } else { - ssql += "false" - } - case "JSON": - ssql += fmt.Sprintf("'%s'", col) - default: - global.LOG.Errorf("unsupported colume type: %s", Type) - return "" - } - } - if i < len(row)-1 { - ssql += "," - } - } - ssql += ");\n" - return ssql -} diff --git a/backend/utils/mysql/helper/source.go b/backend/utils/mysql/helper/source.go deleted file mode 100644 index b15a5cd97..000000000 --- a/backend/utils/mysql/helper/source.go +++ /dev/null @@ -1,244 +0,0 @@ -package helper - -import ( - "bufio" - "database/sql" - "errors" - "fmt" - "io" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" -) - -type sourceOption struct { - dryRun bool - mergeInsert int - debug bool -} -type SourceOption func(*sourceOption) - -func WithMergeInsert(size int) SourceOption { - return func(o *sourceOption) { - o.mergeInsert = size - } -} - -type dbWrapper struct { - DB *sql.DB - debug bool - dryRun bool -} - -func newDBWrapper(db *sql.DB, dryRun, debug bool) *dbWrapper { - - return &dbWrapper{ - DB: db, - dryRun: dryRun, - debug: debug, - } -} - -func (db *dbWrapper) Exec(query string, args ...interface{}) (sql.Result, error) { - if db.debug { - global.LOG.Debugf("query %s", query) - } - - if db.dryRun { - return nil, nil - } - return db.DB.Exec(query, args...) -} - -func Source(dns string, reader io.Reader, opts ...SourceOption) error { - start := time.Now() - global.LOG.Infof("source start at %s", start.Format(constant.DateTimeLayout)) - defer func() { - end := time.Now() - global.LOG.Infof("source end at %s, cost %s", end.Format(constant.DateTimeLayout), end.Sub(start)) - }() - - var err error - var db *sql.DB - var o sourceOption - for _, opt := range opts { - opt(&o) - } - - dbName, err := getDBNameFromDNS(dns) - if err != nil { - global.LOG.Errorf("get db name from dns failed, err: %v", err) - return err - } - - db, err = sql.Open("mysql", dns) - if err != nil { - global.LOG.Errorf("open mysql db failed, err: %v", err) - return err - } - defer db.Close() - - dbWrapper := newDBWrapper(db, o.dryRun, o.debug) - - _, err = dbWrapper.Exec(fmt.Sprintf("USE `%s`;", dbName)) - if err != nil { - global.LOG.Errorf("exec `use %s` failed, err: %v", dbName, err) - return err - } - - db.SetConnMaxLifetime(3600) - - r := bufio.NewReader(reader) - _, err = dbWrapper.Exec("SET autocommit=0;") - if err != nil { - global.LOG.Errorf("exec `set autocommit=0` failed, err: %v", err) - return err - } - - for { - line, err := readLine(r) - if err != nil { - if err == io.EOF { - break - } - global.LOG.Errorf("read sql failed, err: %v", err) - return err - } - - ssql, err := trim(line) - if err != nil { - global.LOG.Errorf("trim sql failed, err: %v", err) - return err - } - - afterInsertSql := "" - if o.mergeInsert > 1 && strings.HasPrefix(ssql, "INSERT INTO") { - var insertSQLs []string - insertSQLs = append(insertSQLs, ssql) - for i := 0; i < o.mergeInsert-1; i++ { - line, err := readLine(r) - if err != nil { - if err == io.EOF { - break - } - return err - } - ssql2, err := trim(line) - if err != nil { - global.LOG.Errorf("trim merge insert sql failed, err: %v", err) - return err - } - if strings.HasPrefix(ssql2, "INSERT INTO") { - insertSQLs = append(insertSQLs, ssql2) - continue - } - afterInsertSql = ssql2 - break - } - ssql, err = mergeInsert(insertSQLs) - if err != nil { - global.LOG.Errorf("do merge insert failed, err: %v", err) - return err - } - } - - _, err = dbWrapper.Exec(ssql) - if err != nil { - global.LOG.Errorf("exec sql failed, err: %v", err) - return err - } - if len(afterInsertSql) != 0 { - _, err = dbWrapper.Exec(afterInsertSql) - if err != nil { - global.LOG.Errorf("exec sql failed, err: %v", err) - return err - } - } - } - - _, err = dbWrapper.Exec("COMMIT;") - if err != nil { - global.LOG.Errorf("exec `commit` failed, err: %v", err) - return err - } - - _, err = dbWrapper.Exec("SET autocommit=1;") - if err != nil { - global.LOG.Errorf("exec `autocommit=1` failed, err: %v", err) - return err - } - - return nil -} - -func mergeInsert(insertSQLs []string) (string, error) { - if len(insertSQLs) == 0 { - return "", errors.New("no input provided") - } - builder := strings.Builder{} - sql1 := insertSQLs[0] - sql1 = strings.TrimSuffix(sql1, ";") - builder.WriteString(sql1) - for i, insertSQL := range insertSQLs[1:] { - if i < len(insertSQLs)-1 { - builder.WriteString(",") - } - - valuesIdx := strings.Index(insertSQL, "VALUES") - if valuesIdx == -1 { - return "", errors.New("invalid SQL: missing VALUES keyword") - } - sqln := insertSQL[valuesIdx:] - sqln = strings.TrimPrefix(sqln, "VALUES") - sqln = strings.TrimSuffix(sqln, ";") - builder.WriteString(sqln) - - } - builder.WriteString(";") - - return builder.String(), nil -} - -func trim(s string) (string, error) { - s = strings.TrimLeft(s, "\n") - s = strings.TrimSpace(s) - return s, nil -} - -func getDBNameFromDNS(dns string) (string, error) { - ss1 := strings.Split(dns, "/") - if len(ss1) == 2 { - ss2 := strings.Split(ss1[1], "?") - if len(ss2) == 2 { - return ss2[0], nil - } - } - - return "", fmt.Errorf("dns error: %s", dns) -} - -func readLine(r *bufio.Reader) (string, error) { - lineItem, err := r.ReadString('\n') - if err != nil { - if err == io.EOF { - return lineItem, err - } - global.LOG.Errorf("read merge insert sql failed, err: %v", err) - return "", err - } - if strings.HasSuffix(lineItem, ";\n") { - return lineItem, nil - } - lineAppend, err := readLine(r) - if err != nil { - if err == io.EOF { - return lineItem, err - } - global.LOG.Errorf("read merge insert sql failed, err: %v", err) - return "", err - } - - return lineItem + lineAppend, nil -} diff --git a/backend/utils/nginx/components/block.go b/backend/utils/nginx/components/block.go deleted file mode 100644 index 0e07e7793..000000000 --- a/backend/utils/nginx/components/block.go +++ /dev/null @@ -1,88 +0,0 @@ -package components - -type Block struct { - Line int - Comment string - Directives []IDirective - IsLuaBlock bool - LiteralCode string -} - -func (b *Block) GetDirectives() []IDirective { - return b.Directives -} - -func (b *Block) GetComment() string { - return b.Comment -} - -func (b *Block) GetLine() int { - return b.Line -} - -func (b *Block) GetCodeBlock() string { - return b.LiteralCode -} - -func (b *Block) FindDirectives(directiveName string) []IDirective { - directives := make([]IDirective, 0) - for _, directive := range b.GetDirectives() { - if directive.GetName() == directiveName { - directives = append(directives, directive) - } - if directive.GetBlock() != nil { - directives = append(directives, directive.GetBlock().FindDirectives(directiveName)...) - } - } - - return directives -} - -func (b *Block) UpdateDirective(key string, params []string) { - if key == "" || len(params) == 0 { - return - } - directives := b.GetDirectives() - index := -1 - for i, dir := range directives { - if dir.GetName() == key { - if IsRepeatKey(key) { - oldParams := dir.GetParameters() - if !(len(oldParams) > 0 && oldParams[0] == params[0]) { - continue - } - } - index = i - break - } - } - newDirective := &Directive{ - Name: key, - Parameters: params, - } - if index > -1 { - directives[index] = newDirective - } else { - directives = append(directives, newDirective) - } - b.Directives = directives -} - -func (b *Block) RemoveDirective(key string, params []string) { - directives := b.GetDirectives() - var newDirectives []IDirective - for _, dir := range directives { - if dir.GetName() == key { - if IsRepeatKey(key) && len(params) > 0 { - oldParams := dir.GetParameters() - if oldParams[0] == params[0] { - continue - } - } else { - continue - } - } - newDirectives = append(newDirectives, dir) - } - b.Directives = newDirectives -} diff --git a/backend/utils/nginx/components/comment.go b/backend/utils/nginx/components/comment.go deleted file mode 100644 index 31459be09..000000000 --- a/backend/utils/nginx/components/comment.go +++ /dev/null @@ -1,26 +0,0 @@ -package components - -type Comment struct { - Detail string - Line int -} - -func (c *Comment) GetName() string { - return "" -} - -func (c *Comment) GetParameters() []string { - return []string{} -} - -func (c *Comment) GetBlock() IBlock { - return nil -} - -func (c *Comment) GetComment() string { - return c.Detail -} - -func (c *Comment) GetLine() int { - return c.Line -} diff --git a/backend/utils/nginx/components/config.go b/backend/utils/nginx/components/config.go deleted file mode 100644 index 7f9b5bce9..000000000 --- a/backend/utils/nginx/components/config.go +++ /dev/null @@ -1,45 +0,0 @@ -package components - -type Config struct { - *Block - FilePath string -} - -func (c *Config) FindServers() []*Server { - var servers []*Server - directives := c.Block.FindDirectives("server") - for _, directive := range directives { - servers = append(servers, directive.(*Server)) - } - return servers -} - -func (c *Config) FindHttp() *Http { - var http *Http - directives := c.Block.FindDirectives("http") - if len(directives) > 0 { - http = directives[0].(*Http) - } - - return http -} - -var repeatKeys = map[string]struct { -}{ - "limit_conn": {}, - "limit_conn_zone": {}, - "set": {}, - "if": {}, - "proxy_set_header": {}, - "location": {}, - "include": {}, - "sub_filter": {}, - "add_header": {}, -} - -func IsRepeatKey(key string) bool { - if _, ok := repeatKeys[key]; ok { - return true - } - return false -} diff --git a/backend/utils/nginx/components/directive.go b/backend/utils/nginx/components/directive.go deleted file mode 100644 index dfdef75ef..000000000 --- a/backend/utils/nginx/components/directive.go +++ /dev/null @@ -1,29 +0,0 @@ -package components - -type Directive struct { - Line int - Block IBlock - Name string - Comment string - Parameters []string -} - -func (d *Directive) GetComment() string { - return d.Comment -} - -func (d *Directive) GetName() string { - return d.Name -} - -func (d *Directive) GetParameters() []string { - return d.Parameters -} - -func (d *Directive) GetBlock() IBlock { - return d.Block -} - -func (d *Directive) GetLine() int { - return d.Line -} diff --git a/backend/utils/nginx/components/http.go b/backend/utils/nginx/components/http.go deleted file mode 100644 index ff9d3028c..000000000 --- a/backend/utils/nginx/components/http.go +++ /dev/null @@ -1,129 +0,0 @@ -package components - -import ( - "errors" -) - -type Http struct { - Comment string - Servers []*Server - Directives []IDirective - Line int -} - -func (h *Http) GetCodeBlock() string { - return "" -} - -func (h *Http) GetComment() string { - return h.Comment -} - -func NewHttp(directive IDirective) (*Http, error) { - if block := directive.GetBlock(); block != nil { - http := &Http{ - Line: directive.GetBlock().GetLine(), - Servers: []*Server{}, - Directives: []IDirective{}, - Comment: block.GetComment(), - } - for _, directive := range block.GetDirectives() { - if server, ok := directive.(*Server); ok { - http.Servers = append(http.Servers, server) - continue - } - http.Directives = append(http.Directives, directive) - } - - return http, nil - } - return nil, errors.New("http directive must have a block") -} - -func (h *Http) GetName() string { - return "http" -} - -func (h *Http) GetParameters() []string { - return []string{} -} - -func (h *Http) GetDirectives() []IDirective { - directives := make([]IDirective, 0) - directives = append(directives, h.Directives...) - for _, directive := range h.Servers { - directives = append(directives, directive) - } - return directives -} - -func (h *Http) FindDirectives(directiveName string) []IDirective { - directives := make([]IDirective, 0) - for _, directive := range h.GetDirectives() { - if directive.GetName() == directiveName { - directives = append(directives, directive) - } - if directive.GetBlock() != nil { - directives = append(directives, directive.GetBlock().FindDirectives(directiveName)...) - } - } - - return directives -} - -func (h *Http) UpdateDirective(key string, params []string) { - if key == "" || len(params) == 0 { - return - } - directives := h.GetDirectives() - index := -1 - for i, dir := range directives { - if dir.GetName() == key { - if IsRepeatKey(key) { - oldParams := dir.GetParameters() - if !(len(oldParams) > 0 && oldParams[0] == params[0]) { - continue - } - } - index = i - break - } - } - newDirective := &Directive{ - Name: key, - Parameters: params, - } - if index > -1 { - directives[index] = newDirective - } else { - directives = append(directives, newDirective) - } - h.Directives = directives -} - -func (h *Http) RemoveDirective(key string, params []string) { - directives := h.GetDirectives() - var newDirectives []IDirective - for _, dir := range directives { - if dir.GetName() == key { - if IsRepeatKey(key) && len(params) > 0 { - oldParams := dir.GetParameters() - if oldParams[0] == params[0] { - continue - } - } else { - continue - } - } - newDirectives = append(newDirectives, dir) - } - h.Directives = newDirectives -} - -func (h *Http) GetBlock() IBlock { - return h -} - -func (h *Http) GetLine() int { - return h.Line -} diff --git a/backend/utils/nginx/components/location.go b/backend/utils/nginx/components/location.go deleted file mode 100644 index c407c0ede..000000000 --- a/backend/utils/nginx/components/location.go +++ /dev/null @@ -1,244 +0,0 @@ -package components - -import ( - "fmt" - "regexp" - "strconv" - "strings" -) - -type Location struct { - Modifier string - Match string - Cache bool - ProxyPass string - Host string - CacheTime int - CacheUint string - Comment string - Directives []IDirective - Line int - Parameters []string - Replaces map[string]string -} - -func (l *Location) GetCodeBlock() string { - return "" -} - -func NewLocation(directive IDirective) *Location { - location := &Location{ - Modifier: "", - Match: "", - } - directives := make([]IDirective, 0) - if len(directive.GetParameters()) == 0 { - panic("no enough parameter for location") - } - for _, dir := range directive.GetBlock().GetDirectives() { - directives = append(directives, dir) - params := dir.GetParameters() - switch dir.GetName() { - case "proxy_pass": - location.ProxyPass = params[0] - case "proxy_set_header": - if params[0] == "Host" { - location.Host = params[1] - } - case "proxy_cache": - location.Cache = true - case "if": - if params[0] == "(" && params[1] == "$uri" && params[2] == "~*" { - dirs := dir.GetBlock().GetDirectives() - for _, di := range dirs { - if di.GetName() == "expires" { - re := regexp.MustCompile(`^(\d+)(\w+)$`) - matches := re.FindStringSubmatch(di.GetParameters()[0]) - if matches == nil { - continue - } - cacheTime, err := strconv.Atoi(matches[1]) - if err != nil { - continue - } - unit := matches[2] - location.CacheUint = unit - location.CacheTime = cacheTime - } - } - } - case "sub_filter": - if location.Replaces == nil { - location.Replaces = make(map[string]string, 0) - } - location.Replaces[strings.Trim(params[0], "\"")] = strings.Trim(params[1], "\"") - } - } - - params := directive.GetParameters() - if len(params) == 1 { - location.Match = params[0] - } else if len(params) == 2 { - location.Match = params[1] - location.Modifier = params[0] - } - location.Parameters = directive.GetParameters() - location.Line = directive.GetLine() - location.Comment = directive.GetComment() - location.Directives = directives - return location -} - -func (l *Location) GetName() string { - return "location" -} - -func (l *Location) GetParameters() []string { - return l.Parameters -} - -func (l *Location) GetBlock() IBlock { - return l -} - -func (l *Location) GetComment() string { - return l.Comment -} - -func (l *Location) GetLine() int { - return l.Line -} - -func (l *Location) GetDirectives() []IDirective { - return l.Directives -} - -func (l *Location) FindDirectives(directiveName string) []IDirective { - directives := make([]IDirective, 0) - for _, directive := range l.Directives { - if directive.GetName() == directiveName { - directives = append(directives, directive) - } - if directive.GetBlock() != nil { - directives = append(directives, directive.GetBlock().FindDirectives(directiveName)...) - } - } - return directives -} - -func (l *Location) UpdateDirective(key string, params []string) { - if key == "" || len(params) == 0 { - return - } - directives := l.Directives - index := -1 - for i, dir := range directives { - if dir.GetName() == key { - if IsRepeatKey(key) { - oldParams := dir.GetParameters() - if !(len(oldParams) > 0 && oldParams[0] == params[0]) { - continue - } - } - index = i - break - } - } - newDirective := &Directive{ - Name: key, - Parameters: params, - } - if index > -1 { - directives[index] = newDirective - } else { - directives = append(directives, newDirective) - } - l.Directives = directives -} - -func (l *Location) RemoveDirective(key string, params []string) { - directives := l.Directives - var newDirectives []IDirective - for _, dir := range directives { - if dir.GetName() == key { - if len(params) > 0 { - oldParams := dir.GetParameters() - if oldParams[0] == params[0] { - continue - } - } else { - continue - } - } - newDirectives = append(newDirectives, dir) - } - l.Directives = newDirectives -} - -func (l *Location) ChangePath(Modifier string, Match string) { - if Match != "" && Modifier != "" { - l.Parameters = []string{Modifier, Match} - } - if Match != "" && Modifier == "" { - l.Parameters = []string{Match} - } - l.Modifier = Modifier - l.Match = Match -} - -func (l *Location) AddCache(cacheTime int, cacheUint string) { - l.RemoveDirective("add_header", []string{"Cache-Control", "no-cache"}) - l.RemoveDirective("if", []string{"(", "$uri", "~*", `"\.(gif|png|jpg|css|js|woff|woff2)$"`, ")"}) - directives := l.GetDirectives() - newDir := &Directive{ - Name: "if", - Parameters: []string{"(", "$uri", "~*", `"\.(gif|png|jpg|css|js|woff|woff2)$"`, ")"}, - Block: &Block{}, - } - block := &Block{} - block.Directives = append(block.Directives, &Directive{ - Name: "expires", - Parameters: []string{strconv.Itoa(cacheTime) + cacheUint}, - }) - newDir.Block = block - directives = append(directives, newDir) - l.Directives = directives - l.UpdateDirective("proxy_ignore_headers", []string{"Set-Cookie", "Cache-Control", "expires"}) - l.UpdateDirective("proxy_cache", []string{"proxy_cache_panel"}) - l.UpdateDirective("proxy_cache_key", []string{"$host$uri$is_args$args"}) - l.UpdateDirective("proxy_cache_valid", []string{"200", "304", "301", "302", "10m"}) - l.Cache = true - l.CacheTime = cacheTime - l.CacheUint = cacheUint -} - -func (l *Location) RemoveCache() { - l.RemoveDirective("if", []string{"(", "$uri", "~*", `"\.(gif|png|jpg|css|js|woff|woff2)$"`, ")"}) - l.RemoveDirective("proxy_ignore_headers", []string{"Set-Cookie"}) - l.RemoveDirective("proxy_cache", []string{"proxy_cache_panel"}) - l.RemoveDirective("proxy_cache_key", []string{"$host$uri$is_args$args"}) - l.RemoveDirective("proxy_cache_valid", []string{"200"}) - - l.UpdateDirective("add_header", []string{"Cache-Control", "no-cache"}) - - l.CacheTime = 0 - l.CacheUint = "" - l.Cache = false -} - -func (l *Location) AddSubFilter(subFilters map[string]string) { - l.RemoveDirective("sub_filter", []string{}) - l.Replaces = subFilters - for k, v := range subFilters { - l.UpdateDirective("sub_filter", []string{fmt.Sprintf(`"%s"`, k), fmt.Sprintf(`"%s"`, v)}) - } - l.UpdateDirective("proxy_set_header", []string{"Accept-Encoding", `""`}) - l.UpdateDirective("sub_filter_once", []string{"off"}) -} - -func (l *Location) RemoveSubFilter() { - l.RemoveDirective("sub_filter", []string{}) - l.RemoveDirective("proxy_set_header", []string{"Accept-Encoding", `""`}) - l.RemoveDirective("sub_filter_once", []string{"off"}) - l.Replaces = nil -} diff --git a/backend/utils/nginx/components/lua_block.go b/backend/utils/nginx/components/lua_block.go deleted file mode 100644 index d9b4b3676..000000000 --- a/backend/utils/nginx/components/lua_block.go +++ /dev/null @@ -1,120 +0,0 @@ -package components - -import ( - "fmt" -) - -type LuaBlock struct { - Directives []IDirective - Name string - Comment string - LuaCode string - Line int -} - -func NewLuaBlock(directive IDirective) (*LuaBlock, error) { - if block := directive.GetBlock(); block != nil { - lb := &LuaBlock{ - Directives: []IDirective{}, - Name: directive.GetName(), - LuaCode: block.GetCodeBlock(), - } - - lb.Directives = append(lb.Directives, block.GetDirectives()...) - return lb, nil - } - return nil, fmt.Errorf("%s must have a block", directive.GetName()) -} - -func (lb *LuaBlock) GetName() string { - return lb.Name -} - -func (lb *LuaBlock) GetParameters() []string { - return []string{} -} - -func (lb *LuaBlock) GetDirectives() []IDirective { - directives := make([]IDirective, 0) - directives = append(directives, lb.Directives...) - return directives -} - -func (lb *LuaBlock) FindDirectives(directiveName string) []IDirective { - directives := make([]IDirective, 0) - for _, directive := range lb.GetDirectives() { - if directive.GetName() == directiveName { - directives = append(directives, directive) - } - if directive.GetBlock() != nil { - directives = append(directives, directive.GetBlock().FindDirectives(directiveName)...) - } - } - - return directives -} - -func (lb *LuaBlock) GetCodeBlock() string { - return lb.LuaCode -} - -func (lb *LuaBlock) GetBlock() IBlock { - return lb -} - -func (lb *LuaBlock) GetComment() string { - return lb.Comment -} - -func (lb *LuaBlock) RemoveDirective(key string, params []string) { - directives := lb.Directives - var newDirectives []IDirective - for _, dir := range directives { - if dir.GetName() == key { - if len(params) > 0 { - oldParams := dir.GetParameters() - if oldParams[0] == params[0] { - continue - } - } else { - continue - } - } - newDirectives = append(newDirectives, dir) - } - lb.Directives = newDirectives -} - -func (lb *LuaBlock) UpdateDirective(key string, params []string) { - if key == "" || len(params) == 0 { - return - } - directives := lb.Directives - index := -1 - for i, dir := range directives { - if dir.GetName() == key { - if IsRepeatKey(key) { - oldParams := dir.GetParameters() - if !(len(oldParams) > 0 && oldParams[0] == params[0]) { - continue - } - } - index = i - break - } - } - newDirective := &Directive{ - Name: key, - Parameters: params, - } - if index > -1 { - directives[index] = newDirective - } else { - directives = append(directives, newDirective) - } - lb.Directives = directives -} - -func (lb *LuaBlock) GetLine() int { - return lb.Line -} diff --git a/backend/utils/nginx/components/server.go b/backend/utils/nginx/components/server.go deleted file mode 100644 index c7138936f..000000000 --- a/backend/utils/nginx/components/server.go +++ /dev/null @@ -1,371 +0,0 @@ -package components - -import ( - "errors" -) - -type Server struct { - Comment string - Listens []*ServerListen - Directives []IDirective - Line int -} - -func (s *Server) GetCodeBlock() string { - return "" -} - -func NewServer(directive IDirective) (*Server, error) { - server := &Server{} - if block := directive.GetBlock(); block != nil { - server.Line = directive.GetBlock().GetLine() - server.Comment = block.GetComment() - directives := block.GetDirectives() - for _, dir := range directives { - switch dir.GetName() { - case "listen": - server.Listens = append(server.Listens, NewServerListen(dir.GetParameters(), dir.GetLine())) - default: - server.Directives = append(server.Directives, dir) - } - } - return server, nil - } - return nil, errors.New("server directive must have a block") -} - -func (s *Server) GetName() string { - return "server" -} - -func (s *Server) GetParameters() []string { - return []string{} -} - -func (s *Server) GetBlock() IBlock { - return s -} - -func (s *Server) GetComment() string { - return s.Comment -} - -func (s *Server) GetDirectives() []IDirective { - directives := make([]IDirective, 0) - for _, ls := range s.Listens { - directives = append(directives, ls) - } - directives = append(directives, s.Directives...) - return directives -} - -func (s *Server) FindDirectives(directiveName string) []IDirective { - directives := make([]IDirective, 0) - for _, directive := range s.Directives { - if directive.GetName() == directiveName { - directives = append(directives, directive) - } - if directive.GetBlock() != nil { - directives = append(directives, directive.GetBlock().FindDirectives(directiveName)...) - } - } - if directiveName == "listen" { - for _, listen := range s.Listens { - params := []string{listen.Bind} - params = append(params, listen.Parameters...) - if listen.DefaultServer != "" { - params = append(params, DefaultServer) - } - directives = append(directives, &Directive{ - Name: "listen", - Parameters: params, - }) - } - } - return directives -} - -func (s *Server) UpdateDirective(key string, params []string) { - if key == "" || len(params) == 0 { - return - } - if key == "listen" { - defaultServer := false - paramLen := len(params) - if paramLen > 0 && params[paramLen-1] == "default_server" { - params = params[:paramLen-1] - defaultServer = true - } - s.UpdateListen(params[0], defaultServer, params[1:]...) - return - } - - directives := s.Directives - index := -1 - for i, dir := range directives { - if dir.GetName() == key { - if IsRepeatKey(key) { - oldParams := dir.GetParameters() - if !(len(oldParams) > 0 && oldParams[0] == params[0]) { - continue - } - } - index = i - break - } - } - newDirective := &Directive{ - Name: key, - Parameters: params, - } - if index > -1 { - directives[index] = newDirective - } else { - directives = append(directives, newDirective) - } - s.Directives = directives -} - -func (s *Server) RemoveDirective(key string, params []string) { - directives := s.Directives - var newDirectives []IDirective - for _, dir := range directives { - if dir.GetName() == key { - if len(params) == 0 { - continue - } - oldParams := dir.GetParameters() - if key == "location" { - if len(params) == len(oldParams) { - exist := true - for i := range params { - if params[i] != oldParams[i] { - exist = false - break - } - } - if exist { - continue - } - } - } else { - if oldParams[0] == params[0] { - continue - } - } - } - newDirectives = append(newDirectives, dir) - } - s.Directives = newDirectives -} - -func (s *Server) GetLine() int { - return s.Line -} - -func (s *Server) AddListen(bind string, defaultServer bool, params ...string) { - listen := &ServerListen{ - Bind: bind, - Parameters: params, - } - if defaultServer { - listen.DefaultServer = DefaultServer - } - s.Listens = append(s.Listens, listen) -} - -func (s *Server) UpdateListen(bind string, defaultServer bool, params ...string) { - listen := &ServerListen{ - Bind: bind, - Parameters: params, - } - if defaultServer { - listen.DefaultServer = DefaultServer - } - var newListens []*ServerListen - exist := false - for _, li := range s.Listens { - if li.Bind == bind { - exist = true - newListens = append(newListens, listen) - } else { - newListens = append(newListens, li) - } - } - if !exist { - newListens = append(newListens, listen) - } - - s.Listens = newListens -} - -func (s *Server) DeleteListen(bind string) { - var newListens []*ServerListen - for _, li := range s.Listens { - if li.Bind != bind { - newListens = append(newListens, li) - } - } - s.Listens = newListens -} - -func (s *Server) DeleteServerName(name string) { - var names []string - dirs := s.FindDirectives("server_name") - params := dirs[0].GetParameters() - for _, param := range params { - if param != name { - names = append(names, param) - } - } - s.UpdateServerName(names) -} - -func (s *Server) AddServerName(name string) { - dirs := s.FindDirectives("server_name") - params := dirs[0].GetParameters() - params = append(params, name) - s.UpdateServerName(params) -} - -func (s *Server) UpdateServerName(names []string) { - s.UpdateDirective("server_name", names) -} - -func (s *Server) UpdateRoot(path string) { - s.UpdateDirective("root", []string{path}) -} - -func (s *Server) UpdateRootLocation() { - newDir := Directive{ - Name: "location", - Parameters: []string{"/"}, - Block: &Block{}, - } - block := &Block{} - block.Directives = append(block.Directives, &Directive{ - Name: "root", - Parameters: []string{"index.html"}, - }) - newDir.Block = block -} - -func (s *Server) UpdateRootProxy(proxy []string) { - newDir := Directive{ - Name: "location", - Parameters: []string{"/"}, - Block: &Block{}, - } - block := &Block{} - block.Directives = append(block.Directives, &Directive{ - Name: "proxy_pass", - Parameters: proxy, - }) - newDir.Block = block - s.UpdateDirectiveBySecondKey("location", "/", newDir) -} - -func (s *Server) UpdatePHPProxy(proxy []string, localPath string) { - newDir := Directive{ - Name: "location", - Parameters: []string{"~ [^/]\\.php(/|$)"}, - Block: &Block{}, - } - block := &Block{} - block.Directives = append(block.Directives, &Directive{ - Name: "fastcgi_pass", - Parameters: proxy, - }) - block.Directives = append(block.Directives, &Directive{ - Name: "include", - Parameters: []string{"fastcgi-php.conf"}, - }) - block.Directives = append(block.Directives, &Directive{ - Name: "include", - Parameters: []string{"fastcgi_params"}, - }) - if localPath == "" { - block.Directives = append(block.Directives, &Directive{ - Name: "set", - Parameters: []string{"$real_script_name", "$fastcgi_script_name"}, - }) - ifDir := &Directive{ - Name: "if", - Parameters: []string{"($fastcgi_script_name ~ \"^(.+?\\.php)(/.+)$\")"}, - } - ifDir.Block = &Block{ - Directives: []IDirective{ - &Directive{ - Name: "set", - Parameters: []string{"$real_script_name", "$1"}, - }, - &Directive{ - Name: "set", - Parameters: []string{"$path_info", "$2"}, - }, - }, - } - block.Directives = append(block.Directives, ifDir) - block.Directives = append(block.Directives, &Directive{ - Name: "fastcgi_param", - Parameters: []string{"SCRIPT_FILENAME", "$document_root$real_script_name"}, - }) - block.Directives = append(block.Directives, &Directive{ - Name: "fastcgi_param", - Parameters: []string{"SCRIPT_NAME", "$real_script_name"}, - }) - block.Directives = append(block.Directives, &Directive{ - Name: "fastcgi_param", - Parameters: []string{"PATH_INFO", "$path_info"}, - }) - } else { - block.Directives = append(block.Directives, &Directive{ - Name: "fastcgi_param", - Parameters: []string{"SCRIPT_FILENAME", localPath}, - }) - } - newDir.Block = block - s.UpdateDirectiveBySecondKey("location", "~ [^/]\\.php(/|$)", newDir) -} - -func (s *Server) UpdateDirectiveBySecondKey(name string, key string, directive Directive) { - directives := s.Directives - index := -1 - for i, dir := range directives { - if dir.GetName() == name && dir.GetParameters()[0] == key { - index = i - break - } - } - if index > -1 { - directives[index] = &directive - } else { - directives = append(directives, &directive) - } - s.Directives = directives -} - -func (s *Server) RemoveListenByBind(bind string) { - var listens []*ServerListen - for _, listen := range s.Listens { - if listen.Bind != bind { - listens = append(listens, listen) - } - } - s.Listens = listens -} - -func (s *Server) AddHTTP2HTTPS() { - newDir := Directive{ - Name: "if", - Parameters: []string{"($scheme = http)"}, - Block: &Block{}, - } - block := &Block{} - block.Directives = append(block.Directives, &Directive{ - Name: "return", - Parameters: []string{"301", "https://$host$request_uri"}, - }) - newDir.Block = block - s.UpdateDirectiveBySecondKey("if", "($scheme", newDir) -} diff --git a/backend/utils/nginx/components/server_listen.go b/backend/utils/nginx/components/server_listen.go deleted file mode 100644 index 8a811be4c..000000000 --- a/backend/utils/nginx/components/server_listen.go +++ /dev/null @@ -1,74 +0,0 @@ -package components - -import ( - "github.com/1Panel-dev/1Panel/backend/utils/common" - "strings" -) - -const DefaultServer = "default_server" - -type ServerListen struct { - Bind string - DefaultServer string - Parameters []string - Comment string - Line int -} - -func NewServerListen(params []string, line int) *ServerListen { - server := &ServerListen{ - Parameters: []string{}, - Line: line, - } - for _, param := range params { - if isBind(param) { - server.Bind = param - } else if param == DefaultServer { - server.DefaultServer = DefaultServer - } else { - server.Parameters = append(server.Parameters, param) - } - } - return server -} - -func isBind(param string) bool { - if common.IsNum(param) { - return true - } - if strings.Contains(param, "*") || strings.Contains(param, ":") || strings.Contains(param, ".") { - return true - } - return false -} - -func (sl *ServerListen) GetName() string { - return "listen" -} - -func (sl *ServerListen) GetBlock() IBlock { - return nil -} - -func (sl *ServerListen) GetParameters() []string { - params := []string{sl.Bind} - params = append(params, sl.Parameters...) - params = append(params, sl.DefaultServer) - return params -} - -func (sl *ServerListen) GetComment() string { - return sl.Comment -} - -func (sl *ServerListen) AddDefaultServer() { - sl.DefaultServer = DefaultServer -} - -func (sl *ServerListen) RemoveDefaultServe() { - sl.DefaultServer = "" -} - -func (sl *ServerListen) GetLine() int { - return sl.Line -} diff --git a/backend/utils/nginx/components/statement.go b/backend/utils/nginx/components/statement.go deleted file mode 100644 index 432a4c165..000000000 --- a/backend/utils/nginx/components/statement.go +++ /dev/null @@ -1,19 +0,0 @@ -package components - -type IBlock interface { - GetDirectives() []IDirective - FindDirectives(directiveName string) []IDirective - RemoveDirective(name string, params []string) - UpdateDirective(name string, params []string) - GetComment() string - GetLine() int - GetCodeBlock() string -} - -type IDirective interface { - GetName() string - GetParameters() []string - GetBlock() IBlock - GetComment() string - GetLine() int -} diff --git a/backend/utils/nginx/components/upstream.go b/backend/utils/nginx/components/upstream.go deleted file mode 100644 index 68e26d42d..000000000 --- a/backend/utils/nginx/components/upstream.go +++ /dev/null @@ -1,135 +0,0 @@ -package components - -import ( - "errors" -) - -type Upstream struct { - UpstreamName string - UpstreamServers []*UpstreamServer - Directives []IDirective - Comment string - Line int -} - -func (us *Upstream) GetCodeBlock() string { - return "" -} - -func (us *Upstream) GetName() string { - return "upstream" -} - -func (us *Upstream) GetParameters() []string { - return []string{us.UpstreamName} -} - -func (us *Upstream) GetBlock() IBlock { - return us -} - -func (us *Upstream) GetComment() string { - return us.Comment -} - -func (us *Upstream) GetDirectives() []IDirective { - directives := make([]IDirective, 0) - directives = append(directives, us.Directives...) - for _, uss := range us.UpstreamServers { - directives = append(directives, uss) - } - return directives -} - -func NewUpstream(directive IDirective) (*Upstream, error) { - parameters := directive.GetParameters() - us := &Upstream{ - UpstreamName: parameters[0], - Line: directive.GetLine(), - } - - if block := directive.GetBlock(); block != nil { - us.Comment = block.GetComment() - for _, d := range block.GetDirectives() { - if d.GetName() == "server" { - us.UpstreamServers = append(us.UpstreamServers, NewUpstreamServer(d)) - } else { - us.Directives = append(us.Directives, d) - } - } - return us, nil - } - - return nil, errors.New("missing upstream block") -} - -func (us *Upstream) AddServer(server *UpstreamServer) { - us.UpstreamServers = append(us.UpstreamServers, server) -} - -func (us *Upstream) FindDirectives(directiveName string) []IDirective { - directives := make([]IDirective, 0) - for _, directive := range us.Directives { - if directive.GetName() == directiveName { - directives = append(directives, directive) - } - if directive.GetBlock() != nil { - directives = append(directives, directive.GetBlock().FindDirectives(directiveName)...) - } - } - - return directives -} - -func (us *Upstream) UpdateDirective(key string, params []string) { - if key == "" || len(params) == 0 { - return - } - directives := us.GetDirectives() - index := -1 - for i, dir := range directives { - if dir.GetName() == key { - if IsRepeatKey(key) { - oldParams := dir.GetParameters() - if !(len(oldParams) > 0 && oldParams[0] == params[0]) { - continue - } - } - index = i - break - } - } - newDirective := &Directive{ - Name: key, - Parameters: params, - } - if index > -1 { - directives[index] = newDirective - } else { - directives = append(directives, newDirective) - } - us.Directives = directives -} - -func (us *Upstream) RemoveDirective(key string, params []string) { - directives := us.GetDirectives() - var newDirectives []IDirective - for _, dir := range directives { - if dir.GetName() == key { - if IsRepeatKey(key) && len(params) > 0 { - oldParams := dir.GetParameters() - if oldParams[0] == params[0] { - continue - } - } else { - continue - } - } - newDirectives = append(newDirectives, dir) - } - us.Directives = newDirectives -} - -func (us *Upstream) GetLine() int { - return us.Line -} diff --git a/backend/utils/nginx/components/upstream_server.go b/backend/utils/nginx/components/upstream_server.go deleted file mode 100644 index f5af46493..000000000 --- a/backend/utils/nginx/components/upstream_server.go +++ /dev/null @@ -1,83 +0,0 @@ -package components - -import ( - "fmt" - "sort" - "strings" -) - -type UpstreamServer struct { - Comment string - Address string - Flags []string - Parameters map[string]string - Line int -} - -func (uss *UpstreamServer) GetName() string { - return "server" -} - -func (uss *UpstreamServer) GetBlock() IBlock { - return nil -} - -func (uss *UpstreamServer) GetParameters() []string { - return uss.GetDirective().Parameters -} - -func (uss *UpstreamServer) GetComment() string { - return uss.Comment -} - -func (uss *UpstreamServer) GetDirective() *Directive { - directive := &Directive{ - Name: "server", - Parameters: make([]string, 0), - Block: nil, - } - - directive.Parameters = append(directive.Parameters, uss.Address) - - paramNames := make([]string, 0) - for k := range uss.Parameters { - paramNames = append(paramNames, k) - } - sort.Strings(paramNames) - - for _, k := range paramNames { - directive.Parameters = append(directive.Parameters, fmt.Sprintf("%s=%s", k, uss.Parameters[k])) - } - - directive.Parameters = append(directive.Parameters, uss.Flags...) - - return directive -} - -func NewUpstreamServer(directive IDirective) *UpstreamServer { - uss := &UpstreamServer{ - Comment: directive.GetComment(), - Flags: make([]string, 0), - Parameters: make(map[string]string, 0), - Line: directive.GetLine(), - } - - for i, parameter := range directive.GetParameters() { - if i == 0 { - uss.Address = parameter - continue - } - if strings.Contains(parameter, "=") { - s := strings.SplitN(parameter, "=", 2) - uss.Parameters[s[0]] = s[1] - } else { - uss.Flags = append(uss.Flags, parameter) - } - } - - return uss -} - -func (uss *UpstreamServer) GetLine() int { - return uss.Line -} diff --git a/backend/utils/nginx/dumper.go b/backend/utils/nginx/dumper.go deleted file mode 100644 index 06bc2bb15..000000000 --- a/backend/utils/nginx/dumper.go +++ /dev/null @@ -1,115 +0,0 @@ -package nginx - -import ( - "bytes" - "fmt" - "os" - "strings" - - "github.com/1Panel-dev/1Panel/backend/utils/nginx/components" -) - -var ( - IndentedStyle = &Style{ - SpaceBeforeBlocks: false, - StartIndent: 0, - Indent: 4, - } -) - -type Style struct { - SpaceBeforeBlocks bool - StartIndent int - Indent int -} - -func (s *Style) Iterate() *Style { - newStyle := &Style{ - SpaceBeforeBlocks: s.SpaceBeforeBlocks, - StartIndent: s.StartIndent + s.Indent, - Indent: s.Indent, - } - return newStyle -} - -func DumpDirective(d components.IDirective, style *Style) string { - var buf bytes.Buffer - - if style.SpaceBeforeBlocks && d.GetBlock() != nil { - buf.WriteString("\n") - } - buf.WriteString(fmt.Sprintf("%s%s", strings.Repeat(" ", style.StartIndent), d.GetName())) - if len(d.GetParameters()) > 0 { - buf.WriteString(fmt.Sprintf(" %s", strings.Join(d.GetParameters(), " "))) - } - if d.GetBlock() == nil { - if d.GetName() != "" { - buf.WriteRune(';') - buf.WriteString(" ") - } - if d.GetComment() != "" { - buf.WriteString(d.GetComment()) - } - } else { - buf.WriteString(" {") - if d.GetComment() != "" { - buf.WriteString(" ") - buf.WriteString(d.GetComment()) - } - buf.WriteString("\n") - buf.WriteString(DumpBlock(d.GetBlock(), style.Iterate(), d.GetBlock().GetLine())) - buf.WriteString(fmt.Sprintf("\n%s}", strings.Repeat(" ", style.StartIndent))) - } - return buf.String() -} - -func DumpBlock(b components.IBlock, style *Style, startLine int) string { - var buf bytes.Buffer - - if b.GetCodeBlock() != "" { - luaLines := strings.Split(b.GetCodeBlock(), "\n") - for i, line := range luaLines { - if strings.Replace(line, " ", "", -1) == "" { - continue - } - buf.WriteString(line) - if i != len(luaLines)-1 { - buf.WriteString("\n") - } - } - return buf.String() - } - - line := startLine - if b.GetLine() > startLine { - for i := 0; i < b.GetLine()-startLine; i++ { - buf.WriteString("\n") - } - line = b.GetLine() - } - - directives := b.GetDirectives() - for i, directive := range directives { - - if directive.GetLine() > line { - for i := 0; i < b.GetLine()-line; i++ { - buf.WriteString("\n") - } - line = b.GetLine() - } - - buf.WriteString(DumpDirective(directive, style)) - if i != len(directives)-1 { - buf.WriteString("\n") - } - } - return buf.String() -} - -func DumpConfig(c *components.Config, style *Style) string { - return DumpBlock(c.Block, style, 1) -} - -func WriteConfig(c *components.Config, style *Style) error { - return os.WriteFile(c.FilePath, []byte(DumpConfig(c, style)), 0644) -} diff --git a/backend/utils/nginx/parser/flag/flag.go b/backend/utils/nginx/parser/flag/flag.go deleted file mode 100644 index b39d9e7ac..000000000 --- a/backend/utils/nginx/parser/flag/flag.go +++ /dev/null @@ -1,59 +0,0 @@ -package flag - -type Type int - -const ( - EOF Type = iota - Eol - Keyword - QuotedString - Variable - BlockStart - BlockEnd - Semicolon - Comment - Illegal - Regex - LuaCode -) - -var ( - FlagName = map[Type]string{ - QuotedString: "QuotedString", - EOF: "Eof", - Keyword: "Keyword", - Variable: "Variable", - BlockStart: "BlockStart", - BlockEnd: "BlockEnd", - Semicolon: "Semicolon", - Comment: "Comment", - Illegal: "Illegal", - Regex: "Regex", - } -) - -func (tt Type) String() string { - return FlagName[tt] -} - -type Flag struct { - Type Type - Literal string - Line int - Column int -} - -func (t Flag) Lit(literal string) Flag { - t.Literal = literal - return t -} - -type Flags []Flag - -func (t Flag) Is(typ Type) bool { - return t.Type == typ -} - -func (t Flag) IsParameterEligible() bool { - return t.Is(Keyword) || t.Is(QuotedString) || t.Is(Variable) || t.Is(Regex) -} diff --git a/backend/utils/nginx/parser/lexer.go b/backend/utils/nginx/parser/lexer.go deleted file mode 100644 index fe64ee153..000000000 --- a/backend/utils/nginx/parser/lexer.go +++ /dev/null @@ -1,261 +0,0 @@ -package parser - -import ( - "bufio" - "bytes" - "github.com/1Panel-dev/1Panel/backend/utils/nginx/parser/flag" - "io" - "strings" -) - -type lexer struct { - reader *bufio.Reader - file string - line int - column int - inLuaBlock bool - Latest flag.Flag -} - -func lex(content string) *lexer { - return newLexer(bytes.NewBuffer([]byte(content))) -} - -func newLexer(r io.Reader) *lexer { - return &lexer{ - line: 1, - reader: bufio.NewReader(r), - } -} - -func (s *lexer) scan() flag.Flag { - s.Latest = s.getNextFlag() - return s.Latest -} - -//func (s *lexer) all() flag.Flags { -// tokens := make([]flag.Flag, 0) -// for { -// v := s.scan() -// if v.Type == flag.EOF || v.Type == -1 { -// break -// } -// tokens = append(tokens, v) -// } -// return tokens -//} - -func (s *lexer) getNextFlag() flag.Flag { - if s.inLuaBlock { - s.inLuaBlock = false - flag := s.scanLuaCode() - return flag - } -retoFlag: - ch := s.peek() - switch { - case isSpace(ch): - s.skipWhitespace() - goto retoFlag - case isEOF(ch): - return s.NewToken(flag.EOF).Lit(string(s.read())) - case ch == ';': - return s.NewToken(flag.Semicolon).Lit(string(s.read())) - case ch == '{': - if isLuaBlock(s.Latest) { - s.inLuaBlock = true - } - return s.NewToken(flag.BlockStart).Lit(string(s.read())) - case ch == '}': - return s.NewToken(flag.BlockEnd).Lit(string(s.read())) - case ch == '#': - return s.scanComment() - case ch == '$': - return s.scanVariable() - case isQuote(ch): - return s.scanQuotedString(ch) - default: - return s.scanKeyword() - } -} - -func (s *lexer) scanLuaCode() flag.Flag { - ret := s.NewToken(flag.LuaCode) - stack := make([]rune, 0, 50) - code := strings.Builder{} - - for { - ch := s.read() - if ch == rune(flag.EOF) { - panic("unexpected end of file while scanning a string, maybe an unclosed lua code?") - } - if ch == '#' { - code.WriteRune(ch) - code.WriteString(s.readUntil(isEndOfLine)) - continue - } else if ch == '}' { - if len(stack) == 0 { - _ = s.reader.UnreadRune() - return ret.Lit(strings.TrimRight(strings.Trim(code.String(), "\n"), "\n ")) - } - if stack[len(stack)-1] == '{' { - stack = stack[0 : len(stack)-1] - } - } else if ch == '{' { - stack = append(stack, ch) - } - code.WriteRune(ch) - } -} - -func (s *lexer) peek() rune { - r, _, _ := s.reader.ReadRune() - _ = s.reader.UnreadRune() - return r -} - -type runeCheck func(rune) bool - -func (s *lexer) readUntil(until runeCheck) string { - var buf bytes.Buffer - buf.WriteRune(s.read()) - - for { - if ch := s.peek(); isEOF(ch) { - break - } else if until(ch) { - break - } else { - buf.WriteRune(s.read()) - } - } - - return buf.String() -} - -func (s *lexer) NewToken(tokenType flag.Type) flag.Flag { - return flag.Flag{ - Type: tokenType, - Line: s.line, - Column: s.column, - } -} - -func (s *lexer) readWhile(while runeCheck) string { - var buf bytes.Buffer - buf.WriteRune(s.read()) - - for { - if ch := s.peek(); while(ch) { - buf.WriteRune(s.read()) - } else { - break - } - } - return buf.String() -} - -func (s *lexer) skipWhitespace() { - s.readWhile(isSpace) -} - -func (s *lexer) scanComment() flag.Flag { - return s.NewToken(flag.Comment).Lit(s.readUntil(isEndOfLine)) -} - -func (s *lexer) scanQuotedString(delimiter rune) flag.Flag { - var buf bytes.Buffer - tok := s.NewToken(flag.QuotedString) - _, _ = buf.WriteRune(s.read()) - for { - ch := s.read() - - if ch == rune(flag.EOF) { - panic("unexpected end of file while scanning a string, maybe an unclosed quote?") - } - - if ch == '\\' && (s.peek() == delimiter) { - buf.WriteRune(ch) - buf.WriteRune(s.read()) - continue - } - - _, _ = buf.WriteRune(ch) - if ch == delimiter { - break - } - } - - return tok.Lit(buf.String()) -} - -func (s *lexer) scanKeyword() flag.Flag { - var buf bytes.Buffer - tok := s.NewToken(flag.Keyword) - prev := s.read() - buf.WriteRune(prev) - for { - ch := s.peek() - - if isSpace(ch) || isEOF(ch) || ch == ';' { - break - } - - if ch == '{' { - if prev == '$' { - buf.WriteString(s.readUntil(func(r rune) bool { - return r == '}' - })) - buf.WriteRune(s.read()) //consume latest '}' - } else { - break - } - } - buf.WriteRune(s.read()) - } - - return tok.Lit(buf.String()) -} - -func (s *lexer) scanVariable() flag.Flag { - return s.NewToken(flag.Variable).Lit(s.readUntil(isKeywordTerminator)) -} - -func (s *lexer) read() rune { - ch, _, err := s.reader.ReadRune() - if err != nil { - return rune(flag.EOF) - } - - if ch == '\n' { - s.column = 1 - s.line++ - } else { - s.column++ - } - return ch -} - -func isQuote(ch rune) bool { - return ch == '"' || ch == '\'' || ch == '`' -} - -func isKeywordTerminator(ch rune) bool { - return isSpace(ch) || isEndOfLine(ch) || ch == '{' || ch == ';' -} - -func isSpace(ch rune) bool { - return ch == ' ' || ch == '\t' || isEndOfLine(ch) -} - -func isEOF(ch rune) bool { - return ch == rune(flag.EOF) -} - -func isEndOfLine(ch rune) bool { - return ch == '\r' || ch == '\n' -} - -func isLuaBlock(t flag.Flag) bool { - return t.Type == flag.Keyword && strings.HasSuffix(t.Literal, "_by_lua_block") -} diff --git a/backend/utils/nginx/parser/parser.go b/backend/utils/nginx/parser/parser.go deleted file mode 100644 index cd4de3dd6..000000000 --- a/backend/utils/nginx/parser/parser.go +++ /dev/null @@ -1,209 +0,0 @@ -package parser - -import ( - "bufio" - "errors" - "fmt" - components "github.com/1Panel-dev/1Panel/backend/utils/nginx/components" - "github.com/1Panel-dev/1Panel/backend/utils/nginx/parser/flag" - "os" - "strings" -) - -type Parser struct { - lexer *lexer - currentToken flag.Flag - followingToken flag.Flag - blockWrappers map[string]func(*components.Directive) (components.IDirective, error) - directiveWrappers map[string]func(*components.Directive) components.IDirective -} - -func NewStringParser(str string) *Parser { - return NewParserFromLexer(lex(str)) -} - -func NewParser(filePath string) (*Parser, error) { - f, err := os.Open(filePath) - if err != nil { - return nil, err - } - defer f.Close() - l := newLexer(bufio.NewReader(f)) - l.file = filePath - p := NewParserFromLexer(l) - return p, nil -} - -func NewParserFromLexer(lexer *lexer) *Parser { - parser := &Parser{ - lexer: lexer, - } - - parser.nextToken() - parser.nextToken() - - parser.blockWrappers = map[string]func(*components.Directive) (components.IDirective, error){ - "http": func(directive *components.Directive) (components.IDirective, error) { - return parser.wrapHttp(directive), nil - }, - "server": func(directive *components.Directive) (components.IDirective, error) { - return parser.wrapServer(directive), nil - }, - "location": func(directive *components.Directive) (components.IDirective, error) { - return parser.wrapLocation(directive), nil - }, - "upstream": func(directive *components.Directive) (components.IDirective, error) { - return parser.wrapUpstream(directive), nil - }, - "_by_lua_block": func(directive *components.Directive) (components.IDirective, error) { - return parser.wrapLuaBlock(directive) - }, - } - - parser.directiveWrappers = map[string]func(*components.Directive) components.IDirective{ - "server": func(directive *components.Directive) components.IDirective { - return parser.parseUpstreamServer(directive) - }, - } - - return parser -} - -func (p *Parser) nextToken() { - p.currentToken = p.followingToken - p.followingToken = p.lexer.scan() -} - -func (p *Parser) curTokenIs(t flag.Type) bool { - return p.currentToken.Type == t -} - -func (p *Parser) followingTokenIs(t flag.Type) bool { - return p.followingToken.Type == t -} - -func (p *Parser) Parse() (*components.Config, error) { - parsedBlock, err := p.parseBlock(false) - if err != nil { - return nil, err - } - c := &components.Config{ - FilePath: p.lexer.file, - Block: parsedBlock, - } - return c, err -} - -func (p *Parser) parseBlock(inBlock bool) (*components.Block, error) { - context := &components.Block{ - Comment: "", - Directives: make([]components.IDirective, 0), - Line: p.currentToken.Line, - } - -parsingloop: - for { - switch { - case p.curTokenIs(flag.EOF): - if inBlock { - return nil, errors.New("unexpected eof in block") - } - break parsingloop - case p.curTokenIs(flag.BlockEnd): - break parsingloop - case p.curTokenIs(flag.LuaCode): - context.IsLuaBlock = true - context.LiteralCode = p.currentToken.Literal - case p.curTokenIs(flag.Keyword) || p.curTokenIs(flag.QuotedString): - s, err := p.parseStatement() - if err != nil { - return nil, err - } - context.Directives = append(context.Directives, s) - case p.curTokenIs(flag.Comment): - context.Directives = append(context.Directives, &components.Comment{ - Detail: p.currentToken.Literal, - Line: p.currentToken.Line, - }) - } - p.nextToken() - } - - return context, nil -} - -func (p *Parser) parseStatement() (components.IDirective, error) { - d := &components.Directive{ - Name: p.currentToken.Literal, - Line: p.currentToken.Line, - } - - for p.nextToken(); p.currentToken.IsParameterEligible(); p.nextToken() { - d.Parameters = append(d.Parameters, p.currentToken.Literal) - } - - if p.curTokenIs(flag.Semicolon) { - if dw, ok := p.directiveWrappers[d.Name]; ok { - return dw(d), nil - } - if p.followingTokenIs(flag.Comment) && p.currentToken.Line == p.followingToken.Line { - d.Comment = p.followingToken.Literal - p.nextToken() - } - return d, nil - } - - if p.curTokenIs(flag.BlockStart) { - inLineComment := "" - if p.followingTokenIs(flag.Comment) && p.currentToken.Line == p.followingToken.Line { - inLineComment = p.followingToken.Literal - p.nextToken() - p.nextToken() - } - block, err := p.parseBlock(false) - if err != nil { - return nil, err - } - - block.Comment = inLineComment - d.Block = block - - if strings.HasSuffix(d.Name, "_by_lua_block") { - return p.blockWrappers["_by_lua_block"](d) - } - - if bw, ok := p.blockWrappers[d.Name]; ok { - return bw(d) - } - return d, nil - } - - panic(fmt.Errorf("unexpected token %s (%s) on line %d, column %d", p.currentToken.Type.String(), p.currentToken.Literal, p.currentToken.Line, p.currentToken.Column)) -} - -func (p *Parser) wrapLocation(directive *components.Directive) *components.Location { - return components.NewLocation(directive) -} - -func (p *Parser) wrapServer(directive *components.Directive) *components.Server { - s, _ := components.NewServer(directive) - return s -} - -func (p *Parser) wrapUpstream(directive *components.Directive) *components.Upstream { - s, _ := components.NewUpstream(directive) - return s -} - -func (p *Parser) wrapHttp(directive *components.Directive) *components.Http { - h, _ := components.NewHttp(directive) - return h -} - -func (p *Parser) wrapLuaBlock(directive *components.Directive) (*components.LuaBlock, error) { - return components.NewLuaBlock(directive) -} - -func (p *Parser) parseUpstreamServer(directive *components.Directive) *components.UpstreamServer { - return components.NewUpstreamServer(directive) -} diff --git a/backend/utils/ntp/ntp.go b/backend/utils/ntp/ntp.go deleted file mode 100644 index 920e1eae1..000000000 --- a/backend/utils/ntp/ntp.go +++ /dev/null @@ -1,84 +0,0 @@ -package ntp - -import ( - "encoding/binary" - "fmt" - "net" - "runtime" - "time" - - "github.com/1Panel-dev/1Panel/backend/utils/cmd" -) - -const ntpEpochOffset = 2208988800 - -type packet struct { - Settings uint8 - Stratum uint8 - Poll int8 - Precision int8 - RootDelay uint32 - RootDispersion uint32 - ReferenceID uint32 - RefTimeSec uint32 - RefTimeFrac uint32 - OrigTimeSec uint32 - OrigTimeFrac uint32 - RxTimeSec uint32 - RxTimeFrac uint32 - TxTimeSec uint32 - TxTimeFrac uint32 -} - -func GetRemoteTime(site string) (time.Time, error) { - conn, err := net.Dial("udp", site+":123") - if err != nil { - return time.Time{}, fmt.Errorf("failed to connect: %v", err) - } - defer conn.Close() - if err := conn.SetDeadline(time.Now().Add(15 * time.Second)); err != nil { - return time.Time{}, fmt.Errorf("failed to set deadline: %v", err) - } - - req := &packet{Settings: 0x1B} - - if err := binary.Write(conn, binary.BigEndian, req); err != nil { - return time.Time{}, fmt.Errorf("failed to set request: %v", err) - } - - rsp := &packet{} - if err := binary.Read(conn, binary.BigEndian, rsp); err != nil { - return time.Time{}, fmt.Errorf("failed to read server response: %v", err) - } - - secs := float64(rsp.TxTimeSec) - ntpEpochOffset - nanos := (int64(rsp.TxTimeFrac) * 1e9) >> 32 - - showtime := time.Unix(int64(secs), nanos) - - return showtime, nil -} - -func UpdateSystemTime(dateTime string) error { - system := runtime.GOOS - if system == "linux" { - stdout2, err := cmd.Execf(`%s date -s "%s"`, cmd.SudoHandleCmd(), dateTime) - if err != nil { - return fmt.Errorf("update system time failed,stdout: %s, err: %v", stdout2, err) - } - return nil - } - return fmt.Errorf("the current system architecture %v does not support synchronization", system) -} - -func UpdateSystemTimeZone(timezone string) error { - system := runtime.GOOS - if system == "linux" { - stdout, err := cmd.Execf(`%s timedatectl set-timezone "%s"`, cmd.SudoHandleCmd(), timezone) - if err != nil { - return fmt.Errorf("update system time zone failed, stdout: %s, err: %v", stdout, err) - } - return nil - } - return fmt.Errorf("the current system architecture %v does not support synchronization", system) -} diff --git a/backend/utils/postgresql/client.go b/backend/utils/postgresql/client.go deleted file mode 100644 index 2122c28bb..000000000 --- a/backend/utils/postgresql/client.go +++ /dev/null @@ -1,59 +0,0 @@ -package postgresql - -import ( - "context" - "database/sql" - "errors" - "fmt" - "time" - - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/postgresql/client" - _ "github.com/jackc/pgx/v5/stdlib" -) - -type PostgresqlClient interface { - Create(info client.CreateInfo) error - CreateUser(info client.CreateInfo, withDeleteDB bool) error - Delete(info client.DeleteInfo) error - ChangePrivileges(info client.Privileges) error - ChangePassword(info client.PasswordChangeInfo) error - - Backup(info client.BackupInfo) error - Recover(info client.RecoverInfo) error - SyncDB() ([]client.SyncDBInfo, error) - Close() -} - -func NewPostgresqlClient(conn client.DBInfo) (PostgresqlClient, error) { - if conn.From == "local" { - connArgs := []string{"exec", conn.Address, "psql", "-t", "-U", conn.Username, "-c"} - return client.NewLocal(connArgs, conn.Address, conn.Username, conn.Password, conn.Database), nil - } - - connArgs := fmt.Sprintf("postgres://%s:%s@%s:%d/?sslmode=disable", conn.Username, conn.Password, conn.Address, conn.Port) - db, err := sql.Open("pgx", connArgs) - if err != nil { - return nil, err - } - - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(conn.Timeout)*time.Second) - defer cancel() - if err := db.PingContext(ctx); err != nil { - return nil, err - } - if errors.Is(ctx.Err(), context.DeadlineExceeded) { - return nil, buserr.New(constant.ErrExecTimeOut) - } - - return client.NewRemote(client.Remote{ - Client: db, - From: "remote", - Database: conn.Database, - User: conn.Username, - Password: conn.Password, - Address: conn.Address, - Port: conn.Port, - }), nil -} diff --git a/backend/utils/postgresql/client/info.go b/backend/utils/postgresql/client/info.go deleted file mode 100644 index b1b789dcf..000000000 --- a/backend/utils/postgresql/client/info.go +++ /dev/null @@ -1,81 +0,0 @@ -package client - -import ( - _ "github.com/jackc/pgx/v5/stdlib" -) - -type DBInfo struct { - From string `json:"from"` - Database string `json:"database"` - Address string `json:"address"` - Port uint `json:"port"` - Username string `json:"userName"` - Password string `json:"password"` - - Timeout uint `json:"timeout"` // second -} - -type CreateInfo struct { - Name string `json:"name"` - Username string `json:"userName"` - Password string `json:"password"` - SuperUser bool `json:"superUser"` - - Timeout uint `json:"timeout"` // second -} - -type Privileges struct { - Username string `json:"userName"` - SuperUser bool `json:"superUser"` - - Timeout uint `json:"timeout"` // second -} - -type DeleteInfo struct { - Name string `json:"name"` - Username string `json:"userName"` - - ForceDelete bool `json:"forceDelete"` - Timeout uint `json:"timeout"` // second -} - -type PasswordChangeInfo struct { - Username string `json:"userName"` - Password string `json:"password"` - - Timeout uint `json:"timeout"` // second -} - -type BackupInfo struct { - Name string `json:"name"` - TargetDir string `json:"targetDir"` - FileName string `json:"fileName"` - - Timeout uint `json:"timeout"` // second -} - -type RecoverInfo struct { - Name string `json:"name"` - SourceFile string `json:"sourceFile"` - Username string `json:"username"` - - Timeout uint `json:"timeout"` // second -} - -type SyncDBInfo struct { - Name string `json:"name"` - From string `json:"from"` - PostgresqlName string `json:"postgresqlName"` -} -type Status struct { - Uptime string `json:"uptime"` - Version string `json:"version"` - MaxConnections string `json:"max_connections"` - Autovacuum string `json:"autovacuum"` - CurrentConnections string `json:"current_connections"` - HitRatio string `json:"hit_ratio"` - SharedBuffers string `json:"shared_buffers"` - BuffersClean string `json:"buffers_clean"` - MaxwrittenClean string `json:"maxwritten_clean"` - BuffersBackendFsync string `json:"buffers_backend_fsync"` -} diff --git a/backend/utils/postgresql/client/local.go b/backend/utils/postgresql/client/local.go deleted file mode 100644 index b36fe6608..000000000 --- a/backend/utils/postgresql/client/local.go +++ /dev/null @@ -1,230 +0,0 @@ -package client - -import ( - "bytes" - "compress/gzip" - "context" - "errors" - "fmt" - "os" - "os/exec" - "path" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/files" -) - -type Local struct { - PrefixCommand []string - Database string - Username string - Password string - ContainerName string -} - -func NewLocal(command []string, containerName, username, password, database string) *Local { - return &Local{PrefixCommand: command, ContainerName: containerName, Username: username, Password: password, Database: database} -} - -func (r *Local) Create(info CreateInfo) error { - createSql := fmt.Sprintf("CREATE DATABASE \"%s\"", info.Name) - if err := r.ExecSQL(createSql, info.Timeout); err != nil { - if strings.Contains(strings.ToLower(err.Error()), "already exists") { - return buserr.New(constant.ErrDatabaseIsExist) - } - return err - } - - if err := r.CreateUser(info, true); err != nil { - _ = r.ExecSQL(fmt.Sprintf("DROP DATABASE \"%s\"", info.Name), info.Timeout) - return err - } - - return nil -} - -func (r *Local) ChangePrivileges(info Privileges) error { - super := "SUPERUSER" - if !info.SuperUser { - super = "NOSUPERUSER" - } - changeSql := fmt.Sprintf("ALTER USER \"%s\" WITH %s", info.Username, super) - return r.ExecSQL(changeSql, info.Timeout) -} - -func (r *Local) CreateUser(info CreateInfo, withDeleteDB bool) error { - createSql := fmt.Sprintf("CREATE USER \"%s\" WITH PASSWORD '%s'", info.Username, info.Password) - if err := r.ExecSQL(createSql, info.Timeout); err != nil { - if strings.Contains(strings.ToLower(err.Error()), "already exists") { - return buserr.New(constant.ErrUserIsExist) - } - if withDeleteDB { - _ = r.Delete(DeleteInfo{ - Name: info.Name, - Username: info.Username, - ForceDelete: true, - Timeout: 300}) - } - return err - } - if info.SuperUser { - if err := r.ChangePrivileges(Privileges{SuperUser: true, Username: info.Username, Timeout: info.Timeout}); err != nil { - if withDeleteDB { - _ = r.Delete(DeleteInfo{ - Name: info.Name, - Username: info.Username, - ForceDelete: true, - Timeout: 300}) - } - return err - } - } - grantStr := fmt.Sprintf("GRANT ALL PRIVILEGES ON DATABASE \"%s\" TO \"%s\"", info.Name, info.Username) - if err := r.ExecSQL(grantStr, info.Timeout); err != nil { - if withDeleteDB { - _ = r.Delete(DeleteInfo{ - Name: info.Name, - Username: info.Username, - ForceDelete: true, - Timeout: 300}) - } - return err - } - return nil -} - -func (r *Local) Delete(info DeleteInfo) error { - if len(info.Name) != 0 { - dropSql := fmt.Sprintf("DROP DATABASE \"%s\"", info.Name) - if err := r.ExecSQL(dropSql, info.Timeout); err != nil && !info.ForceDelete { - return err - } - } - dropSql := fmt.Sprintf("DROP USER \"%s\"", info.Username) - if err := r.ExecSQL(dropSql, info.Timeout); err != nil && !info.ForceDelete { - if strings.Contains(strings.ToLower(err.Error()), "depend on it") { - return buserr.WithDetail(constant.ErrInUsed, info.Username, nil) - } - return err - } - return nil -} - -func (r *Local) ChangePassword(info PasswordChangeInfo) error { - changeSql := fmt.Sprintf("ALTER USER \"%s\" WITH PASSWORD '%s'", info.Username, info.Password) - if err := r.ExecSQL(changeSql, info.Timeout); err != nil { - return err - } - - return nil -} - -func (r *Local) Backup(info BackupInfo) error { - fileOp := files.NewFileOp() - if !fileOp.Stat(info.TargetDir) { - if err := os.MkdirAll(info.TargetDir, os.ModePerm); err != nil { - return fmt.Errorf("mkdir %s failed, err: %v", info.TargetDir, err) - } - } - outfile, err := os.OpenFile(path.Join(info.TargetDir, info.FileName), os.O_RDWR|os.O_CREATE, 0755) - if err != nil { - return fmt.Errorf("open file %s failed, err: %v", path.Join(info.TargetDir, info.FileName), err) - } - defer outfile.Close() - global.LOG.Infof("start to pg_dump | gzip > %s.gzip", info.TargetDir+"/"+info.FileName) - cmd := exec.Command("docker", "exec", r.ContainerName, "pg_dump", "-F", "c", "-U", r.Username, "-d", info.Name) - var stderr bytes.Buffer - cmd.Stderr = &stderr - - gzipCmd := exec.Command("gzip", "-cf") - gzipCmd.Stdin, _ = cmd.StdoutPipe() - gzipCmd.Stdout = outfile - _ = gzipCmd.Start() - - if err := cmd.Run(); err != nil { - return fmt.Errorf("handle backup database failed, err: %v", stderr.String()) - } - _ = gzipCmd.Wait() - return nil -} - -func (r *Local) Recover(info RecoverInfo) error { - fi, _ := os.Open(info.SourceFile) - defer fi.Close() - cmd := exec.Command("docker", "exec", "-i", r.ContainerName, "pg_restore", "-F", "c", "-c", "-U", r.Username, "-d", info.Name) - if strings.HasSuffix(info.SourceFile, ".gz") { - gzipFile, err := os.Open(info.SourceFile) - if err != nil { - return err - } - defer gzipFile.Close() - gzipReader, err := gzip.NewReader(gzipFile) - if err != nil { - return err - } - defer gzipReader.Close() - cmd.Stdin = gzipReader - } else { - cmd.Stdin = fi - } - stdout, err := cmd.CombinedOutput() - if err != nil || strings.HasPrefix(string(stdout), "ERROR ") { - return errors.New(string(stdout)) - } - - return nil -} - -func (r *Local) SyncDB() ([]SyncDBInfo, error) { - var datas []SyncDBInfo - lines, err := r.ExecSQLForRows("SELECT datname FROM pg_database", 300) - if err != nil { - return datas, err - } - for _, line := range lines { - itemLine := strings.TrimLeft(line, " ") - if len(itemLine) == 0 || itemLine == "postgres" || itemLine == "template1" || itemLine == "template0" || itemLine == r.Username { - continue - } - datas = append(datas, SyncDBInfo{Name: itemLine, From: "local", PostgresqlName: r.Database}) - } - return datas, nil -} - -func (r *Local) Close() {} - -func (r *Local) ExecSQL(command string, timeout uint) error { - itemCommand := r.PrefixCommand[:] - itemCommand = append(itemCommand, command) - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) - defer cancel() - cmd := exec.CommandContext(ctx, "docker", itemCommand...) - stdout, err := cmd.CombinedOutput() - if errors.Is(ctx.Err(), context.DeadlineExceeded) { - return buserr.New(constant.ErrExecTimeOut) - } - if err != nil || strings.HasPrefix(string(stdout), "ERROR ") { - return errors.New(string(stdout)) - } - return nil -} - -func (r *Local) ExecSQLForRows(command string, timeout uint) ([]string, error) { - itemCommand := r.PrefixCommand[:] - itemCommand = append(itemCommand, command) - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) - defer cancel() - cmd := exec.CommandContext(ctx, "docker", itemCommand...) - stdout, err := cmd.CombinedOutput() - if errors.Is(ctx.Err(), context.DeadlineExceeded) { - return nil, buserr.New(constant.ErrExecTimeOut) - } - if err != nil || strings.HasPrefix(string(stdout), "ERROR ") { - return nil, errors.New(string(stdout)) - } - return strings.Split(string(stdout), "\n"), nil -} diff --git a/backend/utils/postgresql/client/remote.go b/backend/utils/postgresql/client/remote.go deleted file mode 100644 index b4a954181..000000000 --- a/backend/utils/postgresql/client/remote.go +++ /dev/null @@ -1,311 +0,0 @@ -package client - -import ( - "bufio" - "context" - "database/sql" - "fmt" - "io" - "os" - "os/exec" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/docker/docker/api/types/image" - "github.com/pkg/errors" - - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/1Panel-dev/1Panel/backend/utils/files" - _ "github.com/jackc/pgx/v5/stdlib" -) - -type Remote struct { - Client *sql.DB - From string - Database string - User string - Password string - Address string - Port uint -} - -func NewRemote(db Remote) *Remote { - return &db -} -func (r *Remote) Create(info CreateInfo) error { - createSql := fmt.Sprintf("CREATE DATABASE \"%s\"", info.Name) - if err := r.ExecSQL(createSql, info.Timeout); err != nil { - if strings.Contains(strings.ToLower(err.Error()), "already exists") { - return buserr.New(constant.ErrDatabaseIsExist) - } - return err - } - if err := r.CreateUser(info, true); err != nil { - return err - } - return nil -} - -func (r *Remote) CreateUser(info CreateInfo, withDeleteDB bool) error { - createSql := fmt.Sprintf("CREATE USER \"%s\" WITH PASSWORD '%s'", info.Username, info.Password) - if err := r.ExecSQL(createSql, info.Timeout); err != nil { - if strings.Contains(strings.ToLower(err.Error()), "already exists") { - return buserr.New(constant.ErrUserIsExist) - } - if withDeleteDB { - _ = r.Delete(DeleteInfo{ - Name: info.Name, - Username: info.Username, - ForceDelete: true, - Timeout: 300}) - } - return err - } - if info.SuperUser { - if err := r.ChangePrivileges(Privileges{SuperUser: true, Username: info.Username, Timeout: info.Timeout}); err != nil { - if withDeleteDB { - _ = r.Delete(DeleteInfo{ - Name: info.Name, - Username: info.Username, - ForceDelete: true, - Timeout: 300}) - } - return err - } - } - grantSql := fmt.Sprintf("GRANT ALL PRIVILEGES ON DATABASE \"%s\" TO \"%s\"", info.Name, info.Username) - if err := r.ExecSQL(grantSql, info.Timeout); err != nil { - if withDeleteDB { - _ = r.Delete(DeleteInfo{ - Name: info.Name, - Username: info.Username, - ForceDelete: true, - Timeout: 300}) - } - return err - } - - return nil -} - -func (r *Remote) Delete(info DeleteInfo) error { - if len(info.Name) != 0 { - dropSql := fmt.Sprintf("DROP DATABASE \"%s\"", info.Name) - if err := r.ExecSQL(dropSql, info.Timeout); err != nil && !info.ForceDelete { - return err - } - } - dropSql := fmt.Sprintf("DROP USER \"%s\"", info.Username) - if err := r.ExecSQL(dropSql, info.Timeout); err != nil && !info.ForceDelete { - if strings.Contains(strings.ToLower(err.Error()), "depend on it") { - return buserr.WithDetail(constant.ErrInUsed, info.Username, nil) - } - return err - } - return nil -} - -func (r *Remote) ChangePrivileges(info Privileges) error { - super := "SUPERUSER" - if !info.SuperUser { - super = "NOSUPERUSER" - } - return r.ExecSQL(fmt.Sprintf("ALTER USER \"%s\" WITH %s", info.Username, super), info.Timeout) -} - -func (r *Remote) ChangePassword(info PasswordChangeInfo) error { - return r.ExecSQL(fmt.Sprintf("ALTER USER \"%s\" WITH ENCRYPTED PASSWORD '%s'", info.Username, info.Password), info.Timeout) -} - -func (r *Remote) Backup(info BackupInfo) error { - imageTag, err := loadImageTag() - if err != nil { - return err - } - fileOp := files.NewFileOp() - if !fileOp.Stat(info.TargetDir) { - if err := os.MkdirAll(info.TargetDir, os.ModePerm); err != nil { - return fmt.Errorf("mkdir %s failed, err: %v", info.TargetDir, err) - } - } - fileNameItem := info.TargetDir + "/" + strings.TrimSuffix(info.FileName, ".gz") - backupCommand := exec.Command("bash", "-c", - fmt.Sprintf("docker run --rm --net=host -i %s /bin/bash -c 'PGPASSWORD=%s pg_dump -h %s -p %d --no-owner -Fc -U %s %s' > %s", - imageTag, r.Password, r.Address, r.Port, r.User, info.Name, fileNameItem)) - _ = backupCommand.Run() - b := make([]byte, 5) - n := []byte{80, 71, 68, 77, 80} - handle, err := os.OpenFile(fileNameItem, os.O_RDONLY, os.ModePerm) - if err != nil { - return fmt.Errorf("backup file not found,err:%v", err) - } - defer handle.Close() - _, _ = handle.Read(b) - if string(b) != string(n) { - errBytes, _ := os.ReadFile(fileNameItem) - return fmt.Errorf("backup failed,err:%s", string(errBytes)) - } - - gzipCmd := exec.Command("gzip", fileNameItem) - stdout, err := gzipCmd.CombinedOutput() - if err != nil { - return fmt.Errorf("gzip file %s failed, stdout: %v, err: %v", strings.TrimSuffix(info.FileName, ".gz"), string(stdout), err) - } - return nil -} - -func (r *Remote) Recover(info RecoverInfo) error { - imageTag, err := loadImageTag() - if err != nil { - return err - } - fileName := info.SourceFile - if strings.HasSuffix(info.SourceFile, ".sql.gz") { - fileName = strings.TrimSuffix(info.SourceFile, ".gz") - gzipCmd := exec.Command("gunzip", info.SourceFile) - stdout, err := gzipCmd.CombinedOutput() - if err != nil { - return fmt.Errorf("gunzip file %s failed, stdout: %v, err: %v", info.SourceFile, string(stdout), err) - } - defer func() { - gzipCmd := exec.Command("gzip", fileName) - _, _ = gzipCmd.CombinedOutput() - }() - } - recoverCommand := exec.Command("bash", "-c", - fmt.Sprintf("docker run --rm --net=host -i %s /bin/bash -c 'PGPASSWORD=%s pg_restore -h %s -p %d --verbose --clean --no-privileges --no-owner -Fc -U %s -d %s --role=%s' < %s", - imageTag, r.Password, r.Address, r.Port, r.User, info.Name, info.Username, fileName)) - pipe, _ := recoverCommand.StdoutPipe() - stderrPipe, _ := recoverCommand.StderrPipe() - defer pipe.Close() - defer stderrPipe.Close() - if err := recoverCommand.Start(); err != nil { - return err - } - reader := bufio.NewReader(pipe) - for { - readString, err := reader.ReadString('\n') - if errors.Is(err, io.EOF) { - break - } - if err != nil { - all, _ := io.ReadAll(stderrPipe) - global.LOG.Errorf("[Postgresql] DB:[%s] Recover Error: %s", info.Name, string(all)) - return err - } - global.LOG.Infof("[Postgresql] DB:[%s] Restoring: %s", info.Name, readString) - } - - return nil -} - -func (r *Remote) SyncDB() ([]SyncDBInfo, error) { - ctx, cancel := context.WithTimeout(context.Background(), 300*time.Second) - defer cancel() - - var datas []SyncDBInfo - rows, err := r.Client.Query("SELECT datname FROM pg_database;") - if err != nil { - return nil, err - } - defer rows.Close() - for rows.Next() { - var dbName string - if err := rows.Scan(&dbName); err != nil { - continue - } - if len(dbName) == 0 || dbName == "postgres" || dbName == "template1" || dbName == "template0" || dbName == r.User { - continue - } - datas = append(datas, SyncDBInfo{Name: dbName, From: r.From, PostgresqlName: r.Database}) - } - if errors.Is(ctx.Err(), context.DeadlineExceeded) { - return nil, buserr.New(constant.ErrExecTimeOut) - } - return datas, nil -} - -func (r *Remote) Close() { - _ = r.Client.Close() -} - -func (r *Remote) ExecSQL(command string, timeout uint) error { - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) - defer cancel() - - if _, err := r.Client.ExecContext(ctx, command); err != nil { - return err - } - if errors.Is(ctx.Err(), context.DeadlineExceeded) { - return buserr.New(constant.ErrExecTimeOut) - } - - return nil -} - -func loadImageTag() (string, error) { - var ( - app model.App - appDetails []model.AppDetail - versions []string - ) - if err := global.DB.Where("key = ?", "postgresql").First(&app).Error; err != nil { - versions = []string{"postgres:16.1-alpine", "postgres:16.0-alpine"} - } else { - if err := global.DB.Where("app_id = ?", app.ID).Find(&appDetails).Error; err != nil { - versions = []string{"postgres:16.1-alpine", "postgres:16.0-alpine"} - } else { - for _, item := range appDetails { - versions = append(versions, "postgres:"+item.Version) - } - } - } - - client, err := docker.NewDockerClient() - if err != nil { - return "", err - } - defer client.Close() - images, err := client.ImageList(context.Background(), image.ListOptions{}) - if err != nil { - return "", err - } - - itemTag := "" - for _, item := range versions { - for _, image := range images { - for _, tag := range image.RepoTags { - if tag == item { - itemTag = tag - break - } - } - if len(itemTag) != 0 { - break - } - } - if len(itemTag) != 0 { - break - } - } - if len(itemTag) != 0 { - return itemTag, nil - } - - itemTag = "postgres:16.1-alpine" - ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute) - defer cancel() - if _, err := client.ImagePull(ctx, itemTag, image.PullOptions{}); err != nil { - if errors.Is(ctx.Err(), context.DeadlineExceeded) { - return itemTag, buserr.New(constant.ErrPgImagePull) - } - global.LOG.Errorf("image %s pull failed, err: %v", itemTag, err) - return itemTag, fmt.Errorf("image %s pull failed, err: %v", itemTag, err) - } - - return itemTag, nil -} diff --git a/backend/utils/qqwry/qqwry.go b/backend/utils/qqwry/qqwry.go deleted file mode 100644 index bd2b3d46a..000000000 --- a/backend/utils/qqwry/qqwry.go +++ /dev/null @@ -1,165 +0,0 @@ -package qqwry - -import ( - "encoding/binary" - "net" - "strings" - - "github.com/1Panel-dev/1Panel/cmd/server/qqwry" - "golang.org/x/text/encoding/simplifiedchinese" -) - -const ( - indexLen = 7 - redirectMode1 = 0x01 - redirectMode2 = 0x02 -) - -var IpCommonDictionary []byte - -type QQwry struct { - Data []byte - Offset int64 -} - -func NewQQwry() (*QQwry, error) { - IpCommonDictionary := qqwry.QQwryByte - return &QQwry{Data: IpCommonDictionary}, nil -} - -// readData 从文件中读取数据 -func (q *QQwry) readData(num int, offset ...int64) (rs []byte) { - if len(offset) > 0 { - q.setOffset(offset[0]) - } - nums := int64(num) - end := q.Offset + nums - dataNum := int64(len(q.Data)) - if q.Offset > dataNum { - return nil - } - - if end > dataNum { - end = dataNum - } - rs = q.Data[q.Offset:end] - q.Offset = end - return -} - -// setOffset 设置偏移量 -func (q *QQwry) setOffset(offset int64) { - q.Offset = offset -} - -// Find ip地址查询对应归属地信息 -func (q *QQwry) Find(ip string) (res ResultQQwry) { - res = ResultQQwry{} - res.IP = ip - if strings.Count(ip, ".") != 3 { - return res - } - offset := q.searchIndex(binary.BigEndian.Uint32(net.ParseIP(ip).To4())) - if offset <= 0 { - return - } - - var area []byte - mode := q.readMode(offset + 4) - if mode == redirectMode1 { - countryOffset := q.readUInt24() - mode = q.readMode(countryOffset) - if mode == redirectMode2 { - c := q.readUInt24() - area = q.readString(c) - } else { - area = q.readString(countryOffset) - } - } else if mode == redirectMode2 { - countryOffset := q.readUInt24() - area = q.readString(countryOffset) - } else { - area = q.readString(offset + 4) - } - - enc := simplifiedchinese.GBK.NewDecoder() - res.Area, _ = enc.String(string(area)) - - return -} - -type ResultQQwry struct { - IP string `json:"ip"` - Area string `json:"area"` -} - -// readMode 获取偏移值类型 -func (q *QQwry) readMode(offset uint32) byte { - mode := q.readData(1, int64(offset)) - return mode[0] -} - -// readString 获取字符串 -func (q *QQwry) readString(offset uint32) []byte { - q.setOffset(int64(offset)) - data := make([]byte, 0, 30) - for { - buf := q.readData(1) - if buf[0] == 0 { - break - } - data = append(data, buf[0]) - } - return data -} - -// searchIndex 查找索引位置 -func (q *QQwry) searchIndex(ip uint32) uint32 { - header := q.readData(8, 0) - - start := binary.LittleEndian.Uint32(header[:4]) - end := binary.LittleEndian.Uint32(header[4:]) - - for { - mid := q.getMiddleOffset(start, end) - buf := q.readData(indexLen, int64(mid)) - _ip := binary.LittleEndian.Uint32(buf[:4]) - - if end-start == indexLen { - offset := byteToUInt32(buf[4:]) - buf = q.readData(indexLen) - if ip < binary.LittleEndian.Uint32(buf[:4]) { - return offset - } - return 0 - } - - if _ip > ip { - end = mid - } else if _ip < ip { - start = mid - } else if _ip == ip { - return byteToUInt32(buf[4:]) - } - } -} - -// readUInt24 -func (q *QQwry) readUInt24() uint32 { - buf := q.readData(3) - return byteToUInt32(buf) -} - -// getMiddleOffset -func (q *QQwry) getMiddleOffset(start uint32, end uint32) uint32 { - records := ((end - start) / indexLen) >> 1 - return start + records*indexLen -} - -// byteToUInt32 将 byte 转换为uint32 -func byteToUInt32(data []byte) uint32 { - i := uint32(data[0]) & 0xff - i |= (uint32(data[1]) << 8) & 0xff00 - i |= (uint32(data[2]) << 16) & 0xff0000 - return i -} diff --git a/backend/utils/redis/redis.go b/backend/utils/redis/redis.go deleted file mode 100644 index c30053f6a..000000000 --- a/backend/utils/redis/redis.go +++ /dev/null @@ -1,28 +0,0 @@ -package redis - -import ( - "fmt" - - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/go-redis/redis" -) - -type DBInfo struct { - Address string `json:"address"` - Port uint `json:"port"` - Password string `json:"password"` -} - -func NewRedisClient(conn DBInfo) (*redis.Client, error) { - client := redis.NewClient(&redis.Options{ - Addr: fmt.Sprintf("%s:%v", conn.Address, conn.Port), - Password: conn.Password, - DB: 0, - }) - - if _, err := client.Ping().Result(); err != nil { - global.LOG.Errorf("check redis conn failed, err: %v", err) - return client, err - } - return client, nil -} diff --git a/backend/utils/ssh/ssh.go b/backend/utils/ssh/ssh.go deleted file mode 100644 index f487182d4..000000000 --- a/backend/utils/ssh/ssh.go +++ /dev/null @@ -1,142 +0,0 @@ -package ssh - -import ( - "bytes" - "fmt" - "io" - "strings" - "sync" - "time" - - gossh "golang.org/x/crypto/ssh" -) - -type ConnInfo struct { - User string `json:"user"` - Addr string `json:"addr"` - Port int `json:"port"` - AuthMode string `json:"authMode"` - Password string `json:"password"` - PrivateKey []byte `json:"privateKey"` - PassPhrase []byte `json:"passPhrase"` - DialTimeOut time.Duration `json:"dialTimeOut"` - - Client *gossh.Client `json:"client"` - Session *gossh.Session `json:"session"` - LastResult string `json:"lastResult"` -} - -func (c *ConnInfo) NewClient() (*ConnInfo, error) { - if strings.Contains(c.Addr, ":") { - c.Addr = fmt.Sprintf("[%s]", c.Addr) - } - config := &gossh.ClientConfig{} - config.SetDefaults() - addr := fmt.Sprintf("%s:%d", c.Addr, c.Port) - config.User = c.User - if c.AuthMode == "password" { - config.Auth = []gossh.AuthMethod{gossh.Password(c.Password)} - } else { - signer, err := makePrivateKeySigner(c.PrivateKey, c.PassPhrase) - if err != nil { - return nil, err - } - config.Auth = []gossh.AuthMethod{gossh.PublicKeys(signer)} - } - if c.DialTimeOut == 0 { - c.DialTimeOut = 5 * time.Second - } - config.Timeout = c.DialTimeOut - - config.HostKeyCallback = gossh.InsecureIgnoreHostKey() - proto := "tcp" - if strings.Contains(c.Addr, ":") { - proto = "tcp6" - } - client, err := gossh.Dial(proto, addr, config) - if nil != err { - return c, err - } - c.Client = client - return c, nil -} - -func (c *ConnInfo) Run(shell string) (string, error) { - if c.Client == nil { - if _, err := c.NewClient(); err != nil { - return "", err - } - } - session, err := c.Client.NewSession() - if err != nil { - return "", err - } - defer session.Close() - buf, err := session.CombinedOutput(shell) - - c.LastResult = string(buf) - return c.LastResult, err -} - -func (c *ConnInfo) Close() { - _ = c.Client.Close() -} - -type SshConn struct { - StdinPipe io.WriteCloser - ComboOutput *wsBufferWriter - Session *gossh.Session -} - -func (c *ConnInfo) NewSshConn(cols, rows int) (*SshConn, error) { - sshSession, err := c.Client.NewSession() - if err != nil { - return nil, err - } - - stdinP, err := sshSession.StdinPipe() - if err != nil { - return nil, err - } - - comboWriter := new(wsBufferWriter) - sshSession.Stdout = comboWriter - sshSession.Stderr = comboWriter - - modes := gossh.TerminalModes{ - gossh.ECHO: 1, - gossh.TTY_OP_ISPEED: 14400, - gossh.TTY_OP_OSPEED: 14400, - } - if err := sshSession.RequestPty("xterm", rows, cols, modes); err != nil { - return nil, err - } - if err := sshSession.Shell(); err != nil { - return nil, err - } - return &SshConn{StdinPipe: stdinP, ComboOutput: comboWriter, Session: sshSession}, nil -} - -func (s *SshConn) Close() { - if s.Session != nil { - s.Session.Close() - } -} - -type wsBufferWriter struct { - buffer bytes.Buffer - mu sync.Mutex -} - -func (w *wsBufferWriter) Write(p []byte) (int, error) { - w.mu.Lock() - defer w.mu.Unlock() - return w.buffer.Write(p) -} - -func makePrivateKeySigner(privateKey []byte, passPhrase []byte) (gossh.Signer, error) { - if len(passPhrase) != 0 { - return gossh.ParsePrivateKeyWithPassphrase(privateKey, passPhrase) - } - return gossh.ParsePrivateKey(privateKey) -} diff --git a/backend/utils/ssl/acme.go b/backend/utils/ssl/acme.go deleted file mode 100644 index 0d140dcf6..000000000 --- a/backend/utils/ssl/acme.go +++ /dev/null @@ -1,205 +0,0 @@ -package ssl - -import ( - "crypto" - "crypto/ecdsa" - "crypto/rsa" - "crypto/x509" - "encoding/json" - "encoding/pem" - "fmt" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/go-acme/lego/v4/certcrypto" - "github.com/go-acme/lego/v4/lego" - "github.com/go-acme/lego/v4/registration" - "io" - "net/http" - "net/url" -) - -type domainError struct { - Domain string - Error error -} - -type zeroSSLRes struct { - Success bool `json:"success"` - EabKid string `json:"eab_kid"` - EabHmacKey string `json:"eab_hmac_key"` -} - -type KeyType = certcrypto.KeyType - -const ( - KeyEC256 = certcrypto.EC256 - KeyEC384 = certcrypto.EC384 - KeyRSA2048 = certcrypto.RSA2048 - KeyRSA3072 = certcrypto.RSA3072 - KeyRSA4096 = certcrypto.RSA4096 -) - -func GetPrivateKey(priKey crypto.PrivateKey, keyType KeyType) ([]byte, error) { - var ( - marshal []byte - block *pem.Block - err error - ) - - switch keyType { - case KeyEC256, KeyEC384: - key := priKey.(*ecdsa.PrivateKey) - marshal, err = x509.MarshalECPrivateKey(key) - if err != nil { - return nil, err - } - block = &pem.Block{ - Type: "EC PRIVATE KEY", - Bytes: marshal, - } - case KeyRSA2048, KeyRSA3072, KeyRSA4096: - key := priKey.(*rsa.PrivateKey) - marshal = x509.MarshalPKCS1PrivateKey(key) - block = &pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: marshal, - } - } - - return pem.EncodeToMemory(block), nil -} - -func NewRegisterClient(acmeAccount *model.WebsiteAcmeAccount) (*AcmeClient, error) { - var ( - priKey crypto.PrivateKey - err error - ) - - if acmeAccount.PrivateKey != "" { - switch KeyType(acmeAccount.KeyType) { - case KeyEC256, KeyEC384: - block, _ := pem.Decode([]byte(acmeAccount.PrivateKey)) - priKey, err = x509.ParseECPrivateKey(block.Bytes) - if err != nil { - return nil, err - } - case KeyRSA2048, KeyRSA3072, KeyRSA4096: - block, _ := pem.Decode([]byte(acmeAccount.PrivateKey)) - priKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - return nil, err - } - } - - } else { - priKey, err = certcrypto.GeneratePrivateKey(KeyType(acmeAccount.KeyType)) - if err != nil { - return nil, err - } - } - - myUser := &AcmeUser{ - Email: acmeAccount.Email, - Key: priKey, - } - config := newConfig(myUser, acmeAccount.Type) - client, err := lego.NewClient(config) - if err != nil { - return nil, err - } - var reg *registration.Resource - if acmeAccount.Type == "zerossl" || acmeAccount.Type == "google" { - if acmeAccount.Type == "zerossl" { - var res *zeroSSLRes - res, err = getZeroSSLEabCredentials(acmeAccount.Email) - if err != nil { - return nil, err - } - if res.Success { - acmeAccount.EabKid = res.EabKid - acmeAccount.EabHmacKey = res.EabHmacKey - } else { - return nil, fmt.Errorf("get zero ssl eab credentials failed") - } - } - - eabOptions := registration.RegisterEABOptions{ - TermsOfServiceAgreed: true, - Kid: acmeAccount.EabKid, - HmacEncoded: acmeAccount.EabHmacKey, - } - reg, err = client.Registration.RegisterWithExternalAccountBinding(eabOptions) - if err != nil { - return nil, err - } - } else { - reg, err = client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true}) - if err != nil { - return nil, err - } - } - myUser.Registration = reg - - acmeClient := &AcmeClient{ - User: myUser, - Client: client, - Config: config, - } - - return acmeClient, nil -} - -func newConfig(user *AcmeUser, accountType string) *lego.Config { - config := lego.NewConfig(user) - switch accountType { - case "letsencrypt": - config.CADirURL = "https://acme-v02.api.letsencrypt.org/directory" - case "zerossl": - config.CADirURL = "https://acme.zerossl.com/v2/DV90" - case "buypass": - config.CADirURL = "https://api.buypass.com/acme/directory" - case "google": - config.CADirURL = "https://dv.acme-v02.api.pki.goog/directory" - } - - config.UserAgent = "1Panel" - config.Certificate.KeyType = certcrypto.RSA2048 - return config -} - -func getZeroSSLEabCredentials(email string) (*zeroSSLRes, error) { - baseURL := "https://api.zerossl.com/acme/eab-credentials-email" - params := url.Values{} - params.Add("email", email) - requestURL := fmt.Sprintf("%s?%s", baseURL, params.Encode()) - - req, err := http.NewRequest("POST", requestURL, nil) - if err != nil { - return nil, err - } - - req.Header.Set("Content-Type", "application/json") - - client := &http.Client{} - resp, err := client.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("server returned non-200 status: %d %s", resp.StatusCode, http.StatusText(resp.StatusCode)) - } - - var result zeroSSLRes - err = json.Unmarshal(body, &result) - if err != nil { - return nil, err - } - - return &result, nil -} diff --git a/backend/utils/ssl/client.go b/backend/utils/ssl/client.go deleted file mode 100644 index e3cfd7b3b..000000000 --- a/backend/utils/ssl/client.go +++ /dev/null @@ -1,302 +0,0 @@ -package ssl - -import ( - "crypto" - "encoding/json" - "os" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/go-acme/lego/v4/acme" - "github.com/go-acme/lego/v4/acme/api" - "github.com/go-acme/lego/v4/certificate" - "github.com/go-acme/lego/v4/challenge" - "github.com/go-acme/lego/v4/challenge/dns01" - "github.com/go-acme/lego/v4/lego" - "github.com/go-acme/lego/v4/providers/dns/alidns" - "github.com/go-acme/lego/v4/providers/dns/cloudflare" - "github.com/go-acme/lego/v4/providers/dns/dnspod" - "github.com/go-acme/lego/v4/providers/dns/godaddy" - "github.com/go-acme/lego/v4/providers/dns/namecheap" - "github.com/go-acme/lego/v4/providers/dns/namedotcom" - "github.com/go-acme/lego/v4/providers/dns/namesilo" - "github.com/go-acme/lego/v4/providers/dns/tencentcloud" - "github.com/go-acme/lego/v4/providers/http/webroot" - "github.com/go-acme/lego/v4/registration" - "github.com/pkg/errors" -) - -type AcmeUser struct { - Email string - Registration *registration.Resource - Key crypto.PrivateKey -} - -func (u *AcmeUser) GetEmail() string { - return u.Email -} - -func (u *AcmeUser) GetRegistration() *registration.Resource { - return u.Registration -} -func (u *AcmeUser) GetPrivateKey() crypto.PrivateKey { - return u.Key -} - -type AcmeClient struct { - Config *lego.Config - Client *lego.Client - User *AcmeUser -} - -func NewAcmeClient(acmeAccount *model.WebsiteAcmeAccount) (*AcmeClient, error) { - if acmeAccount.Email == "" { - return nil, errors.New("email can not blank") - } - client, err := NewRegisterClient(acmeAccount) - if err != nil { - return nil, err - } - return client, nil -} - -type DnsType string - -const ( - DnsPod DnsType = "DnsPod" - AliYun DnsType = "AliYun" - CloudFlare DnsType = "CloudFlare" - NameSilo DnsType = "NameSilo" - NameCheap DnsType = "NameCheap" - NameCom DnsType = "NameCom" - Godaddy DnsType = "Godaddy" - TencentCloud DnsType = "TencentCloud" -) - -type DNSParam struct { - ID string `json:"id"` - Token string `json:"token"` - AccessKey string `json:"accessKey"` - SecretKey string `json:"secretKey"` - Email string `json:"email"` - APIkey string `json:"apiKey"` - APIUser string `json:"apiUser"` - APISecret string `json:"apiSecret"` - SecretID string `json:"secretID"` -} - -var ( - propagationTimeout = 30 * time.Minute - pollingInterval = 10 * time.Second - ttl = 3600 -) - -func (c *AcmeClient) UseDns(dnsType DnsType, params string, websiteSSL model.WebsiteSSL) error { - var ( - param DNSParam - p challenge.Provider - err error - ) - - if err = json.Unmarshal([]byte(params), ¶m); err != nil { - return err - } - - switch dnsType { - case DnsPod: - dnsPodConfig := dnspod.NewDefaultConfig() - dnsPodConfig.LoginToken = param.ID + "," + param.Token - dnsPodConfig.PropagationTimeout = propagationTimeout - dnsPodConfig.PollingInterval = pollingInterval - dnsPodConfig.TTL = ttl - p, err = dnspod.NewDNSProviderConfig(dnsPodConfig) - case AliYun: - alidnsConfig := alidns.NewDefaultConfig() - alidnsConfig.SecretKey = param.SecretKey - alidnsConfig.APIKey = param.AccessKey - alidnsConfig.PropagationTimeout = propagationTimeout - alidnsConfig.PollingInterval = pollingInterval - alidnsConfig.TTL = ttl - p, err = alidns.NewDNSProviderConfig(alidnsConfig) - case CloudFlare: - cloudflareConfig := cloudflare.NewDefaultConfig() - cloudflareConfig.AuthEmail = param.Email - cloudflareConfig.AuthToken = param.APIkey - cloudflareConfig.PropagationTimeout = propagationTimeout - cloudflareConfig.PollingInterval = pollingInterval - cloudflareConfig.TTL = 3600 - p, err = cloudflare.NewDNSProviderConfig(cloudflareConfig) - case NameCheap: - namecheapConfig := namecheap.NewDefaultConfig() - namecheapConfig.APIKey = param.APIkey - namecheapConfig.APIUser = param.APIUser - namecheapConfig.PropagationTimeout = propagationTimeout - namecheapConfig.PollingInterval = pollingInterval - namecheapConfig.TTL = ttl - p, err = namecheap.NewDNSProviderConfig(namecheapConfig) - case NameSilo: - nameSiloConfig := namesilo.NewDefaultConfig() - nameSiloConfig.APIKey = param.APIkey - nameSiloConfig.PropagationTimeout = propagationTimeout - nameSiloConfig.PollingInterval = pollingInterval - nameSiloConfig.TTL = ttl - p, err = namesilo.NewDNSProviderConfig(nameSiloConfig) - case Godaddy: - godaddyConfig := godaddy.NewDefaultConfig() - godaddyConfig.APIKey = param.APIkey - godaddyConfig.APISecret = param.APISecret - godaddyConfig.PropagationTimeout = propagationTimeout - godaddyConfig.PollingInterval = pollingInterval - godaddyConfig.TTL = ttl - p, err = godaddy.NewDNSProviderConfig(godaddyConfig) - case NameCom: - nameComConfig := namedotcom.NewDefaultConfig() - nameComConfig.APIToken = param.Token - nameComConfig.Username = param.APIUser - nameComConfig.PropagationTimeout = propagationTimeout - nameComConfig.PollingInterval = pollingInterval - nameComConfig.TTL = ttl - p, err = namedotcom.NewDNSProviderConfig(nameComConfig) - case TencentCloud: - tencentCloudConfig := tencentcloud.NewDefaultConfig() - tencentCloudConfig.SecretID = param.SecretID - tencentCloudConfig.SecretKey = param.SecretKey - tencentCloudConfig.PropagationTimeout = propagationTimeout - tencentCloudConfig.PollingInterval = pollingInterval - tencentCloudConfig.TTL = ttl - p, err = tencentcloud.NewDNSProviderConfig(tencentCloudConfig) - } - if err != nil { - return err - } - var nameservers []string - if websiteSSL.Nameserver1 != "" { - nameservers = append(nameservers, websiteSSL.Nameserver1) - } - if websiteSSL.Nameserver2 != "" { - nameservers = append(nameservers, websiteSSL.Nameserver2) - } - if websiteSSL.DisableCNAME { - _ = os.Setenv("LEGO_DISABLE_CNAME_SUPPORT", "true") - } else { - _ = os.Setenv("LEGO_DISABLE_CNAME_SUPPORT", "false") - } - - return c.Client.Challenge.SetDNS01Provider(p, - dns01.CondOption(len(nameservers) > 0, - dns01.AddRecursiveNameservers(nameservers)), - dns01.CondOption(websiteSSL.SkipDNS, - dns01.DisableCompletePropagationRequirement()), - dns01.AddDNSTimeout(10*time.Minute), - ) -} - -func (c *AcmeClient) UseManualDns() error { - p := &manualDnsProvider{} - if err := c.Client.Challenge.SetDNS01Provider(p, dns01.AddDNSTimeout(10*time.Minute)); err != nil { - return err - } - return nil -} - -func (c *AcmeClient) UseHTTP(path string) error { - httpProvider, err := webroot.NewHTTPProvider(path) - if err != nil { - return err - } - - err = c.Client.Challenge.SetHTTP01Provider(httpProvider) - if err != nil { - return err - } - return nil -} - -func (c *AcmeClient) ObtainSSL(domains []string, privateKey crypto.PrivateKey) (certificate.Resource, error) { - request := certificate.ObtainRequest{ - Domains: domains, - Bundle: true, - PrivateKey: privateKey, - } - - certificates, err := c.Client.Certificate.Obtain(request) - if err != nil { - return certificate.Resource{}, err - } - - return *certificates, nil -} - -type Resolve struct { - Key string - Value string - Err string -} - -type manualDnsProvider struct { - Resolve *Resolve -} - -func (p *manualDnsProvider) Present(domain, token, keyAuth string) error { - return nil -} - -func (p *manualDnsProvider) CleanUp(domain, token, keyAuth string) error { - return nil -} - -func (c *AcmeClient) GetDNSResolve(domains []string) (map[string]Resolve, error) { - core, err := api.New(c.Config.HTTPClient, c.Config.UserAgent, c.Config.CADirURL, c.User.Registration.URI, c.User.Key) - if err != nil { - return nil, err - } - order, err := core.Orders.New(domains) - if err != nil { - return nil, err - } - resolves := make(map[string]Resolve) - resc, errc := make(chan acme.Authorization), make(chan domainError) - for _, authzURL := range order.Authorizations { - go func(authzURL string) { - authz, err := core.Authorizations.Get(authzURL) - if err != nil { - errc <- domainError{Domain: authz.Identifier.Value, Error: err} - return - } - resc <- authz - }(authzURL) - } - - var responses []acme.Authorization - for i := 0; i < len(order.Authorizations); i++ { - select { - case res := <-resc: - responses = append(responses, res) - case err := <-errc: - resolves[err.Domain] = Resolve{Err: err.Error.Error()} - } - } - close(resc) - close(errc) - - for _, auth := range responses { - domain := challenge.GetTargetedDomain(auth) - chlng, err := challenge.FindChallenge(challenge.DNS01, auth) - if err != nil { - resolves[domain] = Resolve{Err: err.Error()} - continue - } - keyAuth, err := core.GetKeyAuthorization(chlng.Token) - if err != nil { - resolves[domain] = Resolve{Err: err.Error()} - continue - } - challengeInfo := dns01.GetChallengeInfo(domain, keyAuth) - resolves[domain] = Resolve{ - Key: challengeInfo.FQDN, - Value: challengeInfo.Value, - } - } - - return resolves, nil -} diff --git a/backend/utils/systemctl/systemctl.go b/backend/utils/systemctl/systemctl.go deleted file mode 100644 index 0f7ef19db..000000000 --- a/backend/utils/systemctl/systemctl.go +++ /dev/null @@ -1,64 +0,0 @@ -package systemctl - -import ( - "fmt" - "github.com/pkg/errors" - "os/exec" - "strings" -) - -func RunSystemCtl(args ...string) (string, error) { - cmd := exec.Command("systemctl", args...) - output, err := cmd.CombinedOutput() - if err != nil { - return string(output), fmt.Errorf("failed to run command: %w", err) - } - return string(output), nil -} - -func IsActive(serviceName string) (bool, error) { - out, err := RunSystemCtl("is-active", serviceName) - if err != nil { - return false, err - } - return out == "active\n", nil -} - -func IsEnable(serviceName string) (bool, error) { - out, err := RunSystemCtl("is-enabled", serviceName) - if err != nil { - return false, err - } - return out == "enabled\n", nil -} - -func IsExist(serviceName string) (bool, error) { - out, err := RunSystemCtl("is-enabled", serviceName) - if err != nil { - if strings.Contains(out, "disabled") { - return true, nil - } - return false, nil - } - return true, nil -} - -func handlerErr(out string, err error) error { - if err != nil { - if out != "" { - return errors.New(out) - } - return err - } - return nil -} - -func Restart(serviceName string) error { - out, err := RunSystemCtl("restart", serviceName) - return handlerErr(out, err) -} - -func Operate(operate, serviceName string) error { - out, err := RunSystemCtl(operate, serviceName) - return handlerErr(out, err) -} diff --git a/backend/utils/terminal/local_cmd.go b/backend/utils/terminal/local_cmd.go deleted file mode 100644 index 098dbcea3..000000000 --- a/backend/utils/terminal/local_cmd.go +++ /dev/null @@ -1,93 +0,0 @@ -package terminal - -import ( - "os" - "os/exec" - "syscall" - "time" - "unsafe" - - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/creack/pty" - "github.com/pkg/errors" -) - -const ( - DefaultCloseSignal = syscall.SIGINT - DefaultCloseTimeout = 10 * time.Second -) - -type LocalCommand struct { - closeSignal syscall.Signal - closeTimeout time.Duration - - cmd *exec.Cmd - pty *os.File -} - -func NewCommand(commands []string) (*LocalCommand, error) { - cmd := exec.Command("docker", commands...) - - pty, err := pty.Start(cmd) - if err != nil { - return nil, errors.Wrapf(err, "failed to start command") - } - - lcmd := &LocalCommand{ - closeSignal: DefaultCloseSignal, - closeTimeout: DefaultCloseTimeout, - - cmd: cmd, - pty: pty, - } - - return lcmd, nil -} - -func (lcmd *LocalCommand) Read(p []byte) (n int, err error) { - return lcmd.pty.Read(p) -} - -func (lcmd *LocalCommand) Write(p []byte) (n int, err error) { - return lcmd.pty.Write(p) -} - -func (lcmd *LocalCommand) Close() error { - if lcmd.cmd != nil && lcmd.cmd.Process != nil { - _ = lcmd.cmd.Process.Kill() - } - _ = lcmd.pty.Close() - return nil -} - -func (lcmd *LocalCommand) ResizeTerminal(width int, height int) error { - window := struct { - row uint16 - col uint16 - x uint16 - y uint16 - }{ - uint16(height), - uint16(width), - 0, - 0, - } - _, _, errno := syscall.Syscall( - syscall.SYS_IOCTL, - lcmd.pty.Fd(), - syscall.TIOCSWINSZ, - uintptr(unsafe.Pointer(&window)), - ) - if errno != 0 { - return errno - } else { - return nil - } -} - -func (lcmd *LocalCommand) Wait(quitChan chan bool) { - if err := lcmd.cmd.Wait(); err != nil { - global.LOG.Errorf("ssh session wait failed, err: %v", err) - setQuit(quitChan) - } -} diff --git a/backend/utils/terminal/ws_local_session.go b/backend/utils/terminal/ws_local_session.go deleted file mode 100644 index 1a7a99adf..000000000 --- a/backend/utils/terminal/ws_local_session.go +++ /dev/null @@ -1,122 +0,0 @@ -package terminal - -import ( - "encoding/base64" - "encoding/json" - "sync" - - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/gorilla/websocket" - "github.com/pkg/errors" -) - -type LocalWsSession struct { - slave *LocalCommand - wsConn *websocket.Conn - - allowCtrlC bool - writeMutex sync.Mutex -} - -func NewLocalWsSession(cols, rows int, wsConn *websocket.Conn, slave *LocalCommand, allowCtrlC bool) (*LocalWsSession, error) { - if err := slave.ResizeTerminal(cols, rows); err != nil { - global.LOG.Errorf("ssh pty change windows size failed, err: %v", err) - } - - return &LocalWsSession{ - slave: slave, - wsConn: wsConn, - - allowCtrlC: allowCtrlC, - }, nil -} - -func (sws *LocalWsSession) Start(quitChan chan bool) { - go sws.handleSlaveEvent(quitChan) - go sws.receiveWsMsg(quitChan) -} - -func (sws *LocalWsSession) handleSlaveEvent(exitCh chan bool) { - defer setQuit(exitCh) - defer global.LOG.Debug("thread of handle slave event has exited now") - - buffer := make([]byte, 1024) - for { - select { - case <-exitCh: - return - default: - n, _ := sws.slave.Read(buffer) - _ = sws.masterWrite(buffer[:n]) - } - } -} - -func (sws *LocalWsSession) masterWrite(data []byte) error { - sws.writeMutex.Lock() - defer sws.writeMutex.Unlock() - wsData, err := json.Marshal(WsMsg{ - Type: WsMsgCmd, - Data: base64.StdEncoding.EncodeToString(data), - }) - if err != nil { - return errors.Wrapf(err, "failed to encoding to json") - } - err = sws.wsConn.WriteMessage(websocket.TextMessage, wsData) - if err != nil { - return errors.Wrapf(err, "failed to write to master") - } - return nil -} - -func (sws *LocalWsSession) receiveWsMsg(exitCh chan bool) { - defer func() { - if r := recover(); r != nil { - global.LOG.Errorf("A panic occurred during receive ws message, error message: %v", r) - } - }() - wsConn := sws.wsConn - defer setQuit(exitCh) - defer global.LOG.Debug("thread of receive ws msg has exited now") - for { - select { - case <-exitCh: - return - default: - _, wsData, err := wsConn.ReadMessage() - if err != nil { - global.LOG.Errorf("reading webSocket message failed, err: %v", err) - return - } - msgObj := WsMsg{} - _ = json.Unmarshal(wsData, &msgObj) - switch msgObj.Type { - case WsMsgResize: - if msgObj.Cols > 0 && msgObj.Rows > 0 { - if err := sws.slave.ResizeTerminal(msgObj.Cols, msgObj.Rows); err != nil { - global.LOG.Errorf("ssh pty change windows size failed, err: %v", err) - } - } - case WsMsgCmd: - decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Data) - if err != nil { - global.LOG.Errorf("websock cmd string base64 decoding failed, err: %v", err) - } - if string(decodeBytes) != "\x03" || sws.allowCtrlC { - sws.sendWebsocketInputCommandToSshSessionStdinPipe(decodeBytes) - } - case WsMsgHeartbeat: - err = wsConn.WriteMessage(websocket.TextMessage, wsData) - if err != nil { - global.LOG.Errorf("ssh sending heartbeat to webSocket failed, err: %v", err) - } - } - } - } -} - -func (sws *LocalWsSession) sendWebsocketInputCommandToSshSessionStdinPipe(cmdBytes []byte) { - if _, err := sws.slave.Write(cmdBytes); err != nil { - global.LOG.Errorf("ws cmd bytes write to ssh.stdin pipe failed, err: %v", err) - } -} diff --git a/backend/utils/terminal/ws_session.go b/backend/utils/terminal/ws_session.go deleted file mode 100644 index 2d66fab2f..000000000 --- a/backend/utils/terminal/ws_session.go +++ /dev/null @@ -1,218 +0,0 @@ -package terminal - -import ( - "bytes" - "encoding/base64" - "encoding/json" - "io" - "sync" - "time" - - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/gorilla/websocket" - "golang.org/x/crypto/ssh" -) - -type safeBuffer struct { - buffer bytes.Buffer - mu sync.Mutex -} - -func (w *safeBuffer) Write(p []byte) (int, error) { - w.mu.Lock() - defer w.mu.Unlock() - return w.buffer.Write(p) -} -func (w *safeBuffer) Bytes() []byte { - w.mu.Lock() - defer w.mu.Unlock() - return w.buffer.Bytes() -} -func (w *safeBuffer) Reset() { - w.mu.Lock() - defer w.mu.Unlock() - w.buffer.Reset() -} - -const ( - WsMsgCmd = "cmd" - WsMsgResize = "resize" - WsMsgHeartbeat = "heartbeat" -) - -type WsMsg struct { - Type string `json:"type"` - Data string `json:"data,omitempty"` // WsMsgCmd - Cols int `json:"cols,omitempty"` // WsMsgResize - Rows int `json:"rows,omitempty"` // WsMsgResize - Timestamp int `json:"timestamp,omitempty"` // WsMsgHeartbeat -} - -type LogicSshWsSession struct { - stdinPipe io.WriteCloser - comboOutput *safeBuffer - logBuff *safeBuffer - inputFilterBuff *safeBuffer - session *ssh.Session - wsConn *websocket.Conn - isAdmin bool - IsFlagged bool -} - -func NewLogicSshWsSession(cols, rows int, isAdmin bool, sshClient *ssh.Client, wsConn *websocket.Conn) (*LogicSshWsSession, error) { - sshSession, err := sshClient.NewSession() - if err != nil { - return nil, err - } - - stdinP, err := sshSession.StdinPipe() - if err != nil { - return nil, err - } - - comboWriter := new(safeBuffer) - logBuf := new(safeBuffer) - inputBuf := new(safeBuffer) - sshSession.Stdout = comboWriter - sshSession.Stderr = comboWriter - - modes := ssh.TerminalModes{ - ssh.ECHO: 1, - ssh.TTY_OP_ISPEED: 14400, - ssh.TTY_OP_OSPEED: 14400, - } - if err := sshSession.RequestPty("xterm", rows, cols, modes); err != nil { - return nil, err - } - if err := sshSession.Shell(); err != nil { - return nil, err - } - return &LogicSshWsSession{ - stdinPipe: stdinP, - comboOutput: comboWriter, - logBuff: logBuf, - inputFilterBuff: inputBuf, - session: sshSession, - wsConn: wsConn, - isAdmin: isAdmin, - IsFlagged: false, - }, nil -} - -func (sws *LogicSshWsSession) Close() { - if sws.session != nil { - sws.session.Close() - } - if sws.logBuff != nil { - sws.logBuff = nil - } - if sws.comboOutput != nil { - sws.comboOutput = nil - } -} -func (sws *LogicSshWsSession) Start(quitChan chan bool) { - go sws.receiveWsMsg(quitChan) - go sws.sendComboOutput(quitChan) -} - -func (sws *LogicSshWsSession) receiveWsMsg(exitCh chan bool) { - defer func() { - if r := recover(); r != nil { - global.LOG.Errorf("[A panic occurred during receive ws message, error message: %v", r) - } - }() - wsConn := sws.wsConn - defer setQuit(exitCh) - for { - select { - case <-exitCh: - return - default: - _, wsData, err := wsConn.ReadMessage() - if err != nil { - return - } - msgObj := WsMsg{} - _ = json.Unmarshal(wsData, &msgObj) - switch msgObj.Type { - case WsMsgResize: - if msgObj.Cols > 0 && msgObj.Rows > 0 { - if err := sws.session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil { - global.LOG.Errorf("ssh pty change windows size failed, err: %v", err) - } - } - case WsMsgCmd: - decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Data) - if err != nil { - global.LOG.Errorf("websock cmd string base64 decoding failed, err: %v", err) - } - sws.sendWebsocketInputCommandToSshSessionStdinPipe(decodeBytes) - case WsMsgHeartbeat: - // 接收到心跳包后将心跳包原样返回,可以用于网络延迟检测等情况 - err = wsConn.WriteMessage(websocket.TextMessage, wsData) - if err != nil { - global.LOG.Errorf("ssh sending heartbeat to webSocket failed, err: %v", err) - } - } - } - } -} - -func (sws *LogicSshWsSession) sendWebsocketInputCommandToSshSessionStdinPipe(cmdBytes []byte) { - if _, err := sws.stdinPipe.Write(cmdBytes); err != nil { - global.LOG.Errorf("ws cmd bytes write to ssh.stdin pipe failed, err: %v", err) - } -} - -func (sws *LogicSshWsSession) sendComboOutput(exitCh chan bool) { - wsConn := sws.wsConn - defer setQuit(exitCh) - - tick := time.NewTicker(time.Millisecond * time.Duration(60)) - defer tick.Stop() - for { - select { - case <-tick.C: - if sws.comboOutput == nil { - return - } - bs := sws.comboOutput.Bytes() - if len(bs) > 0 { - wsData, err := json.Marshal(WsMsg{ - Type: WsMsgCmd, - Data: base64.StdEncoding.EncodeToString(bs), - }) - if err != nil { - global.LOG.Errorf("encoding combo output to json failed, err: %v", err) - continue - } - err = wsConn.WriteMessage(websocket.TextMessage, wsData) - if err != nil { - global.LOG.Errorf("ssh sending combo output to webSocket failed, err: %v", err) - } - _, err = sws.logBuff.Write(bs) - if err != nil { - global.LOG.Errorf("combo output to log buffer failed, err: %v", err) - } - sws.comboOutput.buffer.Reset() - } - if string(bs) == string([]byte{13, 10, 108, 111, 103, 111, 117, 116, 13, 10}) { - sws.Close() - return - } - - case <-exitCh: - return - } - } -} - -func (sws *LogicSshWsSession) Wait(quitChan chan bool) { - if err := sws.session.Wait(); err != nil { - setQuit(quitChan) - } -} - -func setQuit(ch chan bool) { - ch <- true -} diff --git a/backend/utils/toolbox/fail2ban.go b/backend/utils/toolbox/fail2ban.go deleted file mode 100644 index ce7f9c715..000000000 --- a/backend/utils/toolbox/fail2ban.go +++ /dev/null @@ -1,181 +0,0 @@ -package toolbox - -import ( - "fmt" - "os" - "strings" - - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/systemctl" -) - -type Fail2ban struct{} - -const defaultPath = "/etc/fail2ban/jail.local" - -type FirewallClient interface { - Status() (bool, bool, bool) - Version() (string, error) - Operate(operate string) error - OperateSSHD(operate, ip string) error -} - -func NewFail2Ban() (*Fail2ban, error) { - isExist, _ := systemctl.IsExist("fail2ban.service") - if isExist { - if _, err := os.Stat(defaultPath); err != nil { - if err := initLocalFile(); err != nil { - return nil, err - } - stdout, err := cmd.Exec("systemctl restart fail2ban.service") - if err != nil { - global.LOG.Errorf("restart fail2ban failed, err: %s", stdout) - return nil, err - } - } - } - return &Fail2ban{}, nil -} - -func (f *Fail2ban) Status() (bool, bool, bool) { - isEnable, _ := systemctl.IsEnable("fail2ban.service") - isActive, _ := systemctl.IsActive("fail2ban.service") - isExist, _ := systemctl.IsExist("fail2ban.service") - - return isEnable, isActive, isExist -} - -func (f *Fail2ban) Version() string { - stdout, err := cmd.Exec("fail2ban-client version") - if err != nil { - global.LOG.Errorf("load the fail2ban version failed, err: %s", stdout) - return "-" - } - return strings.ReplaceAll(stdout, "\n", "") -} - -func (f *Fail2ban) Operate(operate string) error { - switch operate { - case "start", "restart", "stop", "enable", "disable": - stdout, err := cmd.Execf("systemctl %s fail2ban.service", operate) - if err != nil { - return fmt.Errorf("%s the fail2ban.service failed, err: %s", operate, stdout) - } - return nil - case "reload": - stdout, err := cmd.Exec("fail2ban-client reload") - if err != nil { - return fmt.Errorf("fail2ban-client reload, err: %s", stdout) - } - return nil - default: - return fmt.Errorf("not support such operation: %v", operate) - } -} - -func (f *Fail2ban) ReBanIPs(ips []string) error { - ipItems, _ := f.ListBanned() - stdout, err := cmd.Execf("fail2ban-client unban --all") - if err != nil { - stdout1, err := cmd.Execf("fail2ban-client set sshd banip %s", strings.Join(ipItems, " ")) - if err != nil { - global.LOG.Errorf("rebanip after fail2ban-client unban --all failed, err: %s", stdout1) - } - return fmt.Errorf("fail2ban-client unban --all failed, err: %s", stdout) - } - stdout1, err := cmd.Execf("fail2ban-client set sshd banip %s", strings.Join(ips, " ")) - if err != nil { - return fmt.Errorf("handle `fail2ban-client set sshd banip %s` failed, err: %s", strings.Join(ips, " "), stdout1) - } - return nil -} - -func (f *Fail2ban) ListBanned() ([]string, error) { - var lists []string - stdout, err := cmd.Exec("fail2ban-client status sshd | grep 'Banned IP list:'") - if err != nil { - return lists, err - } - itemList := strings.Split(strings.Trim(stdout, "\n"), "Banned IP list:") - if len(itemList) != 2 { - return lists, nil - } - - ips := strings.Fields(itemList[1]) - for _, item := range ips { - if len(item) != 0 { - lists = append(lists, item) - } - } - return lists, nil -} - -func (f *Fail2ban) ListIgnore() ([]string, error) { - var lists []string - stdout, err := cmd.Exec("fail2ban-client get sshd ignoreip") - if err != nil { - return lists, err - } - stdout = strings.ReplaceAll(stdout, "|", "") - stdout = strings.ReplaceAll(stdout, "`", "") - stdout = strings.ReplaceAll(stdout, "\n", "") - addrs := strings.Split(stdout, "-") - for _, addr := range addrs { - if !strings.HasPrefix(addr, " ") { - continue - } - lists = append(lists, strings.ReplaceAll(addr, " ", "")) - } - return lists, nil -} - -func initLocalFile() error { - f, err := os.Create(defaultPath) - if err != nil { - return err - } - defer f.Close() - initFile := `#DEFAULT-START -[DEFAULT] -bantime = 600 -findtime = 300 -maxretry = 5 -banaction = $banaction -action = %(action_mwl)s -#DEFAULT-END - -[sshd] -ignoreip = 127.0.0.1/8 -enabled = true -filter = sshd -port = 22 -maxretry = 5 -findtime = 300 -bantime = 600 -banaction = $banaction -action = %(action_mwl)s -logpath = $logpath` - - banaction := "" - if active, _ := systemctl.IsActive("firewalld"); active { - banaction = "firewallcmd-ipset" - } else if active, _ := systemctl.IsActive("ufw"); active { - banaction = "ufw" - } else { - banaction = "iptables-allports" - } - initFile = strings.ReplaceAll(initFile, "$banaction", banaction) - - logPath := "" - if _, err := os.Stat("/var/log/secure"); err == nil { - logPath = "/var/log/secure" - } else { - logPath = "/var/log/auth.log" - } - initFile = strings.ReplaceAll(initFile, "$logpath", logPath) - if err := os.WriteFile(defaultPath, []byte(initFile), 0640); err != nil { - return err - } - return nil -} diff --git a/backend/utils/toolbox/pure-ftpd.go b/backend/utils/toolbox/pure-ftpd.go deleted file mode 100644 index 8538ea599..000000000 --- a/backend/utils/toolbox/pure-ftpd.go +++ /dev/null @@ -1,272 +0,0 @@ -package toolbox - -import ( - "errors" - "fmt" - "os" - "os/user" - "path" - "path/filepath" - "strings" - "time" - - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/1Panel-dev/1Panel/backend/utils/systemctl" -) - -type Ftp struct { - DefaultUser string - DefaultGroup string -} - -type FtpClient interface { - Status() (bool, bool) - Operate(operate string) error - LoadList() ([]FtpList, error) - UserAdd(username, path, passwd string) error - UserDel(username string) error - SetPasswd(username, passwd string) error - Reload() error - LoadLogs() ([]FtpLog, error) -} - -func NewFtpClient() (*Ftp, error) { - userItem, err := user.LookupId("1000") - if err == nil { - groupItem, err := user.LookupGroupId(userItem.Gid) - if err != nil { - return nil, err - } - return &Ftp{DefaultUser: userItem.Username, DefaultGroup: groupItem.Name}, err - } - if err.Error() != user.UnknownUserIdError(1000).Error() { - return nil, err - } - - groupItem, err := user.LookupGroupId("1000") - if err == nil { - stdout2, err := cmd.Execf("useradd -u 1000 -g %s %s", groupItem.Name, "1panel") - if err != nil { - return nil, errors.New(stdout2) - } - return &Ftp{DefaultUser: "1panel", DefaultGroup: groupItem.Name}, nil - } - if err.Error() != user.UnknownGroupIdError("1000").Error() { - return nil, err - } - stdout, err := cmd.Exec("groupadd -g 1000 1panel") - if err != nil { - return nil, errors.New(string(stdout)) - } - stdout2, err := cmd.Exec("useradd -u 1000 -g 1panel 1panel") - if err != nil { - return nil, errors.New(stdout2) - } - return &Ftp{DefaultUser: "1panel", DefaultGroup: "1panel"}, nil -} - -func (f *Ftp) Status() (bool, bool) { - isActive, _ := systemctl.IsActive("pure-ftpd.service") - isExist, _ := systemctl.IsExist("pure-ftpd.service") - - return isActive, isExist -} - -func (f *Ftp) Operate(operate string) error { - switch operate { - case "start", "restart", "stop": - stdout, err := cmd.Execf("systemctl %s pure-ftpd.service", operate) - if err != nil { - return fmt.Errorf("%s the pure-ftpd.service failed, err: %s", operate, stdout) - } - return nil - default: - return fmt.Errorf("not support such operation: %v", operate) - } -} - -func (f *Ftp) UserAdd(username, passwd, path string) error { - std, err := cmd.Execf("pure-pw useradd %s -u %s -d %s < 0 && processConfig.Pid != proc.Pid { - return - } - if procName, err := proc.Name(); err == nil { - procData.Name = procName - } else { - procData.Name = "" - } - if processConfig.Name != "" && !strings.Contains(procData.Name, processConfig.Name) { - return - } - if username, err := proc.Username(); err == nil { - procData.Username = username - } - if processConfig.Username != "" && !strings.Contains(procData.Username, processConfig.Username) { - return - } - procData.PPID, _ = proc.Ppid() - statusArray, _ := proc.Status() - if len(statusArray) > 0 { - procData.Status = strings.Join(statusArray, ",") - } - createTime, procErr := proc.CreateTime() - if procErr == nil { - t := time.Unix(createTime/1000, 0) - procData.StartTime = t.Format("2006-1-2 15:04:05") - } - procData.NumThreads, _ = proc.NumThreads() - connections, procErr := proc.Connections() - if procErr == nil { - procData.NumConnections = len(connections) - for _, conn := range connections { - if conn.Laddr.IP != "" || conn.Raddr.IP != "" { - procData.Connects = append(procData.Connects, processConnect{ - Status: conn.Status, - Laddr: conn.Laddr, - Raddr: conn.Raddr, - }) - } - } - } - procData.CpuValue, _ = proc.CPUPercent() - procData.CpuPercent = fmt.Sprintf("%.2f", procData.CpuValue) + "%" - menInfo, procErr := proc.MemoryInfo() - if procErr == nil { - procData.Rss = 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) - } else { - procData.Rss = "--" - procData.Data = "--" - procData.VMS = "--" - procData.HWM = "--" - procData.Stack = "--" - procData.Locked = "--" - procData.Swap = "--" - - procData.RssValue = 0 - } - ioStat, procErr := proc.IOCounters() - if procErr == nil { - procData.DiskWrite = formatBytes(ioStat.WriteBytes) - procData.DiskRead = formatBytes(ioStat.ReadBytes) - } else { - procData.DiskWrite = "--" - procData.DiskRead = "--" - } - procData.CmdLine, _ = proc.Cmdline() - procData.OpenFiles, _ = proc.OpenFiles() - procData.Envs, _ = proc.Environ() - - resultMutex.Lock() - result = append(result, procData) - resultMutex.Unlock() - } - - chunkSize := (len(processes) + numWorkers - 1) / numWorkers - for i := 0; i < numWorkers; i++ { - wg.Add(1) - start := i * chunkSize - end := (i + 1) * chunkSize - if end > len(processes) { - end = len(processes) - } - - go func(start, end int) { - defer wg.Done() - for j := start; j < end; j++ { - handleData(processes[j]) - } - }(start, end) - } - - wg.Wait() - - sort.Slice(result, func(i, j int) bool { - return result[i].PID < result[j].PID - }) - res, err = json.Marshal(result) - return -} - -func getSSHSessions(config SSHSessionConfig) (res []byte, err error) { - var ( - result []sshSession - users []host.UserStat - processes []*process.Process - ) - processes, err = process.Processes() - if err != nil { - return - } - users, err = host.Users() - if err != nil { - return - } - for _, proc := range processes { - name, _ := proc.Name() - if name != "sshd" || proc.Pid == 0 { - continue - } - connections, _ := proc.Connections() - for _, conn := range connections { - for _, user := range users { - if user.Host == "" { - continue - } - if conn.Raddr.IP == user.Host { - if config.LoginUser != "" && !strings.Contains(user.User, config.LoginUser) { - continue - } - if config.LoginIP != "" && !strings.Contains(user.Host, config.LoginIP) { - continue - } - if terminal, err := proc.Cmdline(); err == nil { - if strings.Contains(terminal, user.Terminal) { - session := sshSession{ - Username: user.User, - Host: user.Host, - Terminal: user.Terminal, - PID: proc.Pid, - } - t := time.Unix(int64(user.Started), 0) - session.LoginTime = t.Format("2006-1-2 15:04:05") - result = append(result, session) - } - } - } - } - } - } - res, err = json.Marshal(result) - return -} - -var netTypes = [...]string{"tcp", "udp"} - -func getNetConnections(config NetConfig) (res []byte, err error) { - var ( - result []processConnect - proc *process.Process - ) - for _, netType := range netTypes { - connections, _ := net.Connections(netType) - if err == nil { - for _, conn := range connections { - if config.ProcessID > 0 && config.ProcessID != conn.Pid { - continue - } - proc, err = process.NewProcess(conn.Pid) - if err == nil { - name, _ := proc.Name() - if name != "" && config.ProcessName != "" && !strings.Contains(name, config.ProcessName) { - continue - } - if config.Port > 0 && config.Port != conn.Laddr.Port && config.Port != conn.Raddr.Port { - continue - } - result = append(result, processConnect{ - Type: netType, - Status: conn.Status, - Laddr: conn.Laddr, - Raddr: conn.Raddr, - PID: conn.Pid, - Name: name, - }) - } - - } - } - } - res, err = json.Marshal(result) - return -} diff --git a/backend/utils/xpack/xpack.go b/backend/utils/xpack/xpack.go deleted file mode 100644 index 14cf0b913..000000000 --- a/backend/utils/xpack/xpack.go +++ /dev/null @@ -1,37 +0,0 @@ -//go:build !xpack - -package xpack - -import ( - "crypto/tls" - "net" - "net/http" - "time" - - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" -) - -func RemoveTamper(website string) {} - -func LoadRequestTransport() *http.Transport { - return &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - DialContext: (&net.Dialer{ - Timeout: 60 * time.Second, - KeepAlive: 60 * time.Second, - }).DialContext, - TLSHandshakeTimeout: 5 * time.Second, - ResponseHeaderTimeout: 10 * time.Second, - IdleConnTimeout: 15 * time.Second, - } -} - -func LoadGpuInfo() []interface{} { - return nil -} - -func StartClam(startClam model.Clam, isUpdate bool) (int, error) { - return 0, buserr.New(constant.ErrXpackNotFound) -} diff --git a/cmd/server/app/app_config.go b/cmd/server/app/app_config.go deleted file mode 100644 index d4d155998..000000000 --- a/cmd/server/app/app_config.go +++ /dev/null @@ -1,14 +0,0 @@ -package app - -import ( - _ "embed" -) - -//go:embed app_config.yml -var Config []byte - -//go:embed logo.png -var Logo []byte - -//go:embed app_param.yml -var Param []byte diff --git a/cmd/server/app/app_config.yml b/cmd/server/app/app_config.yml deleted file mode 100644 index 3a2ec0827..000000000 --- a/cmd/server/app/app_config.yml +++ /dev/null @@ -1,13 +0,0 @@ -additionalProperties: - key: #应用的 key ,仅限英文,用于在 Linux 创建文件夹 - name: #应用名称 - tags: - - Tool #应用标签,可以有多个,请参照下方的标签列表 - shortDescZh: #应用中文描述,不要超过30个字 - shortDescEn: #应用英文描述 - type: tool #应用类型,区别于应用分类,只能有一个,请参照下方的类型列表 - crossVersionUpdate: #是否可以跨大版本升级 - limit: #应用安装数量限制,0 代表无限制 - website: #官网地址 - github: #github 地址 - document: #文档地址 \ No newline at end of file diff --git a/cmd/server/app/app_param.yml b/cmd/server/app/app_param.yml deleted file mode 100644 index 426fa78c6..000000000 --- a/cmd/server/app/app_param.yml +++ /dev/null @@ -1,10 +0,0 @@ -additionalProperties: - formFields: - - default: 8080 - edit: true - envKey: PANEL_APP_PORT_HTTP - labelEn: Port - labelZh: 端口 - required: true - rule: paramPort - type: number diff --git a/cmd/server/app/logo.png b/cmd/server/app/logo.png deleted file mode 100644 index 6f82a12d5..000000000 Binary files a/cmd/server/app/logo.png and /dev/null differ diff --git a/core/cmd/server/cmd/listen-ip.go b/cmd/server/cmd/listen-ip.go similarity index 100% rename from core/cmd/server/cmd/listen-ip.go rename to cmd/server/cmd/listen-ip.go diff --git a/core/cmd/server/cmd/reset.go b/cmd/server/cmd/reset.go similarity index 100% rename from core/cmd/server/cmd/reset.go rename to cmd/server/cmd/reset.go diff --git a/core/cmd/server/cmd/restore.go b/cmd/server/cmd/restore.go similarity index 100% rename from core/cmd/server/cmd/restore.go rename to cmd/server/cmd/restore.go diff --git a/core/cmd/server/cmd/root.go b/cmd/server/cmd/root.go similarity index 100% rename from core/cmd/server/cmd/root.go rename to cmd/server/cmd/root.go diff --git a/core/cmd/server/cmd/update.go b/cmd/server/cmd/update.go similarity index 100% rename from core/cmd/server/cmd/update.go rename to cmd/server/cmd/update.go diff --git a/core/cmd/server/cmd/user-info.go b/cmd/server/cmd/user-info.go similarity index 100% rename from core/cmd/server/cmd/user-info.go rename to cmd/server/cmd/user-info.go diff --git a/core/cmd/server/cmd/version.go b/cmd/server/cmd/version.go similarity index 94% rename from core/cmd/server/cmd/version.go rename to cmd/server/cmd/version.go index 0559573c3..b81cebb89 100644 --- a/core/cmd/server/cmd/version.go +++ b/cmd/server/cmd/version.go @@ -3,7 +3,7 @@ package cmd import ( "fmt" - "github.com/1Panel-dev/1Panel/core/cmd/server/conf" + "github.com/1Panel-dev/1Panel/cmd/server/conf" "github.com/1Panel-dev/1Panel/core/configs" "gopkg.in/yaml.v3" diff --git a/cmd/server/conf/app.yaml b/cmd/server/conf/app.yaml index 0da0e5163..61c29db47 100644 --- a/cmd/server/conf/app.yaml +++ b/cmd/server/conf/app.yaml @@ -1,5 +1,6 @@ system: - db_file: 1Panel.db + db_core_file: 1Panel_Core.db + db_file: 1Panel_Core.db base_dir: /opt mode: dev repo_url: https://resource.fit2cloud.com/1panel/package diff --git a/cmd/server/qqwry/qqwey.go b/cmd/server/conf/qqwry/qqwey.go similarity index 100% rename from cmd/server/qqwry/qqwey.go rename to cmd/server/conf/qqwry/qqwey.go diff --git a/cmd/server/qqwry/qqwry.dat b/cmd/server/conf/qqwry/qqwry.dat similarity index 100% rename from cmd/server/qqwry/qqwry.dat rename to cmd/server/conf/qqwry/qqwry.dat diff --git a/cmd/server/main.go b/cmd/server/main.go index e9af05c8d..0876387f3 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -1,9 +1,12 @@ package main import ( + "fmt" + "os" + _ "net/http/pprof" - "github.com/1Panel-dev/1Panel/backend/server" + "github.com/1Panel-dev/1Panel/cmd/server/cmd" _ "github.com/1Panel-dev/1Panel/cmd/server/docs" ) @@ -18,5 +21,8 @@ import ( //go:generate swag init -o ./docs -g main.go -d ../../backend -g ../cmd/server/main.go func main() { - server.Start() + if err := cmd.RootCmd.Execute(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } } diff --git a/cmd/server/nginx_conf/404.html b/cmd/server/nginx_conf/404.html deleted file mode 100644 index d75ed7812..000000000 --- a/cmd/server/nginx_conf/404.html +++ /dev/null @@ -1,6 +0,0 @@ - -404 Not Found - -

404 Not Found

-
nginx
- \ No newline at end of file diff --git a/cmd/server/nginx_conf/cache.conf b/cmd/server/nginx_conf/cache.conf deleted file mode 100644 index ef1285ba8..000000000 --- a/cmd/server/nginx_conf/cache.conf +++ /dev/null @@ -1,12 +0,0 @@ -proxy_temp_path /www/common/proxy/proxy_temp_dir; -proxy_cache_path /www/common/proxy/proxy_cache_dir levels=1:2 keys_zone=proxy_cache_panel:20m inactive=1d max_size=5g; -client_body_buffer_size 512k; -proxy_connect_timeout 60; -proxy_read_timeout 60; -proxy_send_timeout 60; -proxy_buffer_size 32k; -proxy_buffers 4 64k; -proxy_busy_buffers_size 128k; -proxy_temp_file_write_size 128k; -proxy_next_upstream error timeout invalid_header http_500 http_503 http_404; -proxy_cache proxy_cache_panel; \ No newline at end of file diff --git a/cmd/server/nginx_conf/domain404.html b/cmd/server/nginx_conf/domain404.html deleted file mode 100644 index d75ed7812..000000000 --- a/cmd/server/nginx_conf/domain404.html +++ /dev/null @@ -1,6 +0,0 @@ - -404 Not Found - -

404 Not Found

-
nginx
- \ No newline at end of file diff --git a/cmd/server/nginx_conf/gzip.conf b/cmd/server/nginx_conf/gzip.conf deleted file mode 100644 index b277f1f89..000000000 --- a/cmd/server/nginx_conf/gzip.conf +++ /dev/null @@ -1,4 +0,0 @@ -gzip on; -gzip_comp_level 6; -gzip_min_length 1k; -gzip_types text/plain text/css text/xml text/javascript text/x-component application/json application/javascript application/x-javascript application/xml application/xhtml+xml application/rss+xml application/atom+xml application/x-font-ttf application/vnd.ms-fontobject image/svg+xml image/x-icon font/opentype; \ No newline at end of file diff --git a/cmd/server/nginx_conf/index.html b/cmd/server/nginx_conf/index.html deleted file mode 100644 index 6c9cb573d..000000000 --- a/cmd/server/nginx_conf/index.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - 恭喜,站点创建成功! - - - -
-

恭喜, 站点创建成功!

-

这是默认index.html,本页面由系统自动生成

-
- - \ No newline at end of file diff --git a/cmd/server/nginx_conf/index.php b/cmd/server/nginx_conf/index.php deleted file mode 100644 index 5cd4e8c46..000000000 --- a/cmd/server/nginx_conf/index.php +++ /dev/null @@ -1,25 +0,0 @@ -欢迎使用 PHP!'; -echo '

版本信息

'; - -echo '
    '; -echo '
  • PHP版本:', PHP_VERSION, '
  • '; -echo '
'; - -echo '

已安装扩展

'; -printExtensions(); - -/** - * 获取已安装扩展列表 - */ -function printExtensions() -{ - echo '
    '; - foreach (get_loaded_extensions() as $i => $name) { - echo "
  1. ", $name, '=', phpversion($name), '
  2. '; - } - echo '
'; -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/nginx_conf.go b/cmd/server/nginx_conf/nginx_conf.go deleted file mode 100644 index 7b376a9b0..000000000 --- a/cmd/server/nginx_conf/nginx_conf.go +++ /dev/null @@ -1,39 +0,0 @@ -package nginx_conf - -import ( - "embed" - _ "embed" -) - -//go:embed ssl.conf -var SSL []byte - -//go:embed website_default.conf -var WebsiteDefault []byte - -//go:embed index.html -var Index []byte - -//go:embed index.php -var IndexPHP []byte - -//go:embed rewrite/* -var Rewrites embed.FS - -//go:embed cache.conf -var Cache []byte - -//go:embed proxy.conf -var Proxy []byte - -//go:embed proxy_cache.conf -var ProxyCache []byte - -//go:embed 404.html -var NotFoundHTML []byte - -//go:embed domain404.html -var DomainNotFoundHTML []byte - -//go:embed stop.html -var StopHTML []byte diff --git a/cmd/server/nginx_conf/proxy.conf b/cmd/server/nginx_conf/proxy.conf deleted file mode 100644 index d1914fb69..000000000 --- a/cmd/server/nginx_conf/proxy.conf +++ /dev/null @@ -1,13 +0,0 @@ -location ^~ /test { - proxy_pass http://1panel.cloud/; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header REMOTE-HOST $remote_addr; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_http_version 1.1; - - add_header X-Cache $upstream_cache_status; -} diff --git a/cmd/server/nginx_conf/proxy_cache.conf b/cmd/server/nginx_conf/proxy_cache.conf deleted file mode 100644 index 45172d6b6..000000000 --- a/cmd/server/nginx_conf/proxy_cache.conf +++ /dev/null @@ -1,4 +0,0 @@ -proxy_ignore_headers Set-Cookie Cache-Control expires; -proxy_cache cache_one; -proxy_cache_key $host$uri$is_args$args; -proxy_cache_valid 200 304 301 302 10m; \ No newline at end of file diff --git a/cmd/server/nginx_conf/proxy_no_cache.conf b/cmd/server/nginx_conf/proxy_no_cache.conf deleted file mode 100644 index 597f25ac4..000000000 --- a/cmd/server/nginx_conf/proxy_no_cache.conf +++ /dev/null @@ -1,10 +0,0 @@ -set $static_fileg 0; -if ( $uri ~* "\.(gif|png|jpg|css|js|woff|woff2)$" ) -{ - set $static_fileg 1; - expires 1m; -} -if ( $static_fileg = 0 ) -{ - add_header Cache-Control no-cache; -} diff --git a/cmd/server/nginx_conf/rewrite/crmeb.conf b/cmd/server/nginx_conf/rewrite/crmeb.conf deleted file mode 100644 index 4260774ee..000000000 --- a/cmd/server/nginx_conf/rewrite/crmeb.conf +++ /dev/null @@ -1,6 +0,0 @@ -location / { - if (!-e $request_filename) { - rewrite ^(.*)$ /index.php?s=/$1 last; - break; - } -} diff --git a/cmd/server/nginx_conf/rewrite/dabr.conf b/cmd/server/nginx_conf/rewrite/dabr.conf deleted file mode 100644 index 37c13132f..000000000 --- a/cmd/server/nginx_conf/rewrite/dabr.conf +++ /dev/null @@ -1,5 +0,0 @@ -location / { -if (!-e $request_filename) { -rewrite ^/(.*)$ /index.php?q=$1 last; -} -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/dbshop.conf b/cmd/server/nginx_conf/rewrite/dbshop.conf deleted file mode 100644 index 61d23f711..000000000 --- a/cmd/server/nginx_conf/rewrite/dbshop.conf +++ /dev/null @@ -1,7 +0,0 @@ -location /{ - try_files $uri $uri/ /index.php$is_args$args; -} - -location ~ \.htaccess{ - deny all; -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/dedecms.conf b/cmd/server/nginx_conf/rewrite/dedecms.conf deleted file mode 100644 index 6e110cba5..000000000 --- a/cmd/server/nginx_conf/rewrite/dedecms.conf +++ /dev/null @@ -1,10 +0,0 @@ -rewrite "^/list-([0-9]+)\.html$" /plus/list.php?tid=$1 last; -rewrite "^/list-([0-9]+)-([0-9]+)-([0-9]+)\.html$" /plus/list.php?tid=$1&totalresult=$2&PageNo=$3 last; -rewrite "^/view-([0-9]+)-1\.html$" /plus/view.php?arcID=$1 last; -rewrite "^/view-([0-9]+)-([0-9]+)\.html$" /plus/view.php?aid=$1&pageno=$2 last; -rewrite "^/plus/list-([0-9]+)\.html$" /plus/list.php?tid=$1 last; -rewrite "^/plus/list-([0-9]+)-([0-9]+)-([0-9]+)\.html$" /plus/list.php?tid=$1&totalresult=$2&PageNo=$3 last; -rewrite "^/plus/view-([0-9]+)-1\.html$" /plus/view.php?arcID=$1 last; -rewrite "^/plus/view-([0-9]+)-([0-9]+)\.html$" /plus/view.php?aid=$1&pageno=$2 last; -rewrite "^/tags.html$" /tags.php last; -rewrite "^/tag-([0-9]+)-([0-9]+)\.html$" /tags.php?/$1/$2/ last; diff --git a/cmd/server/nginx_conf/rewrite/default.conf b/cmd/server/nginx_conf/rewrite/default.conf deleted file mode 100644 index e69de29bb..000000000 diff --git a/cmd/server/nginx_conf/rewrite/discuz.conf b/cmd/server/nginx_conf/rewrite/discuz.conf deleted file mode 100644 index 578da7653..000000000 --- a/cmd/server/nginx_conf/rewrite/discuz.conf +++ /dev/null @@ -1,7 +0,0 @@ -location / { - rewrite ^/archiver/((fid|tid)-[\w\-]+\.html)$ /archiver/index.php?$1 last; - rewrite ^/forum-([0-9]+)-([0-9]+)\.html$ /forumdisplay.php?fid=$1&page=$2 last; - rewrite ^/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /viewthread.php?tid=$1&extra=page%3D$3&page=$2 last; - rewrite ^/space-(username|uid)-(.+)\.html$ /space.php?$1=$2 last; - rewrite ^/tag-(.+)\.html$ /tag.php?name=$1 last; - } \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/discuzx.conf b/cmd/server/nginx_conf/rewrite/discuzx.conf deleted file mode 100644 index 8058495a2..000000000 --- a/cmd/server/nginx_conf/rewrite/discuzx.conf +++ /dev/null @@ -1,12 +0,0 @@ -rewrite ^([^\.]*)/topic-(.+)\.html$ $1/portal.php?mod=topic&topic=$2 last; -rewrite ^([^\.]*)/article-([0-9]+)-([0-9]+)\.html$ $1/portal.php?mod=view&aid=$2&page=$3 last; -rewrite ^([^\.]*)/forum-(\w+)-([0-9]+)\.html$ $1/forum.php?mod=forumdisplay&fid=$2&page=$3 last; -rewrite ^([^\.]*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=viewthread&tid=$2&extra=page%3D$4&page=$3 last; -rewrite ^([^\.]*)/group-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=group&fid=$2&page=$3 last; -rewrite ^([^\.]*)/space-(username|uid)-(.+)\.html$ $1/home.php?mod=space&$2=$3 last; -rewrite ^([^\.]*)/blog-([0-9]+)-([0-9]+)\.html$ $1/home.php?mod=space&uid=$2&do=blog&id=$3 last; -rewrite ^([^\.]*)/(fid|tid)-([0-9]+)\.html$ $1/index.php?action=$2&value=$3 last; -rewrite ^([^\.]*)/([a-z]+[a-z0-9_]*)-([a-z0-9_\-]+)\.html$ $1/plugin.php?id=$2:$3 last; -if (!-e $request_filename) { - return 404; -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/discuzx2.conf b/cmd/server/nginx_conf/rewrite/discuzx2.conf deleted file mode 100644 index 61059e21e..000000000 --- a/cmd/server/nginx_conf/rewrite/discuzx2.conf +++ /dev/null @@ -1,14 +0,0 @@ -location /bbs/ { - rewrite ^([^\.]*)/topic-(.+)\.html$ $1/portal.php?mod=topic&topic=$2 last; - rewrite ^([^\.]*)/article-([0-9]+)-([0-9]+)\.html$ $1/portal.php?mod=view&aid=$2&page=$3 last; - rewrite ^([^\.]*)/forum-(\w+)-([0-9]+)\.html$ $1/forum.php?mod=forumdisplay&fid=$2&page=$3 last; - rewrite ^([^\.]*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=viewthread&tid=$2&extra=page%3D$4&page=$3 last; - rewrite ^([^\.]*)/group-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=group&fid=$2&page=$3 last; - rewrite ^([^\.]*)/space-(username|uid)-(.+)\.html$ $1/home.php?mod=space&$2=$3 last; - rewrite ^([^\.]*)/blog-([0-9]+)-([0-9]+)\.html$ $1/home.php?mod=space&uid=$2&do=blog&id=$3 last; - rewrite ^([^\.]*)/(fid|tid)-([0-9]+)\.html$ $1/index.php?action=$2&value=$3 last; - rewrite ^([^\.]*)/([a-z]+[a-z0-9_]*)-([a-z0-9_\-]+)\.html$ $1/plugin.php?id=$2:$3 last; - if (!-e $request_filename) { - return 404; - } -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/discuzx3.conf b/cmd/server/nginx_conf/rewrite/discuzx3.conf deleted file mode 100644 index 661889734..000000000 --- a/cmd/server/nginx_conf/rewrite/discuzx3.conf +++ /dev/null @@ -1,15 +0,0 @@ -location / { - rewrite ^([^\.]*)/topic-(.+)\.html$ $1/portal.php?mod=topic&topic=$2 last; - rewrite ^([^\.]*)/article-([0-9]+)-([0-9]+)\.html$ $1/portal.php?mod=view&aid=$2&page=$3 last; - rewrite ^([^\.]*)/forum-(\w+)-([0-9]+)\.html$ $1/forum.php?mod=forumdisplay&fid=$2&page=$3 last; - rewrite ^([^\.]*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=viewthread&tid=$2&extra=page%3D$4&page=$3 last; - rewrite ^([^\.]*)/group-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=group&fid=$2&page=$3 last; - rewrite ^([^\.]*)/space-(username|uid)-(.+)\.html$ $1/home.php?mod=space&$2=$3 last; - rewrite ^([^\.]*)/blog-([0-9]+)-([0-9]+)\.html$ $1/home.php?mod=space&uid=$2&do=blog&id=$3 last; - rewrite ^([^\.]*)/(fid|tid)-([0-9]+)\.html$ $1/index.php?action=$2&value=$3 last; - rewrite ^([^\.]*)/([a-z]+[a-z0-9_]*)-([a-z0-9_\-]+)\.html$ $1/plugin.php?id=$2:$3 last; - if (!-e $request_filename) { - return 404; - } -} - diff --git a/cmd/server/nginx_conf/rewrite/drupal.conf b/cmd/server/nginx_conf/rewrite/drupal.conf deleted file mode 100644 index 460b7791d..000000000 --- a/cmd/server/nginx_conf/rewrite/drupal.conf +++ /dev/null @@ -1,3 +0,0 @@ -if (!-e $request_filename) { - rewrite ^/(.*)$ /index.php?q=$1 last; - } \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/ecshop.conf b/cmd/server/nginx_conf/rewrite/ecshop.conf deleted file mode 100644 index 3574daa73..000000000 --- a/cmd/server/nginx_conf/rewrite/ecshop.conf +++ /dev/null @@ -1,32 +0,0 @@ -if (!-e $request_filename) -{ -rewrite "^/index\.html" /index.php last; -rewrite "^/category$" /index.php last; -rewrite "^/feed-c([0-9]+)\.xml$" /feed.php?cat=$1 last; -rewrite "^/feed-b([0-9]+)\.xml$" /feed.php?brand=$1 last; -rewrite "^/feed\.xml$" /feed.php last; -rewrite "^/category-([0-9]+)-b([0-9]+)-min([0-9]+)-max([0-9]+)-attr([^-]*)-([0-9]+)-(.+)-([a-zA-Z]+)(.*)\.html$" /category.php?id=$1&brand=$2&price_min=$3&price_max=$4&filter_attr=$5&page=$6&sort=$7&order=$8 last; -rewrite "^/category-([0-9]+)-b([0-9]+)-min([0-9]+)-max([0-9]+)-attr([^-]*)(.*)\.html$" /category.php?id=$1&brand=$2&price_min=$3&price_max=$4&filter_attr=$5 last; -rewrite "^/category-([0-9]+)-b([0-9]+)-([0-9]+)-(.+)-([a-zA-Z]+)(.*)\.html$" /category.php?id=$1&brand=$2&page=$3&sort=$4&order=$5 last; -rewrite "^/category-([0-9]+)-b([0-9]+)-([0-9]+)(.*)\.html$" /category.php?id=$1&brand=$2&page=$3 last; -rewrite "^/category-([0-9]+)-b([0-9]+)(.*)\.html$" /category.php?id=$1&brand=$2 last; -rewrite "^/category-([0-9]+)(.*)\.html$" /category.php?id=$1 last; -rewrite "^/goods-([0-9]+)(.*)\.html" /goods.php?id=$1 last; -rewrite "^/article_cat-([0-9]+)-([0-9]+)-(.+)-([a-zA-Z]+)(.*)\.html$" /article_cat.php?id=$1&page=$2&sort=$3&order=$4 last; -rewrite "^/article_cat-([0-9]+)-([0-9]+)(.*)\.html$" /article_cat.php?id=$1&page=$2 last; -rewrite "^/article_cat-([0-9]+)(.*)\.html$" /article_cat.php?id=$1 last; -rewrite "^/article-([0-9]+)(.*)\.html$" /article.php?id=$1 last; -rewrite "^/brand-([0-9]+)-c([0-9]+)-([0-9]+)-(.+)-([a-zA-Z]+)\.html" /brand.php?id=$1&cat=$2&page=$3&sort=$4&order=$5 last; -rewrite "^/brand-([0-9]+)-c([0-9]+)-([0-9]+)(.*)\.html" /brand.php?id=$1&cat=$2&page=$3 last; -rewrite "^/brand-([0-9]+)-c([0-9]+)(.*)\.html" /brand.php?id=$1&cat=$2 last; -rewrite "^/brand-([0-9]+)(.*)\.html" /brand.php?id=$1 last; -rewrite "^/tag-(.*)\.html" /search.php?keywords=$1 last; -rewrite "^/snatch-([0-9]+)\.html$" /snatch.php?id=$1 last; -rewrite "^/group_buy-([0-9]+)\.html$" /group_buy.php?act=view&id=$1 last; -rewrite "^/auction-([0-9]+)\.html$" /auction.php?act=view&id=$1 last; -rewrite "^/exchange-id([0-9]+)(.*)\.html$" /exchange.php?id=$1&act=view last; -rewrite "^/exchange-([0-9]+)-min([0-9]+)-max([0-9]+)-([0-9]+)-(.+)-([a-zA-Z]+)(.*)\.html$" /exchange.php?cat_id=$1&integral_min=$2&integral_max=$3&page=$4&sort=$5&order=$6 last; -rewrite ^/exchange-([0-9]+)-([0-9]+)-(.+)-([a-zA-Z]+)(.*)\.html$" /exchange.php?cat_id=$1&page=$2&sort=$3&order=$4 last; -rewrite "^/exchange-([0-9]+)-([0-9]+)(.*)\.html$" /exchange.php?cat_id=$1&page=$2 last; -rewrite "^/exchange-([0-9]+)(.*)\.html$" /exchange.php?cat_id=$1 last; -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/edusoho.conf b/cmd/server/nginx_conf/rewrite/edusoho.conf deleted file mode 100644 index b0099dcff..000000000 --- a/cmd/server/nginx_conf/rewrite/edusoho.conf +++ /dev/null @@ -1,8 +0,0 @@ -location / { - index app.php; - try_files $uri @rewriteapp; -} - -location @rewriteapp { - rewrite ^(.*)$ /app.php/$1 last; -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/emlog.conf b/cmd/server/nginx_conf/rewrite/emlog.conf deleted file mode 100644 index e122a854d..000000000 --- a/cmd/server/nginx_conf/rewrite/emlog.conf +++ /dev/null @@ -1,7 +0,0 @@ -location / { -index index.php index.html; - if (!-e $request_filename) - { - rewrite ^/(.*)$ /index.php last; - } -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/empirecms.conf b/cmd/server/nginx_conf/rewrite/empirecms.conf deleted file mode 100644 index c68b92d85..000000000 --- a/cmd/server/nginx_conf/rewrite/empirecms.conf +++ /dev/null @@ -1,8 +0,0 @@ -rewrite ^([^\.]*)/listinfo-(.+?)-(.+?)\.html$ $1/e/action/ListInfo/index.php?classid=$2&page=$3 last; -rewrite ^([^\.]*)/showinfo-(.+?)-(.+?)-(.+?)\.html$ $1/e/action/ShowInfo.php?classid=$2&id=$3&page=$4 last; -rewrite ^([^\.]*)/infotype-(.+?)-(.+?)\.html$ $1/e/action/InfoType/index.php?ttid=$2&page=$3 last; -rewrite ^([^\.]*)/tags-(.+?)-(.+?)\.html$ $1/e/tags/index.php?tagname=$2&page=$3 last; -rewrite ^([^\.]*)/comment-(.+?)-(.+?)-(.+?)-(.+?)-(.+?)-(.+?)\.html$ $1/e/pl/index\.php\?doaction=$2&classid=$3&id=$4&page=$5&myorder=$6&tempid=$7 last; -if (!-e $request_filename) { - return 404; -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/laravel5.conf b/cmd/server/nginx_conf/rewrite/laravel5.conf deleted file mode 100644 index da4c67474..000000000 --- a/cmd/server/nginx_conf/rewrite/laravel5.conf +++ /dev/null @@ -1,3 +0,0 @@ -location / { - try_files $uri $uri/ /index.php?$query_string; -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/maccms.conf b/cmd/server/nginx_conf/rewrite/maccms.conf deleted file mode 100644 index b08325169..000000000 --- a/cmd/server/nginx_conf/rewrite/maccms.conf +++ /dev/null @@ -1,13 +0,0 @@ -if (!-e $request_filename) { - rewrite ^/index.php(.*)$ /index.php?s=$1 break; - # MacCMS要求强制修改后台文件名称 所以需要手动修改下方这条重写规则 将admin修改为你修改后的文件名即可 - rewrite ^/admin.php(.*)$ /admin.php?s=$1 break; - rewrite ^/api.php(.*)$ /api.php?s=$1 break; - rewrite ^/(.*)$ /index.php?s=$1 break; - rewrite ^/vod-(.*)$ /index.php?m=vod-$1 break; - rewrite ^/art-(.*)$ /index.php?m=art-$1 break; - rewrite ^/gbook-(.*)$ /index.php?m=gbook-$1 break; - rewrite ^/label-(.*)$ /index.php?m=label-$1 break; - rewrite ^/map-(.*)$ /index.php?m=map-$1 break; - } -try_files $uri $uri/ /index.php?$query_string; \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/mvc.conf b/cmd/server/nginx_conf/rewrite/mvc.conf deleted file mode 100644 index bf906257b..000000000 --- a/cmd/server/nginx_conf/rewrite/mvc.conf +++ /dev/null @@ -1,6 +0,0 @@ -location /{ - if (!-e $request_filename) { - rewrite ^(.*)$ /index.php/$1 last; - break; - } -} diff --git a/cmd/server/nginx_conf/rewrite/niushop.conf b/cmd/server/nginx_conf/rewrite/niushop.conf deleted file mode 100644 index c32c40c71..000000000 --- a/cmd/server/nginx_conf/rewrite/niushop.conf +++ /dev/null @@ -1,6 +0,0 @@ -location / { - if (!-e $request_filename) { - rewrite ^(.*)$ /index.php?s=$1 last; - break; - } -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/phpcms.conf b/cmd/server/nginx_conf/rewrite/phpcms.conf deleted file mode 100644 index a6e0df346..000000000 --- a/cmd/server/nginx_conf/rewrite/phpcms.conf +++ /dev/null @@ -1,9 +0,0 @@ -location / { - ###以下为PHPCMS 伪静态化rewrite法则 - rewrite ^(.*)show-([0-9]+)-([0-9]+)\.html$ $1/show.php?itemid=$2&page=$3; - rewrite ^(.*)list-([0-9]+)-([0-9]+)\.html$ $1/list.php?catid=$2&page=$3; - rewrite ^(.*)show-([0-9]+)\.html$ $1/show.php?specialid=$2; - ####以下为PHPWind 伪静态化rewrite法则 - rewrite ^(.*)-htm-(.*)$ $1.php?$2 last; - rewrite ^(.*)/simple/([a-z0-9\_]+\.html)$ $1/simple/index.php?$2 last; -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/phpwind.conf b/cmd/server/nginx_conf/rewrite/phpwind.conf deleted file mode 100644 index 388af90d3..000000000 --- a/cmd/server/nginx_conf/rewrite/phpwind.conf +++ /dev/null @@ -1,4 +0,0 @@ -location / { - rewrite ^(.*)-htm-(.*)$ $1.php?$2 last; - rewrite ^(.*)/simple/([a-z0-9\_]+\.html)$ $1/simple/index.php?$2 last; - } \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/sablog.conf b/cmd/server/nginx_conf/rewrite/sablog.conf deleted file mode 100644 index fa4f00c49..000000000 --- a/cmd/server/nginx_conf/rewrite/sablog.conf +++ /dev/null @@ -1,16 +0,0 @@ -location / { - rewrite "^/date/([0-9]{6})/?([0-9]+)?/?$" /index.php?action=article&setdate=$1&page=$2 last; - rewrite ^/page/([0-9]+)?/?$ /index.php?action=article&page=$1 last; - rewrite ^/category/([0-9]+)/?([0-9]+)?/?$ /index.php?action=article&cid=$1&page=$2 last; - rewrite ^/category/([^/]+)/?([0-9]+)?/?$ /index.php?action=article&curl=$1&page=$2 last; - rewrite ^/(archives|search|article|links)/?$ /index.php?action=$1 last; - rewrite ^/(comments|tagslist|trackbacks|article)/?([0-9]+)?/?$ /index.php?action=$1&page=$2 last; - rewrite ^/tag/([^/]+)/?([0-9]+)?/?$ /index.php?action=article&item=$1&page=$2 last; - rewrite ^/archives/([0-9]+)/?([0-9]+)?/?$ /index.php?action=show&id=$1&page=$2 last; - rewrite ^/rss/([0-9]+)?/?$ /rss.php?cid=$1 last; - rewrite ^/rss/([^/]+)/?$ /rss.php?url=$1 last; - rewrite ^/uid/([0-9]+)/?([0-9]+)?/?$ /index.php?action=article&uid=$1&page=$2 last; - rewrite ^/user/([^/]+)/?([0-9]+)?/?$ /index.php?action=article&user=$1&page=$2 last; - rewrite sitemap.xml sitemap.php last; - rewrite ^(.*)/([0-9a-zA-Z\-\_]+)/?([0-9]+)?/?$ $1/index.php?action=show&alias=$2&page=$3 last; -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/seacms.conf b/cmd/server/nginx_conf/rewrite/seacms.conf deleted file mode 100644 index 0dc6f3612..000000000 --- a/cmd/server/nginx_conf/rewrite/seacms.conf +++ /dev/null @@ -1,11 +0,0 @@ -location / { - rewrite ^/frim/index(.+?)\.html$ /list/index.php?$1 last; - rewrite ^/movie/index(.+?)\.html$ /detail/index.php?$1 last; - rewrite ^/play/([0-9]+)-([0-9]+)-([0-9]+)\.html$ /video/index.php?$1-$2-$3 last; - rewrite ^/topic/index(.+?)\.html$ /topic/index.php?$1 last; - rewrite ^/topiclist/index(.+?).html$ /topiclist/index.php?$1 last; - rewrite ^/index\.html$ index.php permanent; - rewrite ^/news\.html$ news/ permanent; - rewrite ^/part/index(.+?)\.html$ /articlelist/index.php?$1 last; - rewrite ^/article/index(.+?)\.html$ /article/index.php?$1 last; -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/shopex.conf b/cmd/server/nginx_conf/rewrite/shopex.conf deleted file mode 100644 index f57463c1a..000000000 --- a/cmd/server/nginx_conf/rewrite/shopex.conf +++ /dev/null @@ -1,5 +0,0 @@ -location / { -if (!-e $request_filename) { -rewrite ^/(.+\.(html|xml|json|htm|php|jsp|asp|shtml))$ /index.php?$1 last; -} -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/shopwind.conf b/cmd/server/nginx_conf/rewrite/shopwind.conf deleted file mode 100644 index 0edf086c3..000000000 --- a/cmd/server/nginx_conf/rewrite/shopwind.conf +++ /dev/null @@ -1,14 +0,0 @@ -location / { - #Redirect everything that isn't a real file to index.php - try_files $uri $uri/ /index.php$is_args$args; -} -#If you want a single domain name at the front and back ends -location /admin { - try_files $uri $uri/ /admin/index.php$is_args$args; -} -location /mobile { - try_files $uri $uri/ /mobile/index.php$is_args$args; -} -location /api { - try_files $uri $uri/ /api/index.php$is_args$args; -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/thinkphp.conf b/cmd/server/nginx_conf/rewrite/thinkphp.conf deleted file mode 100644 index 216b1dc23..000000000 --- a/cmd/server/nginx_conf/rewrite/thinkphp.conf +++ /dev/null @@ -1,8 +0,0 @@ -location ~* (runtime|application)/ { - return 403; -} -location / { - if (!-e $request_filename){ - rewrite ^(.*)$ /index.php?s=$1 last; break; - } -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/typecho.conf b/cmd/server/nginx_conf/rewrite/typecho.conf deleted file mode 100644 index dae6ba9cc..000000000 --- a/cmd/server/nginx_conf/rewrite/typecho.conf +++ /dev/null @@ -1,3 +0,0 @@ - if (!-e $request_filename) { - rewrite ^(.*)$ /index.php$1 last; - } diff --git a/cmd/server/nginx_conf/rewrite/typecho2.conf b/cmd/server/nginx_conf/rewrite/typecho2.conf deleted file mode 100644 index 22397d847..000000000 --- a/cmd/server/nginx_conf/rewrite/typecho2.conf +++ /dev/null @@ -1,5 +0,0 @@ -location /typecho/ { - if (!-e $request_filename) { - rewrite ^(.*)$ /typecho/index.php$1 last; - } -} diff --git a/cmd/server/nginx_conf/rewrite/wordpress.conf b/cmd/server/nginx_conf/rewrite/wordpress.conf deleted file mode 100644 index 9fe73c1eb..000000000 --- a/cmd/server/nginx_conf/rewrite/wordpress.conf +++ /dev/null @@ -1,6 +0,0 @@ -location / -{ - try_files $uri $uri/ /index.php?$args; -} - -rewrite /wp-admin$ $scheme://$host$uri/ permanent; \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/wp2.conf b/cmd/server/nginx_conf/rewrite/wp2.conf deleted file mode 100644 index 0e5fbaede..000000000 --- a/cmd/server/nginx_conf/rewrite/wp2.conf +++ /dev/null @@ -1,6 +0,0 @@ -rewrite ^.*/files/(.*)$ /wp-includes/ms-files.php?file=$1 last; -if (!-e $request_filename){ - rewrite ^.+?(/wp-.*) $1 last; - rewrite ^.+?(/.*\.php)$ $1 last; - rewrite ^ /index.php last; -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/yii2.conf b/cmd/server/nginx_conf/rewrite/yii2.conf deleted file mode 100644 index 103ebdc7d..000000000 --- a/cmd/server/nginx_conf/rewrite/yii2.conf +++ /dev/null @@ -1,3 +0,0 @@ -location / { - try_files $uri $uri/ /index.php$is_args$args; -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/zblog.conf b/cmd/server/nginx_conf/rewrite/zblog.conf deleted file mode 100644 index 5d2de2b79..000000000 --- a/cmd/server/nginx_conf/rewrite/zblog.conf +++ /dev/null @@ -1,9 +0,0 @@ -if (-f $request_filename/index.html){ - rewrite (.*) $1/index.html break; -} -if (-f $request_filename/index.php){ - rewrite (.*) $1/index.php; -} -if (!-f $request_filename){ - rewrite (.*) /index.php; -} \ No newline at end of file diff --git a/cmd/server/nginx_conf/ssl.conf b/cmd/server/nginx_conf/ssl.conf deleted file mode 100644 index 908c52fb4..000000000 --- a/cmd/server/nginx_conf/ssl.conf +++ /dev/null @@ -1,9 +0,0 @@ -ssl_certificate /www/server/panel/vhost/cert/1panel.cloud/fullchain.pem; -ssl_certificate_key /www/server/panel/vhost/cert/1panel.cloud/privkey.pem; -ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; -ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK:!KRB5:!SRP:!CAMELLIA:!SEED; -ssl_prefer_server_ciphers on; -ssl_session_cache shared:SSL:10m; -ssl_session_timeout 10m; -error_page 497 https://$host$request_uri; -proxy_set_header X-Forwarded-Proto https; \ No newline at end of file diff --git a/cmd/server/nginx_conf/stop.html b/cmd/server/nginx_conf/stop.html deleted file mode 100644 index a38fa64b6..000000000 --- a/cmd/server/nginx_conf/stop.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - 抱歉,站点已暂停 - - - - -
-

抱歉!该站点已经被管理员停止运行,请联系管理员了解详情!

-
- - \ No newline at end of file diff --git a/cmd/server/nginx_conf/website_default.conf b/cmd/server/nginx_conf/website_default.conf deleted file mode 100644 index 57c439312..000000000 --- a/cmd/server/nginx_conf/website_default.conf +++ /dev/null @@ -1,23 +0,0 @@ -server { - listen 80; - server_name ko.wp-1.com; - - index index.php index.html index.htm default.php default.htm default.html; - - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Host $server_name; - proxy_set_header X-Real-IP $remote_addr; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - - - access_log /www/sites/domain/log/access.log main; - error_log /www/sites/domain/log/error.log; - - location ^~ /.well-known/acme-challenge { - allow all; - root /usr/share/nginx/html; - } -} diff --git a/core/cmd/server/web/favicon.png b/cmd/server/web/favicon.png similarity index 100% rename from core/cmd/server/web/favicon.png rename to cmd/server/web/favicon.png diff --git a/core/cmd/server/web/web.go b/cmd/server/web/web.go similarity index 100% rename from core/cmd/server/web/web.go rename to cmd/server/web/web.go diff --git a/core/cmd/server/conf/app.yaml b/core/cmd/server/conf/app.yaml deleted file mode 100644 index 61c29db47..000000000 --- a/core/cmd/server/conf/app.yaml +++ /dev/null @@ -1,18 +0,0 @@ -system: - db_core_file: 1Panel_Core.db - db_file: 1Panel_Core.db - base_dir: /opt - mode: dev - repo_url: https://resource.fit2cloud.com/1panel/package - app_repo: https://apps-assets.fit2cloud.com - is_demo: false - port: 9999 - username: admin - password: admin123 - -log: - level: debug - time_zone: Asia/Shanghai - log_name: 1Panel - log_suffix: .log - max_backup: 10 diff --git a/core/cmd/server/conf/conf.go b/core/cmd/server/conf/conf.go deleted file mode 100644 index 6654d8bcf..000000000 --- a/core/cmd/server/conf/conf.go +++ /dev/null @@ -1,6 +0,0 @@ -package conf - -import _ "embed" - -//go:embed app.yaml -var AppYaml []byte diff --git a/core/cmd/server/conf/qqwry/qqwey.go b/core/cmd/server/conf/qqwry/qqwey.go deleted file mode 100644 index 94ee4abb8..000000000 --- a/core/cmd/server/conf/qqwry/qqwey.go +++ /dev/null @@ -1,6 +0,0 @@ -package qqwry - -import _ "embed" - -//go:embed qqwry.dat -var QQwryByte []byte diff --git a/core/cmd/server/conf/qqwry/qqwry.dat b/core/cmd/server/conf/qqwry/qqwry.dat deleted file mode 100644 index 0752ec831..000000000 Binary files a/core/cmd/server/conf/qqwry/qqwry.dat and /dev/null differ diff --git a/core/cmd/server/docs/docs.go b/core/cmd/server/docs/docs.go deleted file mode 100644 index b004a49f5..000000000 --- a/core/cmd/server/docs/docs.go +++ /dev/null @@ -1,23464 +0,0 @@ -// Code generated by swaggo/swag. DO NOT EDIT. - -package docs - -import "github.com/swaggo/swag" - -const docTemplate = `{ - "schemes": {{ marshal .Schemes }}, - "swagger": "2.0", - "info": { - "description": "{{escape .Description}}", - "title": "{{.Title}}", - "termsOfService": "http://swagger.io/terms/", - "contact": {}, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "{{.Version}}" - }, - "host": "{{.Host}}", - "basePath": "{{.BasePath}}", - "paths": { - "/apps/:key": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 key 获取应用信息", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search app by key", - "parameters": [ - { - "type": "string", - "description": "app key", - "name": "key", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.AppDTO" - } - } - } - } - }, - "/apps/checkupdate": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取应用更新版本", - "tags": [ - "App" - ], - "summary": "Get app list update", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/apps/detail/:appId/:version/:type": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 appid 获取应用详情", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search app detail by appid", - "parameters": [ - { - "type": "integer", - "description": "app id", - "name": "appId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "app 版本", - "name": "version", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "app 类型", - "name": "version", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.AppDetailDTO" - } - } - } - } - }, - "/apps/details/:id": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 id 获取应用详情", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Get app detail by id", - "parameters": [ - { - "type": "integer", - "description": "id", - "name": "appId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.AppDetailDTO" - } - } - } - } - }, - "/apps/ignored": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取忽略的应用版本", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Get Ignore App", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.IgnoredApp" - } - } - } - } - }, - "/apps/install": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "安装应用", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Install app", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.AppInstallCreate" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.AppInstall" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "app_installs", - "input_column": "name", - "input_value": "name", - "isList": false, - "output_column": "app_id", - "output_value": "appId" - }, - { - "db": "apps", - "info": "appId", - "isList": false, - "output_column": "key", - "output_value": "appKey" - } - ], - "bodyKeys": [ - "name" - ], - "formatEN": "Install app [appKey]-[name]", - "formatZH": "安装应用 [appKey]-[name]", - "paramKeys": [] - } - } - }, - "/apps/installed/check": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "检查应用安装情况", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Check app installed", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.AppInstalledInfo" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.AppInstalledCheck" - } - } - } - } - }, - "/apps/installed/conf": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 key 获取应用默认配置", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search default config by key", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/apps/installed/conninfo/:key": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取应用连接信息", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search app password by key", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/apps/installed/delete/check/:appInstallId": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除前检查", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Check before delete", - "parameters": [ - { - "type": "integer", - "description": "App install id", - "name": "appInstallId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.AppResource" - } - } - } - } - } - }, - "/apps/installed/ignore": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "忽略应用升级版本", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "ignore App Update", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.AppInstalledIgnoreUpgrade" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "installId" - ], - "formatEN": "Application param update [installId]", - "formatZH": "忽略应用 [installId] 版本升级", - "paramKeys": [] - } - } - }, - "/apps/installed/list": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取已安装应用列表", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "List app installed", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.AppInstallInfo" - } - } - } - } - } - }, - "/apps/installed/loadport": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取应用端口", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search app port by key", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "integer" - } - } - } - } - }, - "/apps/installed/op": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作已安装应用", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Operate installed app", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.AppInstalledOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "app_installs", - "input_column": "id", - "input_value": "installId", - "isList": false, - "output_column": "app_id", - "output_value": "appId" - }, - { - "db": "app_installs", - "input_column": "id", - "input_value": "installId", - "isList": false, - "output_column": "name", - "output_value": "appName" - }, - { - "db": "apps", - "input_column": "id", - "input_value": "appId", - "isList": false, - "output_column": "key", - "output_value": "appKey" - } - ], - "bodyKeys": [ - "installId", - "operate" - ], - "formatEN": "[operate] App [appKey][appName]", - "formatZH": "[operate] 应用 [appKey][appName]", - "paramKeys": [] - } - } - }, - "/apps/installed/params/:appInstallId": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 install id 获取应用参数", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search params by appInstallId", - "parameters": [ - { - "type": "string", - "description": "request", - "name": "appInstallId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.AppParam" - } - } - } - } - }, - "/apps/installed/params/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改应用参数", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Change app params", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.AppInstalledUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "installId" - ], - "formatEN": "Application param update [installId]", - "formatZH": "应用参数修改 [installId]", - "paramKeys": [] - } - } - }, - "/apps/installed/port/change": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改应用端口", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Change app port", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.PortUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "key", - "name", - "port" - ], - "formatEN": "Application port update [key]-[name] =\u003e [port]", - "formatZH": "应用端口修改 [key]-[name] =\u003e [port]", - "paramKeys": [] - } - } - }, - "/apps/installed/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "分页获取已安装应用列表", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Page app installed", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.AppInstalledSearch" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/apps/installed/sync": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "同步已安装应用列表", - "tags": [ - "App" - ], - "summary": "Sync app installed", - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "Sync the list of installed apps", - "formatZH": "同步已安装应用列表", - "paramKeys": [] - } - } - }, - "/apps/installed/update/versions": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 install id 获取应用更新版本", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search app update version by install id", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "appInstallId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.AppVersion" - } - } - } - } - } - }, - "/apps/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取应用列表", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "List apps", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.AppSearch" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/apps/services/:key": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 key 获取应用 service", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search app service by key", - "parameters": [ - { - "type": "string", - "description": "request", - "name": "key", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/response.AppService" - } - } - } - } - } - }, - "/apps/sync": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "同步应用列表", - "tags": [ - "App" - ], - "summary": "Sync app list", - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "App store synchronization", - "formatZH": "应用商店同步", - "paramKeys": [] - } - } - }, - "/auth/captcha": { - "get": { - "description": "加载验证码", - "tags": [ - "Auth" - ], - "summary": "Load captcha", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.CaptchaResponse" - } - } - } - } - }, - "/auth/demo": { - "get": { - "description": "判断是否为demo环境", - "tags": [ - "Auth" - ], - "summary": "Check System isDemo", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/auth/issafety": { - "get": { - "description": "获取系统安全登录状态", - "tags": [ - "Auth" - ], - "summary": "Load safety status", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/auth/language": { - "get": { - "description": "获取系统语言设置", - "tags": [ - "Auth" - ], - "summary": "Load System Language", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/auth/login": { - "post": { - "description": "用户登录", - "consumes": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "User login", - "parameters": [ - { - "type": "string", - "description": "安全入口 base64 加密串", - "name": "EntranceCode", - "in": "header", - "required": true - }, - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Login" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.UserLoginInfo" - } - } - } - } - }, - "/auth/logout": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "用户登出", - "tags": [ - "Auth" - ], - "summary": "User logout", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/auth/mfalogin": { - "post": { - "description": "用户 mfa 登录", - "consumes": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "User login with mfa", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MFALogin" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.UserLoginInfo" - }, - "headers": { - "EntranceCode": { - "type": "string", - "description": "安全入口" - } - } - } - } - } - }, - "/containers": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建容器", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Create container", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ContainerOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "image" - ], - "formatEN": "create container [name][image]", - "formatZH": "创建容器 [name][image]", - "paramKeys": [] - } - } - }, - "/containers/clean/log": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "清理容器日志", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Clean container log", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithName" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "clean container [name] logs", - "formatZH": "清理容器 [name] 日志", - "paramKeys": [] - } - } - }, - "/containers/commit": { - "post": { - "description": "容器提交生成新镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Commit Container", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ContainerCommit" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/containers/compose": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建容器编排", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Compose" - ], - "summary": "Create compose", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ComposeCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "create compose [name]", - "formatZH": "创建 compose [name]", - "paramKeys": [] - } - } - }, - "/containers/compose/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "容器编排操作", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Compose" - ], - "summary": "Operate compose", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ComposeOperation" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "operation" - ], - "formatEN": "compose [operation] [name]", - "formatZH": "compose [operation] [name]", - "paramKeys": [] - } - } - }, - "/containers/compose/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取编排列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Compose" - ], - "summary": "Page composes", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/containers/compose/search/log": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "docker-compose 日志", - "tags": [ - "Container Compose" - ], - "summary": "Container Compose logs", - "parameters": [ - { - "type": "string", - "description": "compose 文件地址", - "name": "compose", - "in": "query" - }, - { - "type": "string", - "description": "时间筛选", - "name": "since", - "in": "query" - }, - { - "type": "string", - "description": "是否追踪", - "name": "follow", - "in": "query" - }, - { - "type": "string", - "description": "显示行号", - "name": "tail", - "in": "query" - } - ], - "responses": {} - } - }, - "/containers/compose/test": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "测试 compose 是否可用", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Compose" - ], - "summary": "Test compose", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ComposeCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "check compose [name]", - "formatZH": "检测 compose [name] 格式", - "paramKeys": [] - } - } - }, - "/containers/compose/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新容器编排", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Compose" - ], - "summary": "Update compose", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ComposeUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "update compose information [name]", - "formatZH": "更新 compose [name]", - "paramKeys": [] - } - } - }, - "/containers/daemonjson": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 docker 配置信息", - "produces": [ - "application/json" - ], - "tags": [ - "Container Docker" - ], - "summary": "Load docker daemon.json", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.DaemonJsonConf" - } - } - } - } - }, - "/containers/daemonjson/file": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 docker 配置信息(表单)", - "produces": [ - "application/json" - ], - "tags": [ - "Container Docker" - ], - "summary": "Load docker daemon.json", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/containers/daemonjson/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 docker 配置信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Docker" - ], - "summary": "Update docker daemon.json", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SettingUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "key", - "value" - ], - "formatEN": "Updated configuration [key]", - "formatZH": "更新配置 [key]", - "paramKeys": [] - } - } - }, - "/containers/daemonjson/update/byfile": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "上传替换 docker 配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Docker" - ], - "summary": "Update docker daemon.json by upload file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DaemonJsonUpdateByFile" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "Updated configuration file", - "formatZH": "更新配置文件", - "paramKeys": [] - } - } - }, - "/containers/docker/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Docker 操作", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Docker" - ], - "summary": "Operate docker", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DockerOperation" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operation" - ], - "formatEN": "[operation] docker service", - "formatZH": "docker 服务 [operation]", - "paramKeys": [] - } - } - }, - "/containers/docker/status": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 docker 服务状态", - "produces": [ - "application/json" - ], - "tags": [ - "Container Docker" - ], - "summary": "Load docker status", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/containers/download/log": { - "post": { - "description": "下载容器日志", - "responses": {} - } - }, - "/containers/image": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取镜像名称列表", - "produces": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "load images options", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.Options" - } - } - } - } - } - }, - "/containers/image/all": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取所有镜像列表", - "produces": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "List all images", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.ImageInfo" - } - } - } - } - } - }, - "/containers/image/build": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "构建镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "Build image", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImageBuild" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "build image [name]", - "formatZH": "构建镜像 [name]", - "paramKeys": [] - } - } - }, - "/containers/image/load": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "导入镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "Load image", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImageLoad" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "load image from [path]", - "formatZH": "从 [path] 加载镜像", - "paramKeys": [] - } - } - }, - "/containers/image/pull": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "拉取镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "Pull image", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImagePull" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "image_repos", - "input_column": "id", - "input_value": "repoID", - "isList": false, - "output_column": "name", - "output_value": "reponame" - } - ], - "bodyKeys": [ - "repoID", - "imageName" - ], - "formatEN": "image pull [reponame][imageName]", - "formatZH": "镜像拉取 [reponame][imageName]", - "paramKeys": [] - } - } - }, - "/containers/image/push": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "推送镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "Push image", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImagePush" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "image_repos", - "input_column": "id", - "input_value": "repoID", - "isList": false, - "output_column": "name", - "output_value": "reponame" - } - ], - "bodyKeys": [ - "repoID", - "tagName", - "name" - ], - "formatEN": "push [tagName] to [reponame][name]", - "formatZH": "[tagName] 推送到 [reponame][name]", - "paramKeys": [] - } - } - }, - "/containers/image/remove": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "Delete image", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "names" - ], - "formatEN": "remove image [names]", - "formatZH": "移除镜像 [names]", - "paramKeys": [] - } - } - }, - "/containers/image/save": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "导出镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "Save image", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImageSave" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "tagName", - "path", - "name" - ], - "formatEN": "save [tagName] as [path]/[name]", - "formatZH": "保留 [tagName] 为 [path]/[name]", - "paramKeys": [] - } - } - }, - "/containers/image/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取镜像列表分页", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "Page images", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/containers/image/tag": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Tag 镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "Tag image", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImageTag" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "image_repos", - "input_column": "id", - "input_value": "repoID", - "isList": false, - "output_column": "name", - "output_value": "reponame" - } - ], - "bodyKeys": [ - "repoID", - "targetName" - ], - "formatEN": "tag image [reponame][targetName]", - "formatZH": "tag 镜像 [reponame][targetName]", - "paramKeys": [] - } - } - }, - "/containers/info": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器表单信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Load container info", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithName" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.ContainerOperate" - } - } - } - } - }, - "/containers/inspect": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "容器详情", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Container inspect", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.InspectReq" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/containers/ipv6option/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 docker ipv6 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Docker" - ], - "summary": "Update docker daemon.json ipv6 option", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.LogOption" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "Updated the ipv6 option", - "formatZH": "更新 ipv6 配置", - "paramKeys": [] - } - } - }, - "/containers/limit": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器限制", - "summary": "Load container limits", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.ResourceLimit" - } - } - } - } - }, - "/containers/list": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器名称", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "List containers", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/containers/list/stats": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器列表资源占用", - "summary": "Load container stats", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.ContainerListStats" - } - } - } - } - } - }, - "/containers/load/log": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器操作日志", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Load container log", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/containers/logoption/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 docker 日志配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Docker" - ], - "summary": "Update docker daemon.json log option", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.LogOption" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "Updated the log option", - "formatZH": "更新日志配置", - "paramKeys": [] - } - } - }, - "/containers/network": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器网络列表", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Network" - ], - "summary": "List networks", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.Options" - } - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建容器网络", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Network" - ], - "summary": "Create network", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.NetworkCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "create container network [name]", - "formatZH": "创建容器网络 name", - "paramKeys": [] - } - } - }, - "/containers/network/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除容器网络", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Network" - ], - "summary": "Delete network", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "names" - ], - "formatEN": "delete container network [names]", - "formatZH": "删除容器网络 [names]", - "paramKeys": [] - } - } - }, - "/containers/network/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器网络列表分页", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Network" - ], - "summary": "Page networks", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/containers/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "容器操作", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Operate Container", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ContainerOperation" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "names", - "operation" - ], - "formatEN": "container [operation] [names]", - "formatZH": "容器 [names] 执行 [operation]", - "paramKeys": [] - } - } - }, - "/containers/prune": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "容器清理", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Clean container", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ContainerPrune" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.ContainerPruneReport" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "pruneType" - ], - "formatEN": "clean container [pruneType]", - "formatZH": "清理容器 [pruneType]", - "paramKeys": [] - } - } - }, - "/containers/rename": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "容器重命名", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Rename Container", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ContainerRename" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "newName" - ], - "formatEN": "rename container [name] =\u003e [newName]", - "formatZH": "容器重命名 [name] =\u003e [newName]", - "paramKeys": [] - } - } - }, - "/containers/repo": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取镜像仓库列表", - "produces": [ - "application/json" - ], - "tags": [ - "Container Image-repo" - ], - "summary": "List image repos", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.ImageRepoOption" - } - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建镜像仓库", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Image-repo" - ], - "summary": "Create image repo", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImageRepoDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "create image repo [name]", - "formatZH": "创建镜像仓库 [name]", - "paramKeys": [] - } - } - }, - "/containers/repo/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除镜像仓库", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Image-repo" - ], - "summary": "Delete image repo", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImageRepoDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "image_repos", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "name", - "output_value": "names" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete image repo [names]", - "formatZH": "删除镜像仓库 [names]", - "paramKeys": [] - } - } - }, - "/containers/repo/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取镜像仓库列表分页", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Image-repo" - ], - "summary": "Page image repos", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/containers/repo/status": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 docker 仓库状态", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Image-repo" - ], - "summary": "Load repo status", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/containers/repo/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新镜像仓库", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Image-repo" - ], - "summary": "Update image repo", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImageRepoUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "image_repos", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "update image repo information [name]", - "formatZH": "更新镜像仓库 [name]", - "paramKeys": [] - } - } - }, - "/containers/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器列表分页", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Page containers", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PageContainer" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/containers/search/log": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "容器日志", - "tags": [ - "Container" - ], - "summary": "Container logs", - "parameters": [ - { - "type": "string", - "description": "容器名称", - "name": "container", - "in": "query" - }, - { - "type": "string", - "description": "时间筛选", - "name": "since", - "in": "query" - }, - { - "type": "string", - "description": "是否追踪", - "name": "follow", - "in": "query" - }, - { - "type": "string", - "description": "显示行号", - "name": "tail", - "in": "query" - } - ], - "responses": {} - } - }, - "/containers/stats/:id": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "容器监控信息", - "tags": [ - "Container" - ], - "summary": "Container stats", - "parameters": [ - { - "type": "integer", - "description": "容器id", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.ContainerStats" - } - } - } - } - }, - "/containers/template": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器编排模版列表", - "produces": [ - "application/json" - ], - "tags": [ - "Container Compose-template" - ], - "summary": "List compose templates", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.ComposeTemplateInfo" - } - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建容器编排模版", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Compose-template" - ], - "summary": "Create compose template", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ComposeTemplateCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "create compose template [name]", - "formatZH": "创建 compose 模版 [name]", - "paramKeys": [] - } - } - }, - "/containers/template/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除容器编排模版", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Compose-template" - ], - "summary": "Delete compose template", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "compose_templates", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "name", - "output_value": "names" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete compose template [names]", - "formatZH": "删除 compose 模版 [names]", - "paramKeys": [] - } - } - }, - "/containers/template/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器编排模版列表分页", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Compose-template" - ], - "summary": "Page compose templates", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/containers/template/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新容器编排模版", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Compose-template" - ], - "summary": "Update compose template", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ComposeTemplateUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "compose_templates", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "update compose template information [name]", - "formatZH": "更新 compose 模版 [name]", - "paramKeys": [] - } - } - }, - "/containers/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新容器", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Update container", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ContainerOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "image" - ], - "formatEN": "update container [name][image]", - "formatZH": "更新容器 [name][image]", - "paramKeys": [] - } - } - }, - "/containers/upgrade": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新容器镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Upgrade container", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ContainerUpgrade" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "image" - ], - "formatEN": "upgrade container image [name][image]", - "formatZH": "更新容器镜像 [name][image]", - "paramKeys": [] - } - } - }, - "/containers/volume": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器存储卷列表", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Volume" - ], - "summary": "List volumes", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.Options" - } - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建容器存储卷", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Volume" - ], - "summary": "Create volume", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.VolumeCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "create container volume [name]", - "formatZH": "创建容器存储卷 [name]", - "paramKeys": [] - } - } - }, - "/containers/volume/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除容器存储卷", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Volume" - ], - "summary": "Delete volume", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "names" - ], - "formatEN": "delete container volume [names]", - "formatZH": "删除容器存储卷 [names]", - "paramKeys": [] - } - } - }, - "/containers/volume/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器存储卷分页", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Volume" - ], - "summary": "Page volumes", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/cronjobs": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建计划任务", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Create cronjob", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CronjobCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type", - "name" - ], - "formatEN": "create cronjob [type][name]", - "formatZH": "创建计划任务 [type][name]", - "paramKeys": [] - } - } - }, - "/cronjobs/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除计划任务", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Delete cronjob", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CronjobBatchDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "cronjobs", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "name", - "output_value": "names" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete cronjob [names]", - "formatZH": "删除计划任务 [names]", - "paramKeys": [] - } - } - }, - "/cronjobs/download": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "下载计划任务记录", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Download cronjob records", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CronjobDownload" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "job_records", - "input_column": "id", - "input_value": "recordID", - "isList": false, - "output_column": "file", - "output_value": "file" - } - ], - "bodyKeys": [ - "recordID" - ], - "formatEN": "download the cronjob record [file]", - "formatZH": "下载计划任务记录 [file]", - "paramKeys": [] - } - } - }, - "/cronjobs/handle": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "手动执行计划任务", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Handle cronjob once", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "cronjobs", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "manually execute the cronjob [name]", - "formatZH": "手动执行计划任务 [name]", - "paramKeys": [] - } - } - }, - "/cronjobs/records/clean": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "清空计划任务记录", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Clean job records", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CronjobClean" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "cronjobs", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "clean cronjob [name] records", - "formatZH": "清空计划任务记录 [name]", - "paramKeys": [] - } - } - }, - "/cronjobs/records/log": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取计划任务记录日志", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Load Cronjob record log", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/cronjobs/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取计划任务分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Page cronjobs", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PageCronjob" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/cronjobs/search/records": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取计划任务记录", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Page job records", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchRecord" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/cronjobs/status": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新计划任务状态", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Update cronjob status", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CronjobUpdateStatus" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "cronjobs", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id", - "status" - ], - "formatEN": "change the status of cronjob [name] to [status].", - "formatZH": "修改计划任务 [name] 状态为 [status]", - "paramKeys": [] - } - } - }, - "/cronjobs/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新计划任务", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Update cronjob", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CronjobUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "cronjobs", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "update cronjob [name]", - "formatZH": "更新计划任务 [name]", - "paramKeys": [] - } - } - }, - "/dashboard/base/:ioOption/:netOption": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取首页基础数据", - "consumes": [ - "application/json" - ], - "tags": [ - "Dashboard" - ], - "summary": "Load dashboard base info", - "parameters": [ - { - "type": "string", - "description": "request", - "name": "ioOption", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "request", - "name": "netOption", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.DashboardBase" - } - } - } - } - }, - "/dashboard/base/os": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取服务器基础数据", - "consumes": [ - "application/json" - ], - "tags": [ - "Dashboard" - ], - "summary": "Load os info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.OsInfo" - } - } - } - } - }, - "/dashboard/current/:ioOption/:netOption": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取首页实时数据", - "consumes": [ - "application/json" - ], - "tags": [ - "Dashboard" - ], - "summary": "Load dashboard current info", - "parameters": [ - { - "type": "string", - "description": "request", - "name": "ioOption", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "request", - "name": "netOption", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.DashboardCurrent" - } - } - } - } - }, - "/dashboard/system/restart/:operation": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "重启服务器/面板", - "consumes": [ - "application/json" - ], - "tags": [ - "Dashboard" - ], - "summary": "System restart", - "parameters": [ - { - "type": "string", - "description": "request", - "name": "operation", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/databases": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建 mysql 数据库", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Create mysql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MysqlDBCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "create mysql database [name]", - "formatZH": "创建 mysql 数据库 [name]", - "paramKeys": [] - } - } - }, - "/databases/bind": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "绑定 mysql 数据库用户", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Bind user of mysql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BindUser" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "database", - "username" - ], - "formatEN": "bind mysql database [database] [username]", - "formatZH": "绑定 mysql 数据库名 [database] [username]", - "paramKeys": [] - } - } - }, - "/databases/change/access": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 mysql 访问权限", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Change mysql access", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ChangeDBInfo" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "database_mysqls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Update database [name] access", - "formatZH": "更新数据库 [name] 访问权限", - "paramKeys": [] - } - } - }, - "/databases/change/password": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 mysql 密码", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Change mysql password", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ChangeDBInfo" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "database_mysqls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Update database [name] password", - "formatZH": "更新数据库 [name] 密码", - "paramKeys": [] - } - } - }, - "/databases/common/info": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取数据库基础信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Common" - ], - "summary": "Load base info", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.DBBaseInfo" - } - } - } - } - }, - "/databases/common/load/file": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取数据库配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Common" - ], - "summary": "Load Database conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/databases/common/update/conf": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "上传替换配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Common" - ], - "summary": "Update conf by upload file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DBConfUpdateByFile" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type", - "database" - ], - "formatEN": "update the [type] [database] database configuration information", - "formatZH": "更新 [type] 数据库 [database] 配置信息", - "paramKeys": [] - } - } - }, - "/databases/db": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建远程数据库", - "consumes": [ - "application/json" - ], - "tags": [ - "Database" - ], - "summary": "Create database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DatabaseCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "type" - ], - "formatEN": "create database [name][type]", - "formatZH": "创建远程数据库 [name][type]", - "paramKeys": [] - } - } - }, - "/databases/db/:name": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取远程数据库", - "tags": [ - "Database" - ], - "summary": "Get databases", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.DatabaseInfo" - } - } - } - } - }, - "/databases/db/check": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "检测远程数据库连接性", - "consumes": [ - "application/json" - ], - "tags": [ - "Database" - ], - "summary": "Check database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DatabaseCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "type" - ], - "formatEN": "check if database [name][type] is connectable", - "formatZH": "检测远程数据库 [name][type] 连接性", - "paramKeys": [] - } - } - }, - "/databases/db/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除远程数据库", - "consumes": [ - "application/json" - ], - "tags": [ - "Database" - ], - "summary": "Delete database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DatabaseDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "databases", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "name", - "output_value": "names" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete database [names]", - "formatZH": "删除远程数据库 [names]", - "paramKeys": [] - } - } - }, - "/databases/db/item/:type": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取数据库列表", - "tags": [ - "Database" - ], - "summary": "List databases", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.DatabaseItem" - } - } - } - } - } - }, - "/databases/db/list/:type": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取远程数据库列表", - "tags": [ - "Database" - ], - "summary": "List databases", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.DatabaseOption" - } - } - } - } - } - }, - "/databases/db/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取远程数据库列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Database" - ], - "summary": "Page databases", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DatabaseSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/databases/db/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新远程数据库", - "consumes": [ - "application/json" - ], - "tags": [ - "Database" - ], - "summary": "Update database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DatabaseUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "update database [name]", - "formatZH": "更新远程数据库 [name]", - "paramKeys": [] - } - } - }, - "/databases/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除 mysql 数据库", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Delete mysql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MysqlDBDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "database_mysqls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "delete mysql database [name]", - "formatZH": "删除 mysql 数据库 [name]", - "paramKeys": [] - } - } - }, - "/databases/del/check": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Mysql 数据库删除前检查", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Check before delete mysql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MysqlDBDeleteCheck" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "/databases/description/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 mysql 数据库库描述信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Update mysql database description", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.UpdateDescription" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "database_mysqls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id", - "description" - ], - "formatEN": "The description of the mysql database [name] is modified =\u003e [description]", - "formatZH": "mysql 数据库 [name] 描述信息修改 [description]", - "paramKeys": [] - } - } - }, - "/databases/load": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "从服务器获取", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Load mysql database from remote", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MysqlLoadDB" - } - } - ], - "responses": {} - } - }, - "/databases/options": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 mysql 数据库列表", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "List mysql database names", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PageInfo" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.MysqlOption" - } - } - } - } - } - }, - "/databases/pg": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建 postgresql 数据库", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Create postgresql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PostgresqlDBCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "create postgresql database [name]", - "formatZH": "创建 postgresql 数据库 [name]", - "paramKeys": [] - } - } - }, - "/databases/pg/:database/load": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "从服务器获取", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Load postgresql database from remote", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PostgresqlLoadDB" - } - } - ], - "responses": {} - } - }, - "/databases/pg/bind": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "绑定 postgresql 数据库用户", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Bind postgresql user", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PostgresqlBindUser" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "username" - ], - "formatEN": "bind postgresql database [name] user [username]", - "formatZH": "绑定 postgresql 数据库 [name] 用户 [username]", - "paramKeys": [] - } - } - }, - "/databases/pg/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除 postgresql 数据库", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Delete postgresql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PostgresqlDBDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "database_postgresqls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "delete postgresql database [name]", - "formatZH": "删除 postgresql 数据库 [name]", - "paramKeys": [] - } - } - }, - "/databases/pg/del/check": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Postgresql 数据库删除前检查", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Check before delete postgresql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PostgresqlDBDeleteCheck" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "/databases/pg/description": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 postgresql 数据库库描述信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Update postgresql database description", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.UpdateDescription" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "database_postgresqls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id", - "description" - ], - "formatEN": "The description of the postgresql database [name] is modified =\u003e [description]", - "formatZH": "postgresql 数据库 [name] 描述信息修改 [description]", - "paramKeys": [] - } - } - }, - "/databases/pg/password": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 postgresql 密码", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Change postgresql password", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ChangeDBInfo" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "database_postgresqls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Update database [name] password", - "formatZH": "更新数据库 [name] 密码", - "paramKeys": [] - } - } - }, - "/databases/pg/privileges": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 postgresql 用户权限", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Change postgresql privileges", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ChangeDBInfo" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "database", - "username" - ], - "formatEN": "Update [user] privileges of database [database]", - "formatZH": "更新数据库 [database] 用户 [username] 权限", - "paramKeys": [] - } - } - }, - "/databases/pg/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 postgresql 数据库列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Page postgresql databases", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PostgresqlDBSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/databases/redis/conf": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 redis 配置信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Redis" - ], - "summary": "Load redis conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithName" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.RedisConf" - } - } - } - } - }, - "/databases/redis/conf/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 redis 配置信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Redis" - ], - "summary": "Update redis conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.RedisConfUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "update the redis database configuration information", - "formatZH": "更新 redis 数据库配置信息", - "paramKeys": [] - } - } - }, - "/databases/redis/install/cli": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "安装 redis cli", - "tags": [ - "Database Redis" - ], - "summary": "Install redis-cli", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/databases/redis/password": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 redis 密码", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Redis" - ], - "summary": "Change redis password", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ChangeRedisPass" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "change the password of the redis database", - "formatZH": "修改 redis 数据库密码", - "paramKeys": [] - } - } - }, - "/databases/redis/persistence/conf": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 redis 持久化配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Redis" - ], - "summary": "Load redis persistence conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithName" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.RedisPersistence" - } - } - } - } - }, - "/databases/redis/persistence/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 redis 持久化配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Redis" - ], - "summary": "Update redis persistence conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.RedisConfPersistenceUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "redis database persistence configuration update", - "formatZH": "redis 数据库持久化配置更新", - "paramKeys": [] - } - } - }, - "/databases/redis/status": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 redis 状态信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Redis" - ], - "summary": "Load redis status info", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithName" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.RedisStatus" - } - } - } - } - }, - "/databases/remote": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 mysql 远程访问权限", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Load mysql remote access", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "boolean" - } - } - } - } - }, - "/databases/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 mysql 数据库列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Page mysql databases", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MysqlDBSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/databases/status": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 mysql 状态信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Load mysql status info", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.MysqlStatus" - } - } - } - } - }, - "/databases/variables": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 mysql 性能参数信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Load mysql variables info", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.MysqlVariables" - } - } - } - } - }, - "/databases/variables/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "mysql 性能调优", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Update mysql variables", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MysqlVariablesUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "adjust mysql database performance parameters", - "formatZH": "调整 mysql 数据库性能参数", - "paramKeys": [] - } - } - }, - "/db/remote/del/check": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Mysql 远程数据库删除前检查", - "consumes": [ - "application/json" - ], - "tags": [ - "Database" - ], - "summary": "Check before delete remote database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "/files": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建文件/文件夹", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Create file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "Create dir or file [path]", - "formatZH": "创建文件/文件夹 [path]", - "paramKeys": [] - } - } - }, - "/files/batch/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "批量删除文件/文件夹", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Batch delete file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileBatchDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "paths" - ], - "formatEN": "Batch delete dir or file [paths]", - "formatZH": "批量删除文件/文件夹 [paths]", - "paramKeys": [] - } - } - }, - "/files/batch/role": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "批量修改文件权限和用户/组", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Batch change file mode and owner", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileRoleReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "paths", - "mode", - "user", - "group" - ], - "formatEN": "Batch change file mode and owner [paths] =\u003e [mode]/[user]/[group]", - "formatZH": "批量修改文件权限和用户/组 [paths] =\u003e [mode]/[user]/[group]", - "paramKeys": [] - } - } - }, - "/files/check": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "检测文件是否存在", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Check file exist", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FilePathCheck" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/files/chunkdownload": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "分片下载下载文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Chunk Download file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileDownload" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Download file [name]", - "formatZH": "下载文件 [name]", - "paramKeys": [] - } - } - }, - "/files/chunkupload": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "分片上传文件", - "tags": [ - "File" - ], - "summary": "ChunkUpload file", - "parameters": [ - { - "type": "file", - "description": "request", - "name": "file", - "in": "formData", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/files/compress": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "压缩文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Compress file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileCompress" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Compress file [name]", - "formatZH": "压缩文件 [name]", - "paramKeys": [] - } - } - }, - "/files/content": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取文件内容", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Load file content", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileContentReq" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.FileInfo" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "Load file content [path]", - "formatZH": "获取文件内容 [path]", - "paramKeys": [] - } - } - }, - "/files/decompress": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "解压文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Decompress file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileDeCompress" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "Decompress file [path]", - "formatZH": "解压 [path]", - "paramKeys": [] - } - } - }, - "/files/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除文件/文件夹", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Delete file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "Delete dir or file [path]", - "formatZH": "删除文件/文件夹 [path]", - "paramKeys": [] - } - } - }, - "/files/download": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "下载文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Download file", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/files/favorite": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建收藏", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Create favorite", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FavoriteCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "收藏文件/文件夹 [path]", - "formatZH": "收藏文件/文件夹 [path]", - "paramKeys": [] - } - } - }, - "/files/favorite/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除收藏", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Delete favorite", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FavoriteDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "favorites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "path", - "output_value": "path" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "delete avorite [path]", - "formatZH": "删除收藏 [path]", - "paramKeys": [] - } - } - }, - "/files/favorite/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取收藏列表", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "List favorites", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PageInfo" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/files/mode": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改文件权限", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Change file mode", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path", - "mode" - ], - "formatEN": "Change mode [paths] =\u003e [mode]", - "formatZH": "修改权限 [paths] =\u003e [mode]", - "paramKeys": [] - } - } - }, - "/files/move": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "移动文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Move file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileMove" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "oldPaths", - "newPath" - ], - "formatEN": "Move [oldPaths] =\u003e [newPath]", - "formatZH": "移动文件 [oldPaths] =\u003e [newPath]", - "paramKeys": [] - } - } - }, - "/files/owner": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改文件用户/组", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Change file owner", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileRoleUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path", - "user", - "group" - ], - "formatEN": "Change owner [paths] =\u003e [user]/[group]", - "formatZH": "修改用户/组 [paths] =\u003e [user]/[group]", - "paramKeys": [] - } - } - }, - "/files/read": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "按行读取日志文件", - "tags": [ - "File" - ], - "summary": "Read file by Line", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileReadByLineReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/files/recycle/clear": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "清空回收站文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Clear RecycleBin files", - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "清空回收站", - "formatZH": "清空回收站", - "paramKeys": [] - } - } - }, - "/files/recycle/reduce": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "还原回收站文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Reduce RecycleBin files", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.RecycleBinReduce" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Reduce RecycleBin file [name]", - "formatZH": "还原回收站文件 [name]", - "paramKeys": [] - } - } - }, - "/files/recycle/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取回收站文件列表", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "List RecycleBin files", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PageInfo" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/files/recycle/status": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取回收站状态", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Get RecycleBin status", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/files/rename": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改文件名称", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Change file name", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileRename" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "oldName", - "newName" - ], - "formatEN": "Rename [oldName] =\u003e [newName]", - "formatZH": "重命名 [oldName] =\u003e [newName]", - "paramKeys": [] - } - } - }, - "/files/save": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新文件内容", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Update file content", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileEdit" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "Update file content [path]", - "formatZH": "更新文件内容 [path]", - "paramKeys": [] - } - } - }, - "/files/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取文件列表", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "List files", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileOption" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.FileInfo" - } - } - } - } - }, - "/files/size": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取文件夹大小", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Load file size", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.DirSizeReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "Load file size [path]", - "formatZH": "获取文件夹大小 [path]", - "paramKeys": [] - } - } - }, - "/files/tree": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "加载文件树", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Load files tree", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileOption" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/response.FileTree" - } - } - } - } - } - }, - "/files/upload": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "上传文件", - "tags": [ - "File" - ], - "summary": "Upload file", - "parameters": [ - { - "type": "file", - "description": "request", - "name": "file", - "in": "formData", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "Upload file [path]", - "formatZH": "上传文件 [path]", - "paramKeys": [] - } - } - }, - "/files/upload/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "分页获取上传文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Page file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.SearchUploadWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/response.FileInfo" - } - } - } - } - } - }, - "/files/wget": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "下载远端文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Wget file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileWget" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "url", - "path", - "name" - ], - "formatEN": "Download url =\u003e [path]/[name]", - "formatZH": "下载 url =\u003e [path]/[name]", - "paramKeys": [] - } - } - }, - "/groups": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建系统组", - "consumes": [ - "application/json" - ], - "tags": [ - "System Group" - ], - "summary": "Create group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.GroupCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "type" - ], - "formatEN": "create group [name][type]", - "formatZH": "创建组 [name][type]", - "paramKeys": [] - } - } - }, - "/groups/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除系统组", - "consumes": [ - "application/json" - ], - "tags": [ - "System Group" - ], - "summary": "Delete group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "groups", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - }, - { - "db": "groups", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "type", - "output_value": "type" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "delete group [type][name]", - "formatZH": "删除组 [type][name]", - "paramKeys": [] - } - } - }, - "/groups/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "查询系统组", - "consumes": [ - "application/json" - ], - "tags": [ - "System Group" - ], - "summary": "List groups", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.GroupSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.GroupInfo" - } - } - } - } - } - }, - "/groups/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新系统组", - "consumes": [ - "application/json" - ], - "tags": [ - "System Group" - ], - "summary": "Update group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.GroupUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "type" - ], - "formatEN": "update group [name][type]", - "formatZH": "更新组 [name][type]", - "paramKeys": [] - } - } - }, - "/host/conffile/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "上传文件更新 SSH 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "SSH" - ], - "summary": "Update host SSH setting by file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SSHConf" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "update SSH conf", - "formatZH": "修改 SSH 配置文件", - "paramKeys": [] - } - } - }, - "/host/ssh/conf": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 SSH 配置文件", - "tags": [ - "SSH" - ], - "summary": "Load host SSH conf", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/host/ssh/generate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "生成 SSH 密钥", - "consumes": [ - "application/json" - ], - "tags": [ - "SSH" - ], - "summary": "Generate host SSH secret", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.GenerateSSH" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "generate SSH secret", - "formatZH": "生成 SSH 密钥 ", - "paramKeys": [] - } - } - }, - "/host/ssh/log": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 SSH 登录日志", - "consumes": [ - "application/json" - ], - "tags": [ - "SSH" - ], - "summary": "Load host SSH logs", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchSSHLog" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.SSHLog" - } - } - } - } - }, - "/host/ssh/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 SSH 服务状态", - "consumes": [ - "application/json" - ], - "tags": [ - "SSH" - ], - "summary": "Operate SSH", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Operate" - } - } - ], - "responses": {}, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operation" - ], - "formatEN": "[operation] SSH", - "formatZH": "[operation] SSH ", - "paramKeys": [] - } - } - }, - "/host/ssh/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "加载 SSH 配置信息", - "tags": [ - "SSH" - ], - "summary": "Load host SSH setting info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.SSHInfo" - } - } - } - } - }, - "/host/ssh/secret": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 SSH 密钥", - "consumes": [ - "application/json" - ], - "tags": [ - "SSH" - ], - "summary": "Load host SSH secret", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.GenerateLoad" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/host/ssh/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 SSH 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "SSH" - ], - "summary": "Update host SSH setting", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SSHUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "key", - "value" - ], - "formatEN": "update SSH setting [key] =\u003e [value]", - "formatZH": "修改 SSH 配置 [key] =\u003e [value]", - "paramKeys": [] - } - } - }, - "/host/tool": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取主机工具状态", - "consumes": [ - "application/json" - ], - "tags": [ - "Host tool" - ], - "summary": "Get tool", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.HostToolReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/host/tool/config": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作主机工具配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Host tool" - ], - "summary": "Get tool config", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.HostToolConfig" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operate" - ], - "formatEN": "[operate] tool config", - "formatZH": "[operate] 主机工具配置文件 ", - "paramKeys": [] - } - } - }, - "/host/tool/create": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建主机工具配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Host tool" - ], - "summary": "Create Host tool Config", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.HostToolCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type" - ], - "formatEN": "create [type] config", - "formatZH": "创建 [type] 配置", - "paramKeys": [] - } - } - }, - "/host/tool/log": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取主机工具日志", - "consumes": [ - "application/json" - ], - "tags": [ - "Host tool" - ], - "summary": "Get tool", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.HostToolLogReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/host/tool/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作主机工具", - "consumes": [ - "application/json" - ], - "tags": [ - "Host tool" - ], - "summary": "Operate tool", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.HostToolReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operate", - "type" - ], - "formatEN": "[operate] [type]", - "formatZH": "[operate] [type] ", - "paramKeys": [] - } - } - }, - "/host/tool/supervisor/process": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 Supervisor 进程配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Host tool" - ], - "summary": "Get Supervisor process config", - "responses": { - "200": { - "description": "OK" - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作守护进程", - "consumes": [ - "application/json" - ], - "tags": [ - "Host tool" - ], - "summary": "Create Supervisor process", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.SupervisorProcessConfig" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operate" - ], - "formatEN": "[operate] process", - "formatZH": "[operate] 守护进程 ", - "paramKeys": [] - } - } - }, - "/host/tool/supervisor/process/file": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作 Supervisor 进程文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Host tool" - ], - "summary": "Get Supervisor process config", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.SupervisorProcessFileReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operate" - ], - "formatEN": "[operate] Supervisor Process Config file", - "formatZH": "[operate] Supervisor 进程文件 ", - "paramKeys": [] - } - } - }, - "/hosts": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建主机", - "consumes": [ - "application/json" - ], - "tags": [ - "Host" - ], - "summary": "Create host", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.HostOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "addr" - ], - "formatEN": "create host [name][addr]", - "formatZH": "创建主机 [name][addr]", - "paramKeys": [] - } - } - }, - "/hosts/command": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取快速命令列表", - "tags": [ - "Command" - ], - "summary": "List commands", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.CommandInfo" - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建快速命令", - "consumes": [ - "application/json" - ], - "tags": [ - "Command" - ], - "summary": "Create command", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CommandOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "command" - ], - "formatEN": "create quick command [name][command]", - "formatZH": "创建快捷命令 [name][command]", - "paramKeys": [] - } - } - }, - "/hosts/command/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除快速命令", - "consumes": [ - "application/json" - ], - "tags": [ - "Command" - ], - "summary": "Delete command", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDeleteReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "commands", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "name", - "output_value": "names" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete quick command [names]", - "formatZH": "删除快捷命令 [names]", - "paramKeys": [] - } - } - }, - "/hosts/command/redis": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 redis 快速命令列表", - "tags": [ - "Redis Command" - ], - "summary": "List redis commands", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "Array" - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "保存 Redis 快速命令", - "consumes": [ - "application/json" - ], - "tags": [ - "Redis Command" - ], - "summary": "Save redis command", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.RedisCommand" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "command" - ], - "formatEN": "save quick command for redis [name][command]", - "formatZH": "保存 redis 快捷命令 [name][command]", - "paramKeys": [] - } - } - }, - "/hosts/command/redis/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除 redis 快速命令", - "consumes": [ - "application/json" - ], - "tags": [ - "Redis Command" - ], - "summary": "Delete redis command", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDeleteReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "redis_commands", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "name", - "output_value": "names" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete quick command of redis [names]", - "formatZH": "删除 redis 快捷命令 [names]", - "paramKeys": [] - } - } - }, - "/hosts/command/redis/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 redis 快速命令列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Redis Command" - ], - "summary": "Page redis commands", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/hosts/command/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取快速命令列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Command" - ], - "summary": "Page commands", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/hosts/command/tree": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取快速命令树", - "consumes": [ - "application/json" - ], - "tags": [ - "Command" - ], - "summary": "Tree commands", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "Array" - } - } - } - } - }, - "/hosts/command/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新快速命令", - "consumes": [ - "application/json" - ], - "tags": [ - "Command" - ], - "summary": "Update command", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CommandOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "update quick command [name]", - "formatZH": "更新快捷命令 [name]", - "paramKeys": [] - } - } - }, - "/hosts/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除主机", - "consumes": [ - "application/json" - ], - "tags": [ - "Host" - ], - "summary": "Delete host", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDeleteReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "hosts", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "addr", - "output_value": "addrs" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete host [addrs]", - "formatZH": "删除主机 [addrs]", - "paramKeys": [] - } - } - }, - "/hosts/firewall/base": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取防火墙基础信息", - "tags": [ - "Firewall" - ], - "summary": "Load firewall base info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.FirewallBaseInfo" - } - } - } - } - }, - "/hosts/firewall/batch": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "批量删除防火墙规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Create group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchRuleOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/hosts/firewall/forward": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新防火墙端口转发规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Create group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ForwardRuleOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "source_port" - ], - "formatEN": "update port forward rules [source_port]", - "formatZH": "更新端口转发规则 [source_port]", - "paramKeys": [] - } - } - }, - "/hosts/firewall/ip": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建防火墙 IP 规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Create group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.AddrRuleOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "strategy", - "address" - ], - "formatEN": "create address rules [strategy][address]", - "formatZH": "添加 ip 规则 [strategy] [address]", - "paramKeys": [] - } - } - }, - "/hosts/firewall/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改防火墙状态", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Page firewall status", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.FirewallOperation" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operation" - ], - "formatEN": "[operation] firewall", - "formatZH": "[operation] 防火墙", - "paramKeys": [] - } - } - }, - "/hosts/firewall/port": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建防火墙端口规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Create group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PortRuleOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "port", - "strategy" - ], - "formatEN": "create port rules [strategy][port]", - "formatZH": "添加端口规则 [strategy] [port]", - "paramKeys": [] - } - } - }, - "/hosts/firewall/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取防火墙规则列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Page firewall rules", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.RuleSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/hosts/firewall/update/addr": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 ip 防火墙规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Create group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.AddrRuleUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/hosts/firewall/update/description": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新防火墙描述", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Update rule description", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.UpdateFirewallDescription" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/hosts/firewall/update/port": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新端口防火墙规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Create group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PortRuleUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/hosts/monitor/clean": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "清空监控数据", - "tags": [ - "Monitor" - ], - "summary": "Clean monitor datas", - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "clean monitor datas", - "formatZH": "清空监控数据", - "paramKeys": [] - } - } - }, - "/hosts/monitor/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取监控数据", - "tags": [ - "Monitor" - ], - "summary": "Load monitor datas", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MonitorSearch" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/hosts/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取主机列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Host" - ], - "summary": "Page host", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchHostWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.HostTree" - } - } - } - } - } - }, - "/hosts/test/byid/:id": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "测试主机连接", - "consumes": [ - "application/json" - ], - "tags": [ - "Host" - ], - "summary": "Test host conn by host id", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "boolean" - } - } - } - } - }, - "/hosts/test/byinfo": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "测试主机连接", - "consumes": [ - "application/json" - ], - "tags": [ - "Host" - ], - "summary": "Test host conn by info", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.HostConnTest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/hosts/tree": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "加载主机树", - "consumes": [ - "application/json" - ], - "tags": [ - "Host" - ], - "summary": "Load host tree", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchForTree" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.HostTree" - } - } - } - } - } - }, - "/hosts/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新主机", - "consumes": [ - "application/json" - ], - "tags": [ - "Host" - ], - "summary": "Update host", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.HostOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "addr" - ], - "formatEN": "update host [name][addr]", - "formatZH": "更新主机信息 [name][addr]", - "paramKeys": [] - } - } - }, - "/hosts/update/group": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "切换分组", - "consumes": [ - "application/json" - ], - "tags": [ - "Host" - ], - "summary": "Update host group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ChangeHostGroup" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "hosts", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "addr", - "output_value": "addr" - } - ], - "bodyKeys": [ - "id", - "group" - ], - "formatEN": "change host [addr] group =\u003e [group]", - "formatZH": "切换主机[addr]分组 =\u003e [group]", - "paramKeys": [] - } - } - }, - "/logs/clean": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "清空操作日志", - "consumes": [ - "application/json" - ], - "tags": [ - "Logs" - ], - "summary": "Clean operation logs", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CleanLog" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "logType" - ], - "formatEN": "Clean the [logType] log information", - "formatZH": "清空 [logType] 日志信息", - "paramKeys": [] - } - } - }, - "/logs/login": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统登录日志列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Logs" - ], - "summary": "Page login logs", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchLgLogWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/logs/operation": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统操作日志列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Logs" - ], - "summary": "Page operation logs", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchOpLogWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/logs/system": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统日志", - "tags": [ - "Logs" - ], - "summary": "Load system logs", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/logs/system/files": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统日志文件列表", - "tags": [ - "Logs" - ], - "summary": "Load system log files", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/openresty": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 OpenResty 配置信息", - "tags": [ - "OpenResty" - ], - "summary": "Load OpenResty conf", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.FileInfo" - } - } - } - } - }, - "/openresty/clear": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "清理 OpenResty 代理缓存", - "tags": [ - "OpenResty" - ], - "summary": "Clear OpenResty proxy cache", - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "Clear nginx proxy cache", - "formatZH": "清理 Openresty 代理缓存", - "paramKeys": [] - } - } - }, - "/openresty/file": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "上传更新 OpenResty 配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "OpenResty" - ], - "summary": "Update OpenResty conf by upload file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxConfigFileUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "Update nginx conf", - "formatZH": "更新 nginx 配置", - "paramKeys": [] - } - } - }, - "/openresty/scope": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取部分 OpenResty 配置信息", - "consumes": [ - "application/json" - ], - "tags": [ - "OpenResty" - ], - "summary": "Load partial OpenResty conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxScopeReq" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/response.NginxParam" - } - } - } - } - } - }, - "/openresty/status": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 OpenResty 状态信息", - "tags": [ - "OpenResty" - ], - "summary": "Load OpenResty status info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.NginxStatus" - } - } - } - } - }, - "/openresty/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 OpenResty 配置信息", - "consumes": [ - "application/json" - ], - "tags": [ - "OpenResty" - ], - "summary": "Update OpenResty conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxConfigUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteId", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteId" - ], - "formatEN": "Update nginx conf [domain]", - "formatZH": "更新 nginx 配置 [domain]", - "paramKeys": [] - } - } - }, - "/process/stop": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "停止进程", - "tags": [ - "Process" - ], - "summary": "Stop Process", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.ProcessReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "PID" - ], - "formatEN": "结束进程 [PID]", - "formatZH": "结束进程 [PID]", - "paramKeys": [] - } - } - }, - "/runtimes": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建运行环境", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "Create runtime", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.RuntimeCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Create runtime [name]", - "formatZH": "创建运行环境 [name]", - "paramKeys": [] - } - } - }, - "/runtimes/:id": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取运行环境", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "Get runtime", - "parameters": [ - { - "type": "string", - "description": "request", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除运行环境", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Delete runtime", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.RuntimeDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "id" - ], - "formatEN": "Delete website [name]", - "formatZH": "删除网站 [name]", - "paramKeys": [] - } - } - }, - "/runtimes/node/modules": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 Node 项目的 modules", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "Get Node modules", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NodeModuleReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/node/modules/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作 Node 项目 modules", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "Operate Node modules", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NodeModuleReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/node/package": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 Node 项目的 scripts", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "Get Node package scripts", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NodePackageReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作运行环境", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "Operate runtime", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.RuntimeOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "id" - ], - "formatEN": "Operate runtime [name]", - "formatZH": "操作运行环境 [name]", - "paramKeys": [] - } - } - }, - "/runtimes/php/extensions": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Create Extensions", - "consumes": [ - "application/json" - ], - "tags": [ - "PHP Extensions" - ], - "summary": "Create Extensions", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.PHPExtensionsCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/php/extensions/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Delete Extensions", - "consumes": [ - "application/json" - ], - "tags": [ - "PHP Extensions" - ], - "summary": "Delete Extensions", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.PHPExtensionsDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/php/extensions/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Page Extensions", - "consumes": [ - "application/json" - ], - "tags": [ - "PHP Extensions" - ], - "summary": "Page Extensions", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.PHPExtensionsSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/response.PHPExtensionsDTO" - } - } - } - } - } - }, - "/runtimes/php/extensions/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Update Extensions", - "consumes": [ - "application/json" - ], - "tags": [ - "PHP Extensions" - ], - "summary": "Update Extensions", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.PHPExtensionsUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取运行环境列表", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "List runtimes", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.RuntimeSearch" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/sync": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "同步运行环境状态", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "Sync runtime status", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新运行环境", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "Update runtime", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.RuntimeUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Update runtime [name]", - "formatZH": "更新运行环境 [name]", - "paramKeys": [] - } - } - }, - "/settings/backup": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建备份账号", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Create backup account", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BackupOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type" - ], - "formatEN": "create backup account [type]", - "formatZH": "创建备份账号 [type]", - "paramKeys": [] - } - } - }, - "/settings/backup/backup": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "备份系统数据", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Backup system data", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CommonBackup" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type", - "name", - "detailName" - ], - "formatEN": "backup [type] data [name][detailName]", - "formatZH": "备份 [type] 数据 [name][detailName]", - "paramKeys": [] - } - } - }, - "/settings/backup/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除备份账号", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Delete backup account", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "backup_accounts", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "type", - "output_value": "types" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "delete backup account [types]", - "formatZH": "删除备份账号 [types]", - "paramKeys": [] - } - } - }, - "/settings/backup/onedrive": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 OneDrive 信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Load OneDrive info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.OneDriveInfo" - } - } - } - } - }, - "/settings/backup/record/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除备份记录", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Delete backup record", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDeleteReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "backup_records", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "file_name", - "output_value": "files" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete backup records [files]", - "formatZH": "删除备份记录 [files]", - "paramKeys": [] - } - } - }, - "/settings/backup/record/download": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "下载备份记录", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Download backup record", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DownloadRecord" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "source", - "fileName" - ], - "formatEN": "download backup records [source][fileName]", - "formatZH": "下载备份记录 [source][fileName]", - "paramKeys": [] - } - } - }, - "/settings/backup/record/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取备份记录列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Page backup records", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.RecordSearch" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/settings/backup/record/search/bycronjob": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过计划任务获取备份记录列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Page backup records by cronjob", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.RecordSearchByCronjob" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/settings/backup/recover": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "恢复系统数据", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Recover system data", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CommonRecover" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type", - "name", - "detailName", - "file" - ], - "formatEN": "recover [type] data [name][detailName] from [file]", - "formatZH": "从 [file] 恢复 [type] 数据 [name][detailName]", - "paramKeys": [] - } - } - }, - "/settings/backup/recover/byupload": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "从上传恢复系统数据", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Recover system data by upload", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CommonRecover" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type", - "name", - "detailName", - "file" - ], - "formatEN": "recover [type] data [name][detailName] from [file]", - "formatZH": "从 [file] 恢复 [type] 数据 [name][detailName]", - "paramKeys": [] - } - } - }, - "/settings/backup/refresh/onedrive": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "刷新 OneDrive token", - "tags": [ - "Backup Account" - ], - "summary": "Refresh OneDrive token", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/settings/backup/search": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取备份账号列表", - "tags": [ - "Backup Account" - ], - "summary": "List backup accounts", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.BackupInfo" - } - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 bucket 列表", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "List buckets", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ForBuckets" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "/settings/backup/search/files": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取备份账号内文件列表", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "List files from backup accounts", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BackupSearchFile" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "/settings/backup/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新备份账号信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Update backup account", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BackupOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type" - ], - "formatEN": "update backup account [types]", - "formatZH": "更新备份账号 [types]", - "paramKeys": [] - } - } - }, - "/settings/basedir": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取安装根目录", - "tags": [ - "System Setting" - ], - "summary": "Load local backup dir", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/settings/bind/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新系统监听信息", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Update system bind info", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BindInfo" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "ipv6", - "bindAddress" - ], - "formatEN": "update system bind info =\u003e ipv6: [ipv6], 监听 IP: [bindAddress]", - "formatZH": "修改系统监听信息 =\u003e ipv6: [ipv6], 监听 IP: [bindAddress]", - "paramKeys": [] - } - } - }, - "/settings/expired/handle": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "重置过期系统登录密码", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Reset system password expired", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PasswordUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "reset an expired Password", - "formatZH": "重置过期密码", - "paramKeys": [] - } - } - }, - "/settings/interface": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统地址信息", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Load system address", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/settings/menu/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "隐藏高级功能菜单", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Update system setting", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SettingUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "Hide advanced feature menu.", - "formatZH": "隐藏高级功能菜单", - "paramKeys": [] - } - } - }, - "/settings/mfa": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 mfa 信息", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Load mfa info", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MfaCredential" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/mfa.Otp" - } - } - } - } - }, - "/settings/mfa/bind": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Mfa 绑定", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Bind mfa", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MfaCredential" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "bind mfa", - "formatZH": "mfa 绑定", - "paramKeys": [] - } - } - }, - "/settings/password/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新系统登录密码", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Update system password", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PasswordUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "update system password", - "formatZH": "修改系统密码", - "paramKeys": [] - } - } - }, - "/settings/port/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新系统端口", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Update system port", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PortUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "serverPort" - ], - "formatEN": "update system port =\u003e [serverPort]", - "formatZH": "修改系统端口 =\u003e [serverPort]", - "paramKeys": [] - } - } - }, - "/settings/proxy/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "服务器代理配置", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Update proxy setting", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ProxyUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "proxyUrl", - "proxyPort" - ], - "formatEN": "set proxy [proxyPort]:[proxyPort].", - "formatZH": "服务器代理配置 [proxyPort]:[proxyPort]", - "paramKeys": [] - } - } - }, - "/settings/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "加载系统配置信息", - "tags": [ - "System Setting" - ], - "summary": "Load system setting info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.SettingInfo" - } - } - } - } - }, - "/settings/search/available": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统可用状态", - "tags": [ - "System Setting" - ], - "summary": "Load system available status", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/settings/snapshot": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建系统快照", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Create system snapshot", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SnapshotCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "from", - "description" - ], - "formatEN": "Create system backup [description] to [from]", - "formatZH": "创建系统快照 [description] 到 [from]", - "paramKeys": [] - } - } - }, - "/settings/snapshot/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除系统快照", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Delete system backup", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SnapshotBatchDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "snapshots", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "Delete system backup [name]", - "formatZH": "删除系统快照 [name]", - "paramKeys": [] - } - } - }, - "/settings/snapshot/description/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新快照描述信息", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Update snapshot description", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.UpdateDescription" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "snapshots", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id", - "description" - ], - "formatEN": "The description of the snapshot [name] is modified =\u003e [description]", - "formatZH": "快照 [name] 描述信息修改 [description]", - "paramKeys": [] - } - } - }, - "/settings/snapshot/import": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "导入已有快照", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Import system snapshot", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SnapshotImport" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "from", - "names" - ], - "formatEN": "Sync system snapshots [names] from [from]", - "formatZH": "从 [from] 同步系统快照 [names]", - "paramKeys": [] - } - } - }, - "/settings/snapshot/recover": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "从系统快照恢复", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Recover system backup", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SnapshotRecover" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "snapshots", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Recover from system backup [name]", - "formatZH": "从系统快照 [name] 恢复", - "paramKeys": [] - } - } - }, - "/settings/snapshot/rollback": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "从系统快照回滚", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Rollback system backup", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SnapshotRecover" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "snapshots", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Rollback from system backup [name]", - "formatZH": "从系统快照 [name] 回滚", - "paramKeys": [] - } - } - }, - "/settings/snapshot/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统快照列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Page system snapshot", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/settings/snapshot/status": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取快照状态", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Load Snapshot status", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/settings/ssl/download": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "下载证书", - "tags": [ - "System Setting" - ], - "summary": "Download system cert", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/settings/ssl/info": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取证书信息", - "tags": [ - "System Setting" - ], - "summary": "Load system cert info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.SettingInfo" - } - } - } - } - }, - "/settings/ssl/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改系统 ssl 登录", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Update system ssl", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SSLUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "ssl" - ], - "formatEN": "update system ssl =\u003e [ssl]", - "formatZH": "修改系统 ssl =\u003e [ssl]", - "paramKeys": [] - } - } - }, - "/settings/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新系统配置", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Update system setting", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SettingUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "key", - "value" - ], - "formatEN": "update system setting [key] =\u003e [value]", - "formatZH": "修改系统配置 [key] =\u003e [value]", - "paramKeys": [] - } - } - }, - "/settings/upgrade": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取版本 release notes", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Load release notes by version", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Upgrade" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "系统更新", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Upgrade", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Upgrade" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "version" - ], - "formatEN": "upgrade system =\u003e [version]", - "formatZH": "更新系统 =\u003e [version]", - "paramKeys": [] - } - } - }, - "/toolbox/clam": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建扫描规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Create clam", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ClamCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "path" - ], - "formatEN": "create clam [name][path]", - "formatZH": "创建扫描规则 [name][path]", - "paramKeys": [] - } - } - }, - "/toolbox/clam/base": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 Clam 基础信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Load clam base info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.ClamBaseInfo" - } - } - } - } - }, - "/toolbox/clam/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除扫描规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Delete clam", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ClamDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "clams", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "name", - "output_value": "names" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete clam [names]", - "formatZH": "删除扫描规则 [names]", - "paramKeys": [] - } - } - }, - "/toolbox/clam/file/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取扫描文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Load clam file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ClamFileReq" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/toolbox/clam/file/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新病毒扫描配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Update clam file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.UpdateByNameAndFile" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/toolbox/clam/handle": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "执行病毒扫描", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Handle clam scan", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "clams", - "input_column": "id", - "input_value": "id", - "isList": true, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "handle clam scan [name]", - "formatZH": "执行病毒扫描 [name]", - "paramKeys": [] - } - } - }, - "/toolbox/clam/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 Clam 状态", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Operate Clam", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Operate" - } - } - ], - "responses": {}, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operation" - ], - "formatEN": "[operation] FTP", - "formatZH": "[operation] Clam", - "paramKeys": [] - } - } - }, - "/toolbox/clam/record/clean": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "清空扫描报告", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Clean clam record", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": {}, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "clams", - "input_column": "id", - "input_value": "id", - "isList": true, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "clean clam record [name]", - "formatZH": "清空扫描报告 [name]", - "paramKeys": [] - } - } - }, - "/toolbox/clam/record/log": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取扫描结果详情", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Load clam record detail", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ClamLogReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/toolbox/clam/record/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取扫描结果列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Page clam record", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ClamLogSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/toolbox/clam/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取扫描规则列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Page clam", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/toolbox/clam/status/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改扫描规则状态", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Update clam status", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ClamUpdateStatus" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "clams", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id", - "status" - ], - "formatEN": "change the status of clam [name] to [status].", - "formatZH": "修改扫描规则 [name] 状态为 [status]", - "paramKeys": [] - } - } - }, - "/toolbox/clam/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改扫描规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Update clam", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ClamUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "path" - ], - "formatEN": "update clam [name][path]", - "formatZH": "修改扫描规则 [name][path]", - "paramKeys": [] - } - } - }, - "/toolbox/clean": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "清理系统垃圾文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Device" - ], - "summary": "Clean system", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.Clean" - } - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "Clean system junk files", - "formatZH": "清理系统垃圾文件", - "paramKeys": [] - } - } - }, - "/toolbox/device/base": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取设备基础信息", - "tags": [ - "Device" - ], - "summary": "Load device base info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.DeviceBaseInfo" - } - } - } - } - }, - "/toolbox/device/check/dns": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "检查系统 DNS 配置可用性", - "consumes": [ - "application/json" - ], - "tags": [ - "Device" - ], - "summary": "Check device DNS conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SettingUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/toolbox/device/conf": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Device" - ], - "summary": "load conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithName" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/toolbox/device/update/byconf": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过文件修改配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Device" - ], - "summary": "Update device conf by file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.UpdateByNameAndFile" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/toolbox/device/update/conf": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改系统参数", - "consumes": [ - "application/json" - ], - "tags": [ - "Device" - ], - "summary": "Update device", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SettingUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "key", - "value" - ], - "formatEN": "update device conf [key] =\u003e [value]", - "formatZH": "修改主机参数 [key] =\u003e [value]", - "paramKeys": [] - } - } - }, - "/toolbox/device/update/host": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改系统 hosts", - "tags": [ - "Device" - ], - "summary": "Update device hosts", - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "key", - "value" - ], - "formatEN": "update device host [key] =\u003e [value]", - "formatZH": "修改主机 Host [key] =\u003e [value]", - "paramKeys": [] - } - } - }, - "/toolbox/device/update/passwd": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改系统密码", - "consumes": [ - "application/json" - ], - "tags": [ - "Device" - ], - "summary": "Update device passwd", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ChangePasswd" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/toolbox/device/update/swap": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改系统 Swap", - "consumes": [ - "application/json" - ], - "tags": [ - "Device" - ], - "summary": "Update device swap", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SwapHelper" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operate", - "path" - ], - "formatEN": "[operate] device swap [path]", - "formatZH": "[operate] 主机 swap [path]", - "paramKeys": [] - } - } - }, - "/toolbox/device/zone/options": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统可用时区选项", - "consumes": [ - "application/json" - ], - "tags": [ - "Device" - ], - "summary": "list time zone options", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "Array" - } - } - } - } - }, - "/toolbox/fail2ban/base": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 Fail2ban 基础信息", - "tags": [ - "Fail2ban" - ], - "summary": "Load fail2ban base info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.Fail2BanBaseInfo" - } - } - } - } - }, - "/toolbox/fail2ban/load/conf": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 fail2ban 配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Fail2ban" - ], - "summary": "Load fail2ban conf", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/toolbox/fail2ban/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 Fail2ban 状态", - "consumes": [ - "application/json" - ], - "tags": [ - "Fail2ban" - ], - "summary": "Operate fail2ban", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Operate" - } - } - ], - "responses": {}, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operation" - ], - "formatEN": "[operation] Fail2ban", - "formatZH": "[operation] Fail2ban", - "paramKeys": [] - } - } - }, - "/toolbox/fail2ban/operate/sshd": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "配置 sshd", - "consumes": [ - "application/json" - ], - "tags": [ - "Fail2ban" - ], - "summary": "Operate sshd of fail2ban", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Operate" - } - } - ], - "responses": {} - } - }, - "/toolbox/fail2ban/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 Fail2ban ip", - "consumes": [ - "application/json" - ], - "tags": [ - "Fail2ban" - ], - "summary": "Page fail2ban ip list", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Fail2BanSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "Array" - } - } - } - } - }, - "/toolbox/fail2ban/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 Fail2ban 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Fail2ban" - ], - "summary": "Update fail2ban conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Fail2BanUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "key", - "value" - ], - "formatEN": "update fail2ban conf [key] =\u003e [value]", - "formatZH": "修改 Fail2ban 配置 [key] =\u003e [value]", - "paramKeys": [] - } - } - }, - "/toolbox/fail2ban/update/byconf": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过文件修改 fail2ban 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Fail2ban" - ], - "summary": "Update fail2ban conf by file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.UpdateByFile" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/toolbox/ftp": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建 FTP 账户", - "consumes": [ - "application/json" - ], - "tags": [ - "FTP" - ], - "summary": "Create FTP user", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.FtpCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "user", - "path" - ], - "formatEN": "create FTP [user][path]", - "formatZH": "创建 FTP 账户 [user][path]", - "paramKeys": [] - } - } - }, - "/toolbox/ftp/base": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 FTP 基础信息", - "tags": [ - "FTP" - ], - "summary": "Load FTP base info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.FtpBaseInfo" - } - } - } - } - }, - "/toolbox/ftp/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除 FTP 账户", - "consumes": [ - "application/json" - ], - "tags": [ - "FTP" - ], - "summary": "Delete FTP user", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDeleteReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "ftps", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "user", - "output_value": "users" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete FTP users [users]", - "formatZH": "删除 FTP 账户 [users]", - "paramKeys": [] - } - } - }, - "/toolbox/ftp/log/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 FTP 操作日志", - "consumes": [ - "application/json" - ], - "tags": [ - "FTP" - ], - "summary": "Load FTP operation log", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.FtpLogSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/toolbox/ftp/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 FTP 状态", - "consumes": [ - "application/json" - ], - "tags": [ - "FTP" - ], - "summary": "Operate FTP", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Operate" - } - } - ], - "responses": {}, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operation" - ], - "formatEN": "[operation] FTP", - "formatZH": "[operation] FTP", - "paramKeys": [] - } - } - }, - "/toolbox/ftp/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 FTP 账户列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "FTP" - ], - "summary": "Page FTP user", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/toolbox/ftp/sync": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "同步 FTP 账户", - "consumes": [ - "application/json" - ], - "tags": [ - "FTP" - ], - "summary": "Sync FTP user", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDeleteReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "sync FTP users", - "formatZH": "同步 FTP 账户", - "paramKeys": [] - } - } - }, - "/toolbox/ftp/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 FTP 账户", - "consumes": [ - "application/json" - ], - "tags": [ - "FTP" - ], - "summary": "Update FTP user", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.FtpUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "user", - "path" - ], - "formatEN": "update FTP [user][path]", - "formatZH": "修改 FTP 账户 [user][path]", - "paramKeys": [] - } - } - }, - "/toolbox/scan": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "扫描系统垃圾文件", - "tags": [ - "Device" - ], - "summary": "Scan system", - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "scan System Junk Files", - "formatZH": "扫描系统垃圾文件", - "paramKeys": [] - } - } - }, - "/websites": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建网站", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Create website", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "primaryDomain" - ], - "formatEN": "Create website [primaryDomain]", - "formatZH": "创建网站 [primaryDomain]", - "paramKeys": [] - } - } - }, - "/websites/:id": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 id 查询网站", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Search website by id", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.WebsiteDTO" - } - } - } - } - }, - "/websites/:id/config/:type": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 id 查询网站 nginx", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Nginx" - ], - "summary": "Search website nginx by id", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.FileInfo" - } - } - } - } - }, - "/websites/:id/https": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 https 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website HTTPS" - ], - "summary": "Load https conf", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.WebsiteHTTPS" - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 https 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website HTTPS" - ], - "summary": "Update https conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteHTTPSOp" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.WebsiteHTTPS" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteId", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteId" - ], - "formatEN": "Update website https [domain] conf", - "formatZH": "更新网站 [domain] https 配置", - "paramKeys": [] - } - } - }, - "/websites/acme": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建网站 acme", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Acme" - ], - "summary": "Create website acme account", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteAcmeAccountCreate" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.WebsiteAcmeAccountDTO" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "email" - ], - "formatEN": "Create website acme [email]", - "formatZH": "创建网站 acme [email]", - "paramKeys": [] - } - } - }, - "/websites/acme/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除网站 acme", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Acme" - ], - "summary": "Delete website acme account", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteResourceReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_acme_accounts", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "email", - "output_value": "email" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Delete website acme [email]", - "formatZH": "删除网站 acme [email]", - "paramKeys": [] - } - } - }, - "/websites/acme/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站 acme 列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Acme" - ], - "summary": "Page website acme accounts", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PageInfo" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/websites/auths": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取密码访问配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Get AuthBasic conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxAuthReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/auths/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新密码访问配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Get AuthBasic conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxAuthUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/ca": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建网站 ca", - "consumes": [ - "application/json" - ], - "tags": [ - "Website CA" - ], - "summary": "Create website ca", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteCACreate" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/request.WebsiteCACreate" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Create website ca [name]", - "formatZH": "创建网站 ca [name]", - "paramKeys": [] - } - } - }, - "/websites/ca/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除网站 ca", - "consumes": [ - "application/json" - ], - "tags": [ - "Website CA" - ], - "summary": "Delete website ca", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteCommonReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_cas", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Delete website ca [name]", - "formatZH": "删除网站 ca [name]", - "paramKeys": [] - } - } - }, - "/websites/ca/download": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "下载 CA 证书文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Website CA" - ], - "summary": "Download CA file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteResourceReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_cas", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "download ca file [name]", - "formatZH": "下载 CA 证书文件 [name]", - "paramKeys": [] - } - } - }, - "/websites/ca/obtain": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "自签 SSL 证书", - "consumes": [ - "application/json" - ], - "tags": [ - "Website CA" - ], - "summary": "Obtain SSL", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteCAObtain" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_cas", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Obtain SSL [name]", - "formatZH": "自签 SSL 证书 [name]", - "paramKeys": [] - } - } - }, - "/websites/ca/renew": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "续签 SSL 证书", - "consumes": [ - "application/json" - ], - "tags": [ - "Website CA" - ], - "summary": "Obtain SSL", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteCAObtain" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_cas", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Obtain SSL [name]", - "formatZH": "自签 SSL 证书 [name]", - "paramKeys": [] - } - } - }, - "/websites/ca/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站 ca 列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Website CA" - ], - "summary": "Page website ca", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteCASearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/websites/ca/{id}": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站 ca", - "consumes": [ - "application/json" - ], - "tags": [ - "Website CA" - ], - "summary": "Get website ca", - "parameters": [ - { - "type": "integer", - "description": "id", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.WebsiteCADTO" - } - } - } - } - }, - "/websites/check": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "网站创建前检查", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Check before create website", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteInstallCheckReq" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/response.WebsitePreInstallCheck" - } - } - } - } - } - }, - "/websites/config": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 nginx 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Nginx" - ], - "summary": "Load nginx conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxScopeReq" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.WebsiteNginxConfig" - } - } - } - } - }, - "/websites/config/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 nginx 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Nginx" - ], - "summary": "Update nginx conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxConfigUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteId", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteId" - ], - "formatEN": "Nginx conf update [domain]", - "formatZH": "nginx 配置修改 [domain]", - "paramKeys": [] - } - } - }, - "/websites/default/html/:type": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取默认 html", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Get default html", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.FileInfo" - } - } - } - } - }, - "/websites/default/html/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新默认 html", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update default html", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteHtmlUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type" - ], - "formatEN": "Update default html", - "formatZH": "更新默认 html", - "paramKeys": [] - } - } - }, - "/websites/default/server": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作网站日志", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Change default server", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteDefaultUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id", - "operate" - ], - "formatEN": "Change default server =\u003e [domain]", - "formatZH": "修改默认 server =\u003e [domain]", - "paramKeys": [] - } - } - }, - "/websites/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除网站", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Delete website", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Delete website [domain]", - "formatZH": "删除网站 [domain]", - "paramKeys": [] - } - } - }, - "/websites/dir": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站目录配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Get website dir", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteCommonReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/dir/permission": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新网站目录权限", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update Site Dir permission", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteUpdateDirPermission" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Update domain [domain] dir permission", - "formatZH": "更新网站 [domain] 目录权限", - "paramKeys": [] - } - } - }, - "/websites/dir/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新网站目录", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update Site Dir", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteUpdateDir" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Update domain [domain] dir", - "formatZH": "更新网站 [domain] 目录", - "paramKeys": [] - } - } - }, - "/websites/dns": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建网站 dns", - "consumes": [ - "application/json" - ], - "tags": [ - "Website DNS" - ], - "summary": "Create website dns account", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteDnsAccountCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Create website dns [name]", - "formatZH": "创建网站 dns [name]", - "paramKeys": [] - } - } - }, - "/websites/dns/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除网站 dns", - "consumes": [ - "application/json" - ], - "tags": [ - "Website DNS" - ], - "summary": "Delete website dns account", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteResourceReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_dns_accounts", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Delete website dns [name]", - "formatZH": "删除网站 dns [name]", - "paramKeys": [] - } - } - }, - "/websites/dns/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站 dns 列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Website DNS" - ], - "summary": "Page website dns accounts", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PageInfo" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/websites/dns/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新网站 dns", - "consumes": [ - "application/json" - ], - "tags": [ - "Website DNS" - ], - "summary": "Update website dns account", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteDnsAccountUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Update website dns [name]", - "formatZH": "更新网站 dns [name]", - "paramKeys": [] - } - } - }, - "/websites/domains": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建网站域名", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Domain" - ], - "summary": "Create website domain", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteDomainCreate" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.WebsiteDomain" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "domain" - ], - "formatEN": "Create domain [domain]", - "formatZH": "创建域名 [domain]", - "paramKeys": [] - } - } - }, - "/websites/domains/:websiteId": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过网站 id 查询域名", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Domain" - ], - "summary": "Search website domains by websiteId", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "websiteId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.WebsiteDomain" - } - } - } - } - } - }, - "/websites/domains/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除网站域名", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Domain" - ], - "summary": "Delete website domain", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteDomainDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_domains", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Delete domain [domain]", - "formatZH": "删除域名 [domain]", - "paramKeys": [] - } - } - }, - "/websites/leech": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取防盗链配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Get AntiLeech conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxCommonReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/leech/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新防盗链配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update AntiLeech", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxAntiLeechUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/list": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站列表", - "tags": [ - "Website" - ], - "summary": "List websites", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/response.WebsiteDTO" - } - } - } - } - } - }, - "/websites/log": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作网站日志", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Operate website log", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteLogReq" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.WebsiteLog" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id", - "operate" - ], - "formatEN": "[domain][operate] logs", - "formatZH": "[domain][operate] 日志", - "paramKeys": [] - } - } - }, - "/websites/nginx/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 网站 nginx 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Nginx" - ], - "summary": "Update website nginx conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteNginxUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "[domain] Nginx conf update", - "formatZH": "[domain] Nginx 配置修改", - "paramKeys": [] - } - } - }, - "/websites/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作网站", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Operate website", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteOp" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id", - "operate" - ], - "formatEN": "[operate] website [domain]", - "formatZH": "[operate] 网站 [domain]", - "paramKeys": [] - } - } - }, - "/websites/options": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站列表", - "tags": [ - "Website" - ], - "summary": "List website names", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "/websites/php/config": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 网站 PHP 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website PHP" - ], - "summary": "Update website php conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsitePHPConfigUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "[domain] PHP conf update", - "formatZH": "[domain] PHP 配置修改", - "paramKeys": [] - } - } - }, - "/websites/php/config/:id": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站 php 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Load website php conf", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.PHPConfig" - } - } - } - } - }, - "/websites/php/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 php 配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Website PHP" - ], - "summary": "Update php conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsitePHPFileUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteId", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteId" - ], - "formatEN": "Nginx conf update [domain]", - "formatZH": "php 配置修改 [domain]", - "paramKeys": [] - } - } - }, - "/websites/php/version": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "变更 php 版本", - "consumes": [ - "application/json" - ], - "tags": [ - "Website PHP" - ], - "summary": "Update php version", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsitePHPVersionReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteId", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteId" - ], - "formatEN": "php version update [domain]", - "formatZH": "php 版本变更 [domain]", - "paramKeys": [] - } - } - }, - "/websites/proxies": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取反向代理配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Get proxy conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteProxyReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/proxies/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改反向代理配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update proxy conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteProxyConfig" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Update domain [domain] proxy config", - "formatZH": "修改网站 [domain] 反向代理配置 ", - "paramKeys": [] - } - } - }, - "/websites/proxy/file": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新反向代理文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update proxy file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxProxyUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteID", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteID" - ], - "formatEN": "Nginx conf proxy file update [domain]", - "formatZH": "更新反向代理文件 [domain]", - "paramKeys": [] - } - } - }, - "/websites/redirect": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取重定向配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Get redirect conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteProxyReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/redirect/file": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新重定向文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update redirect file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxRedirectUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteID", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteID" - ], - "formatEN": "Nginx conf redirect file update [domain]", - "formatZH": "更新重定向文件 [domain]", - "paramKeys": [] - } - } - }, - "/websites/redirect/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改重定向配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update redirect conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxRedirectReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteID", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteID" - ], - "formatEN": "Update domain [domain] redirect config", - "formatZH": "修改网站 [domain] 重定向理配置 ", - "paramKeys": [] - } - } - }, - "/websites/rewrite": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取伪静态配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Get rewrite conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxRewriteReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/rewrite/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新伪静态配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update rewrite conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxRewriteUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteID", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteID" - ], - "formatEN": "Nginx conf rewrite update [domain]", - "formatZH": "伪静态配置修改 [domain]", - "paramKeys": [] - } - } - }, - "/websites/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Page websites", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/websites/ssl": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建网站 ssl", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Create website ssl", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteSSLCreate" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/request.WebsiteSSLCreate" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "primaryDomain" - ], - "formatEN": "Create website ssl [primaryDomain]", - "formatZH": "创建网站 ssl [primaryDomain]", - "paramKeys": [] - } - } - }, - "/websites/ssl/:id": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 id 查询 ssl", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Search website ssl by id", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/ssl/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除网站 ssl", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Delete website ssl", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteBatchDelReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_ssls", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "Delete ssl [domain]", - "formatZH": "删除 ssl [domain]", - "paramKeys": [] - } - } - }, - "/websites/ssl/download": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "下载证书文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Download SSL file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteResourceReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_ssls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "download ssl file [domain]", - "formatZH": "下载证书文件 [domain]", - "paramKeys": [] - } - } - }, - "/websites/ssl/obtain": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "申请证书", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Apply ssl", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteSSLApply" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_ssls", - "input_column": "id", - "input_value": "ID", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "ID" - ], - "formatEN": "apply ssl [domain]", - "formatZH": "申请证书 [domain]", - "paramKeys": [] - } - } - }, - "/websites/ssl/resolve": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "解析网站 ssl", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Resolve website ssl", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteDNSReq" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/response.WebsiteDNSRes" - } - } - } - } - } - }, - "/websites/ssl/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站 ssl 列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Page website ssl", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteSSLSearch" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/ssl/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 ssl", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Update ssl", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteSSLUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_ssls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Update ssl config [domain]", - "formatZH": "更新证书设置 [domain]", - "paramKeys": [] - } - } - }, - "/websites/ssl/upload": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "上传 ssl", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Upload ssl", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteSSLUpload" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type" - ], - "formatEN": "Upload ssl [type]", - "formatZH": "上传 ssl [type]", - "paramKeys": [] - } - } - }, - "/websites/ssl/website/:websiteId": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过网站 id 查询 ssl", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Search website ssl by website id", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "websiteId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新网站", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update website", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "primaryDomain" - ], - "formatEN": "Update website [primaryDomain]", - "formatZH": "更新网站 [primaryDomain]", - "paramKeys": [] - } - } - } - }, - "definitions": { - "dto.AddrRuleOperate": { - "type": "object", - "required": [ - "address", - "operation", - "strategy" - ], - "properties": { - "address": { - "type": "string" - }, - "description": { - "type": "string" - }, - "operation": { - "type": "string", - "enum": [ - "add", - "remove" - ] - }, - "strategy": { - "type": "string", - "enum": [ - "accept", - "drop" - ] - } - } - }, - "dto.AddrRuleUpdate": { - "type": "object", - "properties": { - "newRule": { - "$ref": "#/definitions/dto.AddrRuleOperate" - }, - "oldRule": { - "$ref": "#/definitions/dto.AddrRuleOperate" - } - } - }, - "dto.AppInstallInfo": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "key": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "dto.AppResource": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "dto.AppVersion": { - "type": "object", - "properties": { - "detailId": { - "type": "integer" - }, - "dockerCompose": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.BackupInfo": { - "type": "object", - "properties": { - "backupPath": { - "type": "string" - }, - "bucket": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "vars": { - "type": "string" - } - } - }, - "dto.BackupOperate": { - "type": "object", - "required": [ - "type", - "vars" - ], - "properties": { - "accessKey": { - "type": "string" - }, - "backupPath": { - "type": "string" - }, - "bucket": { - "type": "string" - }, - "credential": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "vars": { - "type": "string" - } - } - }, - "dto.BackupSearchFile": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string" - } - } - }, - "dto.BatchDelete": { - "type": "object", - "required": [ - "names" - ], - "properties": { - "force": { - "type": "boolean" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "dto.BatchDeleteReq": { - "type": "object", - "required": [ - "ids" - ], - "properties": { - "ids": { - "type": "array", - "items": { - "type": "integer" - } - } - } - }, - "dto.BatchRuleOperate": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "rules": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.PortRuleOperate" - } - }, - "type": { - "type": "string" - } - } - }, - "dto.BindInfo": { - "type": "object", - "required": [ - "bindAddress", - "ipv6" - ], - "properties": { - "bindAddress": { - "type": "string" - }, - "ipv6": { - "type": "string", - "enum": [ - "enable", - "disable" - ] - } - } - }, - "dto.BindUser": { - "type": "object", - "required": [ - "database", - "db", - "password", - "permission", - "username" - ], - "properties": { - "database": { - "type": "string" - }, - "db": { - "type": "string" - }, - "password": { - "type": "string" - }, - "permission": { - "type": "string" - }, - "username": { - "type": "string" - } - } - }, - "dto.CaptchaResponse": { - "type": "object", - "properties": { - "captchaID": { - "type": "string" - }, - "imagePath": { - "type": "string" - } - } - }, - "dto.ChangeDBInfo": { - "type": "object", - "required": [ - "database", - "from", - "type", - "value" - ], - "properties": { - "database": { - "type": "string" - }, - "from": { - "type": "string", - "enum": [ - "local", - "remote" - ] - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string", - "enum": [ - "mysql", - "mariadb", - "postgresql" - ] - }, - "value": { - "type": "string" - } - } - }, - "dto.ChangeHostGroup": { - "type": "object", - "required": [ - "groupID", - "id" - ], - "properties": { - "groupID": { - "type": "integer" - }, - "id": { - "type": "integer" - } - } - }, - "dto.ChangePasswd": { - "type": "object", - "properties": { - "passwd": { - "type": "string" - }, - "user": { - "type": "string" - } - } - }, - "dto.ChangeRedisPass": { - "type": "object", - "required": [ - "database" - ], - "properties": { - "database": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "dto.ClamBaseInfo": { - "type": "object", - "properties": { - "freshIsActive": { - "type": "boolean" - }, - "freshIsExist": { - "type": "boolean" - }, - "freshVersion": { - "type": "string" - }, - "isActive": { - "type": "boolean" - }, - "isExist": { - "type": "boolean" - }, - "version": { - "type": "string" - } - } - }, - "dto.ClamCreate": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "infectedDir": { - "type": "string" - }, - "infectedStrategy": { - "type": "string" - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - }, - "spec": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "dto.ClamDelete": { - "type": "object", - "required": [ - "ids" - ], - "properties": { - "ids": { - "type": "array", - "items": { - "type": "integer" - } - }, - "removeInfected": { - "type": "boolean" - }, - "removeRecord": { - "type": "boolean" - } - } - }, - "dto.ClamFileReq": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string" - }, - "tail": { - "type": "string" - } - } - }, - "dto.ClamLogReq": { - "type": "object", - "properties": { - "clamName": { - "type": "string" - }, - "recordName": { - "type": "string" - }, - "tail": { - "type": "string" - } - } - }, - "dto.ClamLogSearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "clamID": { - "type": "integer" - }, - "endTime": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "startTime": { - "type": "string" - } - } - }, - "dto.ClamUpdate": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "infectedDir": { - "type": "string" - }, - "infectedStrategy": { - "type": "string" - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - }, - "spec": { - "type": "string" - } - } - }, - "dto.ClamUpdateStatus": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "status": { - "type": "string" - } - } - }, - "dto.Clean": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "size": { - "type": "integer" - }, - "treeType": { - "type": "string" - } - } - }, - "dto.CleanLog": { - "type": "object", - "required": [ - "logType" - ], - "properties": { - "logType": { - "type": "string", - "enum": [ - "login", - "operation" - ] - } - } - }, - "dto.CommandInfo": { - "type": "object", - "properties": { - "command": { - "type": "string" - }, - "groupBelong": { - "type": "string" - }, - "groupID": { - "type": "integer" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, - "dto.CommandOperate": { - "type": "object", - "required": [ - "command", - "name" - ], - "properties": { - "command": { - "type": "string" - }, - "groupBelong": { - "type": "string" - }, - "groupID": { - "type": "integer" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, - "dto.CommonBackup": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "detailName": { - "type": "string" - }, - "name": { - "type": "string" - }, - "secret": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "app", - "mysql", - "mariadb", - "redis", - "website", - "postgresql" - ] - } - } - }, - "dto.CommonRecover": { - "type": "object", - "required": [ - "source", - "type" - ], - "properties": { - "detailName": { - "type": "string" - }, - "file": { - "type": "string" - }, - "name": { - "type": "string" - }, - "secret": { - "type": "string" - }, - "source": { - "type": "string", - "enum": [ - "OSS", - "S3", - "SFTP", - "MINIO", - "LOCAL", - "COS", - "KODO", - "OneDrive", - "WebDAV" - ] - }, - "type": { - "type": "string", - "enum": [ - "app", - "mysql", - "mariadb", - "redis", - "website", - "postgresql" - ] - } - } - }, - "dto.ComposeCreate": { - "type": "object", - "required": [ - "from" - ], - "properties": { - "file": { - "type": "string" - }, - "from": { - "type": "string", - "enum": [ - "edit", - "path", - "template" - ] - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - }, - "template": { - "type": "integer" - } - } - }, - "dto.ComposeOperation": { - "type": "object", - "required": [ - "name", - "operation", - "path" - ], - "properties": { - "name": { - "type": "string" - }, - "operation": { - "type": "string", - "enum": [ - "start", - "stop", - "down" - ] - }, - "path": { - "type": "string" - }, - "withFile": { - "type": "boolean" - } - } - }, - "dto.ComposeTemplateCreate": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "content": { - "type": "string" - }, - "description": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "dto.ComposeTemplateInfo": { - "type": "object", - "properties": { - "content": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, - "dto.ComposeTemplateUpdate": { - "type": "object", - "properties": { - "content": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "integer" - } - } - }, - "dto.ComposeUpdate": { - "type": "object", - "required": [ - "content", - "name", - "path" - ], - "properties": { - "content": { - "type": "string" - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - } - } - }, - "dto.ContainerCommit": { - "type": "object", - "required": [ - "containerID" - ], - "properties": { - "author": { - "type": "string" - }, - "comment": { - "type": "string" - }, - "containerID": { - "type": "string" - }, - "containerName": { - "type": "string" - }, - "newImageName": { - "type": "string" - }, - "pause": { - "type": "boolean" - } - } - }, - "dto.ContainerListStats": { - "type": "object", - "properties": { - "containerID": { - "type": "string" - }, - "cpuPercent": { - "type": "number" - }, - "cpuTotalUsage": { - "type": "integer" - }, - "memoryCache": { - "type": "integer" - }, - "memoryLimit": { - "type": "integer" - }, - "memoryPercent": { - "type": "number" - }, - "memoryUsage": { - "type": "integer" - }, - "percpuUsage": { - "type": "integer" - }, - "systemUsage": { - "type": "integer" - } - } - }, - "dto.ContainerOperate": { - "type": "object", - "required": [ - "image", - "name" - ], - "properties": { - "autoRemove": { - "type": "boolean" - }, - "cmd": { - "type": "array", - "items": { - "type": "string" - } - }, - "containerID": { - "type": "string" - }, - "cpuShares": { - "type": "integer" - }, - "entrypoint": { - "type": "array", - "items": { - "type": "string" - } - }, - "env": { - "type": "array", - "items": { - "type": "string" - } - }, - "exposedPorts": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.PortHelper" - } - }, - "forcePull": { - "type": "boolean" - }, - "image": { - "type": "string" - }, - "ipv4": { - "type": "string" - }, - "ipv6": { - "type": "string" - }, - "labels": { - "type": "array", - "items": { - "type": "string" - } - }, - "memory": { - "type": "number" - }, - "name": { - "type": "string" - }, - "nanoCPUs": { - "type": "number" - }, - "network": { - "type": "string" - }, - "openStdin": { - "type": "boolean" - }, - "privileged": { - "type": "boolean" - }, - "publishAllPorts": { - "type": "boolean" - }, - "restartPolicy": { - "type": "string" - }, - "tty": { - "type": "boolean" - }, - "volumes": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.VolumeHelper" - } - } - } - }, - "dto.ContainerOperation": { - "type": "object", - "required": [ - "names", - "operation" - ], - "properties": { - "names": { - "type": "array", - "items": { - "type": "string" - } - }, - "operation": { - "type": "string", - "enum": [ - "start", - "stop", - "restart", - "kill", - "pause", - "unpause", - "remove" - ] - } - } - }, - "dto.ContainerPrune": { - "type": "object", - "required": [ - "pruneType" - ], - "properties": { - "pruneType": { - "type": "string", - "enum": [ - "container", - "image", - "volume", - "network", - "buildcache" - ] - }, - "withTagAll": { - "type": "boolean" - } - } - }, - "dto.ContainerPruneReport": { - "type": "object", - "properties": { - "deletedNumber": { - "type": "integer" - }, - "spaceReclaimed": { - "type": "integer" - } - } - }, - "dto.ContainerRename": { - "type": "object", - "required": [ - "name", - "newName" - ], - "properties": { - "name": { - "type": "string" - }, - "newName": { - "type": "string" - } - } - }, - "dto.ContainerStats": { - "type": "object", - "properties": { - "cache": { - "type": "number" - }, - "cpuPercent": { - "type": "number" - }, - "ioRead": { - "type": "number" - }, - "ioWrite": { - "type": "number" - }, - "memory": { - "type": "number" - }, - "networkRX": { - "type": "number" - }, - "networkTX": { - "type": "number" - }, - "shotTime": { - "type": "string" - } - } - }, - "dto.ContainerUpgrade": { - "type": "object", - "required": [ - "image", - "name" - ], - "properties": { - "forcePull": { - "type": "boolean" - }, - "image": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "dto.CronjobBatchDelete": { - "type": "object", - "required": [ - "ids" - ], - "properties": { - "cleanData": { - "type": "boolean" - }, - "ids": { - "type": "array", - "items": { - "type": "integer" - } - } - } - }, - "dto.CronjobClean": { - "type": "object", - "required": [ - "cronjobID" - ], - "properties": { - "cleanData": { - "type": "boolean" - }, - "cronjobID": { - "type": "integer" - }, - "isDelete": { - "type": "boolean" - } - } - }, - "dto.CronjobCreate": { - "type": "object", - "required": [ - "name", - "spec", - "type" - ], - "properties": { - "appID": { - "type": "string" - }, - "backupAccounts": { - "type": "string" - }, - "command": { - "type": "string" - }, - "containerName": { - "type": "string" - }, - "dbName": { - "type": "string" - }, - "dbType": { - "type": "string" - }, - "defaultDownload": { - "type": "string" - }, - "exclusionRules": { - "type": "string" - }, - "name": { - "type": "string" - }, - "retainCopies": { - "type": "integer", - "minimum": 1 - }, - "script": { - "type": "string" - }, - "secret": { - "type": "string" - }, - "sourceDir": { - "type": "string" - }, - "spec": { - "type": "string" - }, - "type": { - "type": "string" - }, - "url": { - "type": "string" - }, - "website": { - "type": "string" - } - } - }, - "dto.CronjobDownload": { - "type": "object", - "required": [ - "backupAccountID", - "recordID" - ], - "properties": { - "backupAccountID": { - "type": "integer" - }, - "recordID": { - "type": "integer" - } - } - }, - "dto.CronjobUpdate": { - "type": "object", - "required": [ - "id", - "name", - "spec" - ], - "properties": { - "appID": { - "type": "string" - }, - "backupAccounts": { - "type": "string" - }, - "command": { - "type": "string" - }, - "containerName": { - "type": "string" - }, - "dbName": { - "type": "string" - }, - "dbType": { - "type": "string" - }, - "defaultDownload": { - "type": "string" - }, - "exclusionRules": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "retainCopies": { - "type": "integer", - "minimum": 1 - }, - "script": { - "type": "string" - }, - "secret": { - "type": "string" - }, - "sourceDir": { - "type": "string" - }, - "spec": { - "type": "string" - }, - "url": { - "type": "string" - }, - "website": { - "type": "string" - } - } - }, - "dto.CronjobUpdateStatus": { - "type": "object", - "required": [ - "id", - "status" - ], - "properties": { - "id": { - "type": "integer" - }, - "status": { - "type": "string" - } - } - }, - "dto.DBBaseInfo": { - "type": "object", - "properties": { - "containerName": { - "type": "string" - }, - "name": { - "type": "string" - }, - "port": { - "type": "integer" - } - } - }, - "dto.DBConfUpdateByFile": { - "type": "object", - "required": [ - "database", - "type" - ], - "properties": { - "database": { - "type": "string" - }, - "file": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "mysql", - "mariadb", - "postgresql", - "redis" - ] - } - } - }, - "dto.DaemonJsonConf": { - "type": "object", - "properties": { - "cgroupDriver": { - "type": "string" - }, - "experimental": { - "type": "boolean" - }, - "fixedCidrV6": { - "type": "string" - }, - "insecureRegistries": { - "type": "array", - "items": { - "type": "string" - } - }, - "ip6Tables": { - "type": "boolean" - }, - "iptables": { - "type": "boolean" - }, - "ipv6": { - "type": "boolean" - }, - "isSwarm": { - "type": "boolean" - }, - "liveRestore": { - "type": "boolean" - }, - "logMaxFile": { - "type": "string" - }, - "logMaxSize": { - "type": "string" - }, - "registryMirrors": { - "type": "array", - "items": { - "type": "string" - } - }, - "status": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.DaemonJsonUpdateByFile": { - "type": "object", - "properties": { - "file": { - "type": "string" - } - } - }, - "dto.DashboardBase": { - "type": "object", - "properties": { - "appInstalledNumber": { - "type": "integer" - }, - "cpuCores": { - "type": "integer" - }, - "cpuLogicalCores": { - "type": "integer" - }, - "cpuModelName": { - "type": "string" - }, - "cronjobNumber": { - "type": "integer" - }, - "currentInfo": { - "$ref": "#/definitions/dto.DashboardCurrent" - }, - "databaseNumber": { - "type": "integer" - }, - "hostname": { - "type": "string" - }, - "kernelArch": { - "type": "string" - }, - "kernelVersion": { - "type": "string" - }, - "os": { - "type": "string" - }, - "platform": { - "type": "string" - }, - "platformFamily": { - "type": "string" - }, - "platformVersion": { - "type": "string" - }, - "virtualizationSystem": { - "type": "string" - }, - "websiteNumber": { - "type": "integer" - } - } - }, - "dto.DashboardCurrent": { - "type": "object", - "properties": { - "cpuPercent": { - "type": "array", - "items": { - "type": "number" - } - }, - "cpuTotal": { - "type": "integer" - }, - "cpuUsed": { - "type": "number" - }, - "cpuUsedPercent": { - "type": "number" - }, - "diskData": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.DiskInfo" - } - }, - "gpuData": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.GPUInfo" - } - }, - "ioCount": { - "type": "integer" - }, - "ioReadBytes": { - "type": "integer" - }, - "ioReadTime": { - "type": "integer" - }, - "ioWriteBytes": { - "type": "integer" - }, - "ioWriteTime": { - "type": "integer" - }, - "load1": { - "type": "number" - }, - "load15": { - "type": "number" - }, - "load5": { - "type": "number" - }, - "loadUsagePercent": { - "type": "number" - }, - "memoryAvailable": { - "type": "integer" - }, - "memoryTotal": { - "type": "integer" - }, - "memoryUsed": { - "type": "integer" - }, - "memoryUsedPercent": { - "type": "number" - }, - "netBytesRecv": { - "type": "integer" - }, - "netBytesSent": { - "type": "integer" - }, - "procs": { - "type": "integer" - }, - "shotTime": { - "type": "string" - }, - "swapMemoryAvailable": { - "type": "integer" - }, - "swapMemoryTotal": { - "type": "integer" - }, - "swapMemoryUsed": { - "type": "integer" - }, - "swapMemoryUsedPercent": { - "type": "number" - }, - "timeSinceUptime": { - "type": "string" - }, - "uptime": { - "type": "integer" - } - } - }, - "dto.DatabaseCreate": { - "type": "object", - "required": [ - "from", - "name", - "type", - "username", - "version" - ], - "properties": { - "address": { - "type": "string" - }, - "clientCert": { - "type": "string" - }, - "clientKey": { - "type": "string" - }, - "description": { - "type": "string" - }, - "from": { - "type": "string", - "enum": [ - "local", - "remote" - ] - }, - "name": { - "type": "string", - "maxLength": 256 - }, - "password": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "rootCert": { - "type": "string" - }, - "skipVerify": { - "type": "boolean" - }, - "ssl": { - "type": "boolean" - }, - "type": { - "type": "string" - }, - "username": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.DatabaseDelete": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "deleteBackup": { - "type": "boolean" - }, - "forceDelete": { - "type": "boolean" - }, - "id": { - "type": "integer" - } - } - }, - "dto.DatabaseInfo": { - "type": "object", - "properties": { - "address": { - "type": "string" - }, - "clientCert": { - "type": "string" - }, - "clientKey": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "from": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string", - "maxLength": 256 - }, - "password": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "rootCert": { - "type": "string" - }, - "skipVerify": { - "type": "boolean" - }, - "ssl": { - "type": "boolean" - }, - "type": { - "type": "string" - }, - "username": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.DatabaseItem": { - "type": "object", - "properties": { - "database": { - "type": "string" - }, - "from": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, - "dto.DatabaseOption": { - "type": "object", - "properties": { - "address": { - "type": "string" - }, - "database": { - "type": "string" - }, - "from": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.DatabaseSearch": { - "type": "object", - "required": [ - "order", - "orderBy", - "page", - "pageSize" - ], - "properties": { - "info": { - "type": "string" - }, - "order": { - "type": "string", - "enum": [ - "null", - "ascending", - "descending" - ] - }, - "orderBy": { - "type": "string", - "enum": [ - "name", - "created_at" - ] - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "type": { - "type": "string" - } - } - }, - "dto.DatabaseUpdate": { - "type": "object", - "required": [ - "type", - "username", - "version" - ], - "properties": { - "address": { - "type": "string" - }, - "clientCert": { - "type": "string" - }, - "clientKey": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "password": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "rootCert": { - "type": "string" - }, - "skipVerify": { - "type": "boolean" - }, - "ssl": { - "type": "boolean" - }, - "type": { - "type": "string" - }, - "username": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.DeviceBaseInfo": { - "type": "object", - "properties": { - "dns": { - "type": "array", - "items": { - "type": "string" - } - }, - "hostname": { - "type": "string" - }, - "hosts": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.HostHelper" - } - }, - "localTime": { - "type": "string" - }, - "maxSize": { - "type": "integer" - }, - "ntp": { - "type": "string" - }, - "swapDetails": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.SwapHelper" - } - }, - "swapMemoryAvailable": { - "type": "integer" - }, - "swapMemoryTotal": { - "type": "integer" - }, - "swapMemoryUsed": { - "type": "integer" - }, - "timeZone": { - "type": "string" - }, - "user": { - "type": "string" - } - } - }, - "dto.DiskInfo": { - "type": "object", - "properties": { - "device": { - "type": "string" - }, - "free": { - "type": "integer" - }, - "inodesFree": { - "type": "integer" - }, - "inodesTotal": { - "type": "integer" - }, - "inodesUsed": { - "type": "integer" - }, - "inodesUsedPercent": { - "type": "number" - }, - "path": { - "type": "string" - }, - "total": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "used": { - "type": "integer" - }, - "usedPercent": { - "type": "number" - } - } - }, - "dto.DockerOperation": { - "type": "object", - "required": [ - "operation" - ], - "properties": { - "operation": { - "type": "string", - "enum": [ - "start", - "restart", - "stop" - ] - } - } - }, - "dto.DownloadRecord": { - "type": "object", - "required": [ - "fileDir", - "fileName", - "source" - ], - "properties": { - "fileDir": { - "type": "string" - }, - "fileName": { - "type": "string" - }, - "source": { - "type": "string", - "enum": [ - "OSS", - "S3", - "SFTP", - "MINIO", - "LOCAL", - "COS", - "KODO", - "OneDrive", - "WebDAV" - ] - } - } - }, - "dto.Fail2BanBaseInfo": { - "type": "object", - "properties": { - "banAction": { - "type": "string" - }, - "banTime": { - "type": "string" - }, - "findTime": { - "type": "string" - }, - "isActive": { - "type": "boolean" - }, - "isEnable": { - "type": "boolean" - }, - "isExist": { - "type": "boolean" - }, - "logPath": { - "type": "string" - }, - "maxRetry": { - "type": "integer" - }, - "port": { - "type": "integer" - }, - "version": { - "type": "string" - } - } - }, - "dto.Fail2BanSearch": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "banned", - "ignore" - ] - } - } - }, - "dto.Fail2BanUpdate": { - "type": "object", - "required": [ - "key" - ], - "properties": { - "key": { - "type": "string", - "enum": [ - "port", - "bantime", - "findtime", - "maxretry", - "banaction", - "logpath", - "port" - ] - }, - "value": { - "type": "string" - } - } - }, - "dto.FirewallBaseInfo": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "pingStatus": { - "type": "string" - }, - "status": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.FirewallOperation": { - "type": "object", - "required": [ - "operation" - ], - "properties": { - "operation": { - "type": "string", - "enum": [ - "start", - "stop", - "restart", - "disablePing", - "enablePing" - ] - } - } - }, - "dto.ForBuckets": { - "type": "object", - "required": [ - "credential", - "type", - "vars" - ], - "properties": { - "accessKey": { - "type": "string" - }, - "credential": { - "type": "string" - }, - "type": { - "type": "string" - }, - "vars": { - "type": "string" - } - } - }, - "dto.ForwardRuleOperate": { - "type": "object", - "properties": { - "rules": { - "type": "array", - "items": { - "type": "object", - "required": [ - "operation", - "port", - "protocol", - "targetPort" - ], - "properties": { - "num": { - "type": "string" - }, - "operation": { - "type": "string", - "enum": [ - "add", - "remove" - ] - }, - "port": { - "type": "string" - }, - "protocol": { - "type": "string", - "enum": [ - "tcp", - "udp", - "tcp/udp" - ] - }, - "targetIP": { - "type": "string" - }, - "targetPort": { - "type": "string" - } - } - } - } - } - }, - "dto.FtpBaseInfo": { - "type": "object", - "properties": { - "isActive": { - "type": "boolean" - }, - "isExist": { - "type": "boolean" - } - } - }, - "dto.FtpCreate": { - "type": "object", - "required": [ - "password", - "path", - "user" - ], - "properties": { - "description": { - "type": "string" - }, - "password": { - "type": "string" - }, - "path": { - "type": "string" - }, - "user": { - "type": "string" - } - } - }, - "dto.FtpLogSearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "operation": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "user": { - "type": "string" - } - } - }, - "dto.FtpUpdate": { - "type": "object", - "required": [ - "password", - "path" - ], - "properties": { - "description": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "password": { - "type": "string" - }, - "path": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "dto.GPUInfo": { - "type": "object", - "properties": { - "fanSpeed": { - "type": "string" - }, - "gpuUtil": { - "type": "string" - }, - "index": { - "type": "integer" - }, - "maxPowerLimit": { - "type": "string" - }, - "memTotal": { - "type": "string" - }, - "memUsed": { - "type": "string" - }, - "memoryUsage": { - "type": "string" - }, - "performanceState": { - "type": "string" - }, - "powerDraw": { - "type": "string" - }, - "powerUsage": { - "type": "string" - }, - "productName": { - "type": "string" - }, - "temperature": { - "type": "string" - } - } - }, - "dto.GenerateLoad": { - "type": "object", - "required": [ - "encryptionMode" - ], - "properties": { - "encryptionMode": { - "type": "string", - "enum": [ - "rsa", - "ed25519", - "ecdsa", - "dsa" - ] - } - } - }, - "dto.GenerateSSH": { - "type": "object", - "required": [ - "encryptionMode" - ], - "properties": { - "encryptionMode": { - "type": "string", - "enum": [ - "rsa", - "ed25519", - "ecdsa", - "dsa" - ] - }, - "password": { - "type": "string" - } - } - }, - "dto.GroupCreate": { - "type": "object", - "required": [ - "name", - "type" - ], - "properties": { - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "dto.GroupInfo": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "isDefault": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "dto.GroupSearch": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string" - } - } - }, - "dto.GroupUpdate": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "id": { - "type": "integer" - }, - "isDefault": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "dto.HostConnTest": { - "type": "object", - "required": [ - "addr", - "port", - "user" - ], - "properties": { - "addr": { - "type": "string" - }, - "authMode": { - "type": "string", - "enum": [ - "password", - "key" - ] - }, - "passPhrase": { - "type": "string" - }, - "password": { - "type": "string" - }, - "port": { - "type": "integer", - "maximum": 65535, - "minimum": 1 - }, - "privateKey": { - "type": "string" - }, - "user": { - "type": "string" - } - } - }, - "dto.HostHelper": { - "type": "object", - "properties": { - "host": { - "type": "string" - }, - "ip": { - "type": "string" - } - } - }, - "dto.HostOperate": { - "type": "object", - "required": [ - "addr", - "port", - "user" - ], - "properties": { - "addr": { - "type": "string" - }, - "authMode": { - "type": "string", - "enum": [ - "password", - "key" - ] - }, - "description": { - "type": "string" - }, - "groupID": { - "type": "integer" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "passPhrase": { - "type": "string" - }, - "password": { - "type": "string" - }, - "port": { - "type": "integer", - "maximum": 65535, - "minimum": 1 - }, - "privateKey": { - "type": "string" - }, - "rememberPassword": { - "type": "boolean" - }, - "user": { - "type": "string" - } - } - }, - "dto.HostTree": { - "type": "object", - "properties": { - "children": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.TreeChild" - } - }, - "id": { - "type": "integer" - }, - "label": { - "type": "string" - } - } - }, - "dto.ImageBuild": { - "type": "object", - "required": [ - "dockerfile", - "from", - "name" - ], - "properties": { - "dockerfile": { - "type": "string" - }, - "from": { - "type": "string" - }, - "name": { - "type": "string" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "dto.ImageInfo": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "id": { - "type": "string" - }, - "isUsed": { - "type": "boolean" - }, - "size": { - "type": "string" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "dto.ImageLoad": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "type": "string" - } - } - }, - "dto.ImagePull": { - "type": "object", - "required": [ - "imageName" - ], - "properties": { - "imageName": { - "type": "string" - }, - "repoID": { - "type": "integer" - } - } - }, - "dto.ImagePush": { - "type": "object", - "required": [ - "name", - "repoID", - "tagName" - ], - "properties": { - "name": { - "type": "string" - }, - "repoID": { - "type": "integer" - }, - "tagName": { - "type": "string" - } - } - }, - "dto.ImageRepoDelete": { - "type": "object", - "required": [ - "ids" - ], - "properties": { - "ids": { - "type": "array", - "items": { - "type": "integer" - } - } - } - }, - "dto.ImageRepoOption": { - "type": "object", - "properties": { - "downloadUrl": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, - "dto.ImageRepoUpdate": { - "type": "object", - "properties": { - "auth": { - "type": "boolean" - }, - "downloadUrl": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "password": { - "type": "string", - "maxLength": 256 - }, - "protocol": { - "type": "string" - }, - "username": { - "type": "string", - "maxLength": 256 - } - } - }, - "dto.ImageSave": { - "type": "object", - "required": [ - "name", - "path", - "tagName" - ], - "properties": { - "name": { - "type": "string" - }, - "path": { - "type": "string" - }, - "tagName": { - "type": "string" - } - } - }, - "dto.ImageTag": { - "type": "object", - "required": [ - "sourceID", - "targetName" - ], - "properties": { - "sourceID": { - "type": "string" - }, - "targetName": { - "type": "string" - } - } - }, - "dto.InspectReq": { - "type": "object", - "required": [ - "id", - "type" - ], - "properties": { - "id": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "dto.LogOption": { - "type": "object", - "properties": { - "logMaxFile": { - "type": "string" - }, - "logMaxSize": { - "type": "string" - } - } - }, - "dto.Login": { - "type": "object", - "required": [ - "authMethod", - "language", - "name", - "password" - ], - "properties": { - "authMethod": { - "type": "string", - "enum": [ - "jwt", - "session" - ] - }, - "captcha": { - "type": "string" - }, - "captchaID": { - "type": "string" - }, - "ignoreCaptcha": { - "type": "boolean" - }, - "language": { - "type": "string", - "enum": [ - "zh", - "en", - "tw" - ] - }, - "name": { - "type": "string" - }, - "password": { - "type": "string" - } - } - }, - "dto.MFALogin": { - "type": "object", - "required": [ - "code", - "name", - "password" - ], - "properties": { - "authMethod": { - "type": "string" - }, - "code": { - "type": "string" - }, - "name": { - "type": "string" - }, - "password": { - "type": "string" - } - } - }, - "dto.MfaCredential": { - "type": "object", - "required": [ - "code", - "interval", - "secret" - ], - "properties": { - "code": { - "type": "string" - }, - "interval": { - "type": "string" - }, - "secret": { - "type": "string" - } - } - }, - "dto.MonitorSearch": { - "type": "object", - "required": [ - "param" - ], - "properties": { - "endTime": { - "type": "string" - }, - "info": { - "type": "string" - }, - "param": { - "type": "string", - "enum": [ - "all", - "cpu", - "memory", - "load", - "io", - "network" - ] - }, - "startTime": { - "type": "string" - } - } - }, - "dto.MysqlDBCreate": { - "type": "object", - "required": [ - "database", - "format", - "from", - "name", - "password", - "permission", - "username" - ], - "properties": { - "database": { - "type": "string" - }, - "description": { - "type": "string" - }, - "format": { - "type": "string", - "enum": [ - "utf8mb4", - "utf8", - "gbk", - "big5" - ] - }, - "from": { - "type": "string", - "enum": [ - "local", - "remote" - ] - }, - "name": { - "type": "string" - }, - "password": { - "type": "string" - }, - "permission": { - "type": "string" - }, - "username": { - "type": "string" - } - } - }, - "dto.MysqlDBDelete": { - "type": "object", - "required": [ - "database", - "id", - "type" - ], - "properties": { - "database": { - "type": "string" - }, - "deleteBackup": { - "type": "boolean" - }, - "forceDelete": { - "type": "boolean" - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string", - "enum": [ - "mysql", - "mariadb" - ] - } - } - }, - "dto.MysqlDBDeleteCheck": { - "type": "object", - "required": [ - "database", - "id", - "type" - ], - "properties": { - "database": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string", - "enum": [ - "mysql", - "mariadb" - ] - } - } - }, - "dto.MysqlDBSearch": { - "type": "object", - "required": [ - "database", - "order", - "orderBy", - "page", - "pageSize" - ], - "properties": { - "database": { - "type": "string" - }, - "info": { - "type": "string" - }, - "order": { - "type": "string", - "enum": [ - "null", - "ascending", - "descending" - ] - }, - "orderBy": { - "type": "string", - "enum": [ - "name", - "created_at" - ] - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "dto.MysqlLoadDB": { - "type": "object", - "required": [ - "database", - "from", - "type" - ], - "properties": { - "database": { - "type": "string" - }, - "from": { - "type": "string", - "enum": [ - "local", - "remote" - ] - }, - "type": { - "type": "string", - "enum": [ - "mysql", - "mariadb" - ] - } - } - }, - "dto.MysqlOption": { - "type": "object", - "properties": { - "database": { - "type": "string" - }, - "from": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "dto.MysqlStatus": { - "type": "object", - "properties": { - "Aborted_clients": { - "type": "string" - }, - "Aborted_connects": { - "type": "string" - }, - "Bytes_received": { - "type": "string" - }, - "Bytes_sent": { - "type": "string" - }, - "Com_commit": { - "type": "string" - }, - "Com_rollback": { - "type": "string" - }, - "Connections": { - "type": "string" - }, - "Created_tmp_disk_tables": { - "type": "string" - }, - "Created_tmp_tables": { - "type": "string" - }, - "File": { - "type": "string" - }, - "Innodb_buffer_pool_pages_dirty": { - "type": "string" - }, - "Innodb_buffer_pool_read_requests": { - "type": "string" - }, - "Innodb_buffer_pool_reads": { - "type": "string" - }, - "Key_read_requests": { - "type": "string" - }, - "Key_reads": { - "type": "string" - }, - "Key_write_requests": { - "type": "string" - }, - "Key_writes": { - "type": "string" - }, - "Max_used_connections": { - "type": "string" - }, - "Open_tables": { - "type": "string" - }, - "Opened_files": { - "type": "string" - }, - "Opened_tables": { - "type": "string" - }, - "Position": { - "type": "string" - }, - "Qcache_hits": { - "type": "string" - }, - "Qcache_inserts": { - "type": "string" - }, - "Questions": { - "type": "string" - }, - "Run": { - "type": "string" - }, - "Select_full_join": { - "type": "string" - }, - "Select_range_check": { - "type": "string" - }, - "Sort_merge_passes": { - "type": "string" - }, - "Table_locks_waited": { - "type": "string" - }, - "Threads_cached": { - "type": "string" - }, - "Threads_connected": { - "type": "string" - }, - "Threads_created": { - "type": "string" - }, - "Threads_running": { - "type": "string" - }, - "Uptime": { - "type": "string" - } - } - }, - "dto.MysqlVariables": { - "type": "object", - "properties": { - "binlog_cache_size": { - "type": "string" - }, - "innodb_buffer_pool_size": { - "type": "string" - }, - "innodb_log_buffer_size": { - "type": "string" - }, - "join_buffer_size": { - "type": "string" - }, - "key_buffer_size": { - "type": "string" - }, - "long_query_time": { - "type": "string" - }, - "max_connections": { - "type": "string" - }, - "max_heap_table_size": { - "type": "string" - }, - "query_cache_size": { - "type": "string" - }, - "query_cache_type": { - "type": "string" - }, - "read_buffer_size": { - "type": "string" - }, - "read_rnd_buffer_size": { - "type": "string" - }, - "slow_query_log": { - "type": "string" - }, - "sort_buffer_size": { - "type": "string" - }, - "table_open_cache": { - "type": "string" - }, - "thread_cache_size": { - "type": "string" - }, - "thread_stack": { - "type": "string" - }, - "tmp_table_size": { - "type": "string" - } - } - }, - "dto.MysqlVariablesUpdate": { - "type": "object", - "required": [ - "database", - "type" - ], - "properties": { - "database": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "mysql", - "mariadb" - ] - }, - "variables": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.MysqlVariablesUpdateHelper" - } - } - } - }, - "dto.MysqlVariablesUpdateHelper": { - "type": "object", - "properties": { - "param": { - "type": "string" - }, - "value": {} - } - }, - "dto.NetworkCreate": { - "type": "object", - "required": [ - "driver", - "name" - ], - "properties": { - "auxAddress": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.SettingUpdate" - } - }, - "auxAddressV6": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.SettingUpdate" - } - }, - "driver": { - "type": "string" - }, - "gateway": { - "type": "string" - }, - "gatewayV6": { - "type": "string" - }, - "ipRange": { - "type": "string" - }, - "ipRangeV6": { - "type": "string" - }, - "ipv4": { - "type": "boolean" - }, - "ipv6": { - "type": "boolean" - }, - "labels": { - "type": "array", - "items": { - "type": "string" - } - }, - "name": { - "type": "string" - }, - "options": { - "type": "array", - "items": { - "type": "string" - } - }, - "subnet": { - "type": "string" - }, - "subnetV6": { - "type": "string" - } - } - }, - "dto.NginxKey": { - "type": "string", - "enum": [ - "index", - "limit-conn", - "ssl", - "cache", - "http-per", - "proxy-cache" - ], - "x-enum-varnames": [ - "Index", - "LimitConn", - "SSL", - "CACHE", - "HttpPer", - "ProxyCache" - ] - }, - "dto.OneDriveInfo": { - "type": "object", - "properties": { - "client_id": { - "type": "string" - }, - "client_secret": { - "type": "string" - }, - "redirect_uri": { - "type": "string" - } - } - }, - "dto.Operate": { - "type": "object", - "required": [ - "operation" - ], - "properties": { - "operation": { - "type": "string" - } - } - }, - "dto.OperateByID": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - } - } - }, - "dto.OperationWithName": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string" - } - } - }, - "dto.OperationWithNameAndType": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "dto.Options": { - "type": "object", - "properties": { - "option": { - "type": "string" - } - } - }, - "dto.OsInfo": { - "type": "object", - "properties": { - "diskSize": { - "type": "integer" - }, - "kernelArch": { - "type": "string" - }, - "kernelVersion": { - "type": "string" - }, - "os": { - "type": "string" - }, - "platform": { - "type": "string" - }, - "platformFamily": { - "type": "string" - } - } - }, - "dto.PageContainer": { - "type": "object", - "required": [ - "order", - "orderBy", - "page", - "pageSize", - "state" - ], - "properties": { - "excludeAppStore": { - "type": "boolean" - }, - "filters": { - "type": "string" - }, - "name": { - "type": "string" - }, - "order": { - "type": "string", - "enum": [ - "null", - "ascending", - "descending" - ] - }, - "orderBy": { - "type": "string", - "enum": [ - "name", - "state", - "created_at" - ] - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "state": { - "type": "string", - "enum": [ - "all", - "created", - "running", - "paused", - "restarting", - "removing", - "exited", - "dead" - ] - } - } - }, - "dto.PageCronjob": { - "type": "object", - "required": [ - "order", - "orderBy", - "page", - "pageSize" - ], - "properties": { - "info": { - "type": "string" - }, - "order": { - "type": "string", - "enum": [ - "null", - "ascending", - "descending" - ] - }, - "orderBy": { - "type": "string", - "enum": [ - "name", - "status", - "created_at" - ] - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "dto.PageInfo": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "dto.PageResult": { - "type": "object", - "properties": { - "items": {}, - "total": { - "type": "integer" - } - } - }, - "dto.PasswordUpdate": { - "type": "object", - "required": [ - "newPassword", - "oldPassword" - ], - "properties": { - "newPassword": { - "type": "string" - }, - "oldPassword": { - "type": "string" - } - } - }, - "dto.PortHelper": { - "type": "object", - "properties": { - "containerPort": { - "type": "string" - }, - "hostIP": { - "type": "string" - }, - "hostPort": { - "type": "string" - }, - "protocol": { - "type": "string" - } - } - }, - "dto.PortRuleOperate": { - "type": "object", - "required": [ - "operation", - "port", - "protocol", - "strategy" - ], - "properties": { - "address": { - "type": "string" - }, - "description": { - "type": "string" - }, - "operation": { - "type": "string", - "enum": [ - "add", - "remove" - ] - }, - "port": { - "type": "string" - }, - "protocol": { - "type": "string", - "enum": [ - "tcp", - "udp", - "tcp/udp" - ] - }, - "strategy": { - "type": "string", - "enum": [ - "accept", - "drop" - ] - } - } - }, - "dto.PortRuleUpdate": { - "type": "object", - "properties": { - "newRule": { - "$ref": "#/definitions/dto.PortRuleOperate" - }, - "oldRule": { - "$ref": "#/definitions/dto.PortRuleOperate" - } - } - }, - "dto.PortUpdate": { - "type": "object", - "required": [ - "serverPort" - ], - "properties": { - "serverPort": { - "type": "integer", - "maximum": 65535, - "minimum": 1 - } - } - }, - "dto.PostgresqlBindUser": { - "type": "object", - "required": [ - "database", - "name", - "password", - "username" - ], - "properties": { - "database": { - "type": "string" - }, - "name": { - "type": "string" - }, - "password": { - "type": "string" - }, - "superUser": { - "type": "boolean" - }, - "username": { - "type": "string" - } - } - }, - "dto.PostgresqlDBCreate": { - "type": "object", - "required": [ - "database", - "from", - "name", - "password", - "username" - ], - "properties": { - "database": { - "type": "string" - }, - "description": { - "type": "string" - }, - "format": { - "type": "string" - }, - "from": { - "type": "string", - "enum": [ - "local", - "remote" - ] - }, - "name": { - "type": "string" - }, - "password": { - "type": "string" - }, - "superUser": { - "type": "boolean" - }, - "username": { - "type": "string" - } - } - }, - "dto.PostgresqlDBDelete": { - "type": "object", - "required": [ - "database", - "id", - "type" - ], - "properties": { - "database": { - "type": "string" - }, - "deleteBackup": { - "type": "boolean" - }, - "forceDelete": { - "type": "boolean" - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string", - "enum": [ - "postgresql" - ] - } - } - }, - "dto.PostgresqlDBDeleteCheck": { - "type": "object", - "required": [ - "database", - "id", - "type" - ], - "properties": { - "database": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string", - "enum": [ - "postgresql" - ] - } - } - }, - "dto.PostgresqlDBSearch": { - "type": "object", - "required": [ - "database", - "order", - "orderBy", - "page", - "pageSize" - ], - "properties": { - "database": { - "type": "string" - }, - "info": { - "type": "string" - }, - "order": { - "type": "string", - "enum": [ - "null", - "ascending", - "descending" - ] - }, - "orderBy": { - "type": "string", - "enum": [ - "name", - "created_at" - ] - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "dto.PostgresqlLoadDB": { - "type": "object", - "required": [ - "database", - "from", - "type" - ], - "properties": { - "database": { - "type": "string" - }, - "from": { - "type": "string", - "enum": [ - "local", - "remote" - ] - }, - "type": { - "type": "string", - "enum": [ - "postgresql" - ] - } - } - }, - "dto.ProxyUpdate": { - "type": "object", - "properties": { - "proxyPasswd": { - "type": "string" - }, - "proxyPasswdKeep": { - "type": "string" - }, - "proxyPort": { - "type": "string" - }, - "proxyType": { - "type": "string" - }, - "proxyUrl": { - "type": "string" - }, - "proxyUser": { - "type": "string" - } - } - }, - "dto.RecordSearch": { - "type": "object", - "required": [ - "page", - "pageSize", - "type" - ], - "properties": { - "detailName": { - "type": "string" - }, - "name": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "type": { - "type": "string" - } - } - }, - "dto.RecordSearchByCronjob": { - "type": "object", - "required": [ - "cronjobID", - "page", - "pageSize" - ], - "properties": { - "cronjobID": { - "type": "integer" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "dto.RedisCommand": { - "type": "object", - "properties": { - "command": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, - "dto.RedisConf": { - "type": "object", - "required": [ - "database" - ], - "properties": { - "containerName": { - "type": "string" - }, - "database": { - "type": "string" - }, - "maxclients": { - "type": "string" - }, - "maxmemory": { - "type": "string" - }, - "name": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "requirepass": { - "type": "string" - }, - "timeout": { - "type": "string" - } - } - }, - "dto.RedisConfPersistenceUpdate": { - "type": "object", - "required": [ - "database", - "type" - ], - "properties": { - "appendfsync": { - "type": "string" - }, - "appendonly": { - "type": "string" - }, - "database": { - "type": "string" - }, - "save": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "aof", - "rbd" - ] - } - } - }, - "dto.RedisConfUpdate": { - "type": "object", - "required": [ - "database" - ], - "properties": { - "database": { - "type": "string" - }, - "maxclients": { - "type": "string" - }, - "maxmemory": { - "type": "string" - }, - "timeout": { - "type": "string" - } - } - }, - "dto.RedisPersistence": { - "type": "object", - "required": [ - "database" - ], - "properties": { - "appendfsync": { - "type": "string" - }, - "appendonly": { - "type": "string" - }, - "database": { - "type": "string" - }, - "save": { - "type": "string" - } - } - }, - "dto.RedisStatus": { - "type": "object", - "required": [ - "database" - ], - "properties": { - "connected_clients": { - "type": "string" - }, - "database": { - "type": "string" - }, - "instantaneous_ops_per_sec": { - "type": "string" - }, - "keyspace_hits": { - "type": "string" - }, - "keyspace_misses": { - "type": "string" - }, - "latest_fork_usec": { - "type": "string" - }, - "mem_fragmentation_ratio": { - "type": "string" - }, - "tcp_port": { - "type": "string" - }, - "total_commands_processed": { - "type": "string" - }, - "total_connections_received": { - "type": "string" - }, - "uptime_in_days": { - "type": "string" - }, - "used_memory": { - "type": "string" - }, - "used_memory_peak": { - "type": "string" - }, - "used_memory_rss": { - "type": "string" - } - } - }, - "dto.ResourceLimit": { - "type": "object", - "properties": { - "cpu": { - "type": "integer" - }, - "memory": { - "type": "integer" - } - } - }, - "dto.RuleSearch": { - "type": "object", - "required": [ - "page", - "pageSize", - "type" - ], - "properties": { - "info": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "status": { - "type": "string" - }, - "strategy": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "dto.SSHConf": { - "type": "object", - "properties": { - "file": { - "type": "string" - } - } - }, - "dto.SSHHistory": { - "type": "object", - "properties": { - "address": { - "type": "string" - }, - "area": { - "type": "string" - }, - "authMode": { - "type": "string" - }, - "date": { - "type": "string" - }, - "dateStr": { - "type": "string" - }, - "message": { - "type": "string" - }, - "port": { - "type": "string" - }, - "status": { - "type": "string" - }, - "user": { - "type": "string" - } - } - }, - "dto.SSHInfo": { - "type": "object", - "properties": { - "autoStart": { - "type": "boolean" - }, - "listenAddress": { - "type": "string" - }, - "message": { - "type": "string" - }, - "passwordAuthentication": { - "type": "string" - }, - "permitRootLogin": { - "type": "string" - }, - "port": { - "type": "string" - }, - "pubkeyAuthentication": { - "type": "string" - }, - "status": { - "type": "string" - }, - "useDNS": { - "type": "string" - } - } - }, - "dto.SSHLog": { - "type": "object", - "properties": { - "failedCount": { - "type": "integer" - }, - "logs": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.SSHHistory" - } - }, - "successfulCount": { - "type": "integer" - }, - "totalCount": { - "type": "integer" - } - } - }, - "dto.SSHUpdate": { - "type": "object", - "required": [ - "key" - ], - "properties": { - "key": { - "type": "string" - }, - "newValue": { - "type": "string" - }, - "oldValue": { - "type": "string" - } - } - }, - "dto.SSLUpdate": { - "type": "object", - "required": [ - "ssl", - "sslType" - ], - "properties": { - "cert": { - "type": "string" - }, - "domain": { - "type": "string" - }, - "key": { - "type": "string" - }, - "ssl": { - "type": "string", - "enum": [ - "enable", - "disable" - ] - }, - "sslID": { - "type": "integer" - }, - "sslType": { - "type": "string", - "enum": [ - "self", - "select", - "import", - "import-paste", - "import-local" - ] - } - } - }, - "dto.SearchForTree": { - "type": "object", - "properties": { - "info": { - "type": "string" - } - } - }, - "dto.SearchHostWithPage": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "groupID": { - "type": "integer" - }, - "info": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "dto.SearchLgLogWithPage": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "ip": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "status": { - "type": "string" - } - } - }, - "dto.SearchOpLogWithPage": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "operation": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "source": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "dto.SearchRecord": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "cronjobID": { - "type": "integer" - }, - "endTime": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "startTime": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "dto.SearchSSHLog": { - "type": "object", - "required": [ - "Status", - "page", - "pageSize" - ], - "properties": { - "Status": { - "type": "string", - "enum": [ - "Success", - "Failed", - "All" - ] - }, - "info": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "dto.SearchWithPage": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "info": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "dto.SettingInfo": { - "type": "object", - "properties": { - "allowIPs": { - "type": "string" - }, - "appStoreLastModified": { - "type": "string" - }, - "appStoreSyncStatus": { - "type": "string" - }, - "appStoreVersion": { - "type": "string" - }, - "bindAddress": { - "type": "string" - }, - "bindDomain": { - "type": "string" - }, - "complexityVerification": { - "type": "string" - }, - "defaultNetwork": { - "type": "string" - }, - "developerMode": { - "type": "string" - }, - "dingVars": { - "type": "string" - }, - "dockerSockPath": { - "type": "string" - }, - "email": { - "type": "string" - }, - "emailVars": { - "type": "string" - }, - "expirationDays": { - "type": "string" - }, - "expirationTime": { - "type": "string" - }, - "fileRecycleBin": { - "type": "string" - }, - "ipv6": { - "type": "string" - }, - "language": { - "type": "string" - }, - "lastCleanData": { - "type": "string" - }, - "lastCleanSize": { - "type": "string" - }, - "lastCleanTime": { - "type": "string" - }, - "localTime": { - "type": "string" - }, - "menuTabs": { - "type": "string" - }, - "messageType": { - "type": "string" - }, - "mfaInterval": { - "type": "string" - }, - "mfaSecret": { - "type": "string" - }, - "mfaStatus": { - "type": "string" - }, - "monitorInterval": { - "type": "string" - }, - "monitorStatus": { - "type": "string" - }, - "monitorStoreDays": { - "type": "string" - }, - "noAuthSetting": { - "type": "string" - }, - "ntpSite": { - "type": "string" - }, - "panelName": { - "type": "string" - }, - "port": { - "type": "string" - }, - "proxyPasswd": { - "type": "string" - }, - "proxyPasswdKeep": { - "type": "string" - }, - "proxyPort": { - "type": "string" - }, - "proxyType": { - "type": "string" - }, - "proxyUrl": { - "type": "string" - }, - "proxyUser": { - "type": "string" - }, - "securityEntrance": { - "type": "string" - }, - "serverPort": { - "type": "string" - }, - "sessionTimeout": { - "type": "string" - }, - "snapshotIgnore": { - "type": "string" - }, - "ssl": { - "type": "string" - }, - "sslType": { - "type": "string" - }, - "systemIP": { - "type": "string" - }, - "systemVersion": { - "type": "string" - }, - "theme": { - "type": "string" - }, - "timeZone": { - "type": "string" - }, - "userName": { - "type": "string" - }, - "weChatVars": { - "type": "string" - }, - "xpackHideMenu": { - "type": "string" - } - } - }, - "dto.SettingUpdate": { - "type": "object", - "required": [ - "key" - ], - "properties": { - "key": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "dto.SnapshotBatchDelete": { - "type": "object", - "required": [ - "ids" - ], - "properties": { - "deleteWithFile": { - "type": "boolean" - }, - "ids": { - "type": "array", - "items": { - "type": "integer" - } - } - } - }, - "dto.SnapshotCreate": { - "type": "object", - "required": [ - "defaultDownload", - "from" - ], - "properties": { - "defaultDownload": { - "type": "string" - }, - "description": { - "type": "string", - "maxLength": 256 - }, - "from": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "secret": { - "type": "string" - } - } - }, - "dto.SnapshotImport": { - "type": "object", - "properties": { - "description": { - "type": "string", - "maxLength": 256 - }, - "from": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "dto.SnapshotRecover": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - }, - "isNew": { - "type": "boolean" - }, - "reDownload": { - "type": "boolean" - }, - "secret": { - "type": "string" - } - } - }, - "dto.SwapHelper": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "isNew": { - "type": "boolean" - }, - "path": { - "type": "string" - }, - "size": { - "type": "integer" - }, - "used": { - "type": "string" - } - } - }, - "dto.TreeChild": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "label": { - "type": "string" - } - } - }, - "dto.UpdateByFile": { - "type": "object", - "properties": { - "file": { - "type": "string" - } - } - }, - "dto.UpdateByNameAndFile": { - "type": "object", - "properties": { - "file": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "dto.UpdateDescription": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "description": { - "type": "string", - "maxLength": 256 - }, - "id": { - "type": "integer" - } - } - }, - "dto.UpdateFirewallDescription": { - "type": "object", - "required": [ - "strategy" - ], - "properties": { - "address": { - "type": "string" - }, - "description": { - "type": "string" - }, - "port": { - "type": "string" - }, - "protocol": { - "type": "string" - }, - "strategy": { - "type": "string", - "enum": [ - "accept", - "drop" - ] - }, - "type": { - "type": "string" - } - } - }, - "dto.Upgrade": { - "type": "object", - "required": [ - "version" - ], - "properties": { - "version": { - "type": "string" - } - } - }, - "dto.UpgradeInfo": { - "type": "object", - "properties": { - "latestVersion": { - "type": "string" - }, - "newVersion": { - "type": "string" - }, - "releaseNote": { - "type": "string" - }, - "testVersion": { - "type": "string" - } - } - }, - "dto.UserLoginInfo": { - "type": "object", - "properties": { - "mfaStatus": { - "type": "string" - }, - "name": { - "type": "string" - }, - "token": { - "type": "string" - } - } - }, - "dto.VolumeCreate": { - "type": "object", - "required": [ - "driver", - "name" - ], - "properties": { - "driver": { - "type": "string" - }, - "labels": { - "type": "array", - "items": { - "type": "string" - } - }, - "name": { - "type": "string" - }, - "options": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "dto.VolumeHelper": { - "type": "object", - "properties": { - "containerDir": { - "type": "string" - }, - "mode": { - "type": "string" - }, - "sourceDir": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "files.FileInfo": { - "type": "object", - "properties": { - "content": { - "type": "string" - }, - "extension": { - "type": "string" - }, - "favoriteID": { - "type": "integer" - }, - "gid": { - "type": "string" - }, - "group": { - "type": "string" - }, - "isDetail": { - "type": "boolean" - }, - "isDir": { - "type": "boolean" - }, - "isHidden": { - "type": "boolean" - }, - "isSymlink": { - "type": "boolean" - }, - "itemTotal": { - "type": "integer" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/files.FileInfo" - } - }, - "linkPath": { - "type": "string" - }, - "mimeType": { - "type": "string" - }, - "modTime": { - "type": "string" - }, - "mode": { - "type": "string" - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - }, - "size": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "uid": { - "type": "string" - }, - "updateTime": { - "type": "string" - }, - "user": { - "type": "string" - } - } - }, - "mfa.Otp": { - "type": "object", - "properties": { - "qrImage": { - "type": "string" - }, - "secret": { - "type": "string" - } - } - }, - "model.App": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "crossVersionUpdate": { - "type": "boolean" - }, - "document": { - "type": "string" - }, - "github": { - "type": "string" - }, - "icon": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "key": { - "type": "string" - }, - "lastModified": { - "type": "integer" - }, - "limit": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "readMe": { - "type": "string" - }, - "recommend": { - "type": "integer" - }, - "required": { - "type": "string" - }, - "resource": { - "type": "string" - }, - "shortDescEn": { - "type": "string" - }, - "shortDescZh": { - "type": "string" - }, - "status": { - "type": "string" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "website": { - "type": "string" - } - } - }, - "model.AppInstall": { - "type": "object", - "properties": { - "app": { - "$ref": "#/definitions/model.App" - }, - "appDetailId": { - "type": "integer" - }, - "appId": { - "type": "integer" - }, - "containerName": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "dockerCompose": { - "type": "string" - }, - "env": { - "type": "string" - }, - "httpPort": { - "type": "integer" - }, - "httpsPort": { - "type": "integer" - }, - "id": { - "type": "integer" - }, - "message": { - "type": "string" - }, - "name": { - "type": "string" - }, - "param": { - "type": "string" - }, - "serviceName": { - "type": "string" - }, - "status": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "model.Tag": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "key": { - "type": "string" - }, - "name": { - "type": "string" - }, - "sort": { - "type": "integer" - }, - "updatedAt": { - "type": "string" - } - } - }, - "model.Website": { - "type": "object", - "properties": { - "IPV6": { - "type": "boolean" - }, - "accessLog": { - "type": "boolean" - }, - "alias": { - "type": "string" - }, - "appInstallId": { - "type": "integer" - }, - "createdAt": { - "type": "string" - }, - "defaultServer": { - "type": "boolean" - }, - "domains": { - "type": "array", - "items": { - "$ref": "#/definitions/model.WebsiteDomain" - } - }, - "errorLog": { - "type": "boolean" - }, - "expireDate": { - "type": "string" - }, - "ftpId": { - "type": "integer" - }, - "group": { - "type": "string" - }, - "httpConfig": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "primaryDomain": { - "type": "string" - }, - "protocol": { - "type": "string" - }, - "proxy": { - "type": "string" - }, - "proxyType": { - "type": "string" - }, - "remark": { - "type": "string" - }, - "rewrite": { - "type": "string" - }, - "runtimeID": { - "type": "integer" - }, - "siteDir": { - "type": "string" - }, - "status": { - "type": "string" - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "user": { - "type": "string" - }, - "webSiteGroupId": { - "type": "integer" - }, - "webSiteSSL": { - "$ref": "#/definitions/model.WebsiteSSL" - }, - "webSiteSSLId": { - "type": "integer" - } - } - }, - "model.WebsiteAcmeAccount": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "eabHmacKey": { - "type": "string" - }, - "eabKid": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "keyType": { - "type": "string" - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "url": { - "type": "string" - } - } - }, - "model.WebsiteDnsAccount": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "model.WebsiteDomain": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "domain": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "port": { - "type": "integer" - }, - "updatedAt": { - "type": "string" - }, - "websiteId": { - "type": "integer" - } - } - }, - "model.WebsiteSSL": { - "type": "object", - "properties": { - "acmeAccount": { - "$ref": "#/definitions/model.WebsiteAcmeAccount" - }, - "acmeAccountId": { - "type": "integer" - }, - "autoRenew": { - "type": "boolean" - }, - "caId": { - "type": "integer" - }, - "certURL": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "dir": { - "type": "string" - }, - "disableCNAME": { - "type": "boolean" - }, - "dnsAccount": { - "$ref": "#/definitions/model.WebsiteDnsAccount" - }, - "dnsAccountId": { - "type": "integer" - }, - "domains": { - "type": "string" - }, - "execShell": { - "type": "boolean" - }, - "expireDate": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "keyType": { - "type": "string" - }, - "message": { - "type": "string" - }, - "nameserver1": { - "type": "string" - }, - "nameserver2": { - "type": "string" - }, - "organization": { - "type": "string" - }, - "pem": { - "type": "string" - }, - "primaryDomain": { - "type": "string" - }, - "privateKey": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "pushDir": { - "type": "boolean" - }, - "shell": { - "type": "string" - }, - "skipDNS": { - "type": "boolean" - }, - "startDate": { - "type": "string" - }, - "status": { - "type": "string" - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "websites": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Website" - } - } - } - }, - "request.AppInstallCreate": { - "type": "object", - "required": [ - "appDetailId", - "name" - ], - "properties": { - "advanced": { - "type": "boolean" - }, - "allowPort": { - "type": "boolean" - }, - "appDetailId": { - "type": "integer" - }, - "containerName": { - "type": "string" - }, - "cpuQuota": { - "type": "number" - }, - "dockerCompose": { - "type": "string" - }, - "editCompose": { - "type": "boolean" - }, - "hostMode": { - "type": "boolean" - }, - "memoryLimit": { - "type": "number" - }, - "memoryUnit": { - "type": "string" - }, - "name": { - "type": "string" - }, - "params": { - "type": "object", - "additionalProperties": true - }, - "pullImage": { - "type": "boolean" - }, - "services": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - }, - "request.AppInstalledIgnoreUpgrade": { - "type": "object", - "required": [ - "detailID", - "operate" - ], - "properties": { - "detailID": { - "type": "integer" - }, - "operate": { - "type": "string", - "enum": [ - "cancel", - "ignore" - ] - } - } - }, - "request.AppInstalledInfo": { - "type": "object", - "required": [ - "key" - ], - "properties": { - "key": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "request.AppInstalledOperate": { - "type": "object", - "required": [ - "installId", - "operate" - ], - "properties": { - "backup": { - "type": "boolean" - }, - "backupId": { - "type": "integer" - }, - "deleteBackup": { - "type": "boolean" - }, - "deleteDB": { - "type": "boolean" - }, - "detailId": { - "type": "integer" - }, - "dockerCompose": { - "type": "string" - }, - "forceDelete": { - "type": "boolean" - }, - "installId": { - "type": "integer" - }, - "operate": { - "type": "string" - }, - "pullImage": { - "type": "boolean" - } - } - }, - "request.AppInstalledSearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "all": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "sync": { - "type": "boolean" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - }, - "type": { - "type": "string" - }, - "unused": { - "type": "boolean" - }, - "update": { - "type": "boolean" - } - } - }, - "request.AppInstalledUpdate": { - "type": "object", - "required": [ - "installId", - "params" - ], - "properties": { - "advanced": { - "type": "boolean" - }, - "allowPort": { - "type": "boolean" - }, - "containerName": { - "type": "string" - }, - "cpuQuota": { - "type": "number" - }, - "dockerCompose": { - "type": "string" - }, - "editCompose": { - "type": "boolean" - }, - "hostMode": { - "type": "boolean" - }, - "installId": { - "type": "integer" - }, - "memoryLimit": { - "type": "number" - }, - "memoryUnit": { - "type": "string" - }, - "params": { - "type": "object", - "additionalProperties": true - }, - "pullImage": { - "type": "boolean" - } - } - }, - "request.AppSearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "name": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "recommend": { - "type": "boolean" - }, - "resource": { - "type": "string" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - }, - "type": { - "type": "string" - } - } - }, - "request.DirSizeReq": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "type": "string" - } - } - }, - "request.ExposedPort": { - "type": "object", - "properties": { - "containerPort": { - "type": "integer" - }, - "hostPort": { - "type": "integer" - } - } - }, - "request.FavoriteCreate": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "type": "string" - } - } - }, - "request.FavoriteDelete": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - } - } - }, - "request.FileBatchDelete": { - "type": "object", - "required": [ - "paths" - ], - "properties": { - "isDir": { - "type": "boolean" - }, - "paths": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "request.FileCompress": { - "type": "object", - "required": [ - "dst", - "files", - "name", - "type" - ], - "properties": { - "dst": { - "type": "string" - }, - "files": { - "type": "array", - "items": { - "type": "string" - } - }, - "name": { - "type": "string" - }, - "replace": { - "type": "boolean" - }, - "secret": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "request.FileContentReq": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "isDetail": { - "type": "boolean" - }, - "path": { - "type": "string" - } - } - }, - "request.FileCreate": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "content": { - "type": "string" - }, - "isDir": { - "type": "boolean" - }, - "isLink": { - "type": "boolean" - }, - "isSymlink": { - "type": "boolean" - }, - "linkPath": { - "type": "string" - }, - "mode": { - "type": "integer" - }, - "path": { - "type": "string" - }, - "sub": { - "type": "boolean" - } - } - }, - "request.FileDeCompress": { - "type": "object", - "required": [ - "dst", - "path", - "type" - ], - "properties": { - "dst": { - "type": "string" - }, - "path": { - "type": "string" - }, - "secret": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "request.FileDelete": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "forceDelete": { - "type": "boolean" - }, - "isDir": { - "type": "boolean" - }, - "path": { - "type": "string" - } - } - }, - "request.FileDownload": { - "type": "object", - "required": [ - "name", - "paths", - "type" - ], - "properties": { - "compress": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "paths": { - "type": "array", - "items": { - "type": "string" - } - }, - "type": { - "type": "string" - } - } - }, - "request.FileEdit": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "content": { - "type": "string" - }, - "path": { - "type": "string" - } - } - }, - "request.FileMove": { - "type": "object", - "required": [ - "newPath", - "oldPaths", - "type" - ], - "properties": { - "cover": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "newPath": { - "type": "string" - }, - "oldPaths": { - "type": "array", - "items": { - "type": "string" - } - }, - "type": { - "type": "string" - } - } - }, - "request.FileOption": { - "type": "object", - "properties": { - "containSub": { - "type": "boolean" - }, - "dir": { - "type": "boolean" - }, - "expand": { - "type": "boolean" - }, - "isDetail": { - "type": "boolean" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "path": { - "type": "string" - }, - "search": { - "type": "string" - }, - "showHidden": { - "type": "boolean" - }, - "sortBy": { - "type": "string" - }, - "sortOrder": { - "type": "string" - } - } - }, - "request.FilePathCheck": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "type": "string" - } - } - }, - "request.FileReadByLineReq": { - "type": "object", - "required": [ - "page", - "pageSize", - "type" - ], - "properties": { - "ID": { - "type": "integer" - }, - "latest": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "type": { - "type": "string" - } - } - }, - "request.FileRename": { - "type": "object", - "required": [ - "newName", - "oldName" - ], - "properties": { - "newName": { - "type": "string" - }, - "oldName": { - "type": "string" - } - } - }, - "request.FileRoleReq": { - "type": "object", - "required": [ - "group", - "mode", - "paths", - "user" - ], - "properties": { - "group": { - "type": "string" - }, - "mode": { - "type": "integer" - }, - "paths": { - "type": "array", - "items": { - "type": "string" - } - }, - "sub": { - "type": "boolean" - }, - "user": { - "type": "string" - } - } - }, - "request.FileRoleUpdate": { - "type": "object", - "required": [ - "group", - "path", - "user" - ], - "properties": { - "group": { - "type": "string" - }, - "path": { - "type": "string" - }, - "sub": { - "type": "boolean" - }, - "user": { - "type": "string" - } - } - }, - "request.FileWget": { - "type": "object", - "required": [ - "name", - "path", - "url" - ], - "properties": { - "ignoreCertificate": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - }, - "url": { - "type": "string" - } - } - }, - "request.HostToolConfig": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "content": { - "type": "string" - }, - "operate": { - "type": "string", - "enum": [ - "get", - "set" - ] - }, - "type": { - "type": "string", - "enum": [ - "supervisord" - ] - } - } - }, - "request.HostToolCreate": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "configPath": { - "type": "string" - }, - "serviceName": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "request.HostToolLogReq": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "supervisord" - ] - } - } - }, - "request.HostToolReq": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "operate": { - "type": "string", - "enum": [ - "status", - "restart", - "start", - "stop" - ] - }, - "type": { - "type": "string", - "enum": [ - "supervisord" - ] - } - } - }, - "request.NewAppInstall": { - "type": "object", - "properties": { - "advanced": { - "type": "boolean" - }, - "allowPort": { - "type": "boolean" - }, - "appDetailID": { - "type": "integer" - }, - "containerName": { - "type": "string" - }, - "cpuQuota": { - "type": "number" - }, - "dockerCompose": { - "type": "string" - }, - "editCompose": { - "type": "boolean" - }, - "hostMode": { - "type": "boolean" - }, - "memoryLimit": { - "type": "number" - }, - "memoryUnit": { - "type": "string" - }, - "name": { - "type": "string" - }, - "params": { - "type": "object", - "additionalProperties": true - }, - "pullImage": { - "type": "boolean" - } - } - }, - "request.NginxAntiLeechUpdate": { - "type": "object", - "required": [ - "extends", - "return", - "websiteID" - ], - "properties": { - "blocked": { - "type": "boolean" - }, - "cache": { - "type": "boolean" - }, - "cacheTime": { - "type": "integer" - }, - "cacheUint": { - "type": "string" - }, - "enable": { - "type": "boolean" - }, - "extends": { - "type": "string" - }, - "logEnable": { - "type": "boolean" - }, - "noneRef": { - "type": "boolean" - }, - "return": { - "type": "string" - }, - "serverNames": { - "type": "array", - "items": { - "type": "string" - } - }, - "websiteID": { - "type": "integer" - } - } - }, - "request.NginxAuthReq": { - "type": "object", - "required": [ - "websiteID" - ], - "properties": { - "websiteID": { - "type": "integer" - } - } - }, - "request.NginxAuthUpdate": { - "type": "object", - "required": [ - "operate", - "websiteID" - ], - "properties": { - "operate": { - "type": "string" - }, - "password": { - "type": "string" - }, - "remark": { - "type": "string" - }, - "username": { - "type": "string" - }, - "websiteID": { - "type": "integer" - } - } - }, - "request.NginxCommonReq": { - "type": "object", - "required": [ - "websiteID" - ], - "properties": { - "websiteID": { - "type": "integer" - } - } - }, - "request.NginxConfigFileUpdate": { - "type": "object", - "required": [ - "content" - ], - "properties": { - "backup": { - "type": "boolean" - }, - "content": { - "type": "string" - } - } - }, - "request.NginxConfigUpdate": { - "type": "object", - "required": [ - "operate" - ], - "properties": { - "operate": { - "type": "string", - "enum": [ - "add", - "update", - "delete" - ] - }, - "params": {}, - "scope": { - "$ref": "#/definitions/dto.NginxKey" - }, - "websiteId": { - "type": "integer" - } - } - }, - "request.NginxProxyUpdate": { - "type": "object", - "required": [ - "content", - "name", - "websiteID" - ], - "properties": { - "content": { - "type": "string" - }, - "name": { - "type": "string" - }, - "websiteID": { - "type": "integer" - } - } - }, - "request.NginxRedirectReq": { - "type": "object", - "required": [ - "name", - "operate", - "redirect", - "target", - "type", - "websiteID" - ], - "properties": { - "domains": { - "type": "array", - "items": { - "type": "string" - } - }, - "enable": { - "type": "boolean" - }, - "keepPath": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "operate": { - "type": "string" - }, - "path": { - "type": "string" - }, - "redirect": { - "type": "string" - }, - "redirectRoot": { - "type": "boolean" - }, - "target": { - "type": "string" - }, - "type": { - "type": "string" - }, - "websiteID": { - "type": "integer" - } - } - }, - "request.NginxRedirectUpdate": { - "type": "object", - "required": [ - "content", - "name", - "websiteID" - ], - "properties": { - "content": { - "type": "string" - }, - "name": { - "type": "string" - }, - "websiteID": { - "type": "integer" - } - } - }, - "request.NginxRewriteReq": { - "type": "object", - "required": [ - "name", - "websiteId" - ], - "properties": { - "name": { - "type": "string" - }, - "websiteId": { - "type": "integer" - } - } - }, - "request.NginxRewriteUpdate": { - "type": "object", - "required": [ - "name", - "websiteId" - ], - "properties": { - "content": { - "type": "string" - }, - "name": { - "type": "string" - }, - "websiteId": { - "type": "integer" - } - } - }, - "request.NginxScopeReq": { - "type": "object", - "required": [ - "scope" - ], - "properties": { - "scope": { - "$ref": "#/definitions/dto.NginxKey" - }, - "websiteId": { - "type": "integer" - } - } - }, - "request.NodeModuleReq": { - "type": "object", - "required": [ - "ID" - ], - "properties": { - "ID": { - "type": "integer" - } - } - }, - "request.NodePackageReq": { - "type": "object", - "properties": { - "codeDir": { - "type": "string" - } - } - }, - "request.PHPExtensionsCreate": { - "type": "object", - "required": [ - "extensions", - "name" - ], - "properties": { - "extensions": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "request.PHPExtensionsDelete": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - } - } - }, - "request.PHPExtensionsSearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "all": { - "type": "boolean" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "request.PHPExtensionsUpdate": { - "type": "object", - "required": [ - "extensions", - "id" - ], - "properties": { - "extensions": { - "type": "string" - }, - "id": { - "type": "integer" - } - } - }, - "request.PortUpdate": { - "type": "object", - "properties": { - "key": { - "type": "string" - }, - "name": { - "type": "string" - }, - "port": { - "type": "integer" - } - } - }, - "request.ProcessReq": { - "type": "object", - "required": [ - "PID" - ], - "properties": { - "PID": { - "type": "integer" - } - } - }, - "request.RecycleBinReduce": { - "type": "object", - "required": [ - "from", - "rName" - ], - "properties": { - "from": { - "type": "string" - }, - "name": { - "type": "string" - }, - "rName": { - "type": "string" - } - } - }, - "request.RuntimeCreate": { - "type": "object", - "properties": { - "appDetailId": { - "type": "integer" - }, - "clean": { - "type": "boolean" - }, - "codeDir": { - "type": "string" - }, - "exposedPorts": { - "type": "array", - "items": { - "$ref": "#/definitions/request.ExposedPort" - } - }, - "image": { - "type": "string" - }, - "install": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "params": { - "type": "object", - "additionalProperties": true - }, - "port": { - "type": "integer" - }, - "resource": { - "type": "string" - }, - "source": { - "type": "string" - }, - "type": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "request.RuntimeDelete": { - "type": "object", - "properties": { - "forceDelete": { - "type": "boolean" - }, - "id": { - "type": "integer" - } - } - }, - "request.RuntimeOperate": { - "type": "object", - "properties": { - "ID": { - "type": "integer" - }, - "operate": { - "type": "string" - } - } - }, - "request.RuntimeSearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "name": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "status": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "request.RuntimeUpdate": { - "type": "object", - "properties": { - "clean": { - "type": "boolean" - }, - "codeDir": { - "type": "string" - }, - "exposedPorts": { - "type": "array", - "items": { - "$ref": "#/definitions/request.ExposedPort" - } - }, - "id": { - "type": "integer" - }, - "image": { - "type": "string" - }, - "install": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "params": { - "type": "object", - "additionalProperties": true - }, - "port": { - "type": "integer" - }, - "rebuild": { - "type": "boolean" - }, - "source": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "request.SearchUploadWithPage": { - "type": "object", - "required": [ - "page", - "pageSize", - "path" - ], - "properties": { - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "path": { - "type": "string" - } - } - }, - "request.SupervisorProcessConfig": { - "type": "object", - "properties": { - "command": { - "type": "string" - }, - "dir": { - "type": "string" - }, - "name": { - "type": "string" - }, - "numprocs": { - "type": "string" - }, - "operate": { - "type": "string" - }, - "user": { - "type": "string" - } - } - }, - "request.SupervisorProcessFileReq": { - "type": "object", - "required": [ - "file", - "name", - "operate" - ], - "properties": { - "content": { - "type": "string" - }, - "file": { - "type": "string", - "enum": [ - "out.log", - "err.log", - "config" - ] - }, - "name": { - "type": "string" - }, - "operate": { - "type": "string", - "enum": [ - "get", - "clear", - "update" - ] - } - } - }, - "request.WebsiteAcmeAccountCreate": { - "type": "object", - "required": [ - "email", - "keyType", - "type" - ], - "properties": { - "eabHmacKey": { - "type": "string" - }, - "eabKid": { - "type": "string" - }, - "email": { - "type": "string" - }, - "keyType": { - "type": "string", - "enum": [ - "P256", - "P384", - "2048", - "3072", - "4096", - "8192" - ] - }, - "type": { - "type": "string", - "enum": [ - "letsencrypt", - "zerossl", - "buypass", - "google" - ] - } - } - }, - "request.WebsiteBatchDelReq": { - "type": "object", - "required": [ - "ids" - ], - "properties": { - "ids": { - "type": "array", - "items": { - "type": "integer" - } - } - } - }, - "request.WebsiteCACreate": { - "type": "object", - "required": [ - "commonName", - "country", - "keyType", - "name", - "organization" - ], - "properties": { - "city": { - "type": "string" - }, - "commonName": { - "type": "string" - }, - "country": { - "type": "string" - }, - "keyType": { - "type": "string", - "enum": [ - "P256", - "P384", - "2048", - "3072", - "4096", - "8192" - ] - }, - "name": { - "type": "string" - }, - "organization": { - "type": "string" - }, - "organizationUint": { - "type": "string" - }, - "province": { - "type": "string" - } - } - }, - "request.WebsiteCAObtain": { - "type": "object", - "required": [ - "domains", - "id", - "keyType", - "time", - "unit" - ], - "properties": { - "autoRenew": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "dir": { - "type": "string" - }, - "domains": { - "type": "string" - }, - "execShell": { - "type": "boolean" - }, - "id": { - "type": "integer" - }, - "keyType": { - "type": "string", - "enum": [ - "P256", - "P384", - "2048", - "3072", - "4096", - "8192" - ] - }, - "pushDir": { - "type": "boolean" - }, - "renew": { - "type": "boolean" - }, - "shell": { - "type": "string" - }, - "sslID": { - "type": "integer" - }, - "time": { - "type": "integer" - }, - "unit": { - "type": "string" - } - } - }, - "request.WebsiteCASearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "request.WebsiteCommonReq": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - } - } - }, - "request.WebsiteCreate": { - "type": "object", - "required": [ - "alias", - "primaryDomain", - "type", - "webSiteGroupID" - ], - "properties": { - "IPV6": { - "type": "boolean" - }, - "alias": { - "type": "string" - }, - "appID": { - "type": "integer" - }, - "appInstall": { - "$ref": "#/definitions/request.NewAppInstall" - }, - "appInstallID": { - "type": "integer" - }, - "appType": { - "type": "string", - "enum": [ - "new", - "installed" - ] - }, - "ftpPassword": { - "type": "string" - }, - "ftpUser": { - "type": "string" - }, - "otherDomains": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "primaryDomain": { - "type": "string" - }, - "proxy": { - "type": "string" - }, - "proxyType": { - "type": "string" - }, - "remark": { - "type": "string" - }, - "runtimeID": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "webSiteGroupID": { - "type": "integer" - } - } - }, - "request.WebsiteDNSReq": { - "type": "object", - "required": [ - "acmeAccountId", - "domains" - ], - "properties": { - "acmeAccountId": { - "type": "integer" - }, - "domains": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "request.WebsiteDefaultUpdate": { - "type": "object", - "properties": { - "id": { - "type": "integer" - } - } - }, - "request.WebsiteDelete": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "deleteApp": { - "type": "boolean" - }, - "deleteBackup": { - "type": "boolean" - }, - "forceDelete": { - "type": "boolean" - }, - "id": { - "type": "integer" - } - } - }, - "request.WebsiteDnsAccountCreate": { - "type": "object", - "required": [ - "authorization", - "name", - "type" - ], - "properties": { - "authorization": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "request.WebsiteDnsAccountUpdate": { - "type": "object", - "required": [ - "authorization", - "id", - "name", - "type" - ], - "properties": { - "authorization": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "request.WebsiteDomainCreate": { - "type": "object", - "required": [ - "domains", - "websiteID" - ], - "properties": { - "domains": { - "type": "string" - }, - "websiteID": { - "type": "integer" - } - } - }, - "request.WebsiteDomainDelete": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - } - } - }, - "request.WebsiteHTTPSOp": { - "type": "object", - "required": [ - "websiteId" - ], - "properties": { - "SSLProtocol": { - "type": "array", - "items": { - "type": "string" - } - }, - "algorithm": { - "type": "string" - }, - "certificate": { - "type": "string" - }, - "certificatePath": { - "type": "string" - }, - "enable": { - "type": "boolean" - }, - "hsts": { - "type": "boolean" - }, - "httpConfig": { - "type": "string", - "enum": [ - "HTTPSOnly", - "HTTPAlso", - "HTTPToHTTPS" - ] - }, - "importType": { - "type": "string" - }, - "privateKey": { - "type": "string" - }, - "privateKeyPath": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "existed", - "auto", - "manual" - ] - }, - "websiteId": { - "type": "integer" - }, - "websiteSSLId": { - "type": "integer" - } - } - }, - "request.WebsiteHtmlUpdate": { - "type": "object", - "required": [ - "content", - "type" - ], - "properties": { - "content": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "request.WebsiteInstallCheckReq": { - "type": "object", - "properties": { - "InstallIds": { - "type": "array", - "items": { - "type": "integer" - } - } - } - }, - "request.WebsiteLogReq": { - "type": "object", - "required": [ - "id", - "logType", - "operate" - ], - "properties": { - "id": { - "type": "integer" - }, - "logType": { - "type": "string" - }, - "operate": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "request.WebsiteNginxUpdate": { - "type": "object", - "required": [ - "content", - "id" - ], - "properties": { - "content": { - "type": "string" - }, - "id": { - "type": "integer" - } - } - }, - "request.WebsiteOp": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - }, - "operate": { - "type": "string" - } - } - }, - "request.WebsitePHPConfigUpdate": { - "type": "object", - "required": [ - "id", - "scope" - ], - "properties": { - "disableFunctions": { - "type": "array", - "items": { - "type": "string" - } - }, - "id": { - "type": "integer" - }, - "params": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "scope": { - "type": "string" - }, - "uploadMaxSize": { - "type": "string" - } - } - }, - "request.WebsitePHPFileUpdate": { - "type": "object", - "required": [ - "content", - "id", - "type" - ], - "properties": { - "content": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string" - } - } - }, - "request.WebsitePHPVersionReq": { - "type": "object", - "required": [ - "runtimeID", - "websiteID" - ], - "properties": { - "retainConfig": { - "type": "boolean" - }, - "runtimeID": { - "type": "integer" - }, - "websiteID": { - "type": "integer" - } - } - }, - "request.WebsiteProxyConfig": { - "type": "object", - "required": [ - "id", - "match", - "name", - "operate", - "proxyHost", - "proxyPass" - ], - "properties": { - "cache": { - "type": "boolean" - }, - "cacheTime": { - "type": "integer" - }, - "cacheUnit": { - "type": "string" - }, - "content": { - "type": "string" - }, - "enable": { - "type": "boolean" - }, - "filePath": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "match": { - "type": "string" - }, - "modifier": { - "type": "string" - }, - "name": { - "type": "string" - }, - "operate": { - "type": "string" - }, - "proxyHost": { - "type": "string" - }, - "proxyPass": { - "type": "string" - }, - "replaces": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "sni": { - "type": "boolean" - } - } - }, - "request.WebsiteProxyReq": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - } - } - }, - "request.WebsiteResourceReq": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - } - } - }, - "request.WebsiteSSLApply": { - "type": "object", - "required": [ - "ID" - ], - "properties": { - "ID": { - "type": "integer" - }, - "nameservers": { - "type": "array", - "items": { - "type": "string" - } - }, - "skipDNSCheck": { - "type": "boolean" - } - } - }, - "request.WebsiteSSLCreate": { - "type": "object", - "required": [ - "acmeAccountId", - "primaryDomain", - "provider" - ], - "properties": { - "acmeAccountId": { - "type": "integer" - }, - "apply": { - "type": "boolean" - }, - "autoRenew": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "dir": { - "type": "string" - }, - "disableCNAME": { - "type": "boolean" - }, - "dnsAccountId": { - "type": "integer" - }, - "execShell": { - "type": "boolean" - }, - "id": { - "type": "integer" - }, - "keyType": { - "type": "string" - }, - "nameserver1": { - "type": "string" - }, - "nameserver2": { - "type": "string" - }, - "otherDomains": { - "type": "string" - }, - "primaryDomain": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "pushDir": { - "type": "boolean" - }, - "shell": { - "type": "string" - }, - "skipDNS": { - "type": "boolean" - } - } - }, - "request.WebsiteSSLSearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "acmeAccountID": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "request.WebsiteSSLUpdate": { - "type": "object", - "required": [ - "id", - "primaryDomain", - "provider" - ], - "properties": { - "acmeAccountId": { - "type": "integer" - }, - "apply": { - "type": "boolean" - }, - "autoRenew": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "dir": { - "type": "string" - }, - "disableCNAME": { - "type": "boolean" - }, - "dnsAccountId": { - "type": "integer" - }, - "execShell": { - "type": "boolean" - }, - "id": { - "type": "integer" - }, - "keyType": { - "type": "string" - }, - "nameserver1": { - "type": "string" - }, - "nameserver2": { - "type": "string" - }, - "otherDomains": { - "type": "string" - }, - "primaryDomain": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "pushDir": { - "type": "boolean" - }, - "shell": { - "type": "string" - }, - "skipDNS": { - "type": "boolean" - } - } - }, - "request.WebsiteSSLUpload": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "certificate": { - "type": "string" - }, - "certificatePath": { - "type": "string" - }, - "description": { - "type": "string" - }, - "privateKey": { - "type": "string" - }, - "privateKeyPath": { - "type": "string" - }, - "sslID": { - "type": "integer" - }, - "type": { - "type": "string", - "enum": [ - "paste", - "local" - ] - } - } - }, - "request.WebsiteSearch": { - "type": "object", - "required": [ - "order", - "orderBy", - "page", - "pageSize" - ], - "properties": { - "name": { - "type": "string" - }, - "order": { - "type": "string", - "enum": [ - "null", - "ascending", - "descending" - ] - }, - "orderBy": { - "type": "string", - "enum": [ - "primary_domain", - "type", - "status", - "created_at", - "expire_date" - ] - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "websiteGroupId": { - "type": "integer" - } - } - }, - "request.WebsiteUpdate": { - "type": "object", - "required": [ - "id", - "primaryDomain" - ], - "properties": { - "IPV6": { - "type": "boolean" - }, - "expireDate": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "primaryDomain": { - "type": "string" - }, - "remark": { - "type": "string" - }, - "webSiteGroupID": { - "type": "integer" - } - } - }, - "request.WebsiteUpdateDir": { - "type": "object", - "required": [ - "id", - "siteDir" - ], - "properties": { - "id": { - "type": "integer" - }, - "siteDir": { - "type": "string" - } - } - }, - "request.WebsiteUpdateDirPermission": { - "type": "object", - "required": [ - "group", - "id", - "user" - ], - "properties": { - "group": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "user": { - "type": "string" - } - } - }, - "response.AppDTO": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "crossVersionUpdate": { - "type": "boolean" - }, - "document": { - "type": "string" - }, - "github": { - "type": "string" - }, - "icon": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "installed": { - "type": "boolean" - }, - "key": { - "type": "string" - }, - "lastModified": { - "type": "integer" - }, - "limit": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "readMe": { - "type": "string" - }, - "recommend": { - "type": "integer" - }, - "required": { - "type": "string" - }, - "resource": { - "type": "string" - }, - "shortDescEn": { - "type": "string" - }, - "shortDescZh": { - "type": "string" - }, - "status": { - "type": "string" - }, - "tags": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Tag" - } - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "versions": { - "type": "array", - "items": { - "type": "string" - } - }, - "website": { - "type": "string" - } - } - }, - "response.AppDetailDTO": { - "type": "object", - "properties": { - "appId": { - "type": "integer" - }, - "createdAt": { - "type": "string" - }, - "dockerCompose": { - "type": "string" - }, - "downloadCallBackUrl": { - "type": "string" - }, - "downloadUrl": { - "type": "string" - }, - "enable": { - "type": "boolean" - }, - "hostMode": { - "type": "boolean" - }, - "id": { - "type": "integer" - }, - "ignoreUpgrade": { - "type": "boolean" - }, - "image": { - "type": "string" - }, - "lastModified": { - "type": "integer" - }, - "lastVersion": { - "type": "string" - }, - "params": {}, - "status": { - "type": "string" - }, - "update": { - "type": "boolean" - }, - "updatedAt": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "response.AppInstalledCheck": { - "type": "object", - "properties": { - "app": { - "type": "string" - }, - "appInstallId": { - "type": "integer" - }, - "containerName": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "httpPort": { - "type": "integer" - }, - "httpsPort": { - "type": "integer" - }, - "installPath": { - "type": "string" - }, - "isExist": { - "type": "boolean" - }, - "lastBackupAt": { - "type": "string" - }, - "name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "response.AppParam": { - "type": "object", - "properties": { - "edit": { - "type": "boolean" - }, - "key": { - "type": "string" - }, - "labelEn": { - "type": "string" - }, - "labelZh": { - "type": "string" - }, - "multiple": { - "type": "boolean" - }, - "required": { - "type": "boolean" - }, - "rule": { - "type": "string" - }, - "showValue": { - "type": "string" - }, - "type": { - "type": "string" - }, - "value": {}, - "values": {} - } - }, - "response.AppService": { - "type": "object", - "properties": { - "config": {}, - "from": { - "type": "string" - }, - "label": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "response.FileInfo": { - "type": "object", - "properties": { - "content": { - "type": "string" - }, - "extension": { - "type": "string" - }, - "favoriteID": { - "type": "integer" - }, - "gid": { - "type": "string" - }, - "group": { - "type": "string" - }, - "isDetail": { - "type": "boolean" - }, - "isDir": { - "type": "boolean" - }, - "isHidden": { - "type": "boolean" - }, - "isSymlink": { - "type": "boolean" - }, - "itemTotal": { - "type": "integer" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/files.FileInfo" - } - }, - "linkPath": { - "type": "string" - }, - "mimeType": { - "type": "string" - }, - "modTime": { - "type": "string" - }, - "mode": { - "type": "string" - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - }, - "size": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "uid": { - "type": "string" - }, - "updateTime": { - "type": "string" - }, - "user": { - "type": "string" - } - } - }, - "response.FileTree": { - "type": "object", - "properties": { - "children": { - "type": "array", - "items": { - "$ref": "#/definitions/response.FileTree" - } - }, - "extension": { - "type": "string" - }, - "id": { - "type": "string" - }, - "isDir": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - } - } - }, - "response.IgnoredApp": { - "type": "object", - "properties": { - "detailID": { - "type": "integer" - }, - "icon": { - "type": "string" - }, - "name": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "response.NginxParam": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "params": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "response.NginxStatus": { - "type": "object", - "properties": { - "accepts": { - "type": "string" - }, - "active": { - "type": "string" - }, - "handled": { - "type": "string" - }, - "reading": { - "type": "string" - }, - "requests": { - "type": "string" - }, - "waiting": { - "type": "string" - }, - "writing": { - "type": "string" - } - } - }, - "response.PHPConfig": { - "type": "object", - "properties": { - "disableFunctions": { - "type": "array", - "items": { - "type": "string" - } - }, - "params": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "uploadMaxSize": { - "type": "string" - } - } - }, - "response.PHPExtensionsDTO": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "extensions": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "response.WebsiteAcmeAccountDTO": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "eabHmacKey": { - "type": "string" - }, - "eabKid": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "keyType": { - "type": "string" - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "url": { - "type": "string" - } - } - }, - "response.WebsiteCADTO": { - "type": "object", - "properties": { - "city": { - "type": "string" - }, - "commonName": { - "type": "string" - }, - "country": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "csr": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "keyType": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "type": "string" - }, - "organizationUint": { - "type": "string" - }, - "privateKey": { - "type": "string" - }, - "province": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "response.WebsiteDNSRes": { - "type": "object", - "properties": { - "domain": { - "type": "string" - }, - "err": { - "type": "string" - }, - "resolve": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "response.WebsiteDTO": { - "type": "object", - "properties": { - "IPV6": { - "type": "boolean" - }, - "accessLog": { - "type": "boolean" - }, - "accessLogPath": { - "type": "string" - }, - "alias": { - "type": "string" - }, - "appInstallId": { - "type": "integer" - }, - "appName": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "defaultServer": { - "type": "boolean" - }, - "domains": { - "type": "array", - "items": { - "$ref": "#/definitions/model.WebsiteDomain" - } - }, - "errorLog": { - "type": "boolean" - }, - "errorLogPath": { - "type": "string" - }, - "expireDate": { - "type": "string" - }, - "ftpId": { - "type": "integer" - }, - "group": { - "type": "string" - }, - "httpConfig": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "primaryDomain": { - "type": "string" - }, - "protocol": { - "type": "string" - }, - "proxy": { - "type": "string" - }, - "proxyType": { - "type": "string" - }, - "remark": { - "type": "string" - }, - "rewrite": { - "type": "string" - }, - "runtimeID": { - "type": "integer" - }, - "runtimeName": { - "type": "string" - }, - "siteDir": { - "type": "string" - }, - "sitePath": { - "type": "string" - }, - "status": { - "type": "string" - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "user": { - "type": "string" - }, - "webSiteGroupId": { - "type": "integer" - }, - "webSiteSSL": { - "$ref": "#/definitions/model.WebsiteSSL" - }, - "webSiteSSLId": { - "type": "integer" - } - } - }, - "response.WebsiteHTTPS": { - "type": "object", - "properties": { - "SSL": { - "$ref": "#/definitions/model.WebsiteSSL" - }, - "SSLProtocol": { - "type": "array", - "items": { - "type": "string" - } - }, - "algorithm": { - "type": "string" - }, - "enable": { - "type": "boolean" - }, - "hsts": { - "type": "boolean" - }, - "httpConfig": { - "type": "string" - } - } - }, - "response.WebsiteLog": { - "type": "object", - "properties": { - "content": { - "type": "string" - }, - "enable": { - "type": "boolean" - }, - "end": { - "type": "boolean" - }, - "path": { - "type": "string" - } - } - }, - "response.WebsiteNginxConfig": { - "type": "object", - "properties": { - "enable": { - "type": "boolean" - }, - "params": { - "type": "array", - "items": { - "$ref": "#/definitions/response.NginxParam" - } - } - } - }, - "response.WebsitePreInstallCheck": { - "type": "object", - "properties": { - "appName": { - "type": "string" - }, - "name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "version": { - "type": "string" - } - } - } - } -}` - -// SwaggerInfo holds exported Swagger Info so clients can modify it -var SwaggerInfo = &swag.Spec{ - Version: "1.0", - Host: "localhost", - BasePath: "/api/v1", - Schemes: []string{}, - Title: "1Panel", - Description: "开源Linux面板", - InfoInstanceName: "swagger", - SwaggerTemplate: docTemplate, -} - -func init() { - swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo) -} diff --git a/core/cmd/server/docs/swagger.go b/core/cmd/server/docs/swagger.go deleted file mode 100644 index b0022e43c..000000000 --- a/core/cmd/server/docs/swagger.go +++ /dev/null @@ -1,6 +0,0 @@ -package docs - -import _ "embed" - -//go:embed swagger.json -var SwaggerJson []byte diff --git a/core/cmd/server/docs/swagger.json b/core/cmd/server/docs/swagger.json deleted file mode 100644 index de2b02277..000000000 --- a/core/cmd/server/docs/swagger.json +++ /dev/null @@ -1,23441 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "description": "开源Linux面板", - "title": "1Panel", - "termsOfService": "http://swagger.io/terms/", - "contact": {}, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "1.0" - }, - "host": "localhost", - "basePath": "/api/v1", - "paths": { - "/apps/:key": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 key 获取应用信息", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search app by key", - "parameters": [ - { - "type": "string", - "description": "app key", - "name": "key", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.AppDTO" - } - } - } - } - }, - "/apps/checkupdate": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取应用更新版本", - "tags": [ - "App" - ], - "summary": "Get app list update", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/apps/detail/:appId/:version/:type": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 appid 获取应用详情", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search app detail by appid", - "parameters": [ - { - "type": "integer", - "description": "app id", - "name": "appId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "app 版本", - "name": "version", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "app 类型", - "name": "version", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.AppDetailDTO" - } - } - } - } - }, - "/apps/details/:id": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 id 获取应用详情", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Get app detail by id", - "parameters": [ - { - "type": "integer", - "description": "id", - "name": "appId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.AppDetailDTO" - } - } - } - } - }, - "/apps/ignored": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取忽略的应用版本", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Get Ignore App", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.IgnoredApp" - } - } - } - } - }, - "/apps/install": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "安装应用", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Install app", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.AppInstallCreate" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.AppInstall" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "app_installs", - "input_column": "name", - "input_value": "name", - "isList": false, - "output_column": "app_id", - "output_value": "appId" - }, - { - "db": "apps", - "info": "appId", - "isList": false, - "output_column": "key", - "output_value": "appKey" - } - ], - "bodyKeys": [ - "name" - ], - "formatEN": "Install app [appKey]-[name]", - "formatZH": "安装应用 [appKey]-[name]", - "paramKeys": [] - } - } - }, - "/apps/installed/check": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "检查应用安装情况", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Check app installed", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.AppInstalledInfo" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.AppInstalledCheck" - } - } - } - } - }, - "/apps/installed/conf": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 key 获取应用默认配置", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search default config by key", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/apps/installed/conninfo/:key": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取应用连接信息", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search app password by key", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/apps/installed/delete/check/:appInstallId": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除前检查", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Check before delete", - "parameters": [ - { - "type": "integer", - "description": "App install id", - "name": "appInstallId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.AppResource" - } - } - } - } - } - }, - "/apps/installed/ignore": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "忽略应用升级版本", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "ignore App Update", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.AppInstalledIgnoreUpgrade" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "installId" - ], - "formatEN": "Application param update [installId]", - "formatZH": "忽略应用 [installId] 版本升级", - "paramKeys": [] - } - } - }, - "/apps/installed/list": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取已安装应用列表", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "List app installed", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.AppInstallInfo" - } - } - } - } - } - }, - "/apps/installed/loadport": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取应用端口", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search app port by key", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "integer" - } - } - } - } - }, - "/apps/installed/op": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作已安装应用", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Operate installed app", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.AppInstalledOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "app_installs", - "input_column": "id", - "input_value": "installId", - "isList": false, - "output_column": "app_id", - "output_value": "appId" - }, - { - "db": "app_installs", - "input_column": "id", - "input_value": "installId", - "isList": false, - "output_column": "name", - "output_value": "appName" - }, - { - "db": "apps", - "input_column": "id", - "input_value": "appId", - "isList": false, - "output_column": "key", - "output_value": "appKey" - } - ], - "bodyKeys": [ - "installId", - "operate" - ], - "formatEN": "[operate] App [appKey][appName]", - "formatZH": "[operate] 应用 [appKey][appName]", - "paramKeys": [] - } - } - }, - "/apps/installed/params/:appInstallId": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 install id 获取应用参数", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search params by appInstallId", - "parameters": [ - { - "type": "string", - "description": "request", - "name": "appInstallId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.AppParam" - } - } - } - } - }, - "/apps/installed/params/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改应用参数", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Change app params", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.AppInstalledUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "installId" - ], - "formatEN": "Application param update [installId]", - "formatZH": "应用参数修改 [installId]", - "paramKeys": [] - } - } - }, - "/apps/installed/port/change": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改应用端口", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Change app port", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.PortUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "key", - "name", - "port" - ], - "formatEN": "Application port update [key]-[name] =\u003e [port]", - "formatZH": "应用端口修改 [key]-[name] =\u003e [port]", - "paramKeys": [] - } - } - }, - "/apps/installed/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "分页获取已安装应用列表", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Page app installed", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.AppInstalledSearch" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/apps/installed/sync": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "同步已安装应用列表", - "tags": [ - "App" - ], - "summary": "Sync app installed", - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "Sync the list of installed apps", - "formatZH": "同步已安装应用列表", - "paramKeys": [] - } - } - }, - "/apps/installed/update/versions": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 install id 获取应用更新版本", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search app update version by install id", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "appInstallId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.AppVersion" - } - } - } - } - } - }, - "/apps/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取应用列表", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "List apps", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.AppSearch" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/apps/services/:key": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 key 获取应用 service", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search app service by key", - "parameters": [ - { - "type": "string", - "description": "request", - "name": "key", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/response.AppService" - } - } - } - } - } - }, - "/apps/sync": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "同步应用列表", - "tags": [ - "App" - ], - "summary": "Sync app list", - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "App store synchronization", - "formatZH": "应用商店同步", - "paramKeys": [] - } - } - }, - "/auth/captcha": { - "get": { - "description": "加载验证码", - "tags": [ - "Auth" - ], - "summary": "Load captcha", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.CaptchaResponse" - } - } - } - } - }, - "/auth/demo": { - "get": { - "description": "判断是否为demo环境", - "tags": [ - "Auth" - ], - "summary": "Check System isDemo", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/auth/issafety": { - "get": { - "description": "获取系统安全登录状态", - "tags": [ - "Auth" - ], - "summary": "Load safety status", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/auth/language": { - "get": { - "description": "获取系统语言设置", - "tags": [ - "Auth" - ], - "summary": "Load System Language", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/auth/login": { - "post": { - "description": "用户登录", - "consumes": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "User login", - "parameters": [ - { - "type": "string", - "description": "安全入口 base64 加密串", - "name": "EntranceCode", - "in": "header", - "required": true - }, - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Login" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.UserLoginInfo" - } - } - } - } - }, - "/auth/logout": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "用户登出", - "tags": [ - "Auth" - ], - "summary": "User logout", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/auth/mfalogin": { - "post": { - "description": "用户 mfa 登录", - "consumes": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "User login with mfa", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MFALogin" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.UserLoginInfo" - }, - "headers": { - "EntranceCode": { - "type": "string", - "description": "安全入口" - } - } - } - } - } - }, - "/containers": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建容器", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Create container", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ContainerOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "image" - ], - "formatEN": "create container [name][image]", - "formatZH": "创建容器 [name][image]", - "paramKeys": [] - } - } - }, - "/containers/clean/log": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "清理容器日志", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Clean container log", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithName" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "clean container [name] logs", - "formatZH": "清理容器 [name] 日志", - "paramKeys": [] - } - } - }, - "/containers/commit": { - "post": { - "description": "容器提交生成新镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Commit Container", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ContainerCommit" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/containers/compose": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建容器编排", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Compose" - ], - "summary": "Create compose", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ComposeCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "create compose [name]", - "formatZH": "创建 compose [name]", - "paramKeys": [] - } - } - }, - "/containers/compose/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "容器编排操作", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Compose" - ], - "summary": "Operate compose", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ComposeOperation" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "operation" - ], - "formatEN": "compose [operation] [name]", - "formatZH": "compose [operation] [name]", - "paramKeys": [] - } - } - }, - "/containers/compose/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取编排列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Compose" - ], - "summary": "Page composes", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/containers/compose/search/log": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "docker-compose 日志", - "tags": [ - "Container Compose" - ], - "summary": "Container Compose logs", - "parameters": [ - { - "type": "string", - "description": "compose 文件地址", - "name": "compose", - "in": "query" - }, - { - "type": "string", - "description": "时间筛选", - "name": "since", - "in": "query" - }, - { - "type": "string", - "description": "是否追踪", - "name": "follow", - "in": "query" - }, - { - "type": "string", - "description": "显示行号", - "name": "tail", - "in": "query" - } - ], - "responses": {} - } - }, - "/containers/compose/test": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "测试 compose 是否可用", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Compose" - ], - "summary": "Test compose", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ComposeCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "check compose [name]", - "formatZH": "检测 compose [name] 格式", - "paramKeys": [] - } - } - }, - "/containers/compose/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新容器编排", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Compose" - ], - "summary": "Update compose", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ComposeUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "update compose information [name]", - "formatZH": "更新 compose [name]", - "paramKeys": [] - } - } - }, - "/containers/daemonjson": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 docker 配置信息", - "produces": [ - "application/json" - ], - "tags": [ - "Container Docker" - ], - "summary": "Load docker daemon.json", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.DaemonJsonConf" - } - } - } - } - }, - "/containers/daemonjson/file": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 docker 配置信息(表单)", - "produces": [ - "application/json" - ], - "tags": [ - "Container Docker" - ], - "summary": "Load docker daemon.json", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/containers/daemonjson/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 docker 配置信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Docker" - ], - "summary": "Update docker daemon.json", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SettingUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "key", - "value" - ], - "formatEN": "Updated configuration [key]", - "formatZH": "更新配置 [key]", - "paramKeys": [] - } - } - }, - "/containers/daemonjson/update/byfile": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "上传替换 docker 配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Docker" - ], - "summary": "Update docker daemon.json by upload file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DaemonJsonUpdateByFile" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "Updated configuration file", - "formatZH": "更新配置文件", - "paramKeys": [] - } - } - }, - "/containers/docker/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Docker 操作", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Docker" - ], - "summary": "Operate docker", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DockerOperation" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operation" - ], - "formatEN": "[operation] docker service", - "formatZH": "docker 服务 [operation]", - "paramKeys": [] - } - } - }, - "/containers/docker/status": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 docker 服务状态", - "produces": [ - "application/json" - ], - "tags": [ - "Container Docker" - ], - "summary": "Load docker status", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/containers/download/log": { - "post": { - "description": "下载容器日志", - "responses": {} - } - }, - "/containers/image": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取镜像名称列表", - "produces": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "load images options", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.Options" - } - } - } - } - } - }, - "/containers/image/all": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取所有镜像列表", - "produces": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "List all images", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.ImageInfo" - } - } - } - } - } - }, - "/containers/image/build": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "构建镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "Build image", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImageBuild" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "build image [name]", - "formatZH": "构建镜像 [name]", - "paramKeys": [] - } - } - }, - "/containers/image/load": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "导入镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "Load image", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImageLoad" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "load image from [path]", - "formatZH": "从 [path] 加载镜像", - "paramKeys": [] - } - } - }, - "/containers/image/pull": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "拉取镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "Pull image", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImagePull" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "image_repos", - "input_column": "id", - "input_value": "repoID", - "isList": false, - "output_column": "name", - "output_value": "reponame" - } - ], - "bodyKeys": [ - "repoID", - "imageName" - ], - "formatEN": "image pull [reponame][imageName]", - "formatZH": "镜像拉取 [reponame][imageName]", - "paramKeys": [] - } - } - }, - "/containers/image/push": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "推送镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "Push image", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImagePush" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "image_repos", - "input_column": "id", - "input_value": "repoID", - "isList": false, - "output_column": "name", - "output_value": "reponame" - } - ], - "bodyKeys": [ - "repoID", - "tagName", - "name" - ], - "formatEN": "push [tagName] to [reponame][name]", - "formatZH": "[tagName] 推送到 [reponame][name]", - "paramKeys": [] - } - } - }, - "/containers/image/remove": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "Delete image", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "names" - ], - "formatEN": "remove image [names]", - "formatZH": "移除镜像 [names]", - "paramKeys": [] - } - } - }, - "/containers/image/save": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "导出镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "Save image", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImageSave" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "tagName", - "path", - "name" - ], - "formatEN": "save [tagName] as [path]/[name]", - "formatZH": "保留 [tagName] 为 [path]/[name]", - "paramKeys": [] - } - } - }, - "/containers/image/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取镜像列表分页", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "Page images", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/containers/image/tag": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Tag 镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Image" - ], - "summary": "Tag image", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImageTag" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "image_repos", - "input_column": "id", - "input_value": "repoID", - "isList": false, - "output_column": "name", - "output_value": "reponame" - } - ], - "bodyKeys": [ - "repoID", - "targetName" - ], - "formatEN": "tag image [reponame][targetName]", - "formatZH": "tag 镜像 [reponame][targetName]", - "paramKeys": [] - } - } - }, - "/containers/info": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器表单信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Load container info", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithName" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.ContainerOperate" - } - } - } - } - }, - "/containers/inspect": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "容器详情", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Container inspect", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.InspectReq" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/containers/ipv6option/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 docker ipv6 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Docker" - ], - "summary": "Update docker daemon.json ipv6 option", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.LogOption" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "Updated the ipv6 option", - "formatZH": "更新 ipv6 配置", - "paramKeys": [] - } - } - }, - "/containers/limit": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器限制", - "summary": "Load container limits", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.ResourceLimit" - } - } - } - } - }, - "/containers/list": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器名称", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "List containers", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/containers/list/stats": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器列表资源占用", - "summary": "Load container stats", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.ContainerListStats" - } - } - } - } - } - }, - "/containers/load/log": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器操作日志", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Load container log", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/containers/logoption/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 docker 日志配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Docker" - ], - "summary": "Update docker daemon.json log option", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.LogOption" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "Updated the log option", - "formatZH": "更新日志配置", - "paramKeys": [] - } - } - }, - "/containers/network": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器网络列表", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Network" - ], - "summary": "List networks", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.Options" - } - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建容器网络", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Network" - ], - "summary": "Create network", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.NetworkCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "create container network [name]", - "formatZH": "创建容器网络 name", - "paramKeys": [] - } - } - }, - "/containers/network/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除容器网络", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Network" - ], - "summary": "Delete network", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "names" - ], - "formatEN": "delete container network [names]", - "formatZH": "删除容器网络 [names]", - "paramKeys": [] - } - } - }, - "/containers/network/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器网络列表分页", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Network" - ], - "summary": "Page networks", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/containers/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "容器操作", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Operate Container", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ContainerOperation" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "names", - "operation" - ], - "formatEN": "container [operation] [names]", - "formatZH": "容器 [names] 执行 [operation]", - "paramKeys": [] - } - } - }, - "/containers/prune": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "容器清理", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Clean container", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ContainerPrune" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.ContainerPruneReport" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "pruneType" - ], - "formatEN": "clean container [pruneType]", - "formatZH": "清理容器 [pruneType]", - "paramKeys": [] - } - } - }, - "/containers/rename": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "容器重命名", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Rename Container", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ContainerRename" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "newName" - ], - "formatEN": "rename container [name] =\u003e [newName]", - "formatZH": "容器重命名 [name] =\u003e [newName]", - "paramKeys": [] - } - } - }, - "/containers/repo": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取镜像仓库列表", - "produces": [ - "application/json" - ], - "tags": [ - "Container Image-repo" - ], - "summary": "List image repos", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.ImageRepoOption" - } - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建镜像仓库", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Image-repo" - ], - "summary": "Create image repo", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImageRepoDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "create image repo [name]", - "formatZH": "创建镜像仓库 [name]", - "paramKeys": [] - } - } - }, - "/containers/repo/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除镜像仓库", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Image-repo" - ], - "summary": "Delete image repo", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImageRepoDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "image_repos", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "name", - "output_value": "names" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete image repo [names]", - "formatZH": "删除镜像仓库 [names]", - "paramKeys": [] - } - } - }, - "/containers/repo/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取镜像仓库列表分页", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Image-repo" - ], - "summary": "Page image repos", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/containers/repo/status": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 docker 仓库状态", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Image-repo" - ], - "summary": "Load repo status", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/containers/repo/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新镜像仓库", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Image-repo" - ], - "summary": "Update image repo", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ImageRepoUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "image_repos", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "update image repo information [name]", - "formatZH": "更新镜像仓库 [name]", - "paramKeys": [] - } - } - }, - "/containers/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器列表分页", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Page containers", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PageContainer" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/containers/search/log": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "容器日志", - "tags": [ - "Container" - ], - "summary": "Container logs", - "parameters": [ - { - "type": "string", - "description": "容器名称", - "name": "container", - "in": "query" - }, - { - "type": "string", - "description": "时间筛选", - "name": "since", - "in": "query" - }, - { - "type": "string", - "description": "是否追踪", - "name": "follow", - "in": "query" - }, - { - "type": "string", - "description": "显示行号", - "name": "tail", - "in": "query" - } - ], - "responses": {} - } - }, - "/containers/stats/:id": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "容器监控信息", - "tags": [ - "Container" - ], - "summary": "Container stats", - "parameters": [ - { - "type": "integer", - "description": "容器id", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.ContainerStats" - } - } - } - } - }, - "/containers/template": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器编排模版列表", - "produces": [ - "application/json" - ], - "tags": [ - "Container Compose-template" - ], - "summary": "List compose templates", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.ComposeTemplateInfo" - } - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建容器编排模版", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Compose-template" - ], - "summary": "Create compose template", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ComposeTemplateCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "create compose template [name]", - "formatZH": "创建 compose 模版 [name]", - "paramKeys": [] - } - } - }, - "/containers/template/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除容器编排模版", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Compose-template" - ], - "summary": "Delete compose template", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "compose_templates", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "name", - "output_value": "names" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete compose template [names]", - "formatZH": "删除 compose 模版 [names]", - "paramKeys": [] - } - } - }, - "/containers/template/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器编排模版列表分页", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Compose-template" - ], - "summary": "Page compose templates", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/containers/template/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新容器编排模版", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Compose-template" - ], - "summary": "Update compose template", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ComposeTemplateUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "compose_templates", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "update compose template information [name]", - "formatZH": "更新 compose 模版 [name]", - "paramKeys": [] - } - } - }, - "/containers/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新容器", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Update container", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ContainerOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "image" - ], - "formatEN": "update container [name][image]", - "formatZH": "更新容器 [name][image]", - "paramKeys": [] - } - } - }, - "/containers/upgrade": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新容器镜像", - "consumes": [ - "application/json" - ], - "tags": [ - "Container" - ], - "summary": "Upgrade container", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ContainerUpgrade" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "image" - ], - "formatEN": "upgrade container image [name][image]", - "formatZH": "更新容器镜像 [name][image]", - "paramKeys": [] - } - } - }, - "/containers/volume": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器存储卷列表", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Volume" - ], - "summary": "List volumes", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.Options" - } - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建容器存储卷", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Volume" - ], - "summary": "Create volume", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.VolumeCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "create container volume [name]", - "formatZH": "创建容器存储卷 [name]", - "paramKeys": [] - } - } - }, - "/containers/volume/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除容器存储卷", - "consumes": [ - "application/json" - ], - "tags": [ - "Container Volume" - ], - "summary": "Delete volume", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "names" - ], - "formatEN": "delete container volume [names]", - "formatZH": "删除容器存储卷 [names]", - "paramKeys": [] - } - } - }, - "/containers/volume/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取容器存储卷分页", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Container Volume" - ], - "summary": "Page volumes", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/cronjobs": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建计划任务", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Create cronjob", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CronjobCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type", - "name" - ], - "formatEN": "create cronjob [type][name]", - "formatZH": "创建计划任务 [type][name]", - "paramKeys": [] - } - } - }, - "/cronjobs/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除计划任务", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Delete cronjob", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CronjobBatchDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "cronjobs", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "name", - "output_value": "names" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete cronjob [names]", - "formatZH": "删除计划任务 [names]", - "paramKeys": [] - } - } - }, - "/cronjobs/download": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "下载计划任务记录", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Download cronjob records", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CronjobDownload" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "job_records", - "input_column": "id", - "input_value": "recordID", - "isList": false, - "output_column": "file", - "output_value": "file" - } - ], - "bodyKeys": [ - "recordID" - ], - "formatEN": "download the cronjob record [file]", - "formatZH": "下载计划任务记录 [file]", - "paramKeys": [] - } - } - }, - "/cronjobs/handle": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "手动执行计划任务", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Handle cronjob once", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "cronjobs", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "manually execute the cronjob [name]", - "formatZH": "手动执行计划任务 [name]", - "paramKeys": [] - } - } - }, - "/cronjobs/records/clean": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "清空计划任务记录", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Clean job records", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CronjobClean" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "cronjobs", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "clean cronjob [name] records", - "formatZH": "清空计划任务记录 [name]", - "paramKeys": [] - } - } - }, - "/cronjobs/records/log": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取计划任务记录日志", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Load Cronjob record log", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/cronjobs/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取计划任务分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Page cronjobs", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PageCronjob" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/cronjobs/search/records": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取计划任务记录", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Page job records", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchRecord" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/cronjobs/status": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新计划任务状态", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Update cronjob status", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CronjobUpdateStatus" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "cronjobs", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id", - "status" - ], - "formatEN": "change the status of cronjob [name] to [status].", - "formatZH": "修改计划任务 [name] 状态为 [status]", - "paramKeys": [] - } - } - }, - "/cronjobs/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新计划任务", - "consumes": [ - "application/json" - ], - "tags": [ - "Cronjob" - ], - "summary": "Update cronjob", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CronjobUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "cronjobs", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "update cronjob [name]", - "formatZH": "更新计划任务 [name]", - "paramKeys": [] - } - } - }, - "/dashboard/base/:ioOption/:netOption": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取首页基础数据", - "consumes": [ - "application/json" - ], - "tags": [ - "Dashboard" - ], - "summary": "Load dashboard base info", - "parameters": [ - { - "type": "string", - "description": "request", - "name": "ioOption", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "request", - "name": "netOption", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.DashboardBase" - } - } - } - } - }, - "/dashboard/base/os": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取服务器基础数据", - "consumes": [ - "application/json" - ], - "tags": [ - "Dashboard" - ], - "summary": "Load os info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.OsInfo" - } - } - } - } - }, - "/dashboard/current/:ioOption/:netOption": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取首页实时数据", - "consumes": [ - "application/json" - ], - "tags": [ - "Dashboard" - ], - "summary": "Load dashboard current info", - "parameters": [ - { - "type": "string", - "description": "request", - "name": "ioOption", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "request", - "name": "netOption", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.DashboardCurrent" - } - } - } - } - }, - "/dashboard/system/restart/:operation": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "重启服务器/面板", - "consumes": [ - "application/json" - ], - "tags": [ - "Dashboard" - ], - "summary": "System restart", - "parameters": [ - { - "type": "string", - "description": "request", - "name": "operation", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/databases": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建 mysql 数据库", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Create mysql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MysqlDBCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "create mysql database [name]", - "formatZH": "创建 mysql 数据库 [name]", - "paramKeys": [] - } - } - }, - "/databases/bind": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "绑定 mysql 数据库用户", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Bind user of mysql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BindUser" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "database", - "username" - ], - "formatEN": "bind mysql database [database] [username]", - "formatZH": "绑定 mysql 数据库名 [database] [username]", - "paramKeys": [] - } - } - }, - "/databases/change/access": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 mysql 访问权限", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Change mysql access", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ChangeDBInfo" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "database_mysqls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Update database [name] access", - "formatZH": "更新数据库 [name] 访问权限", - "paramKeys": [] - } - } - }, - "/databases/change/password": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 mysql 密码", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Change mysql password", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ChangeDBInfo" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "database_mysqls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Update database [name] password", - "formatZH": "更新数据库 [name] 密码", - "paramKeys": [] - } - } - }, - "/databases/common/info": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取数据库基础信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Common" - ], - "summary": "Load base info", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.DBBaseInfo" - } - } - } - } - }, - "/databases/common/load/file": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取数据库配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Common" - ], - "summary": "Load Database conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/databases/common/update/conf": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "上传替换配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Common" - ], - "summary": "Update conf by upload file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DBConfUpdateByFile" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type", - "database" - ], - "formatEN": "update the [type] [database] database configuration information", - "formatZH": "更新 [type] 数据库 [database] 配置信息", - "paramKeys": [] - } - } - }, - "/databases/db": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建远程数据库", - "consumes": [ - "application/json" - ], - "tags": [ - "Database" - ], - "summary": "Create database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DatabaseCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "type" - ], - "formatEN": "create database [name][type]", - "formatZH": "创建远程数据库 [name][type]", - "paramKeys": [] - } - } - }, - "/databases/db/:name": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取远程数据库", - "tags": [ - "Database" - ], - "summary": "Get databases", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.DatabaseInfo" - } - } - } - } - }, - "/databases/db/check": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "检测远程数据库连接性", - "consumes": [ - "application/json" - ], - "tags": [ - "Database" - ], - "summary": "Check database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DatabaseCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "type" - ], - "formatEN": "check if database [name][type] is connectable", - "formatZH": "检测远程数据库 [name][type] 连接性", - "paramKeys": [] - } - } - }, - "/databases/db/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除远程数据库", - "consumes": [ - "application/json" - ], - "tags": [ - "Database" - ], - "summary": "Delete database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DatabaseDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "databases", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "name", - "output_value": "names" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete database [names]", - "formatZH": "删除远程数据库 [names]", - "paramKeys": [] - } - } - }, - "/databases/db/item/:type": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取数据库列表", - "tags": [ - "Database" - ], - "summary": "List databases", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.DatabaseItem" - } - } - } - } - } - }, - "/databases/db/list/:type": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取远程数据库列表", - "tags": [ - "Database" - ], - "summary": "List databases", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.DatabaseOption" - } - } - } - } - } - }, - "/databases/db/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取远程数据库列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Database" - ], - "summary": "Page databases", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DatabaseSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/databases/db/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新远程数据库", - "consumes": [ - "application/json" - ], - "tags": [ - "Database" - ], - "summary": "Update database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DatabaseUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "update database [name]", - "formatZH": "更新远程数据库 [name]", - "paramKeys": [] - } - } - }, - "/databases/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除 mysql 数据库", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Delete mysql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MysqlDBDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "database_mysqls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "delete mysql database [name]", - "formatZH": "删除 mysql 数据库 [name]", - "paramKeys": [] - } - } - }, - "/databases/del/check": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Mysql 数据库删除前检查", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Check before delete mysql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MysqlDBDeleteCheck" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "/databases/description/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 mysql 数据库库描述信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Update mysql database description", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.UpdateDescription" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "database_mysqls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id", - "description" - ], - "formatEN": "The description of the mysql database [name] is modified =\u003e [description]", - "formatZH": "mysql 数据库 [name] 描述信息修改 [description]", - "paramKeys": [] - } - } - }, - "/databases/load": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "从服务器获取", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Load mysql database from remote", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MysqlLoadDB" - } - } - ], - "responses": {} - } - }, - "/databases/options": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 mysql 数据库列表", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "List mysql database names", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PageInfo" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.MysqlOption" - } - } - } - } - } - }, - "/databases/pg": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建 postgresql 数据库", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Create postgresql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PostgresqlDBCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "create postgresql database [name]", - "formatZH": "创建 postgresql 数据库 [name]", - "paramKeys": [] - } - } - }, - "/databases/pg/:database/load": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "从服务器获取", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Load postgresql database from remote", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PostgresqlLoadDB" - } - } - ], - "responses": {} - } - }, - "/databases/pg/bind": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "绑定 postgresql 数据库用户", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Bind postgresql user", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PostgresqlBindUser" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "username" - ], - "formatEN": "bind postgresql database [name] user [username]", - "formatZH": "绑定 postgresql 数据库 [name] 用户 [username]", - "paramKeys": [] - } - } - }, - "/databases/pg/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除 postgresql 数据库", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Delete postgresql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PostgresqlDBDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "database_postgresqls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "delete postgresql database [name]", - "formatZH": "删除 postgresql 数据库 [name]", - "paramKeys": [] - } - } - }, - "/databases/pg/del/check": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Postgresql 数据库删除前检查", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Check before delete postgresql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PostgresqlDBDeleteCheck" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "/databases/pg/description": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 postgresql 数据库库描述信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Update postgresql database description", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.UpdateDescription" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "database_postgresqls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id", - "description" - ], - "formatEN": "The description of the postgresql database [name] is modified =\u003e [description]", - "formatZH": "postgresql 数据库 [name] 描述信息修改 [description]", - "paramKeys": [] - } - } - }, - "/databases/pg/password": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 postgresql 密码", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Change postgresql password", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ChangeDBInfo" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "database_postgresqls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Update database [name] password", - "formatZH": "更新数据库 [name] 密码", - "paramKeys": [] - } - } - }, - "/databases/pg/privileges": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 postgresql 用户权限", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Change postgresql privileges", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ChangeDBInfo" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "database", - "username" - ], - "formatEN": "Update [user] privileges of database [database]", - "formatZH": "更新数据库 [database] 用户 [username] 权限", - "paramKeys": [] - } - } - }, - "/databases/pg/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 postgresql 数据库列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Postgresql" - ], - "summary": "Page postgresql databases", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PostgresqlDBSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/databases/redis/conf": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 redis 配置信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Redis" - ], - "summary": "Load redis conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithName" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.RedisConf" - } - } - } - } - }, - "/databases/redis/conf/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 redis 配置信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Redis" - ], - "summary": "Update redis conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.RedisConfUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "update the redis database configuration information", - "formatZH": "更新 redis 数据库配置信息", - "paramKeys": [] - } - } - }, - "/databases/redis/install/cli": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "安装 redis cli", - "tags": [ - "Database Redis" - ], - "summary": "Install redis-cli", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/databases/redis/password": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 redis 密码", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Redis" - ], - "summary": "Change redis password", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ChangeRedisPass" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "change the password of the redis database", - "formatZH": "修改 redis 数据库密码", - "paramKeys": [] - } - } - }, - "/databases/redis/persistence/conf": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 redis 持久化配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Redis" - ], - "summary": "Load redis persistence conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithName" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.RedisPersistence" - } - } - } - } - }, - "/databases/redis/persistence/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 redis 持久化配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Redis" - ], - "summary": "Update redis persistence conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.RedisConfPersistenceUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "redis database persistence configuration update", - "formatZH": "redis 数据库持久化配置更新", - "paramKeys": [] - } - } - }, - "/databases/redis/status": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 redis 状态信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Redis" - ], - "summary": "Load redis status info", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithName" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.RedisStatus" - } - } - } - } - }, - "/databases/remote": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 mysql 远程访问权限", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Load mysql remote access", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "boolean" - } - } - } - } - }, - "/databases/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 mysql 数据库列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Page mysql databases", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MysqlDBSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/databases/status": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 mysql 状态信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Load mysql status info", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.MysqlStatus" - } - } - } - } - }, - "/databases/variables": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 mysql 性能参数信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Load mysql variables info", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithNameAndType" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.MysqlVariables" - } - } - } - } - }, - "/databases/variables/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "mysql 性能调优", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Update mysql variables", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MysqlVariablesUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "adjust mysql database performance parameters", - "formatZH": "调整 mysql 数据库性能参数", - "paramKeys": [] - } - } - }, - "/db/remote/del/check": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Mysql 远程数据库删除前检查", - "consumes": [ - "application/json" - ], - "tags": [ - "Database" - ], - "summary": "Check before delete remote database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "/files": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建文件/文件夹", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Create file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "Create dir or file [path]", - "formatZH": "创建文件/文件夹 [path]", - "paramKeys": [] - } - } - }, - "/files/batch/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "批量删除文件/文件夹", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Batch delete file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileBatchDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "paths" - ], - "formatEN": "Batch delete dir or file [paths]", - "formatZH": "批量删除文件/文件夹 [paths]", - "paramKeys": [] - } - } - }, - "/files/batch/role": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "批量修改文件权限和用户/组", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Batch change file mode and owner", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileRoleReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "paths", - "mode", - "user", - "group" - ], - "formatEN": "Batch change file mode and owner [paths] =\u003e [mode]/[user]/[group]", - "formatZH": "批量修改文件权限和用户/组 [paths] =\u003e [mode]/[user]/[group]", - "paramKeys": [] - } - } - }, - "/files/check": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "检测文件是否存在", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Check file exist", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FilePathCheck" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/files/chunkdownload": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "分片下载下载文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Chunk Download file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileDownload" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Download file [name]", - "formatZH": "下载文件 [name]", - "paramKeys": [] - } - } - }, - "/files/chunkupload": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "分片上传文件", - "tags": [ - "File" - ], - "summary": "ChunkUpload file", - "parameters": [ - { - "type": "file", - "description": "request", - "name": "file", - "in": "formData", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/files/compress": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "压缩文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Compress file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileCompress" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Compress file [name]", - "formatZH": "压缩文件 [name]", - "paramKeys": [] - } - } - }, - "/files/content": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取文件内容", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Load file content", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileContentReq" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.FileInfo" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "Load file content [path]", - "formatZH": "获取文件内容 [path]", - "paramKeys": [] - } - } - }, - "/files/decompress": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "解压文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Decompress file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileDeCompress" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "Decompress file [path]", - "formatZH": "解压 [path]", - "paramKeys": [] - } - } - }, - "/files/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除文件/文件夹", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Delete file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "Delete dir or file [path]", - "formatZH": "删除文件/文件夹 [path]", - "paramKeys": [] - } - } - }, - "/files/download": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "下载文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Download file", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/files/favorite": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建收藏", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Create favorite", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FavoriteCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "收藏文件/文件夹 [path]", - "formatZH": "收藏文件/文件夹 [path]", - "paramKeys": [] - } - } - }, - "/files/favorite/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除收藏", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Delete favorite", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FavoriteDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "favorites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "path", - "output_value": "path" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "delete avorite [path]", - "formatZH": "删除收藏 [path]", - "paramKeys": [] - } - } - }, - "/files/favorite/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取收藏列表", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "List favorites", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PageInfo" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/files/mode": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改文件权限", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Change file mode", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path", - "mode" - ], - "formatEN": "Change mode [paths] =\u003e [mode]", - "formatZH": "修改权限 [paths] =\u003e [mode]", - "paramKeys": [] - } - } - }, - "/files/move": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "移动文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Move file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileMove" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "oldPaths", - "newPath" - ], - "formatEN": "Move [oldPaths] =\u003e [newPath]", - "formatZH": "移动文件 [oldPaths] =\u003e [newPath]", - "paramKeys": [] - } - } - }, - "/files/owner": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改文件用户/组", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Change file owner", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileRoleUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path", - "user", - "group" - ], - "formatEN": "Change owner [paths] =\u003e [user]/[group]", - "formatZH": "修改用户/组 [paths] =\u003e [user]/[group]", - "paramKeys": [] - } - } - }, - "/files/read": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "按行读取日志文件", - "tags": [ - "File" - ], - "summary": "Read file by Line", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileReadByLineReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/files/recycle/clear": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "清空回收站文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Clear RecycleBin files", - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "清空回收站", - "formatZH": "清空回收站", - "paramKeys": [] - } - } - }, - "/files/recycle/reduce": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "还原回收站文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Reduce RecycleBin files", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.RecycleBinReduce" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Reduce RecycleBin file [name]", - "formatZH": "还原回收站文件 [name]", - "paramKeys": [] - } - } - }, - "/files/recycle/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取回收站文件列表", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "List RecycleBin files", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PageInfo" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/files/recycle/status": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取回收站状态", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Get RecycleBin status", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/files/rename": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改文件名称", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Change file name", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileRename" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "oldName", - "newName" - ], - "formatEN": "Rename [oldName] =\u003e [newName]", - "formatZH": "重命名 [oldName] =\u003e [newName]", - "paramKeys": [] - } - } - }, - "/files/save": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新文件内容", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Update file content", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileEdit" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "Update file content [path]", - "formatZH": "更新文件内容 [path]", - "paramKeys": [] - } - } - }, - "/files/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取文件列表", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "List files", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileOption" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.FileInfo" - } - } - } - } - }, - "/files/size": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取文件夹大小", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Load file size", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.DirSizeReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "Load file size [path]", - "formatZH": "获取文件夹大小 [path]", - "paramKeys": [] - } - } - }, - "/files/tree": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "加载文件树", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Load files tree", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileOption" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/response.FileTree" - } - } - } - } - } - }, - "/files/upload": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "上传文件", - "tags": [ - "File" - ], - "summary": "Upload file", - "parameters": [ - { - "type": "file", - "description": "request", - "name": "file", - "in": "formData", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "path" - ], - "formatEN": "Upload file [path]", - "formatZH": "上传文件 [path]", - "paramKeys": [] - } - } - }, - "/files/upload/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "分页获取上传文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Page file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.SearchUploadWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/response.FileInfo" - } - } - } - } - } - }, - "/files/wget": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "下载远端文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Wget file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.FileWget" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "url", - "path", - "name" - ], - "formatEN": "Download url =\u003e [path]/[name]", - "formatZH": "下载 url =\u003e [path]/[name]", - "paramKeys": [] - } - } - }, - "/groups": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建系统组", - "consumes": [ - "application/json" - ], - "tags": [ - "System Group" - ], - "summary": "Create group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.GroupCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "type" - ], - "formatEN": "create group [name][type]", - "formatZH": "创建组 [name][type]", - "paramKeys": [] - } - } - }, - "/groups/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除系统组", - "consumes": [ - "application/json" - ], - "tags": [ - "System Group" - ], - "summary": "Delete group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "groups", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - }, - { - "db": "groups", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "type", - "output_value": "type" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "delete group [type][name]", - "formatZH": "删除组 [type][name]", - "paramKeys": [] - } - } - }, - "/groups/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "查询系统组", - "consumes": [ - "application/json" - ], - "tags": [ - "System Group" - ], - "summary": "List groups", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.GroupSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.GroupInfo" - } - } - } - } - } - }, - "/groups/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新系统组", - "consumes": [ - "application/json" - ], - "tags": [ - "System Group" - ], - "summary": "Update group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.GroupUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "type" - ], - "formatEN": "update group [name][type]", - "formatZH": "更新组 [name][type]", - "paramKeys": [] - } - } - }, - "/host/conffile/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "上传文件更新 SSH 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "SSH" - ], - "summary": "Update host SSH setting by file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SSHConf" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "update SSH conf", - "formatZH": "修改 SSH 配置文件", - "paramKeys": [] - } - } - }, - "/host/ssh/conf": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 SSH 配置文件", - "tags": [ - "SSH" - ], - "summary": "Load host SSH conf", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/host/ssh/generate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "生成 SSH 密钥", - "consumes": [ - "application/json" - ], - "tags": [ - "SSH" - ], - "summary": "Generate host SSH secret", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.GenerateSSH" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "generate SSH secret", - "formatZH": "生成 SSH 密钥 ", - "paramKeys": [] - } - } - }, - "/host/ssh/log": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 SSH 登录日志", - "consumes": [ - "application/json" - ], - "tags": [ - "SSH" - ], - "summary": "Load host SSH logs", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchSSHLog" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.SSHLog" - } - } - } - } - }, - "/host/ssh/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 SSH 服务状态", - "consumes": [ - "application/json" - ], - "tags": [ - "SSH" - ], - "summary": "Operate SSH", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Operate" - } - } - ], - "responses": {}, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operation" - ], - "formatEN": "[operation] SSH", - "formatZH": "[operation] SSH ", - "paramKeys": [] - } - } - }, - "/host/ssh/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "加载 SSH 配置信息", - "tags": [ - "SSH" - ], - "summary": "Load host SSH setting info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.SSHInfo" - } - } - } - } - }, - "/host/ssh/secret": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 SSH 密钥", - "consumes": [ - "application/json" - ], - "tags": [ - "SSH" - ], - "summary": "Load host SSH secret", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.GenerateLoad" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/host/ssh/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 SSH 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "SSH" - ], - "summary": "Update host SSH setting", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SSHUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "key", - "value" - ], - "formatEN": "update SSH setting [key] =\u003e [value]", - "formatZH": "修改 SSH 配置 [key] =\u003e [value]", - "paramKeys": [] - } - } - }, - "/host/tool": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取主机工具状态", - "consumes": [ - "application/json" - ], - "tags": [ - "Host tool" - ], - "summary": "Get tool", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.HostToolReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/host/tool/config": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作主机工具配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Host tool" - ], - "summary": "Get tool config", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.HostToolConfig" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operate" - ], - "formatEN": "[operate] tool config", - "formatZH": "[operate] 主机工具配置文件 ", - "paramKeys": [] - } - } - }, - "/host/tool/create": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建主机工具配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Host tool" - ], - "summary": "Create Host tool Config", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.HostToolCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type" - ], - "formatEN": "create [type] config", - "formatZH": "创建 [type] 配置", - "paramKeys": [] - } - } - }, - "/host/tool/log": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取主机工具日志", - "consumes": [ - "application/json" - ], - "tags": [ - "Host tool" - ], - "summary": "Get tool", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.HostToolLogReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/host/tool/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作主机工具", - "consumes": [ - "application/json" - ], - "tags": [ - "Host tool" - ], - "summary": "Operate tool", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.HostToolReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operate", - "type" - ], - "formatEN": "[operate] [type]", - "formatZH": "[operate] [type] ", - "paramKeys": [] - } - } - }, - "/host/tool/supervisor/process": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 Supervisor 进程配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Host tool" - ], - "summary": "Get Supervisor process config", - "responses": { - "200": { - "description": "OK" - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作守护进程", - "consumes": [ - "application/json" - ], - "tags": [ - "Host tool" - ], - "summary": "Create Supervisor process", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.SupervisorProcessConfig" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operate" - ], - "formatEN": "[operate] process", - "formatZH": "[operate] 守护进程 ", - "paramKeys": [] - } - } - }, - "/host/tool/supervisor/process/file": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作 Supervisor 进程文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Host tool" - ], - "summary": "Get Supervisor process config", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.SupervisorProcessFileReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operate" - ], - "formatEN": "[operate] Supervisor Process Config file", - "formatZH": "[operate] Supervisor 进程文件 ", - "paramKeys": [] - } - } - }, - "/hosts": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建主机", - "consumes": [ - "application/json" - ], - "tags": [ - "Host" - ], - "summary": "Create host", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.HostOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "addr" - ], - "formatEN": "create host [name][addr]", - "formatZH": "创建主机 [name][addr]", - "paramKeys": [] - } - } - }, - "/hosts/command": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取快速命令列表", - "tags": [ - "Command" - ], - "summary": "List commands", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.CommandInfo" - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建快速命令", - "consumes": [ - "application/json" - ], - "tags": [ - "Command" - ], - "summary": "Create command", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CommandOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "command" - ], - "formatEN": "create quick command [name][command]", - "formatZH": "创建快捷命令 [name][command]", - "paramKeys": [] - } - } - }, - "/hosts/command/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除快速命令", - "consumes": [ - "application/json" - ], - "tags": [ - "Command" - ], - "summary": "Delete command", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDeleteReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "commands", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "name", - "output_value": "names" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete quick command [names]", - "formatZH": "删除快捷命令 [names]", - "paramKeys": [] - } - } - }, - "/hosts/command/redis": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 redis 快速命令列表", - "tags": [ - "Redis Command" - ], - "summary": "List redis commands", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "Array" - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "保存 Redis 快速命令", - "consumes": [ - "application/json" - ], - "tags": [ - "Redis Command" - ], - "summary": "Save redis command", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.RedisCommand" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "command" - ], - "formatEN": "save quick command for redis [name][command]", - "formatZH": "保存 redis 快捷命令 [name][command]", - "paramKeys": [] - } - } - }, - "/hosts/command/redis/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除 redis 快速命令", - "consumes": [ - "application/json" - ], - "tags": [ - "Redis Command" - ], - "summary": "Delete redis command", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDeleteReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "redis_commands", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "name", - "output_value": "names" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete quick command of redis [names]", - "formatZH": "删除 redis 快捷命令 [names]", - "paramKeys": [] - } - } - }, - "/hosts/command/redis/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 redis 快速命令列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Redis Command" - ], - "summary": "Page redis commands", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/hosts/command/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取快速命令列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Command" - ], - "summary": "Page commands", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/hosts/command/tree": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取快速命令树", - "consumes": [ - "application/json" - ], - "tags": [ - "Command" - ], - "summary": "Tree commands", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "Array" - } - } - } - } - }, - "/hosts/command/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新快速命令", - "consumes": [ - "application/json" - ], - "tags": [ - "Command" - ], - "summary": "Update command", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CommandOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "update quick command [name]", - "formatZH": "更新快捷命令 [name]", - "paramKeys": [] - } - } - }, - "/hosts/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除主机", - "consumes": [ - "application/json" - ], - "tags": [ - "Host" - ], - "summary": "Delete host", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDeleteReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "hosts", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "addr", - "output_value": "addrs" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete host [addrs]", - "formatZH": "删除主机 [addrs]", - "paramKeys": [] - } - } - }, - "/hosts/firewall/base": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取防火墙基础信息", - "tags": [ - "Firewall" - ], - "summary": "Load firewall base info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.FirewallBaseInfo" - } - } - } - } - }, - "/hosts/firewall/batch": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "批量删除防火墙规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Create group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchRuleOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/hosts/firewall/forward": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新防火墙端口转发规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Create group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ForwardRuleOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "source_port" - ], - "formatEN": "update port forward rules [source_port]", - "formatZH": "更新端口转发规则 [source_port]", - "paramKeys": [] - } - } - }, - "/hosts/firewall/ip": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建防火墙 IP 规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Create group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.AddrRuleOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "strategy", - "address" - ], - "formatEN": "create address rules [strategy][address]", - "formatZH": "添加 ip 规则 [strategy] [address]", - "paramKeys": [] - } - } - }, - "/hosts/firewall/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改防火墙状态", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Page firewall status", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.FirewallOperation" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operation" - ], - "formatEN": "[operation] firewall", - "formatZH": "[operation] 防火墙", - "paramKeys": [] - } - } - }, - "/hosts/firewall/port": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建防火墙端口规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Create group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PortRuleOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "port", - "strategy" - ], - "formatEN": "create port rules [strategy][port]", - "formatZH": "添加端口规则 [strategy] [port]", - "paramKeys": [] - } - } - }, - "/hosts/firewall/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取防火墙规则列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Page firewall rules", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.RuleSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/hosts/firewall/update/addr": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 ip 防火墙规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Create group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.AddrRuleUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/hosts/firewall/update/description": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新防火墙描述", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Update rule description", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.UpdateFirewallDescription" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/hosts/firewall/update/port": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新端口防火墙规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Firewall" - ], - "summary": "Create group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PortRuleUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/hosts/monitor/clean": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "清空监控数据", - "tags": [ - "Monitor" - ], - "summary": "Clean monitor datas", - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "clean monitor datas", - "formatZH": "清空监控数据", - "paramKeys": [] - } - } - }, - "/hosts/monitor/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取监控数据", - "tags": [ - "Monitor" - ], - "summary": "Load monitor datas", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MonitorSearch" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/hosts/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取主机列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Host" - ], - "summary": "Page host", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchHostWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.HostTree" - } - } - } - } - } - }, - "/hosts/test/byid/:id": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "测试主机连接", - "consumes": [ - "application/json" - ], - "tags": [ - "Host" - ], - "summary": "Test host conn by host id", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "boolean" - } - } - } - } - }, - "/hosts/test/byinfo": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "测试主机连接", - "consumes": [ - "application/json" - ], - "tags": [ - "Host" - ], - "summary": "Test host conn by info", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.HostConnTest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/hosts/tree": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "加载主机树", - "consumes": [ - "application/json" - ], - "tags": [ - "Host" - ], - "summary": "Load host tree", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchForTree" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.HostTree" - } - } - } - } - } - }, - "/hosts/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新主机", - "consumes": [ - "application/json" - ], - "tags": [ - "Host" - ], - "summary": "Update host", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.HostOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "addr" - ], - "formatEN": "update host [name][addr]", - "formatZH": "更新主机信息 [name][addr]", - "paramKeys": [] - } - } - }, - "/hosts/update/group": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "切换分组", - "consumes": [ - "application/json" - ], - "tags": [ - "Host" - ], - "summary": "Update host group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ChangeHostGroup" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "hosts", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "addr", - "output_value": "addr" - } - ], - "bodyKeys": [ - "id", - "group" - ], - "formatEN": "change host [addr] group =\u003e [group]", - "formatZH": "切换主机[addr]分组 =\u003e [group]", - "paramKeys": [] - } - } - }, - "/logs/clean": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "清空操作日志", - "consumes": [ - "application/json" - ], - "tags": [ - "Logs" - ], - "summary": "Clean operation logs", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CleanLog" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "logType" - ], - "formatEN": "Clean the [logType] log information", - "formatZH": "清空 [logType] 日志信息", - "paramKeys": [] - } - } - }, - "/logs/login": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统登录日志列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Logs" - ], - "summary": "Page login logs", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchLgLogWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/logs/operation": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统操作日志列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Logs" - ], - "summary": "Page operation logs", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchOpLogWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/logs/system": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统日志", - "tags": [ - "Logs" - ], - "summary": "Load system logs", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/logs/system/files": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统日志文件列表", - "tags": [ - "Logs" - ], - "summary": "Load system log files", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/openresty": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 OpenResty 配置信息", - "tags": [ - "OpenResty" - ], - "summary": "Load OpenResty conf", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.FileInfo" - } - } - } - } - }, - "/openresty/clear": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "清理 OpenResty 代理缓存", - "tags": [ - "OpenResty" - ], - "summary": "Clear OpenResty proxy cache", - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "Clear nginx proxy cache", - "formatZH": "清理 Openresty 代理缓存", - "paramKeys": [] - } - } - }, - "/openresty/file": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "上传更新 OpenResty 配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "OpenResty" - ], - "summary": "Update OpenResty conf by upload file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxConfigFileUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "Update nginx conf", - "formatZH": "更新 nginx 配置", - "paramKeys": [] - } - } - }, - "/openresty/scope": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取部分 OpenResty 配置信息", - "consumes": [ - "application/json" - ], - "tags": [ - "OpenResty" - ], - "summary": "Load partial OpenResty conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxScopeReq" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/response.NginxParam" - } - } - } - } - } - }, - "/openresty/status": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 OpenResty 状态信息", - "tags": [ - "OpenResty" - ], - "summary": "Load OpenResty status info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.NginxStatus" - } - } - } - } - }, - "/openresty/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 OpenResty 配置信息", - "consumes": [ - "application/json" - ], - "tags": [ - "OpenResty" - ], - "summary": "Update OpenResty conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxConfigUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteId", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteId" - ], - "formatEN": "Update nginx conf [domain]", - "formatZH": "更新 nginx 配置 [domain]", - "paramKeys": [] - } - } - }, - "/process/stop": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "停止进程", - "tags": [ - "Process" - ], - "summary": "Stop Process", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.ProcessReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "PID" - ], - "formatEN": "结束进程 [PID]", - "formatZH": "结束进程 [PID]", - "paramKeys": [] - } - } - }, - "/runtimes": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建运行环境", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "Create runtime", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.RuntimeCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Create runtime [name]", - "formatZH": "创建运行环境 [name]", - "paramKeys": [] - } - } - }, - "/runtimes/:id": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取运行环境", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "Get runtime", - "parameters": [ - { - "type": "string", - "description": "request", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除运行环境", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Delete runtime", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.RuntimeDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "id" - ], - "formatEN": "Delete website [name]", - "formatZH": "删除网站 [name]", - "paramKeys": [] - } - } - }, - "/runtimes/node/modules": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 Node 项目的 modules", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "Get Node modules", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NodeModuleReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/node/modules/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作 Node 项目 modules", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "Operate Node modules", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NodeModuleReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/node/package": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 Node 项目的 scripts", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "Get Node package scripts", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NodePackageReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作运行环境", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "Operate runtime", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.RuntimeOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "id" - ], - "formatEN": "Operate runtime [name]", - "formatZH": "操作运行环境 [name]", - "paramKeys": [] - } - } - }, - "/runtimes/php/extensions": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Create Extensions", - "consumes": [ - "application/json" - ], - "tags": [ - "PHP Extensions" - ], - "summary": "Create Extensions", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.PHPExtensionsCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/php/extensions/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Delete Extensions", - "consumes": [ - "application/json" - ], - "tags": [ - "PHP Extensions" - ], - "summary": "Delete Extensions", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.PHPExtensionsDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/php/extensions/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Page Extensions", - "consumes": [ - "application/json" - ], - "tags": [ - "PHP Extensions" - ], - "summary": "Page Extensions", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.PHPExtensionsSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/response.PHPExtensionsDTO" - } - } - } - } - } - }, - "/runtimes/php/extensions/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Update Extensions", - "consumes": [ - "application/json" - ], - "tags": [ - "PHP Extensions" - ], - "summary": "Update Extensions", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.PHPExtensionsUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取运行环境列表", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "List runtimes", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.RuntimeSearch" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/sync": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "同步运行环境状态", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "Sync runtime status", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/runtimes/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新运行环境", - "consumes": [ - "application/json" - ], - "tags": [ - "Runtime" - ], - "summary": "Update runtime", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.RuntimeUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Update runtime [name]", - "formatZH": "更新运行环境 [name]", - "paramKeys": [] - } - } - }, - "/settings/backup": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建备份账号", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Create backup account", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BackupOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type" - ], - "formatEN": "create backup account [type]", - "formatZH": "创建备份账号 [type]", - "paramKeys": [] - } - } - }, - "/settings/backup/backup": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "备份系统数据", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Backup system data", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CommonBackup" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type", - "name", - "detailName" - ], - "formatEN": "backup [type] data [name][detailName]", - "formatZH": "备份 [type] 数据 [name][detailName]", - "paramKeys": [] - } - } - }, - "/settings/backup/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除备份账号", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Delete backup account", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "backup_accounts", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "type", - "output_value": "types" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "delete backup account [types]", - "formatZH": "删除备份账号 [types]", - "paramKeys": [] - } - } - }, - "/settings/backup/onedrive": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 OneDrive 信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Load OneDrive info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.OneDriveInfo" - } - } - } - } - }, - "/settings/backup/record/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除备份记录", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Delete backup record", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDeleteReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "backup_records", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "file_name", - "output_value": "files" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete backup records [files]", - "formatZH": "删除备份记录 [files]", - "paramKeys": [] - } - } - }, - "/settings/backup/record/download": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "下载备份记录", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Download backup record", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.DownloadRecord" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "source", - "fileName" - ], - "formatEN": "download backup records [source][fileName]", - "formatZH": "下载备份记录 [source][fileName]", - "paramKeys": [] - } - } - }, - "/settings/backup/record/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取备份记录列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Page backup records", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.RecordSearch" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/settings/backup/record/search/bycronjob": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过计划任务获取备份记录列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Page backup records by cronjob", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.RecordSearchByCronjob" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/settings/backup/recover": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "恢复系统数据", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Recover system data", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CommonRecover" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type", - "name", - "detailName", - "file" - ], - "formatEN": "recover [type] data [name][detailName] from [file]", - "formatZH": "从 [file] 恢复 [type] 数据 [name][detailName]", - "paramKeys": [] - } - } - }, - "/settings/backup/recover/byupload": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "从上传恢复系统数据", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Recover system data by upload", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CommonRecover" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type", - "name", - "detailName", - "file" - ], - "formatEN": "recover [type] data [name][detailName] from [file]", - "formatZH": "从 [file] 恢复 [type] 数据 [name][detailName]", - "paramKeys": [] - } - } - }, - "/settings/backup/refresh/onedrive": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "刷新 OneDrive token", - "tags": [ - "Backup Account" - ], - "summary": "Refresh OneDrive token", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/settings/backup/search": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取备份账号列表", - "tags": [ - "Backup Account" - ], - "summary": "List backup accounts", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.BackupInfo" - } - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 bucket 列表", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "List buckets", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ForBuckets" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "/settings/backup/search/files": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取备份账号内文件列表", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "List files from backup accounts", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BackupSearchFile" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "/settings/backup/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新备份账号信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Backup Account" - ], - "summary": "Update backup account", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BackupOperate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type" - ], - "formatEN": "update backup account [types]", - "formatZH": "更新备份账号 [types]", - "paramKeys": [] - } - } - }, - "/settings/basedir": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取安装根目录", - "tags": [ - "System Setting" - ], - "summary": "Load local backup dir", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/settings/bind/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新系统监听信息", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Update system bind info", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BindInfo" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "ipv6", - "bindAddress" - ], - "formatEN": "update system bind info =\u003e ipv6: [ipv6], 监听 IP: [bindAddress]", - "formatZH": "修改系统监听信息 =\u003e ipv6: [ipv6], 监听 IP: [bindAddress]", - "paramKeys": [] - } - } - }, - "/settings/expired/handle": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "重置过期系统登录密码", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Reset system password expired", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PasswordUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "reset an expired Password", - "formatZH": "重置过期密码", - "paramKeys": [] - } - } - }, - "/settings/interface": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统地址信息", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Load system address", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/settings/menu/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "隐藏高级功能菜单", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Update system setting", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SettingUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "Hide advanced feature menu.", - "formatZH": "隐藏高级功能菜单", - "paramKeys": [] - } - } - }, - "/settings/mfa": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 mfa 信息", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Load mfa info", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MfaCredential" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/mfa.Otp" - } - } - } - } - }, - "/settings/mfa/bind": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Mfa 绑定", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Bind mfa", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.MfaCredential" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "bind mfa", - "formatZH": "mfa 绑定", - "paramKeys": [] - } - } - }, - "/settings/password/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新系统登录密码", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Update system password", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PasswordUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "update system password", - "formatZH": "修改系统密码", - "paramKeys": [] - } - } - }, - "/settings/port/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新系统端口", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Update system port", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PortUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "serverPort" - ], - "formatEN": "update system port =\u003e [serverPort]", - "formatZH": "修改系统端口 =\u003e [serverPort]", - "paramKeys": [] - } - } - }, - "/settings/proxy/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "服务器代理配置", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Update proxy setting", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ProxyUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "proxyUrl", - "proxyPort" - ], - "formatEN": "set proxy [proxyPort]:[proxyPort].", - "formatZH": "服务器代理配置 [proxyPort]:[proxyPort]", - "paramKeys": [] - } - } - }, - "/settings/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "加载系统配置信息", - "tags": [ - "System Setting" - ], - "summary": "Load system setting info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.SettingInfo" - } - } - } - } - }, - "/settings/search/available": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统可用状态", - "tags": [ - "System Setting" - ], - "summary": "Load system available status", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/settings/snapshot": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建系统快照", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Create system snapshot", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SnapshotCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "from", - "description" - ], - "formatEN": "Create system backup [description] to [from]", - "formatZH": "创建系统快照 [description] 到 [from]", - "paramKeys": [] - } - } - }, - "/settings/snapshot/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除系统快照", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Delete system backup", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SnapshotBatchDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "snapshots", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "Delete system backup [name]", - "formatZH": "删除系统快照 [name]", - "paramKeys": [] - } - } - }, - "/settings/snapshot/description/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新快照描述信息", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Update snapshot description", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.UpdateDescription" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "snapshots", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id", - "description" - ], - "formatEN": "The description of the snapshot [name] is modified =\u003e [description]", - "formatZH": "快照 [name] 描述信息修改 [description]", - "paramKeys": [] - } - } - }, - "/settings/snapshot/import": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "导入已有快照", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Import system snapshot", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SnapshotImport" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "from", - "names" - ], - "formatEN": "Sync system snapshots [names] from [from]", - "formatZH": "从 [from] 同步系统快照 [names]", - "paramKeys": [] - } - } - }, - "/settings/snapshot/recover": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "从系统快照恢复", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Recover system backup", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SnapshotRecover" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "snapshots", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Recover from system backup [name]", - "formatZH": "从系统快照 [name] 恢复", - "paramKeys": [] - } - } - }, - "/settings/snapshot/rollback": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "从系统快照回滚", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Rollback system backup", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SnapshotRecover" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "snapshots", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Rollback from system backup [name]", - "formatZH": "从系统快照 [name] 回滚", - "paramKeys": [] - } - } - }, - "/settings/snapshot/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统快照列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Page system snapshot", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/settings/snapshot/status": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取快照状态", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Load Snapshot status", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/settings/ssl/download": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "下载证书", - "tags": [ - "System Setting" - ], - "summary": "Download system cert", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/settings/ssl/info": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取证书信息", - "tags": [ - "System Setting" - ], - "summary": "Load system cert info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.SettingInfo" - } - } - } - } - }, - "/settings/ssl/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改系统 ssl 登录", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Update system ssl", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SSLUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "ssl" - ], - "formatEN": "update system ssl =\u003e [ssl]", - "formatZH": "修改系统 ssl =\u003e [ssl]", - "paramKeys": [] - } - } - }, - "/settings/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新系统配置", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Update system setting", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SettingUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "key", - "value" - ], - "formatEN": "update system setting [key] =\u003e [value]", - "formatZH": "修改系统配置 [key] =\u003e [value]", - "paramKeys": [] - } - } - }, - "/settings/upgrade": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取版本 release notes", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Load release notes by version", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Upgrade" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "系统更新", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Upgrade", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Upgrade" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "version" - ], - "formatEN": "upgrade system =\u003e [version]", - "formatZH": "更新系统 =\u003e [version]", - "paramKeys": [] - } - } - }, - "/toolbox/clam": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建扫描规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Create clam", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ClamCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "path" - ], - "formatEN": "create clam [name][path]", - "formatZH": "创建扫描规则 [name][path]", - "paramKeys": [] - } - } - }, - "/toolbox/clam/base": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 Clam 基础信息", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Load clam base info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.ClamBaseInfo" - } - } - } - } - }, - "/toolbox/clam/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除扫描规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Delete clam", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ClamDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "clams", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "name", - "output_value": "names" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete clam [names]", - "formatZH": "删除扫描规则 [names]", - "paramKeys": [] - } - } - }, - "/toolbox/clam/file/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取扫描文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Load clam file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ClamFileReq" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/toolbox/clam/file/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新病毒扫描配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Update clam file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.UpdateByNameAndFile" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/toolbox/clam/handle": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "执行病毒扫描", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Handle clam scan", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "clams", - "input_column": "id", - "input_value": "id", - "isList": true, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "handle clam scan [name]", - "formatZH": "执行病毒扫描 [name]", - "paramKeys": [] - } - } - }, - "/toolbox/clam/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 Clam 状态", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Operate Clam", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Operate" - } - } - ], - "responses": {}, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operation" - ], - "formatEN": "[operation] FTP", - "formatZH": "[operation] Clam", - "paramKeys": [] - } - } - }, - "/toolbox/clam/record/clean": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "清空扫描报告", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Clean clam record", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": {}, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "clams", - "input_column": "id", - "input_value": "id", - "isList": true, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "clean clam record [name]", - "formatZH": "清空扫描报告 [name]", - "paramKeys": [] - } - } - }, - "/toolbox/clam/record/log": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取扫描结果详情", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Load clam record detail", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ClamLogReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/toolbox/clam/record/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取扫描结果列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Page clam record", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ClamLogSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/toolbox/clam/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取扫描规则列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Page clam", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/toolbox/clam/status/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改扫描规则状态", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Update clam status", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ClamUpdateStatus" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "clams", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id", - "status" - ], - "formatEN": "change the status of clam [name] to [status].", - "formatZH": "修改扫描规则 [name] 状态为 [status]", - "paramKeys": [] - } - } - }, - "/toolbox/clam/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改扫描规则", - "consumes": [ - "application/json" - ], - "tags": [ - "Clam" - ], - "summary": "Update clam", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ClamUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name", - "path" - ], - "formatEN": "update clam [name][path]", - "formatZH": "修改扫描规则 [name][path]", - "paramKeys": [] - } - } - }, - "/toolbox/clean": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "清理系统垃圾文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Device" - ], - "summary": "Clean system", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.Clean" - } - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "Clean system junk files", - "formatZH": "清理系统垃圾文件", - "paramKeys": [] - } - } - }, - "/toolbox/device/base": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取设备基础信息", - "tags": [ - "Device" - ], - "summary": "Load device base info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.DeviceBaseInfo" - } - } - } - } - }, - "/toolbox/device/check/dns": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "检查系统 DNS 配置可用性", - "consumes": [ - "application/json" - ], - "tags": [ - "Device" - ], - "summary": "Check device DNS conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SettingUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/toolbox/device/conf": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Device" - ], - "summary": "load conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.OperationWithName" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/toolbox/device/update/byconf": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过文件修改配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Device" - ], - "summary": "Update device conf by file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.UpdateByNameAndFile" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/toolbox/device/update/conf": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改系统参数", - "consumes": [ - "application/json" - ], - "tags": [ - "Device" - ], - "summary": "Update device", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SettingUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "key", - "value" - ], - "formatEN": "update device conf [key] =\u003e [value]", - "formatZH": "修改主机参数 [key] =\u003e [value]", - "paramKeys": [] - } - } - }, - "/toolbox/device/update/host": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改系统 hosts", - "tags": [ - "Device" - ], - "summary": "Update device hosts", - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "key", - "value" - ], - "formatEN": "update device host [key] =\u003e [value]", - "formatZH": "修改主机 Host [key] =\u003e [value]", - "paramKeys": [] - } - } - }, - "/toolbox/device/update/passwd": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改系统密码", - "consumes": [ - "application/json" - ], - "tags": [ - "Device" - ], - "summary": "Update device passwd", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ChangePasswd" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/toolbox/device/update/swap": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改系统 Swap", - "consumes": [ - "application/json" - ], - "tags": [ - "Device" - ], - "summary": "Update device swap", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SwapHelper" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operate", - "path" - ], - "formatEN": "[operate] device swap [path]", - "formatZH": "[operate] 主机 swap [path]", - "paramKeys": [] - } - } - }, - "/toolbox/device/zone/options": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取系统可用时区选项", - "consumes": [ - "application/json" - ], - "tags": [ - "Device" - ], - "summary": "list time zone options", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "Array" - } - } - } - } - }, - "/toolbox/fail2ban/base": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 Fail2ban 基础信息", - "tags": [ - "Fail2ban" - ], - "summary": "Load fail2ban base info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.Fail2BanBaseInfo" - } - } - } - } - }, - "/toolbox/fail2ban/load/conf": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 fail2ban 配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Fail2ban" - ], - "summary": "Load fail2ban conf", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/toolbox/fail2ban/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 Fail2ban 状态", - "consumes": [ - "application/json" - ], - "tags": [ - "Fail2ban" - ], - "summary": "Operate fail2ban", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Operate" - } - } - ], - "responses": {}, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operation" - ], - "formatEN": "[operation] Fail2ban", - "formatZH": "[operation] Fail2ban", - "paramKeys": [] - } - } - }, - "/toolbox/fail2ban/operate/sshd": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "配置 sshd", - "consumes": [ - "application/json" - ], - "tags": [ - "Fail2ban" - ], - "summary": "Operate sshd of fail2ban", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Operate" - } - } - ], - "responses": {} - } - }, - "/toolbox/fail2ban/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 Fail2ban ip", - "consumes": [ - "application/json" - ], - "tags": [ - "Fail2ban" - ], - "summary": "Page fail2ban ip list", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Fail2BanSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "Array" - } - } - } - } - }, - "/toolbox/fail2ban/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 Fail2ban 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Fail2ban" - ], - "summary": "Update fail2ban conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Fail2BanUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "key", - "value" - ], - "formatEN": "update fail2ban conf [key] =\u003e [value]", - "formatZH": "修改 Fail2ban 配置 [key] =\u003e [value]", - "paramKeys": [] - } - } - }, - "/toolbox/fail2ban/update/byconf": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过文件修改 fail2ban 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Fail2ban" - ], - "summary": "Update fail2ban conf by file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.UpdateByFile" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/toolbox/ftp": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建 FTP 账户", - "consumes": [ - "application/json" - ], - "tags": [ - "FTP" - ], - "summary": "Create FTP user", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.FtpCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "user", - "path" - ], - "formatEN": "create FTP [user][path]", - "formatZH": "创建 FTP 账户 [user][path]", - "paramKeys": [] - } - } - }, - "/toolbox/ftp/base": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 FTP 基础信息", - "tags": [ - "FTP" - ], - "summary": "Load FTP base info", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.FtpBaseInfo" - } - } - } - } - }, - "/toolbox/ftp/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除 FTP 账户", - "consumes": [ - "application/json" - ], - "tags": [ - "FTP" - ], - "summary": "Delete FTP user", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDeleteReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "ftps", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "user", - "output_value": "users" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "delete FTP users [users]", - "formatZH": "删除 FTP 账户 [users]", - "paramKeys": [] - } - } - }, - "/toolbox/ftp/log/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 FTP 操作日志", - "consumes": [ - "application/json" - ], - "tags": [ - "FTP" - ], - "summary": "Load FTP operation log", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.FtpLogSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/toolbox/ftp/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 FTP 状态", - "consumes": [ - "application/json" - ], - "tags": [ - "FTP" - ], - "summary": "Operate FTP", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.Operate" - } - } - ], - "responses": {}, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "operation" - ], - "formatEN": "[operation] FTP", - "formatZH": "[operation] FTP", - "paramKeys": [] - } - } - }, - "/toolbox/ftp/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 FTP 账户列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "FTP" - ], - "summary": "Page FTP user", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchWithPage" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/toolbox/ftp/sync": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "同步 FTP 账户", - "consumes": [ - "application/json" - ], - "tags": [ - "FTP" - ], - "summary": "Sync FTP user", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BatchDeleteReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "sync FTP users", - "formatZH": "同步 FTP 账户", - "paramKeys": [] - } - } - }, - "/toolbox/ftp/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改 FTP 账户", - "consumes": [ - "application/json" - ], - "tags": [ - "FTP" - ], - "summary": "Update FTP user", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.FtpUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "user", - "path" - ], - "formatEN": "update FTP [user][path]", - "formatZH": "修改 FTP 账户 [user][path]", - "paramKeys": [] - } - } - }, - "/toolbox/scan": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "扫描系统垃圾文件", - "tags": [ - "Device" - ], - "summary": "Scan system", - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [], - "formatEN": "scan System Junk Files", - "formatZH": "扫描系统垃圾文件", - "paramKeys": [] - } - } - }, - "/websites": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建网站", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Create website", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "primaryDomain" - ], - "formatEN": "Create website [primaryDomain]", - "formatZH": "创建网站 [primaryDomain]", - "paramKeys": [] - } - } - }, - "/websites/:id": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 id 查询网站", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Search website by id", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.WebsiteDTO" - } - } - } - } - }, - "/websites/:id/config/:type": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 id 查询网站 nginx", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Nginx" - ], - "summary": "Search website nginx by id", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.FileInfo" - } - } - } - } - }, - "/websites/:id/https": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 https 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website HTTPS" - ], - "summary": "Load https conf", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.WebsiteHTTPS" - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 https 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website HTTPS" - ], - "summary": "Update https conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteHTTPSOp" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.WebsiteHTTPS" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteId", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteId" - ], - "formatEN": "Update website https [domain] conf", - "formatZH": "更新网站 [domain] https 配置", - "paramKeys": [] - } - } - }, - "/websites/acme": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建网站 acme", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Acme" - ], - "summary": "Create website acme account", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteAcmeAccountCreate" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.WebsiteAcmeAccountDTO" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "email" - ], - "formatEN": "Create website acme [email]", - "formatZH": "创建网站 acme [email]", - "paramKeys": [] - } - } - }, - "/websites/acme/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除网站 acme", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Acme" - ], - "summary": "Delete website acme account", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteResourceReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_acme_accounts", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "email", - "output_value": "email" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Delete website acme [email]", - "formatZH": "删除网站 acme [email]", - "paramKeys": [] - } - } - }, - "/websites/acme/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站 acme 列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Acme" - ], - "summary": "Page website acme accounts", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PageInfo" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/websites/auths": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取密码访问配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Get AuthBasic conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxAuthReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/auths/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新密码访问配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Get AuthBasic conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxAuthUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/ca": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建网站 ca", - "consumes": [ - "application/json" - ], - "tags": [ - "Website CA" - ], - "summary": "Create website ca", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteCACreate" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/request.WebsiteCACreate" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Create website ca [name]", - "formatZH": "创建网站 ca [name]", - "paramKeys": [] - } - } - }, - "/websites/ca/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除网站 ca", - "consumes": [ - "application/json" - ], - "tags": [ - "Website CA" - ], - "summary": "Delete website ca", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteCommonReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_cas", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Delete website ca [name]", - "formatZH": "删除网站 ca [name]", - "paramKeys": [] - } - } - }, - "/websites/ca/download": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "下载 CA 证书文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Website CA" - ], - "summary": "Download CA file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteResourceReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_cas", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "download ca file [name]", - "formatZH": "下载 CA 证书文件 [name]", - "paramKeys": [] - } - } - }, - "/websites/ca/obtain": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "自签 SSL 证书", - "consumes": [ - "application/json" - ], - "tags": [ - "Website CA" - ], - "summary": "Obtain SSL", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteCAObtain" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_cas", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Obtain SSL [name]", - "formatZH": "自签 SSL 证书 [name]", - "paramKeys": [] - } - } - }, - "/websites/ca/renew": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "续签 SSL 证书", - "consumes": [ - "application/json" - ], - "tags": [ - "Website CA" - ], - "summary": "Obtain SSL", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteCAObtain" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_cas", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Obtain SSL [name]", - "formatZH": "自签 SSL 证书 [name]", - "paramKeys": [] - } - } - }, - "/websites/ca/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站 ca 列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Website CA" - ], - "summary": "Page website ca", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteCASearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/websites/ca/{id}": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站 ca", - "consumes": [ - "application/json" - ], - "tags": [ - "Website CA" - ], - "summary": "Get website ca", - "parameters": [ - { - "type": "integer", - "description": "id", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.WebsiteCADTO" - } - } - } - } - }, - "/websites/check": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "网站创建前检查", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Check before create website", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteInstallCheckReq" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/response.WebsitePreInstallCheck" - } - } - } - } - } - }, - "/websites/config": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 nginx 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Nginx" - ], - "summary": "Load nginx conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxScopeReq" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.WebsiteNginxConfig" - } - } - } - } - }, - "/websites/config/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 nginx 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Nginx" - ], - "summary": "Update nginx conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxConfigUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteId", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteId" - ], - "formatEN": "Nginx conf update [domain]", - "formatZH": "nginx 配置修改 [domain]", - "paramKeys": [] - } - } - }, - "/websites/default/html/:type": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取默认 html", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Get default html", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.FileInfo" - } - } - } - } - }, - "/websites/default/html/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新默认 html", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update default html", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteHtmlUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type" - ], - "formatEN": "Update default html", - "formatZH": "更新默认 html", - "paramKeys": [] - } - } - }, - "/websites/default/server": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作网站日志", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Change default server", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteDefaultUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id", - "operate" - ], - "formatEN": "Change default server =\u003e [domain]", - "formatZH": "修改默认 server =\u003e [domain]", - "paramKeys": [] - } - } - }, - "/websites/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除网站", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Delete website", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Delete website [domain]", - "formatZH": "删除网站 [domain]", - "paramKeys": [] - } - } - }, - "/websites/dir": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站目录配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Get website dir", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteCommonReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/dir/permission": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新网站目录权限", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update Site Dir permission", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteUpdateDirPermission" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Update domain [domain] dir permission", - "formatZH": "更新网站 [domain] 目录权限", - "paramKeys": [] - } - } - }, - "/websites/dir/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新网站目录", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update Site Dir", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteUpdateDir" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Update domain [domain] dir", - "formatZH": "更新网站 [domain] 目录", - "paramKeys": [] - } - } - }, - "/websites/dns": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建网站 dns", - "consumes": [ - "application/json" - ], - "tags": [ - "Website DNS" - ], - "summary": "Create website dns account", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteDnsAccountCreate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Create website dns [name]", - "formatZH": "创建网站 dns [name]", - "paramKeys": [] - } - } - }, - "/websites/dns/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除网站 dns", - "consumes": [ - "application/json" - ], - "tags": [ - "Website DNS" - ], - "summary": "Delete website dns account", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteResourceReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_dns_accounts", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Delete website dns [name]", - "formatZH": "删除网站 dns [name]", - "paramKeys": [] - } - } - }, - "/websites/dns/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站 dns 列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Website DNS" - ], - "summary": "Page website dns accounts", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.PageInfo" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/websites/dns/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新网站 dns", - "consumes": [ - "application/json" - ], - "tags": [ - "Website DNS" - ], - "summary": "Update website dns account", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteDnsAccountUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Update website dns [name]", - "formatZH": "更新网站 dns [name]", - "paramKeys": [] - } - } - }, - "/websites/domains": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建网站域名", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Domain" - ], - "summary": "Create website domain", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteDomainCreate" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.WebsiteDomain" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "domain" - ], - "formatEN": "Create domain [domain]", - "formatZH": "创建域名 [domain]", - "paramKeys": [] - } - } - }, - "/websites/domains/:websiteId": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过网站 id 查询域名", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Domain" - ], - "summary": "Search website domains by websiteId", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "websiteId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.WebsiteDomain" - } - } - } - } - } - }, - "/websites/domains/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除网站域名", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Domain" - ], - "summary": "Delete website domain", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteDomainDelete" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_domains", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Delete domain [domain]", - "formatZH": "删除域名 [domain]", - "paramKeys": [] - } - } - }, - "/websites/leech": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取防盗链配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Get AntiLeech conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxCommonReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/leech/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新防盗链配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update AntiLeech", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxAntiLeechUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/list": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站列表", - "tags": [ - "Website" - ], - "summary": "List websites", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/response.WebsiteDTO" - } - } - } - } - } - }, - "/websites/log": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作网站日志", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Operate website log", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteLogReq" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.WebsiteLog" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id", - "operate" - ], - "formatEN": "[domain][operate] logs", - "formatZH": "[domain][operate] 日志", - "paramKeys": [] - } - } - }, - "/websites/nginx/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 网站 nginx 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Nginx" - ], - "summary": "Update website nginx conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteNginxUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "[domain] Nginx conf update", - "formatZH": "[domain] Nginx 配置修改", - "paramKeys": [] - } - } - }, - "/websites/operate": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "操作网站", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Operate website", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteOp" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id", - "operate" - ], - "formatEN": "[operate] website [domain]", - "formatZH": "[operate] 网站 [domain]", - "paramKeys": [] - } - } - }, - "/websites/options": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站列表", - "tags": [ - "Website" - ], - "summary": "List website names", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "/websites/php/config": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 网站 PHP 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website PHP" - ], - "summary": "Update website php conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsitePHPConfigUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "[domain] PHP conf update", - "formatZH": "[domain] PHP 配置修改", - "paramKeys": [] - } - } - }, - "/websites/php/config/:id": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站 php 配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Load website php conf", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.PHPConfig" - } - } - } - } - }, - "/websites/php/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 php 配置文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Website PHP" - ], - "summary": "Update php conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsitePHPFileUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteId", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteId" - ], - "formatEN": "Nginx conf update [domain]", - "formatZH": "php 配置修改 [domain]", - "paramKeys": [] - } - } - }, - "/websites/php/version": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "变更 php 版本", - "consumes": [ - "application/json" - ], - "tags": [ - "Website PHP" - ], - "summary": "Update php version", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsitePHPVersionReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteId", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteId" - ], - "formatEN": "php version update [domain]", - "formatZH": "php 版本变更 [domain]", - "paramKeys": [] - } - } - }, - "/websites/proxies": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取反向代理配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Get proxy conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteProxyReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/proxies/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改反向代理配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update proxy conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteProxyConfig" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Update domain [domain] proxy config", - "formatZH": "修改网站 [domain] 反向代理配置 ", - "paramKeys": [] - } - } - }, - "/websites/proxy/file": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新反向代理文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update proxy file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxProxyUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteID", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteID" - ], - "formatEN": "Nginx conf proxy file update [domain]", - "formatZH": "更新反向代理文件 [domain]", - "paramKeys": [] - } - } - }, - "/websites/redirect": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取重定向配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Get redirect conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteProxyReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/redirect/file": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新重定向文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update redirect file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxRedirectUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteID", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteID" - ], - "formatEN": "Nginx conf redirect file update [domain]", - "formatZH": "更新重定向文件 [domain]", - "paramKeys": [] - } - } - }, - "/websites/redirect/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改重定向配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update redirect conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxRedirectReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteID", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteID" - ], - "formatEN": "Update domain [domain] redirect config", - "formatZH": "修改网站 [domain] 重定向理配置 ", - "paramKeys": [] - } - } - }, - "/websites/rewrite": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取伪静态配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Get rewrite conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxRewriteReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/rewrite/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新伪静态配置", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update rewrite conf", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.NginxRewriteUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "websites", - "input_column": "id", - "input_value": "websiteID", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "websiteID" - ], - "formatEN": "Nginx conf rewrite update [domain]", - "formatZH": "伪静态配置修改 [domain]", - "paramKeys": [] - } - } - }, - "/websites/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Page websites", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteSearch" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.PageResult" - } - } - } - } - }, - "/websites/ssl": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建网站 ssl", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Create website ssl", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteSSLCreate" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/request.WebsiteSSLCreate" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "primaryDomain" - ], - "formatEN": "Create website ssl [primaryDomain]", - "formatZH": "创建网站 ssl [primaryDomain]", - "paramKeys": [] - } - } - }, - "/websites/ssl/:id": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 id 查询 ssl", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Search website ssl by id", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/ssl/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除网站 ssl", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Delete website ssl", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteBatchDelReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_ssls", - "input_column": "id", - "input_value": "ids", - "isList": true, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "ids" - ], - "formatEN": "Delete ssl [domain]", - "formatZH": "删除 ssl [domain]", - "paramKeys": [] - } - } - }, - "/websites/ssl/download": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "下载证书文件", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Download SSL file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteResourceReq" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_ssls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "download ssl file [domain]", - "formatZH": "下载证书文件 [domain]", - "paramKeys": [] - } - } - }, - "/websites/ssl/obtain": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "申请证书", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Apply ssl", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteSSLApply" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_ssls", - "input_column": "id", - "input_value": "ID", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "ID" - ], - "formatEN": "apply ssl [domain]", - "formatZH": "申请证书 [domain]", - "paramKeys": [] - } - } - }, - "/websites/ssl/resolve": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "解析网站 ssl", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Resolve website ssl", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteDNSReq" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/response.WebsiteDNSRes" - } - } - } - } - } - }, - "/websites/ssl/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站 ssl 列表分页", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Page website ssl", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteSSLSearch" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/ssl/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新 ssl", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Update ssl", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteSSLUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [ - { - "db": "website_ssls", - "input_column": "id", - "input_value": "id", - "isList": false, - "output_column": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Update ssl config [domain]", - "formatZH": "更新证书设置 [domain]", - "paramKeys": [] - } - } - }, - "/websites/ssl/upload": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "上传 ssl", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Upload ssl", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteSSLUpload" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "type" - ], - "formatEN": "Upload ssl [type]", - "formatZH": "上传 ssl [type]", - "paramKeys": [] - } - } - }, - "/websites/ssl/website/:websiteId": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过网站 id 查询 ssl", - "consumes": [ - "application/json" - ], - "tags": [ - "Website SSL" - ], - "summary": "Search website ssl by website id", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "websiteId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/websites/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新网站", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Update website", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteUpdate" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "primaryDomain" - ], - "formatEN": "Update website [primaryDomain]", - "formatZH": "更新网站 [primaryDomain]", - "paramKeys": [] - } - } - } - }, - "definitions": { - "dto.AddrRuleOperate": { - "type": "object", - "required": [ - "address", - "operation", - "strategy" - ], - "properties": { - "address": { - "type": "string" - }, - "description": { - "type": "string" - }, - "operation": { - "type": "string", - "enum": [ - "add", - "remove" - ] - }, - "strategy": { - "type": "string", - "enum": [ - "accept", - "drop" - ] - } - } - }, - "dto.AddrRuleUpdate": { - "type": "object", - "properties": { - "newRule": { - "$ref": "#/definitions/dto.AddrRuleOperate" - }, - "oldRule": { - "$ref": "#/definitions/dto.AddrRuleOperate" - } - } - }, - "dto.AppInstallInfo": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "key": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "dto.AppResource": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "dto.AppVersion": { - "type": "object", - "properties": { - "detailId": { - "type": "integer" - }, - "dockerCompose": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.BackupInfo": { - "type": "object", - "properties": { - "backupPath": { - "type": "string" - }, - "bucket": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "vars": { - "type": "string" - } - } - }, - "dto.BackupOperate": { - "type": "object", - "required": [ - "type", - "vars" - ], - "properties": { - "accessKey": { - "type": "string" - }, - "backupPath": { - "type": "string" - }, - "bucket": { - "type": "string" - }, - "credential": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "vars": { - "type": "string" - } - } - }, - "dto.BackupSearchFile": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string" - } - } - }, - "dto.BatchDelete": { - "type": "object", - "required": [ - "names" - ], - "properties": { - "force": { - "type": "boolean" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "dto.BatchDeleteReq": { - "type": "object", - "required": [ - "ids" - ], - "properties": { - "ids": { - "type": "array", - "items": { - "type": "integer" - } - } - } - }, - "dto.BatchRuleOperate": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "rules": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.PortRuleOperate" - } - }, - "type": { - "type": "string" - } - } - }, - "dto.BindInfo": { - "type": "object", - "required": [ - "bindAddress", - "ipv6" - ], - "properties": { - "bindAddress": { - "type": "string" - }, - "ipv6": { - "type": "string", - "enum": [ - "enable", - "disable" - ] - } - } - }, - "dto.BindUser": { - "type": "object", - "required": [ - "database", - "db", - "password", - "permission", - "username" - ], - "properties": { - "database": { - "type": "string" - }, - "db": { - "type": "string" - }, - "password": { - "type": "string" - }, - "permission": { - "type": "string" - }, - "username": { - "type": "string" - } - } - }, - "dto.CaptchaResponse": { - "type": "object", - "properties": { - "captchaID": { - "type": "string" - }, - "imagePath": { - "type": "string" - } - } - }, - "dto.ChangeDBInfo": { - "type": "object", - "required": [ - "database", - "from", - "type", - "value" - ], - "properties": { - "database": { - "type": "string" - }, - "from": { - "type": "string", - "enum": [ - "local", - "remote" - ] - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string", - "enum": [ - "mysql", - "mariadb", - "postgresql" - ] - }, - "value": { - "type": "string" - } - } - }, - "dto.ChangeHostGroup": { - "type": "object", - "required": [ - "groupID", - "id" - ], - "properties": { - "groupID": { - "type": "integer" - }, - "id": { - "type": "integer" - } - } - }, - "dto.ChangePasswd": { - "type": "object", - "properties": { - "passwd": { - "type": "string" - }, - "user": { - "type": "string" - } - } - }, - "dto.ChangeRedisPass": { - "type": "object", - "required": [ - "database" - ], - "properties": { - "database": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "dto.ClamBaseInfo": { - "type": "object", - "properties": { - "freshIsActive": { - "type": "boolean" - }, - "freshIsExist": { - "type": "boolean" - }, - "freshVersion": { - "type": "string" - }, - "isActive": { - "type": "boolean" - }, - "isExist": { - "type": "boolean" - }, - "version": { - "type": "string" - } - } - }, - "dto.ClamCreate": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "infectedDir": { - "type": "string" - }, - "infectedStrategy": { - "type": "string" - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - }, - "spec": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "dto.ClamDelete": { - "type": "object", - "required": [ - "ids" - ], - "properties": { - "ids": { - "type": "array", - "items": { - "type": "integer" - } - }, - "removeInfected": { - "type": "boolean" - }, - "removeRecord": { - "type": "boolean" - } - } - }, - "dto.ClamFileReq": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string" - }, - "tail": { - "type": "string" - } - } - }, - "dto.ClamLogReq": { - "type": "object", - "properties": { - "clamName": { - "type": "string" - }, - "recordName": { - "type": "string" - }, - "tail": { - "type": "string" - } - } - }, - "dto.ClamLogSearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "clamID": { - "type": "integer" - }, - "endTime": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "startTime": { - "type": "string" - } - } - }, - "dto.ClamUpdate": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "infectedDir": { - "type": "string" - }, - "infectedStrategy": { - "type": "string" - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - }, - "spec": { - "type": "string" - } - } - }, - "dto.ClamUpdateStatus": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "status": { - "type": "string" - } - } - }, - "dto.Clean": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "size": { - "type": "integer" - }, - "treeType": { - "type": "string" - } - } - }, - "dto.CleanLog": { - "type": "object", - "required": [ - "logType" - ], - "properties": { - "logType": { - "type": "string", - "enum": [ - "login", - "operation" - ] - } - } - }, - "dto.CommandInfo": { - "type": "object", - "properties": { - "command": { - "type": "string" - }, - "groupBelong": { - "type": "string" - }, - "groupID": { - "type": "integer" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, - "dto.CommandOperate": { - "type": "object", - "required": [ - "command", - "name" - ], - "properties": { - "command": { - "type": "string" - }, - "groupBelong": { - "type": "string" - }, - "groupID": { - "type": "integer" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, - "dto.CommonBackup": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "detailName": { - "type": "string" - }, - "name": { - "type": "string" - }, - "secret": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "app", - "mysql", - "mariadb", - "redis", - "website", - "postgresql" - ] - } - } - }, - "dto.CommonRecover": { - "type": "object", - "required": [ - "source", - "type" - ], - "properties": { - "detailName": { - "type": "string" - }, - "file": { - "type": "string" - }, - "name": { - "type": "string" - }, - "secret": { - "type": "string" - }, - "source": { - "type": "string", - "enum": [ - "OSS", - "S3", - "SFTP", - "MINIO", - "LOCAL", - "COS", - "KODO", - "OneDrive", - "WebDAV" - ] - }, - "type": { - "type": "string", - "enum": [ - "app", - "mysql", - "mariadb", - "redis", - "website", - "postgresql" - ] - } - } - }, - "dto.ComposeCreate": { - "type": "object", - "required": [ - "from" - ], - "properties": { - "file": { - "type": "string" - }, - "from": { - "type": "string", - "enum": [ - "edit", - "path", - "template" - ] - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - }, - "template": { - "type": "integer" - } - } - }, - "dto.ComposeOperation": { - "type": "object", - "required": [ - "name", - "operation", - "path" - ], - "properties": { - "name": { - "type": "string" - }, - "operation": { - "type": "string", - "enum": [ - "start", - "stop", - "down" - ] - }, - "path": { - "type": "string" - }, - "withFile": { - "type": "boolean" - } - } - }, - "dto.ComposeTemplateCreate": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "content": { - "type": "string" - }, - "description": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "dto.ComposeTemplateInfo": { - "type": "object", - "properties": { - "content": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, - "dto.ComposeTemplateUpdate": { - "type": "object", - "properties": { - "content": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "integer" - } - } - }, - "dto.ComposeUpdate": { - "type": "object", - "required": [ - "content", - "name", - "path" - ], - "properties": { - "content": { - "type": "string" - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - } - } - }, - "dto.ContainerCommit": { - "type": "object", - "required": [ - "containerID" - ], - "properties": { - "author": { - "type": "string" - }, - "comment": { - "type": "string" - }, - "containerID": { - "type": "string" - }, - "containerName": { - "type": "string" - }, - "newImageName": { - "type": "string" - }, - "pause": { - "type": "boolean" - } - } - }, - "dto.ContainerListStats": { - "type": "object", - "properties": { - "containerID": { - "type": "string" - }, - "cpuPercent": { - "type": "number" - }, - "cpuTotalUsage": { - "type": "integer" - }, - "memoryCache": { - "type": "integer" - }, - "memoryLimit": { - "type": "integer" - }, - "memoryPercent": { - "type": "number" - }, - "memoryUsage": { - "type": "integer" - }, - "percpuUsage": { - "type": "integer" - }, - "systemUsage": { - "type": "integer" - } - } - }, - "dto.ContainerOperate": { - "type": "object", - "required": [ - "image", - "name" - ], - "properties": { - "autoRemove": { - "type": "boolean" - }, - "cmd": { - "type": "array", - "items": { - "type": "string" - } - }, - "containerID": { - "type": "string" - }, - "cpuShares": { - "type": "integer" - }, - "entrypoint": { - "type": "array", - "items": { - "type": "string" - } - }, - "env": { - "type": "array", - "items": { - "type": "string" - } - }, - "exposedPorts": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.PortHelper" - } - }, - "forcePull": { - "type": "boolean" - }, - "image": { - "type": "string" - }, - "ipv4": { - "type": "string" - }, - "ipv6": { - "type": "string" - }, - "labels": { - "type": "array", - "items": { - "type": "string" - } - }, - "memory": { - "type": "number" - }, - "name": { - "type": "string" - }, - "nanoCPUs": { - "type": "number" - }, - "network": { - "type": "string" - }, - "openStdin": { - "type": "boolean" - }, - "privileged": { - "type": "boolean" - }, - "publishAllPorts": { - "type": "boolean" - }, - "restartPolicy": { - "type": "string" - }, - "tty": { - "type": "boolean" - }, - "volumes": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.VolumeHelper" - } - } - } - }, - "dto.ContainerOperation": { - "type": "object", - "required": [ - "names", - "operation" - ], - "properties": { - "names": { - "type": "array", - "items": { - "type": "string" - } - }, - "operation": { - "type": "string", - "enum": [ - "start", - "stop", - "restart", - "kill", - "pause", - "unpause", - "remove" - ] - } - } - }, - "dto.ContainerPrune": { - "type": "object", - "required": [ - "pruneType" - ], - "properties": { - "pruneType": { - "type": "string", - "enum": [ - "container", - "image", - "volume", - "network", - "buildcache" - ] - }, - "withTagAll": { - "type": "boolean" - } - } - }, - "dto.ContainerPruneReport": { - "type": "object", - "properties": { - "deletedNumber": { - "type": "integer" - }, - "spaceReclaimed": { - "type": "integer" - } - } - }, - "dto.ContainerRename": { - "type": "object", - "required": [ - "name", - "newName" - ], - "properties": { - "name": { - "type": "string" - }, - "newName": { - "type": "string" - } - } - }, - "dto.ContainerStats": { - "type": "object", - "properties": { - "cache": { - "type": "number" - }, - "cpuPercent": { - "type": "number" - }, - "ioRead": { - "type": "number" - }, - "ioWrite": { - "type": "number" - }, - "memory": { - "type": "number" - }, - "networkRX": { - "type": "number" - }, - "networkTX": { - "type": "number" - }, - "shotTime": { - "type": "string" - } - } - }, - "dto.ContainerUpgrade": { - "type": "object", - "required": [ - "image", - "name" - ], - "properties": { - "forcePull": { - "type": "boolean" - }, - "image": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "dto.CronjobBatchDelete": { - "type": "object", - "required": [ - "ids" - ], - "properties": { - "cleanData": { - "type": "boolean" - }, - "ids": { - "type": "array", - "items": { - "type": "integer" - } - } - } - }, - "dto.CronjobClean": { - "type": "object", - "required": [ - "cronjobID" - ], - "properties": { - "cleanData": { - "type": "boolean" - }, - "cronjobID": { - "type": "integer" - }, - "isDelete": { - "type": "boolean" - } - } - }, - "dto.CronjobCreate": { - "type": "object", - "required": [ - "name", - "spec", - "type" - ], - "properties": { - "appID": { - "type": "string" - }, - "backupAccounts": { - "type": "string" - }, - "command": { - "type": "string" - }, - "containerName": { - "type": "string" - }, - "dbName": { - "type": "string" - }, - "dbType": { - "type": "string" - }, - "defaultDownload": { - "type": "string" - }, - "exclusionRules": { - "type": "string" - }, - "name": { - "type": "string" - }, - "retainCopies": { - "type": "integer", - "minimum": 1 - }, - "script": { - "type": "string" - }, - "secret": { - "type": "string" - }, - "sourceDir": { - "type": "string" - }, - "spec": { - "type": "string" - }, - "type": { - "type": "string" - }, - "url": { - "type": "string" - }, - "website": { - "type": "string" - } - } - }, - "dto.CronjobDownload": { - "type": "object", - "required": [ - "backupAccountID", - "recordID" - ], - "properties": { - "backupAccountID": { - "type": "integer" - }, - "recordID": { - "type": "integer" - } - } - }, - "dto.CronjobUpdate": { - "type": "object", - "required": [ - "id", - "name", - "spec" - ], - "properties": { - "appID": { - "type": "string" - }, - "backupAccounts": { - "type": "string" - }, - "command": { - "type": "string" - }, - "containerName": { - "type": "string" - }, - "dbName": { - "type": "string" - }, - "dbType": { - "type": "string" - }, - "defaultDownload": { - "type": "string" - }, - "exclusionRules": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "retainCopies": { - "type": "integer", - "minimum": 1 - }, - "script": { - "type": "string" - }, - "secret": { - "type": "string" - }, - "sourceDir": { - "type": "string" - }, - "spec": { - "type": "string" - }, - "url": { - "type": "string" - }, - "website": { - "type": "string" - } - } - }, - "dto.CronjobUpdateStatus": { - "type": "object", - "required": [ - "id", - "status" - ], - "properties": { - "id": { - "type": "integer" - }, - "status": { - "type": "string" - } - } - }, - "dto.DBBaseInfo": { - "type": "object", - "properties": { - "containerName": { - "type": "string" - }, - "name": { - "type": "string" - }, - "port": { - "type": "integer" - } - } - }, - "dto.DBConfUpdateByFile": { - "type": "object", - "required": [ - "database", - "type" - ], - "properties": { - "database": { - "type": "string" - }, - "file": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "mysql", - "mariadb", - "postgresql", - "redis" - ] - } - } - }, - "dto.DaemonJsonConf": { - "type": "object", - "properties": { - "cgroupDriver": { - "type": "string" - }, - "experimental": { - "type": "boolean" - }, - "fixedCidrV6": { - "type": "string" - }, - "insecureRegistries": { - "type": "array", - "items": { - "type": "string" - } - }, - "ip6Tables": { - "type": "boolean" - }, - "iptables": { - "type": "boolean" - }, - "ipv6": { - "type": "boolean" - }, - "isSwarm": { - "type": "boolean" - }, - "liveRestore": { - "type": "boolean" - }, - "logMaxFile": { - "type": "string" - }, - "logMaxSize": { - "type": "string" - }, - "registryMirrors": { - "type": "array", - "items": { - "type": "string" - } - }, - "status": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.DaemonJsonUpdateByFile": { - "type": "object", - "properties": { - "file": { - "type": "string" - } - } - }, - "dto.DashboardBase": { - "type": "object", - "properties": { - "appInstalledNumber": { - "type": "integer" - }, - "cpuCores": { - "type": "integer" - }, - "cpuLogicalCores": { - "type": "integer" - }, - "cpuModelName": { - "type": "string" - }, - "cronjobNumber": { - "type": "integer" - }, - "currentInfo": { - "$ref": "#/definitions/dto.DashboardCurrent" - }, - "databaseNumber": { - "type": "integer" - }, - "hostname": { - "type": "string" - }, - "kernelArch": { - "type": "string" - }, - "kernelVersion": { - "type": "string" - }, - "os": { - "type": "string" - }, - "platform": { - "type": "string" - }, - "platformFamily": { - "type": "string" - }, - "platformVersion": { - "type": "string" - }, - "virtualizationSystem": { - "type": "string" - }, - "websiteNumber": { - "type": "integer" - } - } - }, - "dto.DashboardCurrent": { - "type": "object", - "properties": { - "cpuPercent": { - "type": "array", - "items": { - "type": "number" - } - }, - "cpuTotal": { - "type": "integer" - }, - "cpuUsed": { - "type": "number" - }, - "cpuUsedPercent": { - "type": "number" - }, - "diskData": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.DiskInfo" - } - }, - "gpuData": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.GPUInfo" - } - }, - "ioCount": { - "type": "integer" - }, - "ioReadBytes": { - "type": "integer" - }, - "ioReadTime": { - "type": "integer" - }, - "ioWriteBytes": { - "type": "integer" - }, - "ioWriteTime": { - "type": "integer" - }, - "load1": { - "type": "number" - }, - "load15": { - "type": "number" - }, - "load5": { - "type": "number" - }, - "loadUsagePercent": { - "type": "number" - }, - "memoryAvailable": { - "type": "integer" - }, - "memoryTotal": { - "type": "integer" - }, - "memoryUsed": { - "type": "integer" - }, - "memoryUsedPercent": { - "type": "number" - }, - "netBytesRecv": { - "type": "integer" - }, - "netBytesSent": { - "type": "integer" - }, - "procs": { - "type": "integer" - }, - "shotTime": { - "type": "string" - }, - "swapMemoryAvailable": { - "type": "integer" - }, - "swapMemoryTotal": { - "type": "integer" - }, - "swapMemoryUsed": { - "type": "integer" - }, - "swapMemoryUsedPercent": { - "type": "number" - }, - "timeSinceUptime": { - "type": "string" - }, - "uptime": { - "type": "integer" - } - } - }, - "dto.DatabaseCreate": { - "type": "object", - "required": [ - "from", - "name", - "type", - "username", - "version" - ], - "properties": { - "address": { - "type": "string" - }, - "clientCert": { - "type": "string" - }, - "clientKey": { - "type": "string" - }, - "description": { - "type": "string" - }, - "from": { - "type": "string", - "enum": [ - "local", - "remote" - ] - }, - "name": { - "type": "string", - "maxLength": 256 - }, - "password": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "rootCert": { - "type": "string" - }, - "skipVerify": { - "type": "boolean" - }, - "ssl": { - "type": "boolean" - }, - "type": { - "type": "string" - }, - "username": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.DatabaseDelete": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "deleteBackup": { - "type": "boolean" - }, - "forceDelete": { - "type": "boolean" - }, - "id": { - "type": "integer" - } - } - }, - "dto.DatabaseInfo": { - "type": "object", - "properties": { - "address": { - "type": "string" - }, - "clientCert": { - "type": "string" - }, - "clientKey": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "from": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string", - "maxLength": 256 - }, - "password": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "rootCert": { - "type": "string" - }, - "skipVerify": { - "type": "boolean" - }, - "ssl": { - "type": "boolean" - }, - "type": { - "type": "string" - }, - "username": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.DatabaseItem": { - "type": "object", - "properties": { - "database": { - "type": "string" - }, - "from": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, - "dto.DatabaseOption": { - "type": "object", - "properties": { - "address": { - "type": "string" - }, - "database": { - "type": "string" - }, - "from": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.DatabaseSearch": { - "type": "object", - "required": [ - "order", - "orderBy", - "page", - "pageSize" - ], - "properties": { - "info": { - "type": "string" - }, - "order": { - "type": "string", - "enum": [ - "null", - "ascending", - "descending" - ] - }, - "orderBy": { - "type": "string", - "enum": [ - "name", - "created_at" - ] - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "type": { - "type": "string" - } - } - }, - "dto.DatabaseUpdate": { - "type": "object", - "required": [ - "type", - "username", - "version" - ], - "properties": { - "address": { - "type": "string" - }, - "clientCert": { - "type": "string" - }, - "clientKey": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "password": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "rootCert": { - "type": "string" - }, - "skipVerify": { - "type": "boolean" - }, - "ssl": { - "type": "boolean" - }, - "type": { - "type": "string" - }, - "username": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.DeviceBaseInfo": { - "type": "object", - "properties": { - "dns": { - "type": "array", - "items": { - "type": "string" - } - }, - "hostname": { - "type": "string" - }, - "hosts": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.HostHelper" - } - }, - "localTime": { - "type": "string" - }, - "maxSize": { - "type": "integer" - }, - "ntp": { - "type": "string" - }, - "swapDetails": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.SwapHelper" - } - }, - "swapMemoryAvailable": { - "type": "integer" - }, - "swapMemoryTotal": { - "type": "integer" - }, - "swapMemoryUsed": { - "type": "integer" - }, - "timeZone": { - "type": "string" - }, - "user": { - "type": "string" - } - } - }, - "dto.DiskInfo": { - "type": "object", - "properties": { - "device": { - "type": "string" - }, - "free": { - "type": "integer" - }, - "inodesFree": { - "type": "integer" - }, - "inodesTotal": { - "type": "integer" - }, - "inodesUsed": { - "type": "integer" - }, - "inodesUsedPercent": { - "type": "number" - }, - "path": { - "type": "string" - }, - "total": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "used": { - "type": "integer" - }, - "usedPercent": { - "type": "number" - } - } - }, - "dto.DockerOperation": { - "type": "object", - "required": [ - "operation" - ], - "properties": { - "operation": { - "type": "string", - "enum": [ - "start", - "restart", - "stop" - ] - } - } - }, - "dto.DownloadRecord": { - "type": "object", - "required": [ - "fileDir", - "fileName", - "source" - ], - "properties": { - "fileDir": { - "type": "string" - }, - "fileName": { - "type": "string" - }, - "source": { - "type": "string", - "enum": [ - "OSS", - "S3", - "SFTP", - "MINIO", - "LOCAL", - "COS", - "KODO", - "OneDrive", - "WebDAV" - ] - } - } - }, - "dto.Fail2BanBaseInfo": { - "type": "object", - "properties": { - "banAction": { - "type": "string" - }, - "banTime": { - "type": "string" - }, - "findTime": { - "type": "string" - }, - "isActive": { - "type": "boolean" - }, - "isEnable": { - "type": "boolean" - }, - "isExist": { - "type": "boolean" - }, - "logPath": { - "type": "string" - }, - "maxRetry": { - "type": "integer" - }, - "port": { - "type": "integer" - }, - "version": { - "type": "string" - } - } - }, - "dto.Fail2BanSearch": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "banned", - "ignore" - ] - } - } - }, - "dto.Fail2BanUpdate": { - "type": "object", - "required": [ - "key" - ], - "properties": { - "key": { - "type": "string", - "enum": [ - "port", - "bantime", - "findtime", - "maxretry", - "banaction", - "logpath", - "port" - ] - }, - "value": { - "type": "string" - } - } - }, - "dto.FirewallBaseInfo": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "pingStatus": { - "type": "string" - }, - "status": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.FirewallOperation": { - "type": "object", - "required": [ - "operation" - ], - "properties": { - "operation": { - "type": "string", - "enum": [ - "start", - "stop", - "restart", - "disablePing", - "enablePing" - ] - } - } - }, - "dto.ForBuckets": { - "type": "object", - "required": [ - "credential", - "type", - "vars" - ], - "properties": { - "accessKey": { - "type": "string" - }, - "credential": { - "type": "string" - }, - "type": { - "type": "string" - }, - "vars": { - "type": "string" - } - } - }, - "dto.ForwardRuleOperate": { - "type": "object", - "properties": { - "rules": { - "type": "array", - "items": { - "type": "object", - "required": [ - "operation", - "port", - "protocol", - "targetPort" - ], - "properties": { - "num": { - "type": "string" - }, - "operation": { - "type": "string", - "enum": [ - "add", - "remove" - ] - }, - "port": { - "type": "string" - }, - "protocol": { - "type": "string", - "enum": [ - "tcp", - "udp", - "tcp/udp" - ] - }, - "targetIP": { - "type": "string" - }, - "targetPort": { - "type": "string" - } - } - } - } - } - }, - "dto.FtpBaseInfo": { - "type": "object", - "properties": { - "isActive": { - "type": "boolean" - }, - "isExist": { - "type": "boolean" - } - } - }, - "dto.FtpCreate": { - "type": "object", - "required": [ - "password", - "path", - "user" - ], - "properties": { - "description": { - "type": "string" - }, - "password": { - "type": "string" - }, - "path": { - "type": "string" - }, - "user": { - "type": "string" - } - } - }, - "dto.FtpLogSearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "operation": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "user": { - "type": "string" - } - } - }, - "dto.FtpUpdate": { - "type": "object", - "required": [ - "password", - "path" - ], - "properties": { - "description": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "password": { - "type": "string" - }, - "path": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "dto.GPUInfo": { - "type": "object", - "properties": { - "fanSpeed": { - "type": "string" - }, - "gpuUtil": { - "type": "string" - }, - "index": { - "type": "integer" - }, - "maxPowerLimit": { - "type": "string" - }, - "memTotal": { - "type": "string" - }, - "memUsed": { - "type": "string" - }, - "memoryUsage": { - "type": "string" - }, - "performanceState": { - "type": "string" - }, - "powerDraw": { - "type": "string" - }, - "powerUsage": { - "type": "string" - }, - "productName": { - "type": "string" - }, - "temperature": { - "type": "string" - } - } - }, - "dto.GenerateLoad": { - "type": "object", - "required": [ - "encryptionMode" - ], - "properties": { - "encryptionMode": { - "type": "string", - "enum": [ - "rsa", - "ed25519", - "ecdsa", - "dsa" - ] - } - } - }, - "dto.GenerateSSH": { - "type": "object", - "required": [ - "encryptionMode" - ], - "properties": { - "encryptionMode": { - "type": "string", - "enum": [ - "rsa", - "ed25519", - "ecdsa", - "dsa" - ] - }, - "password": { - "type": "string" - } - } - }, - "dto.GroupCreate": { - "type": "object", - "required": [ - "name", - "type" - ], - "properties": { - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "dto.GroupInfo": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "isDefault": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "dto.GroupSearch": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string" - } - } - }, - "dto.GroupUpdate": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "id": { - "type": "integer" - }, - "isDefault": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "dto.HostConnTest": { - "type": "object", - "required": [ - "addr", - "port", - "user" - ], - "properties": { - "addr": { - "type": "string" - }, - "authMode": { - "type": "string", - "enum": [ - "password", - "key" - ] - }, - "passPhrase": { - "type": "string" - }, - "password": { - "type": "string" - }, - "port": { - "type": "integer", - "maximum": 65535, - "minimum": 1 - }, - "privateKey": { - "type": "string" - }, - "user": { - "type": "string" - } - } - }, - "dto.HostHelper": { - "type": "object", - "properties": { - "host": { - "type": "string" - }, - "ip": { - "type": "string" - } - } - }, - "dto.HostOperate": { - "type": "object", - "required": [ - "addr", - "port", - "user" - ], - "properties": { - "addr": { - "type": "string" - }, - "authMode": { - "type": "string", - "enum": [ - "password", - "key" - ] - }, - "description": { - "type": "string" - }, - "groupID": { - "type": "integer" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "passPhrase": { - "type": "string" - }, - "password": { - "type": "string" - }, - "port": { - "type": "integer", - "maximum": 65535, - "minimum": 1 - }, - "privateKey": { - "type": "string" - }, - "rememberPassword": { - "type": "boolean" - }, - "user": { - "type": "string" - } - } - }, - "dto.HostTree": { - "type": "object", - "properties": { - "children": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.TreeChild" - } - }, - "id": { - "type": "integer" - }, - "label": { - "type": "string" - } - } - }, - "dto.ImageBuild": { - "type": "object", - "required": [ - "dockerfile", - "from", - "name" - ], - "properties": { - "dockerfile": { - "type": "string" - }, - "from": { - "type": "string" - }, - "name": { - "type": "string" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "dto.ImageInfo": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "id": { - "type": "string" - }, - "isUsed": { - "type": "boolean" - }, - "size": { - "type": "string" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "dto.ImageLoad": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "type": "string" - } - } - }, - "dto.ImagePull": { - "type": "object", - "required": [ - "imageName" - ], - "properties": { - "imageName": { - "type": "string" - }, - "repoID": { - "type": "integer" - } - } - }, - "dto.ImagePush": { - "type": "object", - "required": [ - "name", - "repoID", - "tagName" - ], - "properties": { - "name": { - "type": "string" - }, - "repoID": { - "type": "integer" - }, - "tagName": { - "type": "string" - } - } - }, - "dto.ImageRepoDelete": { - "type": "object", - "required": [ - "ids" - ], - "properties": { - "ids": { - "type": "array", - "items": { - "type": "integer" - } - } - } - }, - "dto.ImageRepoOption": { - "type": "object", - "properties": { - "downloadUrl": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, - "dto.ImageRepoUpdate": { - "type": "object", - "properties": { - "auth": { - "type": "boolean" - }, - "downloadUrl": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "password": { - "type": "string", - "maxLength": 256 - }, - "protocol": { - "type": "string" - }, - "username": { - "type": "string", - "maxLength": 256 - } - } - }, - "dto.ImageSave": { - "type": "object", - "required": [ - "name", - "path", - "tagName" - ], - "properties": { - "name": { - "type": "string" - }, - "path": { - "type": "string" - }, - "tagName": { - "type": "string" - } - } - }, - "dto.ImageTag": { - "type": "object", - "required": [ - "sourceID", - "targetName" - ], - "properties": { - "sourceID": { - "type": "string" - }, - "targetName": { - "type": "string" - } - } - }, - "dto.InspectReq": { - "type": "object", - "required": [ - "id", - "type" - ], - "properties": { - "id": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "dto.LogOption": { - "type": "object", - "properties": { - "logMaxFile": { - "type": "string" - }, - "logMaxSize": { - "type": "string" - } - } - }, - "dto.Login": { - "type": "object", - "required": [ - "authMethod", - "language", - "name", - "password" - ], - "properties": { - "authMethod": { - "type": "string", - "enum": [ - "jwt", - "session" - ] - }, - "captcha": { - "type": "string" - }, - "captchaID": { - "type": "string" - }, - "ignoreCaptcha": { - "type": "boolean" - }, - "language": { - "type": "string", - "enum": [ - "zh", - "en", - "tw" - ] - }, - "name": { - "type": "string" - }, - "password": { - "type": "string" - } - } - }, - "dto.MFALogin": { - "type": "object", - "required": [ - "code", - "name", - "password" - ], - "properties": { - "authMethod": { - "type": "string" - }, - "code": { - "type": "string" - }, - "name": { - "type": "string" - }, - "password": { - "type": "string" - } - } - }, - "dto.MfaCredential": { - "type": "object", - "required": [ - "code", - "interval", - "secret" - ], - "properties": { - "code": { - "type": "string" - }, - "interval": { - "type": "string" - }, - "secret": { - "type": "string" - } - } - }, - "dto.MonitorSearch": { - "type": "object", - "required": [ - "param" - ], - "properties": { - "endTime": { - "type": "string" - }, - "info": { - "type": "string" - }, - "param": { - "type": "string", - "enum": [ - "all", - "cpu", - "memory", - "load", - "io", - "network" - ] - }, - "startTime": { - "type": "string" - } - } - }, - "dto.MysqlDBCreate": { - "type": "object", - "required": [ - "database", - "format", - "from", - "name", - "password", - "permission", - "username" - ], - "properties": { - "database": { - "type": "string" - }, - "description": { - "type": "string" - }, - "format": { - "type": "string", - "enum": [ - "utf8mb4", - "utf8", - "gbk", - "big5" - ] - }, - "from": { - "type": "string", - "enum": [ - "local", - "remote" - ] - }, - "name": { - "type": "string" - }, - "password": { - "type": "string" - }, - "permission": { - "type": "string" - }, - "username": { - "type": "string" - } - } - }, - "dto.MysqlDBDelete": { - "type": "object", - "required": [ - "database", - "id", - "type" - ], - "properties": { - "database": { - "type": "string" - }, - "deleteBackup": { - "type": "boolean" - }, - "forceDelete": { - "type": "boolean" - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string", - "enum": [ - "mysql", - "mariadb" - ] - } - } - }, - "dto.MysqlDBDeleteCheck": { - "type": "object", - "required": [ - "database", - "id", - "type" - ], - "properties": { - "database": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string", - "enum": [ - "mysql", - "mariadb" - ] - } - } - }, - "dto.MysqlDBSearch": { - "type": "object", - "required": [ - "database", - "order", - "orderBy", - "page", - "pageSize" - ], - "properties": { - "database": { - "type": "string" - }, - "info": { - "type": "string" - }, - "order": { - "type": "string", - "enum": [ - "null", - "ascending", - "descending" - ] - }, - "orderBy": { - "type": "string", - "enum": [ - "name", - "created_at" - ] - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "dto.MysqlLoadDB": { - "type": "object", - "required": [ - "database", - "from", - "type" - ], - "properties": { - "database": { - "type": "string" - }, - "from": { - "type": "string", - "enum": [ - "local", - "remote" - ] - }, - "type": { - "type": "string", - "enum": [ - "mysql", - "mariadb" - ] - } - } - }, - "dto.MysqlOption": { - "type": "object", - "properties": { - "database": { - "type": "string" - }, - "from": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "dto.MysqlStatus": { - "type": "object", - "properties": { - "Aborted_clients": { - "type": "string" - }, - "Aborted_connects": { - "type": "string" - }, - "Bytes_received": { - "type": "string" - }, - "Bytes_sent": { - "type": "string" - }, - "Com_commit": { - "type": "string" - }, - "Com_rollback": { - "type": "string" - }, - "Connections": { - "type": "string" - }, - "Created_tmp_disk_tables": { - "type": "string" - }, - "Created_tmp_tables": { - "type": "string" - }, - "File": { - "type": "string" - }, - "Innodb_buffer_pool_pages_dirty": { - "type": "string" - }, - "Innodb_buffer_pool_read_requests": { - "type": "string" - }, - "Innodb_buffer_pool_reads": { - "type": "string" - }, - "Key_read_requests": { - "type": "string" - }, - "Key_reads": { - "type": "string" - }, - "Key_write_requests": { - "type": "string" - }, - "Key_writes": { - "type": "string" - }, - "Max_used_connections": { - "type": "string" - }, - "Open_tables": { - "type": "string" - }, - "Opened_files": { - "type": "string" - }, - "Opened_tables": { - "type": "string" - }, - "Position": { - "type": "string" - }, - "Qcache_hits": { - "type": "string" - }, - "Qcache_inserts": { - "type": "string" - }, - "Questions": { - "type": "string" - }, - "Run": { - "type": "string" - }, - "Select_full_join": { - "type": "string" - }, - "Select_range_check": { - "type": "string" - }, - "Sort_merge_passes": { - "type": "string" - }, - "Table_locks_waited": { - "type": "string" - }, - "Threads_cached": { - "type": "string" - }, - "Threads_connected": { - "type": "string" - }, - "Threads_created": { - "type": "string" - }, - "Threads_running": { - "type": "string" - }, - "Uptime": { - "type": "string" - } - } - }, - "dto.MysqlVariables": { - "type": "object", - "properties": { - "binlog_cache_size": { - "type": "string" - }, - "innodb_buffer_pool_size": { - "type": "string" - }, - "innodb_log_buffer_size": { - "type": "string" - }, - "join_buffer_size": { - "type": "string" - }, - "key_buffer_size": { - "type": "string" - }, - "long_query_time": { - "type": "string" - }, - "max_connections": { - "type": "string" - }, - "max_heap_table_size": { - "type": "string" - }, - "query_cache_size": { - "type": "string" - }, - "query_cache_type": { - "type": "string" - }, - "read_buffer_size": { - "type": "string" - }, - "read_rnd_buffer_size": { - "type": "string" - }, - "slow_query_log": { - "type": "string" - }, - "sort_buffer_size": { - "type": "string" - }, - "table_open_cache": { - "type": "string" - }, - "thread_cache_size": { - "type": "string" - }, - "thread_stack": { - "type": "string" - }, - "tmp_table_size": { - "type": "string" - } - } - }, - "dto.MysqlVariablesUpdate": { - "type": "object", - "required": [ - "database", - "type" - ], - "properties": { - "database": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "mysql", - "mariadb" - ] - }, - "variables": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.MysqlVariablesUpdateHelper" - } - } - } - }, - "dto.MysqlVariablesUpdateHelper": { - "type": "object", - "properties": { - "param": { - "type": "string" - }, - "value": {} - } - }, - "dto.NetworkCreate": { - "type": "object", - "required": [ - "driver", - "name" - ], - "properties": { - "auxAddress": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.SettingUpdate" - } - }, - "auxAddressV6": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.SettingUpdate" - } - }, - "driver": { - "type": "string" - }, - "gateway": { - "type": "string" - }, - "gatewayV6": { - "type": "string" - }, - "ipRange": { - "type": "string" - }, - "ipRangeV6": { - "type": "string" - }, - "ipv4": { - "type": "boolean" - }, - "ipv6": { - "type": "boolean" - }, - "labels": { - "type": "array", - "items": { - "type": "string" - } - }, - "name": { - "type": "string" - }, - "options": { - "type": "array", - "items": { - "type": "string" - } - }, - "subnet": { - "type": "string" - }, - "subnetV6": { - "type": "string" - } - } - }, - "dto.NginxKey": { - "type": "string", - "enum": [ - "index", - "limit-conn", - "ssl", - "cache", - "http-per", - "proxy-cache" - ], - "x-enum-varnames": [ - "Index", - "LimitConn", - "SSL", - "CACHE", - "HttpPer", - "ProxyCache" - ] - }, - "dto.OneDriveInfo": { - "type": "object", - "properties": { - "client_id": { - "type": "string" - }, - "client_secret": { - "type": "string" - }, - "redirect_uri": { - "type": "string" - } - } - }, - "dto.Operate": { - "type": "object", - "required": [ - "operation" - ], - "properties": { - "operation": { - "type": "string" - } - } - }, - "dto.OperateByID": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - } - } - }, - "dto.OperationWithName": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string" - } - } - }, - "dto.OperationWithNameAndType": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "dto.Options": { - "type": "object", - "properties": { - "option": { - "type": "string" - } - } - }, - "dto.OsInfo": { - "type": "object", - "properties": { - "diskSize": { - "type": "integer" - }, - "kernelArch": { - "type": "string" - }, - "kernelVersion": { - "type": "string" - }, - "os": { - "type": "string" - }, - "platform": { - "type": "string" - }, - "platformFamily": { - "type": "string" - } - } - }, - "dto.PageContainer": { - "type": "object", - "required": [ - "order", - "orderBy", - "page", - "pageSize", - "state" - ], - "properties": { - "excludeAppStore": { - "type": "boolean" - }, - "filters": { - "type": "string" - }, - "name": { - "type": "string" - }, - "order": { - "type": "string", - "enum": [ - "null", - "ascending", - "descending" - ] - }, - "orderBy": { - "type": "string", - "enum": [ - "name", - "state", - "created_at" - ] - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "state": { - "type": "string", - "enum": [ - "all", - "created", - "running", - "paused", - "restarting", - "removing", - "exited", - "dead" - ] - } - } - }, - "dto.PageCronjob": { - "type": "object", - "required": [ - "order", - "orderBy", - "page", - "pageSize" - ], - "properties": { - "info": { - "type": "string" - }, - "order": { - "type": "string", - "enum": [ - "null", - "ascending", - "descending" - ] - }, - "orderBy": { - "type": "string", - "enum": [ - "name", - "status", - "created_at" - ] - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "dto.PageInfo": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "dto.PageResult": { - "type": "object", - "properties": { - "items": {}, - "total": { - "type": "integer" - } - } - }, - "dto.PasswordUpdate": { - "type": "object", - "required": [ - "newPassword", - "oldPassword" - ], - "properties": { - "newPassword": { - "type": "string" - }, - "oldPassword": { - "type": "string" - } - } - }, - "dto.PortHelper": { - "type": "object", - "properties": { - "containerPort": { - "type": "string" - }, - "hostIP": { - "type": "string" - }, - "hostPort": { - "type": "string" - }, - "protocol": { - "type": "string" - } - } - }, - "dto.PortRuleOperate": { - "type": "object", - "required": [ - "operation", - "port", - "protocol", - "strategy" - ], - "properties": { - "address": { - "type": "string" - }, - "description": { - "type": "string" - }, - "operation": { - "type": "string", - "enum": [ - "add", - "remove" - ] - }, - "port": { - "type": "string" - }, - "protocol": { - "type": "string", - "enum": [ - "tcp", - "udp", - "tcp/udp" - ] - }, - "strategy": { - "type": "string", - "enum": [ - "accept", - "drop" - ] - } - } - }, - "dto.PortRuleUpdate": { - "type": "object", - "properties": { - "newRule": { - "$ref": "#/definitions/dto.PortRuleOperate" - }, - "oldRule": { - "$ref": "#/definitions/dto.PortRuleOperate" - } - } - }, - "dto.PortUpdate": { - "type": "object", - "required": [ - "serverPort" - ], - "properties": { - "serverPort": { - "type": "integer", - "maximum": 65535, - "minimum": 1 - } - } - }, - "dto.PostgresqlBindUser": { - "type": "object", - "required": [ - "database", - "name", - "password", - "username" - ], - "properties": { - "database": { - "type": "string" - }, - "name": { - "type": "string" - }, - "password": { - "type": "string" - }, - "superUser": { - "type": "boolean" - }, - "username": { - "type": "string" - } - } - }, - "dto.PostgresqlDBCreate": { - "type": "object", - "required": [ - "database", - "from", - "name", - "password", - "username" - ], - "properties": { - "database": { - "type": "string" - }, - "description": { - "type": "string" - }, - "format": { - "type": "string" - }, - "from": { - "type": "string", - "enum": [ - "local", - "remote" - ] - }, - "name": { - "type": "string" - }, - "password": { - "type": "string" - }, - "superUser": { - "type": "boolean" - }, - "username": { - "type": "string" - } - } - }, - "dto.PostgresqlDBDelete": { - "type": "object", - "required": [ - "database", - "id", - "type" - ], - "properties": { - "database": { - "type": "string" - }, - "deleteBackup": { - "type": "boolean" - }, - "forceDelete": { - "type": "boolean" - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string", - "enum": [ - "postgresql" - ] - } - } - }, - "dto.PostgresqlDBDeleteCheck": { - "type": "object", - "required": [ - "database", - "id", - "type" - ], - "properties": { - "database": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string", - "enum": [ - "postgresql" - ] - } - } - }, - "dto.PostgresqlDBSearch": { - "type": "object", - "required": [ - "database", - "order", - "orderBy", - "page", - "pageSize" - ], - "properties": { - "database": { - "type": "string" - }, - "info": { - "type": "string" - }, - "order": { - "type": "string", - "enum": [ - "null", - "ascending", - "descending" - ] - }, - "orderBy": { - "type": "string", - "enum": [ - "name", - "created_at" - ] - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "dto.PostgresqlLoadDB": { - "type": "object", - "required": [ - "database", - "from", - "type" - ], - "properties": { - "database": { - "type": "string" - }, - "from": { - "type": "string", - "enum": [ - "local", - "remote" - ] - }, - "type": { - "type": "string", - "enum": [ - "postgresql" - ] - } - } - }, - "dto.ProxyUpdate": { - "type": "object", - "properties": { - "proxyPasswd": { - "type": "string" - }, - "proxyPasswdKeep": { - "type": "string" - }, - "proxyPort": { - "type": "string" - }, - "proxyType": { - "type": "string" - }, - "proxyUrl": { - "type": "string" - }, - "proxyUser": { - "type": "string" - } - } - }, - "dto.RecordSearch": { - "type": "object", - "required": [ - "page", - "pageSize", - "type" - ], - "properties": { - "detailName": { - "type": "string" - }, - "name": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "type": { - "type": "string" - } - } - }, - "dto.RecordSearchByCronjob": { - "type": "object", - "required": [ - "cronjobID", - "page", - "pageSize" - ], - "properties": { - "cronjobID": { - "type": "integer" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "dto.RedisCommand": { - "type": "object", - "properties": { - "command": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, - "dto.RedisConf": { - "type": "object", - "required": [ - "database" - ], - "properties": { - "containerName": { - "type": "string" - }, - "database": { - "type": "string" - }, - "maxclients": { - "type": "string" - }, - "maxmemory": { - "type": "string" - }, - "name": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "requirepass": { - "type": "string" - }, - "timeout": { - "type": "string" - } - } - }, - "dto.RedisConfPersistenceUpdate": { - "type": "object", - "required": [ - "database", - "type" - ], - "properties": { - "appendfsync": { - "type": "string" - }, - "appendonly": { - "type": "string" - }, - "database": { - "type": "string" - }, - "save": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "aof", - "rbd" - ] - } - } - }, - "dto.RedisConfUpdate": { - "type": "object", - "required": [ - "database" - ], - "properties": { - "database": { - "type": "string" - }, - "maxclients": { - "type": "string" - }, - "maxmemory": { - "type": "string" - }, - "timeout": { - "type": "string" - } - } - }, - "dto.RedisPersistence": { - "type": "object", - "required": [ - "database" - ], - "properties": { - "appendfsync": { - "type": "string" - }, - "appendonly": { - "type": "string" - }, - "database": { - "type": "string" - }, - "save": { - "type": "string" - } - } - }, - "dto.RedisStatus": { - "type": "object", - "required": [ - "database" - ], - "properties": { - "connected_clients": { - "type": "string" - }, - "database": { - "type": "string" - }, - "instantaneous_ops_per_sec": { - "type": "string" - }, - "keyspace_hits": { - "type": "string" - }, - "keyspace_misses": { - "type": "string" - }, - "latest_fork_usec": { - "type": "string" - }, - "mem_fragmentation_ratio": { - "type": "string" - }, - "tcp_port": { - "type": "string" - }, - "total_commands_processed": { - "type": "string" - }, - "total_connections_received": { - "type": "string" - }, - "uptime_in_days": { - "type": "string" - }, - "used_memory": { - "type": "string" - }, - "used_memory_peak": { - "type": "string" - }, - "used_memory_rss": { - "type": "string" - } - } - }, - "dto.ResourceLimit": { - "type": "object", - "properties": { - "cpu": { - "type": "integer" - }, - "memory": { - "type": "integer" - } - } - }, - "dto.RuleSearch": { - "type": "object", - "required": [ - "page", - "pageSize", - "type" - ], - "properties": { - "info": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "status": { - "type": "string" - }, - "strategy": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "dto.SSHConf": { - "type": "object", - "properties": { - "file": { - "type": "string" - } - } - }, - "dto.SSHHistory": { - "type": "object", - "properties": { - "address": { - "type": "string" - }, - "area": { - "type": "string" - }, - "authMode": { - "type": "string" - }, - "date": { - "type": "string" - }, - "dateStr": { - "type": "string" - }, - "message": { - "type": "string" - }, - "port": { - "type": "string" - }, - "status": { - "type": "string" - }, - "user": { - "type": "string" - } - } - }, - "dto.SSHInfo": { - "type": "object", - "properties": { - "autoStart": { - "type": "boolean" - }, - "listenAddress": { - "type": "string" - }, - "message": { - "type": "string" - }, - "passwordAuthentication": { - "type": "string" - }, - "permitRootLogin": { - "type": "string" - }, - "port": { - "type": "string" - }, - "pubkeyAuthentication": { - "type": "string" - }, - "status": { - "type": "string" - }, - "useDNS": { - "type": "string" - } - } - }, - "dto.SSHLog": { - "type": "object", - "properties": { - "failedCount": { - "type": "integer" - }, - "logs": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.SSHHistory" - } - }, - "successfulCount": { - "type": "integer" - }, - "totalCount": { - "type": "integer" - } - } - }, - "dto.SSHUpdate": { - "type": "object", - "required": [ - "key" - ], - "properties": { - "key": { - "type": "string" - }, - "newValue": { - "type": "string" - }, - "oldValue": { - "type": "string" - } - } - }, - "dto.SSLUpdate": { - "type": "object", - "required": [ - "ssl", - "sslType" - ], - "properties": { - "cert": { - "type": "string" - }, - "domain": { - "type": "string" - }, - "key": { - "type": "string" - }, - "ssl": { - "type": "string", - "enum": [ - "enable", - "disable" - ] - }, - "sslID": { - "type": "integer" - }, - "sslType": { - "type": "string", - "enum": [ - "self", - "select", - "import", - "import-paste", - "import-local" - ] - } - } - }, - "dto.SearchForTree": { - "type": "object", - "properties": { - "info": { - "type": "string" - } - } - }, - "dto.SearchHostWithPage": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "groupID": { - "type": "integer" - }, - "info": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "dto.SearchLgLogWithPage": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "ip": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "status": { - "type": "string" - } - } - }, - "dto.SearchOpLogWithPage": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "operation": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "source": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "dto.SearchRecord": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "cronjobID": { - "type": "integer" - }, - "endTime": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "startTime": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "dto.SearchSSHLog": { - "type": "object", - "required": [ - "Status", - "page", - "pageSize" - ], - "properties": { - "Status": { - "type": "string", - "enum": [ - "Success", - "Failed", - "All" - ] - }, - "info": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "dto.SearchWithPage": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "info": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "dto.SettingInfo": { - "type": "object", - "properties": { - "allowIPs": { - "type": "string" - }, - "appStoreLastModified": { - "type": "string" - }, - "appStoreSyncStatus": { - "type": "string" - }, - "appStoreVersion": { - "type": "string" - }, - "bindAddress": { - "type": "string" - }, - "bindDomain": { - "type": "string" - }, - "complexityVerification": { - "type": "string" - }, - "defaultNetwork": { - "type": "string" - }, - "developerMode": { - "type": "string" - }, - "dingVars": { - "type": "string" - }, - "dockerSockPath": { - "type": "string" - }, - "email": { - "type": "string" - }, - "emailVars": { - "type": "string" - }, - "expirationDays": { - "type": "string" - }, - "expirationTime": { - "type": "string" - }, - "fileRecycleBin": { - "type": "string" - }, - "ipv6": { - "type": "string" - }, - "language": { - "type": "string" - }, - "lastCleanData": { - "type": "string" - }, - "lastCleanSize": { - "type": "string" - }, - "lastCleanTime": { - "type": "string" - }, - "localTime": { - "type": "string" - }, - "menuTabs": { - "type": "string" - }, - "messageType": { - "type": "string" - }, - "mfaInterval": { - "type": "string" - }, - "mfaSecret": { - "type": "string" - }, - "mfaStatus": { - "type": "string" - }, - "monitorInterval": { - "type": "string" - }, - "monitorStatus": { - "type": "string" - }, - "monitorStoreDays": { - "type": "string" - }, - "noAuthSetting": { - "type": "string" - }, - "ntpSite": { - "type": "string" - }, - "panelName": { - "type": "string" - }, - "port": { - "type": "string" - }, - "proxyPasswd": { - "type": "string" - }, - "proxyPasswdKeep": { - "type": "string" - }, - "proxyPort": { - "type": "string" - }, - "proxyType": { - "type": "string" - }, - "proxyUrl": { - "type": "string" - }, - "proxyUser": { - "type": "string" - }, - "securityEntrance": { - "type": "string" - }, - "serverPort": { - "type": "string" - }, - "sessionTimeout": { - "type": "string" - }, - "snapshotIgnore": { - "type": "string" - }, - "ssl": { - "type": "string" - }, - "sslType": { - "type": "string" - }, - "systemIP": { - "type": "string" - }, - "systemVersion": { - "type": "string" - }, - "theme": { - "type": "string" - }, - "timeZone": { - "type": "string" - }, - "userName": { - "type": "string" - }, - "weChatVars": { - "type": "string" - }, - "xpackHideMenu": { - "type": "string" - } - } - }, - "dto.SettingUpdate": { - "type": "object", - "required": [ - "key" - ], - "properties": { - "key": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "dto.SnapshotBatchDelete": { - "type": "object", - "required": [ - "ids" - ], - "properties": { - "deleteWithFile": { - "type": "boolean" - }, - "ids": { - "type": "array", - "items": { - "type": "integer" - } - } - } - }, - "dto.SnapshotCreate": { - "type": "object", - "required": [ - "defaultDownload", - "from" - ], - "properties": { - "defaultDownload": { - "type": "string" - }, - "description": { - "type": "string", - "maxLength": 256 - }, - "from": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "secret": { - "type": "string" - } - } - }, - "dto.SnapshotImport": { - "type": "object", - "properties": { - "description": { - "type": "string", - "maxLength": 256 - }, - "from": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "dto.SnapshotRecover": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - }, - "isNew": { - "type": "boolean" - }, - "reDownload": { - "type": "boolean" - }, - "secret": { - "type": "string" - } - } - }, - "dto.SwapHelper": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "isNew": { - "type": "boolean" - }, - "path": { - "type": "string" - }, - "size": { - "type": "integer" - }, - "used": { - "type": "string" - } - } - }, - "dto.TreeChild": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "label": { - "type": "string" - } - } - }, - "dto.UpdateByFile": { - "type": "object", - "properties": { - "file": { - "type": "string" - } - } - }, - "dto.UpdateByNameAndFile": { - "type": "object", - "properties": { - "file": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "dto.UpdateDescription": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "description": { - "type": "string", - "maxLength": 256 - }, - "id": { - "type": "integer" - } - } - }, - "dto.UpdateFirewallDescription": { - "type": "object", - "required": [ - "strategy" - ], - "properties": { - "address": { - "type": "string" - }, - "description": { - "type": "string" - }, - "port": { - "type": "string" - }, - "protocol": { - "type": "string" - }, - "strategy": { - "type": "string", - "enum": [ - "accept", - "drop" - ] - }, - "type": { - "type": "string" - } - } - }, - "dto.Upgrade": { - "type": "object", - "required": [ - "version" - ], - "properties": { - "version": { - "type": "string" - } - } - }, - "dto.UpgradeInfo": { - "type": "object", - "properties": { - "latestVersion": { - "type": "string" - }, - "newVersion": { - "type": "string" - }, - "releaseNote": { - "type": "string" - }, - "testVersion": { - "type": "string" - } - } - }, - "dto.UserLoginInfo": { - "type": "object", - "properties": { - "mfaStatus": { - "type": "string" - }, - "name": { - "type": "string" - }, - "token": { - "type": "string" - } - } - }, - "dto.VolumeCreate": { - "type": "object", - "required": [ - "driver", - "name" - ], - "properties": { - "driver": { - "type": "string" - }, - "labels": { - "type": "array", - "items": { - "type": "string" - } - }, - "name": { - "type": "string" - }, - "options": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "dto.VolumeHelper": { - "type": "object", - "properties": { - "containerDir": { - "type": "string" - }, - "mode": { - "type": "string" - }, - "sourceDir": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "files.FileInfo": { - "type": "object", - "properties": { - "content": { - "type": "string" - }, - "extension": { - "type": "string" - }, - "favoriteID": { - "type": "integer" - }, - "gid": { - "type": "string" - }, - "group": { - "type": "string" - }, - "isDetail": { - "type": "boolean" - }, - "isDir": { - "type": "boolean" - }, - "isHidden": { - "type": "boolean" - }, - "isSymlink": { - "type": "boolean" - }, - "itemTotal": { - "type": "integer" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/files.FileInfo" - } - }, - "linkPath": { - "type": "string" - }, - "mimeType": { - "type": "string" - }, - "modTime": { - "type": "string" - }, - "mode": { - "type": "string" - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - }, - "size": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "uid": { - "type": "string" - }, - "updateTime": { - "type": "string" - }, - "user": { - "type": "string" - } - } - }, - "mfa.Otp": { - "type": "object", - "properties": { - "qrImage": { - "type": "string" - }, - "secret": { - "type": "string" - } - } - }, - "model.App": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "crossVersionUpdate": { - "type": "boolean" - }, - "document": { - "type": "string" - }, - "github": { - "type": "string" - }, - "icon": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "key": { - "type": "string" - }, - "lastModified": { - "type": "integer" - }, - "limit": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "readMe": { - "type": "string" - }, - "recommend": { - "type": "integer" - }, - "required": { - "type": "string" - }, - "resource": { - "type": "string" - }, - "shortDescEn": { - "type": "string" - }, - "shortDescZh": { - "type": "string" - }, - "status": { - "type": "string" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "website": { - "type": "string" - } - } - }, - "model.AppInstall": { - "type": "object", - "properties": { - "app": { - "$ref": "#/definitions/model.App" - }, - "appDetailId": { - "type": "integer" - }, - "appId": { - "type": "integer" - }, - "containerName": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "dockerCompose": { - "type": "string" - }, - "env": { - "type": "string" - }, - "httpPort": { - "type": "integer" - }, - "httpsPort": { - "type": "integer" - }, - "id": { - "type": "integer" - }, - "message": { - "type": "string" - }, - "name": { - "type": "string" - }, - "param": { - "type": "string" - }, - "serviceName": { - "type": "string" - }, - "status": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "model.Tag": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "key": { - "type": "string" - }, - "name": { - "type": "string" - }, - "sort": { - "type": "integer" - }, - "updatedAt": { - "type": "string" - } - } - }, - "model.Website": { - "type": "object", - "properties": { - "IPV6": { - "type": "boolean" - }, - "accessLog": { - "type": "boolean" - }, - "alias": { - "type": "string" - }, - "appInstallId": { - "type": "integer" - }, - "createdAt": { - "type": "string" - }, - "defaultServer": { - "type": "boolean" - }, - "domains": { - "type": "array", - "items": { - "$ref": "#/definitions/model.WebsiteDomain" - } - }, - "errorLog": { - "type": "boolean" - }, - "expireDate": { - "type": "string" - }, - "ftpId": { - "type": "integer" - }, - "group": { - "type": "string" - }, - "httpConfig": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "primaryDomain": { - "type": "string" - }, - "protocol": { - "type": "string" - }, - "proxy": { - "type": "string" - }, - "proxyType": { - "type": "string" - }, - "remark": { - "type": "string" - }, - "rewrite": { - "type": "string" - }, - "runtimeID": { - "type": "integer" - }, - "siteDir": { - "type": "string" - }, - "status": { - "type": "string" - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "user": { - "type": "string" - }, - "webSiteGroupId": { - "type": "integer" - }, - "webSiteSSL": { - "$ref": "#/definitions/model.WebsiteSSL" - }, - "webSiteSSLId": { - "type": "integer" - } - } - }, - "model.WebsiteAcmeAccount": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "eabHmacKey": { - "type": "string" - }, - "eabKid": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "keyType": { - "type": "string" - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "url": { - "type": "string" - } - } - }, - "model.WebsiteDnsAccount": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "model.WebsiteDomain": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "domain": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "port": { - "type": "integer" - }, - "updatedAt": { - "type": "string" - }, - "websiteId": { - "type": "integer" - } - } - }, - "model.WebsiteSSL": { - "type": "object", - "properties": { - "acmeAccount": { - "$ref": "#/definitions/model.WebsiteAcmeAccount" - }, - "acmeAccountId": { - "type": "integer" - }, - "autoRenew": { - "type": "boolean" - }, - "caId": { - "type": "integer" - }, - "certURL": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "dir": { - "type": "string" - }, - "disableCNAME": { - "type": "boolean" - }, - "dnsAccount": { - "$ref": "#/definitions/model.WebsiteDnsAccount" - }, - "dnsAccountId": { - "type": "integer" - }, - "domains": { - "type": "string" - }, - "execShell": { - "type": "boolean" - }, - "expireDate": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "keyType": { - "type": "string" - }, - "message": { - "type": "string" - }, - "nameserver1": { - "type": "string" - }, - "nameserver2": { - "type": "string" - }, - "organization": { - "type": "string" - }, - "pem": { - "type": "string" - }, - "primaryDomain": { - "type": "string" - }, - "privateKey": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "pushDir": { - "type": "boolean" - }, - "shell": { - "type": "string" - }, - "skipDNS": { - "type": "boolean" - }, - "startDate": { - "type": "string" - }, - "status": { - "type": "string" - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "websites": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Website" - } - } - } - }, - "request.AppInstallCreate": { - "type": "object", - "required": [ - "appDetailId", - "name" - ], - "properties": { - "advanced": { - "type": "boolean" - }, - "allowPort": { - "type": "boolean" - }, - "appDetailId": { - "type": "integer" - }, - "containerName": { - "type": "string" - }, - "cpuQuota": { - "type": "number" - }, - "dockerCompose": { - "type": "string" - }, - "editCompose": { - "type": "boolean" - }, - "hostMode": { - "type": "boolean" - }, - "memoryLimit": { - "type": "number" - }, - "memoryUnit": { - "type": "string" - }, - "name": { - "type": "string" - }, - "params": { - "type": "object", - "additionalProperties": true - }, - "pullImage": { - "type": "boolean" - }, - "services": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - }, - "request.AppInstalledIgnoreUpgrade": { - "type": "object", - "required": [ - "detailID", - "operate" - ], - "properties": { - "detailID": { - "type": "integer" - }, - "operate": { - "type": "string", - "enum": [ - "cancel", - "ignore" - ] - } - } - }, - "request.AppInstalledInfo": { - "type": "object", - "required": [ - "key" - ], - "properties": { - "key": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "request.AppInstalledOperate": { - "type": "object", - "required": [ - "installId", - "operate" - ], - "properties": { - "backup": { - "type": "boolean" - }, - "backupId": { - "type": "integer" - }, - "deleteBackup": { - "type": "boolean" - }, - "deleteDB": { - "type": "boolean" - }, - "detailId": { - "type": "integer" - }, - "dockerCompose": { - "type": "string" - }, - "forceDelete": { - "type": "boolean" - }, - "installId": { - "type": "integer" - }, - "operate": { - "type": "string" - }, - "pullImage": { - "type": "boolean" - } - } - }, - "request.AppInstalledSearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "all": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "sync": { - "type": "boolean" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - }, - "type": { - "type": "string" - }, - "unused": { - "type": "boolean" - }, - "update": { - "type": "boolean" - } - } - }, - "request.AppInstalledUpdate": { - "type": "object", - "required": [ - "installId", - "params" - ], - "properties": { - "advanced": { - "type": "boolean" - }, - "allowPort": { - "type": "boolean" - }, - "containerName": { - "type": "string" - }, - "cpuQuota": { - "type": "number" - }, - "dockerCompose": { - "type": "string" - }, - "editCompose": { - "type": "boolean" - }, - "hostMode": { - "type": "boolean" - }, - "installId": { - "type": "integer" - }, - "memoryLimit": { - "type": "number" - }, - "memoryUnit": { - "type": "string" - }, - "params": { - "type": "object", - "additionalProperties": true - }, - "pullImage": { - "type": "boolean" - } - } - }, - "request.AppSearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "name": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "recommend": { - "type": "boolean" - }, - "resource": { - "type": "string" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - }, - "type": { - "type": "string" - } - } - }, - "request.DirSizeReq": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "type": "string" - } - } - }, - "request.ExposedPort": { - "type": "object", - "properties": { - "containerPort": { - "type": "integer" - }, - "hostPort": { - "type": "integer" - } - } - }, - "request.FavoriteCreate": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "type": "string" - } - } - }, - "request.FavoriteDelete": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - } - } - }, - "request.FileBatchDelete": { - "type": "object", - "required": [ - "paths" - ], - "properties": { - "isDir": { - "type": "boolean" - }, - "paths": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "request.FileCompress": { - "type": "object", - "required": [ - "dst", - "files", - "name", - "type" - ], - "properties": { - "dst": { - "type": "string" - }, - "files": { - "type": "array", - "items": { - "type": "string" - } - }, - "name": { - "type": "string" - }, - "replace": { - "type": "boolean" - }, - "secret": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "request.FileContentReq": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "isDetail": { - "type": "boolean" - }, - "path": { - "type": "string" - } - } - }, - "request.FileCreate": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "content": { - "type": "string" - }, - "isDir": { - "type": "boolean" - }, - "isLink": { - "type": "boolean" - }, - "isSymlink": { - "type": "boolean" - }, - "linkPath": { - "type": "string" - }, - "mode": { - "type": "integer" - }, - "path": { - "type": "string" - }, - "sub": { - "type": "boolean" - } - } - }, - "request.FileDeCompress": { - "type": "object", - "required": [ - "dst", - "path", - "type" - ], - "properties": { - "dst": { - "type": "string" - }, - "path": { - "type": "string" - }, - "secret": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "request.FileDelete": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "forceDelete": { - "type": "boolean" - }, - "isDir": { - "type": "boolean" - }, - "path": { - "type": "string" - } - } - }, - "request.FileDownload": { - "type": "object", - "required": [ - "name", - "paths", - "type" - ], - "properties": { - "compress": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "paths": { - "type": "array", - "items": { - "type": "string" - } - }, - "type": { - "type": "string" - } - } - }, - "request.FileEdit": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "content": { - "type": "string" - }, - "path": { - "type": "string" - } - } - }, - "request.FileMove": { - "type": "object", - "required": [ - "newPath", - "oldPaths", - "type" - ], - "properties": { - "cover": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "newPath": { - "type": "string" - }, - "oldPaths": { - "type": "array", - "items": { - "type": "string" - } - }, - "type": { - "type": "string" - } - } - }, - "request.FileOption": { - "type": "object", - "properties": { - "containSub": { - "type": "boolean" - }, - "dir": { - "type": "boolean" - }, - "expand": { - "type": "boolean" - }, - "isDetail": { - "type": "boolean" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "path": { - "type": "string" - }, - "search": { - "type": "string" - }, - "showHidden": { - "type": "boolean" - }, - "sortBy": { - "type": "string" - }, - "sortOrder": { - "type": "string" - } - } - }, - "request.FilePathCheck": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "type": "string" - } - } - }, - "request.FileReadByLineReq": { - "type": "object", - "required": [ - "page", - "pageSize", - "type" - ], - "properties": { - "ID": { - "type": "integer" - }, - "latest": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "type": { - "type": "string" - } - } - }, - "request.FileRename": { - "type": "object", - "required": [ - "newName", - "oldName" - ], - "properties": { - "newName": { - "type": "string" - }, - "oldName": { - "type": "string" - } - } - }, - "request.FileRoleReq": { - "type": "object", - "required": [ - "group", - "mode", - "paths", - "user" - ], - "properties": { - "group": { - "type": "string" - }, - "mode": { - "type": "integer" - }, - "paths": { - "type": "array", - "items": { - "type": "string" - } - }, - "sub": { - "type": "boolean" - }, - "user": { - "type": "string" - } - } - }, - "request.FileRoleUpdate": { - "type": "object", - "required": [ - "group", - "path", - "user" - ], - "properties": { - "group": { - "type": "string" - }, - "path": { - "type": "string" - }, - "sub": { - "type": "boolean" - }, - "user": { - "type": "string" - } - } - }, - "request.FileWget": { - "type": "object", - "required": [ - "name", - "path", - "url" - ], - "properties": { - "ignoreCertificate": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - }, - "url": { - "type": "string" - } - } - }, - "request.HostToolConfig": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "content": { - "type": "string" - }, - "operate": { - "type": "string", - "enum": [ - "get", - "set" - ] - }, - "type": { - "type": "string", - "enum": [ - "supervisord" - ] - } - } - }, - "request.HostToolCreate": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "configPath": { - "type": "string" - }, - "serviceName": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "request.HostToolLogReq": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "supervisord" - ] - } - } - }, - "request.HostToolReq": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "operate": { - "type": "string", - "enum": [ - "status", - "restart", - "start", - "stop" - ] - }, - "type": { - "type": "string", - "enum": [ - "supervisord" - ] - } - } - }, - "request.NewAppInstall": { - "type": "object", - "properties": { - "advanced": { - "type": "boolean" - }, - "allowPort": { - "type": "boolean" - }, - "appDetailID": { - "type": "integer" - }, - "containerName": { - "type": "string" - }, - "cpuQuota": { - "type": "number" - }, - "dockerCompose": { - "type": "string" - }, - "editCompose": { - "type": "boolean" - }, - "hostMode": { - "type": "boolean" - }, - "memoryLimit": { - "type": "number" - }, - "memoryUnit": { - "type": "string" - }, - "name": { - "type": "string" - }, - "params": { - "type": "object", - "additionalProperties": true - }, - "pullImage": { - "type": "boolean" - } - } - }, - "request.NginxAntiLeechUpdate": { - "type": "object", - "required": [ - "extends", - "return", - "websiteID" - ], - "properties": { - "blocked": { - "type": "boolean" - }, - "cache": { - "type": "boolean" - }, - "cacheTime": { - "type": "integer" - }, - "cacheUint": { - "type": "string" - }, - "enable": { - "type": "boolean" - }, - "extends": { - "type": "string" - }, - "logEnable": { - "type": "boolean" - }, - "noneRef": { - "type": "boolean" - }, - "return": { - "type": "string" - }, - "serverNames": { - "type": "array", - "items": { - "type": "string" - } - }, - "websiteID": { - "type": "integer" - } - } - }, - "request.NginxAuthReq": { - "type": "object", - "required": [ - "websiteID" - ], - "properties": { - "websiteID": { - "type": "integer" - } - } - }, - "request.NginxAuthUpdate": { - "type": "object", - "required": [ - "operate", - "websiteID" - ], - "properties": { - "operate": { - "type": "string" - }, - "password": { - "type": "string" - }, - "remark": { - "type": "string" - }, - "username": { - "type": "string" - }, - "websiteID": { - "type": "integer" - } - } - }, - "request.NginxCommonReq": { - "type": "object", - "required": [ - "websiteID" - ], - "properties": { - "websiteID": { - "type": "integer" - } - } - }, - "request.NginxConfigFileUpdate": { - "type": "object", - "required": [ - "content" - ], - "properties": { - "backup": { - "type": "boolean" - }, - "content": { - "type": "string" - } - } - }, - "request.NginxConfigUpdate": { - "type": "object", - "required": [ - "operate" - ], - "properties": { - "operate": { - "type": "string", - "enum": [ - "add", - "update", - "delete" - ] - }, - "params": {}, - "scope": { - "$ref": "#/definitions/dto.NginxKey" - }, - "websiteId": { - "type": "integer" - } - } - }, - "request.NginxProxyUpdate": { - "type": "object", - "required": [ - "content", - "name", - "websiteID" - ], - "properties": { - "content": { - "type": "string" - }, - "name": { - "type": "string" - }, - "websiteID": { - "type": "integer" - } - } - }, - "request.NginxRedirectReq": { - "type": "object", - "required": [ - "name", - "operate", - "redirect", - "target", - "type", - "websiteID" - ], - "properties": { - "domains": { - "type": "array", - "items": { - "type": "string" - } - }, - "enable": { - "type": "boolean" - }, - "keepPath": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "operate": { - "type": "string" - }, - "path": { - "type": "string" - }, - "redirect": { - "type": "string" - }, - "redirectRoot": { - "type": "boolean" - }, - "target": { - "type": "string" - }, - "type": { - "type": "string" - }, - "websiteID": { - "type": "integer" - } - } - }, - "request.NginxRedirectUpdate": { - "type": "object", - "required": [ - "content", - "name", - "websiteID" - ], - "properties": { - "content": { - "type": "string" - }, - "name": { - "type": "string" - }, - "websiteID": { - "type": "integer" - } - } - }, - "request.NginxRewriteReq": { - "type": "object", - "required": [ - "name", - "websiteId" - ], - "properties": { - "name": { - "type": "string" - }, - "websiteId": { - "type": "integer" - } - } - }, - "request.NginxRewriteUpdate": { - "type": "object", - "required": [ - "name", - "websiteId" - ], - "properties": { - "content": { - "type": "string" - }, - "name": { - "type": "string" - }, - "websiteId": { - "type": "integer" - } - } - }, - "request.NginxScopeReq": { - "type": "object", - "required": [ - "scope" - ], - "properties": { - "scope": { - "$ref": "#/definitions/dto.NginxKey" - }, - "websiteId": { - "type": "integer" - } - } - }, - "request.NodeModuleReq": { - "type": "object", - "required": [ - "ID" - ], - "properties": { - "ID": { - "type": "integer" - } - } - }, - "request.NodePackageReq": { - "type": "object", - "properties": { - "codeDir": { - "type": "string" - } - } - }, - "request.PHPExtensionsCreate": { - "type": "object", - "required": [ - "extensions", - "name" - ], - "properties": { - "extensions": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "request.PHPExtensionsDelete": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - } - } - }, - "request.PHPExtensionsSearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "all": { - "type": "boolean" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "request.PHPExtensionsUpdate": { - "type": "object", - "required": [ - "extensions", - "id" - ], - "properties": { - "extensions": { - "type": "string" - }, - "id": { - "type": "integer" - } - } - }, - "request.PortUpdate": { - "type": "object", - "properties": { - "key": { - "type": "string" - }, - "name": { - "type": "string" - }, - "port": { - "type": "integer" - } - } - }, - "request.ProcessReq": { - "type": "object", - "required": [ - "PID" - ], - "properties": { - "PID": { - "type": "integer" - } - } - }, - "request.RecycleBinReduce": { - "type": "object", - "required": [ - "from", - "rName" - ], - "properties": { - "from": { - "type": "string" - }, - "name": { - "type": "string" - }, - "rName": { - "type": "string" - } - } - }, - "request.RuntimeCreate": { - "type": "object", - "properties": { - "appDetailId": { - "type": "integer" - }, - "clean": { - "type": "boolean" - }, - "codeDir": { - "type": "string" - }, - "exposedPorts": { - "type": "array", - "items": { - "$ref": "#/definitions/request.ExposedPort" - } - }, - "image": { - "type": "string" - }, - "install": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "params": { - "type": "object", - "additionalProperties": true - }, - "port": { - "type": "integer" - }, - "resource": { - "type": "string" - }, - "source": { - "type": "string" - }, - "type": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "request.RuntimeDelete": { - "type": "object", - "properties": { - "forceDelete": { - "type": "boolean" - }, - "id": { - "type": "integer" - } - } - }, - "request.RuntimeOperate": { - "type": "object", - "properties": { - "ID": { - "type": "integer" - }, - "operate": { - "type": "string" - } - } - }, - "request.RuntimeSearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "name": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "status": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "request.RuntimeUpdate": { - "type": "object", - "properties": { - "clean": { - "type": "boolean" - }, - "codeDir": { - "type": "string" - }, - "exposedPorts": { - "type": "array", - "items": { - "$ref": "#/definitions/request.ExposedPort" - } - }, - "id": { - "type": "integer" - }, - "image": { - "type": "string" - }, - "install": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "params": { - "type": "object", - "additionalProperties": true - }, - "port": { - "type": "integer" - }, - "rebuild": { - "type": "boolean" - }, - "source": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "request.SearchUploadWithPage": { - "type": "object", - "required": [ - "page", - "pageSize", - "path" - ], - "properties": { - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "path": { - "type": "string" - } - } - }, - "request.SupervisorProcessConfig": { - "type": "object", - "properties": { - "command": { - "type": "string" - }, - "dir": { - "type": "string" - }, - "name": { - "type": "string" - }, - "numprocs": { - "type": "string" - }, - "operate": { - "type": "string" - }, - "user": { - "type": "string" - } - } - }, - "request.SupervisorProcessFileReq": { - "type": "object", - "required": [ - "file", - "name", - "operate" - ], - "properties": { - "content": { - "type": "string" - }, - "file": { - "type": "string", - "enum": [ - "out.log", - "err.log", - "config" - ] - }, - "name": { - "type": "string" - }, - "operate": { - "type": "string", - "enum": [ - "get", - "clear", - "update" - ] - } - } - }, - "request.WebsiteAcmeAccountCreate": { - "type": "object", - "required": [ - "email", - "keyType", - "type" - ], - "properties": { - "eabHmacKey": { - "type": "string" - }, - "eabKid": { - "type": "string" - }, - "email": { - "type": "string" - }, - "keyType": { - "type": "string", - "enum": [ - "P256", - "P384", - "2048", - "3072", - "4096", - "8192" - ] - }, - "type": { - "type": "string", - "enum": [ - "letsencrypt", - "zerossl", - "buypass", - "google" - ] - } - } - }, - "request.WebsiteBatchDelReq": { - "type": "object", - "required": [ - "ids" - ], - "properties": { - "ids": { - "type": "array", - "items": { - "type": "integer" - } - } - } - }, - "request.WebsiteCACreate": { - "type": "object", - "required": [ - "commonName", - "country", - "keyType", - "name", - "organization" - ], - "properties": { - "city": { - "type": "string" - }, - "commonName": { - "type": "string" - }, - "country": { - "type": "string" - }, - "keyType": { - "type": "string", - "enum": [ - "P256", - "P384", - "2048", - "3072", - "4096", - "8192" - ] - }, - "name": { - "type": "string" - }, - "organization": { - "type": "string" - }, - "organizationUint": { - "type": "string" - }, - "province": { - "type": "string" - } - } - }, - "request.WebsiteCAObtain": { - "type": "object", - "required": [ - "domains", - "id", - "keyType", - "time", - "unit" - ], - "properties": { - "autoRenew": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "dir": { - "type": "string" - }, - "domains": { - "type": "string" - }, - "execShell": { - "type": "boolean" - }, - "id": { - "type": "integer" - }, - "keyType": { - "type": "string", - "enum": [ - "P256", - "P384", - "2048", - "3072", - "4096", - "8192" - ] - }, - "pushDir": { - "type": "boolean" - }, - "renew": { - "type": "boolean" - }, - "shell": { - "type": "string" - }, - "sslID": { - "type": "integer" - }, - "time": { - "type": "integer" - }, - "unit": { - "type": "string" - } - } - }, - "request.WebsiteCASearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "request.WebsiteCommonReq": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - } - } - }, - "request.WebsiteCreate": { - "type": "object", - "required": [ - "alias", - "primaryDomain", - "type", - "webSiteGroupID" - ], - "properties": { - "IPV6": { - "type": "boolean" - }, - "alias": { - "type": "string" - }, - "appID": { - "type": "integer" - }, - "appInstall": { - "$ref": "#/definitions/request.NewAppInstall" - }, - "appInstallID": { - "type": "integer" - }, - "appType": { - "type": "string", - "enum": [ - "new", - "installed" - ] - }, - "ftpPassword": { - "type": "string" - }, - "ftpUser": { - "type": "string" - }, - "otherDomains": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "primaryDomain": { - "type": "string" - }, - "proxy": { - "type": "string" - }, - "proxyType": { - "type": "string" - }, - "remark": { - "type": "string" - }, - "runtimeID": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "webSiteGroupID": { - "type": "integer" - } - } - }, - "request.WebsiteDNSReq": { - "type": "object", - "required": [ - "acmeAccountId", - "domains" - ], - "properties": { - "acmeAccountId": { - "type": "integer" - }, - "domains": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "request.WebsiteDefaultUpdate": { - "type": "object", - "properties": { - "id": { - "type": "integer" - } - } - }, - "request.WebsiteDelete": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "deleteApp": { - "type": "boolean" - }, - "deleteBackup": { - "type": "boolean" - }, - "forceDelete": { - "type": "boolean" - }, - "id": { - "type": "integer" - } - } - }, - "request.WebsiteDnsAccountCreate": { - "type": "object", - "required": [ - "authorization", - "name", - "type" - ], - "properties": { - "authorization": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "request.WebsiteDnsAccountUpdate": { - "type": "object", - "required": [ - "authorization", - "id", - "name", - "type" - ], - "properties": { - "authorization": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "request.WebsiteDomainCreate": { - "type": "object", - "required": [ - "domains", - "websiteID" - ], - "properties": { - "domains": { - "type": "string" - }, - "websiteID": { - "type": "integer" - } - } - }, - "request.WebsiteDomainDelete": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - } - } - }, - "request.WebsiteHTTPSOp": { - "type": "object", - "required": [ - "websiteId" - ], - "properties": { - "SSLProtocol": { - "type": "array", - "items": { - "type": "string" - } - }, - "algorithm": { - "type": "string" - }, - "certificate": { - "type": "string" - }, - "certificatePath": { - "type": "string" - }, - "enable": { - "type": "boolean" - }, - "hsts": { - "type": "boolean" - }, - "httpConfig": { - "type": "string", - "enum": [ - "HTTPSOnly", - "HTTPAlso", - "HTTPToHTTPS" - ] - }, - "importType": { - "type": "string" - }, - "privateKey": { - "type": "string" - }, - "privateKeyPath": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "existed", - "auto", - "manual" - ] - }, - "websiteId": { - "type": "integer" - }, - "websiteSSLId": { - "type": "integer" - } - } - }, - "request.WebsiteHtmlUpdate": { - "type": "object", - "required": [ - "content", - "type" - ], - "properties": { - "content": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "request.WebsiteInstallCheckReq": { - "type": "object", - "properties": { - "InstallIds": { - "type": "array", - "items": { - "type": "integer" - } - } - } - }, - "request.WebsiteLogReq": { - "type": "object", - "required": [ - "id", - "logType", - "operate" - ], - "properties": { - "id": { - "type": "integer" - }, - "logType": { - "type": "string" - }, - "operate": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "request.WebsiteNginxUpdate": { - "type": "object", - "required": [ - "content", - "id" - ], - "properties": { - "content": { - "type": "string" - }, - "id": { - "type": "integer" - } - } - }, - "request.WebsiteOp": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - }, - "operate": { - "type": "string" - } - } - }, - "request.WebsitePHPConfigUpdate": { - "type": "object", - "required": [ - "id", - "scope" - ], - "properties": { - "disableFunctions": { - "type": "array", - "items": { - "type": "string" - } - }, - "id": { - "type": "integer" - }, - "params": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "scope": { - "type": "string" - }, - "uploadMaxSize": { - "type": "string" - } - } - }, - "request.WebsitePHPFileUpdate": { - "type": "object", - "required": [ - "content", - "id", - "type" - ], - "properties": { - "content": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "type": { - "type": "string" - } - } - }, - "request.WebsitePHPVersionReq": { - "type": "object", - "required": [ - "runtimeID", - "websiteID" - ], - "properties": { - "retainConfig": { - "type": "boolean" - }, - "runtimeID": { - "type": "integer" - }, - "websiteID": { - "type": "integer" - } - } - }, - "request.WebsiteProxyConfig": { - "type": "object", - "required": [ - "id", - "match", - "name", - "operate", - "proxyHost", - "proxyPass" - ], - "properties": { - "cache": { - "type": "boolean" - }, - "cacheTime": { - "type": "integer" - }, - "cacheUnit": { - "type": "string" - }, - "content": { - "type": "string" - }, - "enable": { - "type": "boolean" - }, - "filePath": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "match": { - "type": "string" - }, - "modifier": { - "type": "string" - }, - "name": { - "type": "string" - }, - "operate": { - "type": "string" - }, - "proxyHost": { - "type": "string" - }, - "proxyPass": { - "type": "string" - }, - "replaces": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "sni": { - "type": "boolean" - } - } - }, - "request.WebsiteProxyReq": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - } - } - }, - "request.WebsiteResourceReq": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer" - } - } - }, - "request.WebsiteSSLApply": { - "type": "object", - "required": [ - "ID" - ], - "properties": { - "ID": { - "type": "integer" - }, - "nameservers": { - "type": "array", - "items": { - "type": "string" - } - }, - "skipDNSCheck": { - "type": "boolean" - } - } - }, - "request.WebsiteSSLCreate": { - "type": "object", - "required": [ - "acmeAccountId", - "primaryDomain", - "provider" - ], - "properties": { - "acmeAccountId": { - "type": "integer" - }, - "apply": { - "type": "boolean" - }, - "autoRenew": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "dir": { - "type": "string" - }, - "disableCNAME": { - "type": "boolean" - }, - "dnsAccountId": { - "type": "integer" - }, - "execShell": { - "type": "boolean" - }, - "id": { - "type": "integer" - }, - "keyType": { - "type": "string" - }, - "nameserver1": { - "type": "string" - }, - "nameserver2": { - "type": "string" - }, - "otherDomains": { - "type": "string" - }, - "primaryDomain": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "pushDir": { - "type": "boolean" - }, - "shell": { - "type": "string" - }, - "skipDNS": { - "type": "boolean" - } - } - }, - "request.WebsiteSSLSearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "acmeAccountID": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - } - } - }, - "request.WebsiteSSLUpdate": { - "type": "object", - "required": [ - "id", - "primaryDomain", - "provider" - ], - "properties": { - "acmeAccountId": { - "type": "integer" - }, - "apply": { - "type": "boolean" - }, - "autoRenew": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "dir": { - "type": "string" - }, - "disableCNAME": { - "type": "boolean" - }, - "dnsAccountId": { - "type": "integer" - }, - "execShell": { - "type": "boolean" - }, - "id": { - "type": "integer" - }, - "keyType": { - "type": "string" - }, - "nameserver1": { - "type": "string" - }, - "nameserver2": { - "type": "string" - }, - "otherDomains": { - "type": "string" - }, - "primaryDomain": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "pushDir": { - "type": "boolean" - }, - "shell": { - "type": "string" - }, - "skipDNS": { - "type": "boolean" - } - } - }, - "request.WebsiteSSLUpload": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "certificate": { - "type": "string" - }, - "certificatePath": { - "type": "string" - }, - "description": { - "type": "string" - }, - "privateKey": { - "type": "string" - }, - "privateKeyPath": { - "type": "string" - }, - "sslID": { - "type": "integer" - }, - "type": { - "type": "string", - "enum": [ - "paste", - "local" - ] - } - } - }, - "request.WebsiteSearch": { - "type": "object", - "required": [ - "order", - "orderBy", - "page", - "pageSize" - ], - "properties": { - "name": { - "type": "string" - }, - "order": { - "type": "string", - "enum": [ - "null", - "ascending", - "descending" - ] - }, - "orderBy": { - "type": "string", - "enum": [ - "primary_domain", - "type", - "status", - "created_at", - "expire_date" - ] - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "websiteGroupId": { - "type": "integer" - } - } - }, - "request.WebsiteUpdate": { - "type": "object", - "required": [ - "id", - "primaryDomain" - ], - "properties": { - "IPV6": { - "type": "boolean" - }, - "expireDate": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "primaryDomain": { - "type": "string" - }, - "remark": { - "type": "string" - }, - "webSiteGroupID": { - "type": "integer" - } - } - }, - "request.WebsiteUpdateDir": { - "type": "object", - "required": [ - "id", - "siteDir" - ], - "properties": { - "id": { - "type": "integer" - }, - "siteDir": { - "type": "string" - } - } - }, - "request.WebsiteUpdateDirPermission": { - "type": "object", - "required": [ - "group", - "id", - "user" - ], - "properties": { - "group": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "user": { - "type": "string" - } - } - }, - "response.AppDTO": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "crossVersionUpdate": { - "type": "boolean" - }, - "document": { - "type": "string" - }, - "github": { - "type": "string" - }, - "icon": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "installed": { - "type": "boolean" - }, - "key": { - "type": "string" - }, - "lastModified": { - "type": "integer" - }, - "limit": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "readMe": { - "type": "string" - }, - "recommend": { - "type": "integer" - }, - "required": { - "type": "string" - }, - "resource": { - "type": "string" - }, - "shortDescEn": { - "type": "string" - }, - "shortDescZh": { - "type": "string" - }, - "status": { - "type": "string" - }, - "tags": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Tag" - } - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "versions": { - "type": "array", - "items": { - "type": "string" - } - }, - "website": { - "type": "string" - } - } - }, - "response.AppDetailDTO": { - "type": "object", - "properties": { - "appId": { - "type": "integer" - }, - "createdAt": { - "type": "string" - }, - "dockerCompose": { - "type": "string" - }, - "downloadCallBackUrl": { - "type": "string" - }, - "downloadUrl": { - "type": "string" - }, - "enable": { - "type": "boolean" - }, - "hostMode": { - "type": "boolean" - }, - "id": { - "type": "integer" - }, - "ignoreUpgrade": { - "type": "boolean" - }, - "image": { - "type": "string" - }, - "lastModified": { - "type": "integer" - }, - "lastVersion": { - "type": "string" - }, - "params": {}, - "status": { - "type": "string" - }, - "update": { - "type": "boolean" - }, - "updatedAt": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "response.AppInstalledCheck": { - "type": "object", - "properties": { - "app": { - "type": "string" - }, - "appInstallId": { - "type": "integer" - }, - "containerName": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "httpPort": { - "type": "integer" - }, - "httpsPort": { - "type": "integer" - }, - "installPath": { - "type": "string" - }, - "isExist": { - "type": "boolean" - }, - "lastBackupAt": { - "type": "string" - }, - "name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "response.AppParam": { - "type": "object", - "properties": { - "edit": { - "type": "boolean" - }, - "key": { - "type": "string" - }, - "labelEn": { - "type": "string" - }, - "labelZh": { - "type": "string" - }, - "multiple": { - "type": "boolean" - }, - "required": { - "type": "boolean" - }, - "rule": { - "type": "string" - }, - "showValue": { - "type": "string" - }, - "type": { - "type": "string" - }, - "value": {}, - "values": {} - } - }, - "response.AppService": { - "type": "object", - "properties": { - "config": {}, - "from": { - "type": "string" - }, - "label": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "response.FileInfo": { - "type": "object", - "properties": { - "content": { - "type": "string" - }, - "extension": { - "type": "string" - }, - "favoriteID": { - "type": "integer" - }, - "gid": { - "type": "string" - }, - "group": { - "type": "string" - }, - "isDetail": { - "type": "boolean" - }, - "isDir": { - "type": "boolean" - }, - "isHidden": { - "type": "boolean" - }, - "isSymlink": { - "type": "boolean" - }, - "itemTotal": { - "type": "integer" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/files.FileInfo" - } - }, - "linkPath": { - "type": "string" - }, - "mimeType": { - "type": "string" - }, - "modTime": { - "type": "string" - }, - "mode": { - "type": "string" - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - }, - "size": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "uid": { - "type": "string" - }, - "updateTime": { - "type": "string" - }, - "user": { - "type": "string" - } - } - }, - "response.FileTree": { - "type": "object", - "properties": { - "children": { - "type": "array", - "items": { - "$ref": "#/definitions/response.FileTree" - } - }, - "extension": { - "type": "string" - }, - "id": { - "type": "string" - }, - "isDir": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - } - } - }, - "response.IgnoredApp": { - "type": "object", - "properties": { - "detailID": { - "type": "integer" - }, - "icon": { - "type": "string" - }, - "name": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "response.NginxParam": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "params": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "response.NginxStatus": { - "type": "object", - "properties": { - "accepts": { - "type": "string" - }, - "active": { - "type": "string" - }, - "handled": { - "type": "string" - }, - "reading": { - "type": "string" - }, - "requests": { - "type": "string" - }, - "waiting": { - "type": "string" - }, - "writing": { - "type": "string" - } - } - }, - "response.PHPConfig": { - "type": "object", - "properties": { - "disableFunctions": { - "type": "array", - "items": { - "type": "string" - } - }, - "params": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "uploadMaxSize": { - "type": "string" - } - } - }, - "response.PHPExtensionsDTO": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "extensions": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "response.WebsiteAcmeAccountDTO": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "eabHmacKey": { - "type": "string" - }, - "eabKid": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "keyType": { - "type": "string" - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "url": { - "type": "string" - } - } - }, - "response.WebsiteCADTO": { - "type": "object", - "properties": { - "city": { - "type": "string" - }, - "commonName": { - "type": "string" - }, - "country": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "csr": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "keyType": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "type": "string" - }, - "organizationUint": { - "type": "string" - }, - "privateKey": { - "type": "string" - }, - "province": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "response.WebsiteDNSRes": { - "type": "object", - "properties": { - "domain": { - "type": "string" - }, - "err": { - "type": "string" - }, - "resolve": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "response.WebsiteDTO": { - "type": "object", - "properties": { - "IPV6": { - "type": "boolean" - }, - "accessLog": { - "type": "boolean" - }, - "accessLogPath": { - "type": "string" - }, - "alias": { - "type": "string" - }, - "appInstallId": { - "type": "integer" - }, - "appName": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "defaultServer": { - "type": "boolean" - }, - "domains": { - "type": "array", - "items": { - "$ref": "#/definitions/model.WebsiteDomain" - } - }, - "errorLog": { - "type": "boolean" - }, - "errorLogPath": { - "type": "string" - }, - "expireDate": { - "type": "string" - }, - "ftpId": { - "type": "integer" - }, - "group": { - "type": "string" - }, - "httpConfig": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "primaryDomain": { - "type": "string" - }, - "protocol": { - "type": "string" - }, - "proxy": { - "type": "string" - }, - "proxyType": { - "type": "string" - }, - "remark": { - "type": "string" - }, - "rewrite": { - "type": "string" - }, - "runtimeID": { - "type": "integer" - }, - "runtimeName": { - "type": "string" - }, - "siteDir": { - "type": "string" - }, - "sitePath": { - "type": "string" - }, - "status": { - "type": "string" - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "user": { - "type": "string" - }, - "webSiteGroupId": { - "type": "integer" - }, - "webSiteSSL": { - "$ref": "#/definitions/model.WebsiteSSL" - }, - "webSiteSSLId": { - "type": "integer" - } - } - }, - "response.WebsiteHTTPS": { - "type": "object", - "properties": { - "SSL": { - "$ref": "#/definitions/model.WebsiteSSL" - }, - "SSLProtocol": { - "type": "array", - "items": { - "type": "string" - } - }, - "algorithm": { - "type": "string" - }, - "enable": { - "type": "boolean" - }, - "hsts": { - "type": "boolean" - }, - "httpConfig": { - "type": "string" - } - } - }, - "response.WebsiteLog": { - "type": "object", - "properties": { - "content": { - "type": "string" - }, - "enable": { - "type": "boolean" - }, - "end": { - "type": "boolean" - }, - "path": { - "type": "string" - } - } - }, - "response.WebsiteNginxConfig": { - "type": "object", - "properties": { - "enable": { - "type": "boolean" - }, - "params": { - "type": "array", - "items": { - "$ref": "#/definitions/response.NginxParam" - } - } - } - }, - "response.WebsitePreInstallCheck": { - "type": "object", - "properties": { - "appName": { - "type": "string" - }, - "name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "version": { - "type": "string" - } - } - } - } -} \ No newline at end of file diff --git a/core/cmd/server/docs/swagger.yaml b/core/cmd/server/docs/swagger.yaml deleted file mode 100644 index 9dabd1965..000000000 --- a/core/cmd/server/docs/swagger.yaml +++ /dev/null @@ -1,15166 +0,0 @@ -basePath: /api/v1 -definitions: - dto.AddrRuleOperate: - properties: - address: - type: string - description: - type: string - operation: - enum: - - add - - remove - type: string - strategy: - enum: - - accept - - drop - type: string - required: - - address - - operation - - strategy - type: object - dto.AddrRuleUpdate: - properties: - newRule: - $ref: '#/definitions/dto.AddrRuleOperate' - oldRule: - $ref: '#/definitions/dto.AddrRuleOperate' - type: object - dto.AppInstallInfo: - properties: - id: - type: integer - key: - type: string - name: - type: string - type: object - dto.AppResource: - properties: - name: - type: string - type: - type: string - type: object - dto.AppVersion: - properties: - detailId: - type: integer - dockerCompose: - type: string - version: - type: string - type: object - dto.BackupInfo: - properties: - backupPath: - type: string - bucket: - type: string - createdAt: - type: string - id: - type: integer - type: - type: string - vars: - type: string - type: object - dto.BackupOperate: - properties: - accessKey: - type: string - backupPath: - type: string - bucket: - type: string - credential: - type: string - id: - type: integer - type: - type: string - vars: - type: string - required: - - type - - vars - type: object - dto.BackupSearchFile: - properties: - type: - type: string - required: - - type - type: object - dto.BatchDelete: - properties: - force: - type: boolean - names: - items: - type: string - type: array - required: - - names - type: object - dto.BatchDeleteReq: - properties: - ids: - items: - type: integer - type: array - required: - - ids - type: object - dto.BatchRuleOperate: - properties: - rules: - items: - $ref: '#/definitions/dto.PortRuleOperate' - type: array - type: - type: string - required: - - type - type: object - dto.BindInfo: - properties: - bindAddress: - type: string - ipv6: - enum: - - enable - - disable - type: string - required: - - bindAddress - - ipv6 - type: object - dto.BindUser: - properties: - database: - type: string - db: - type: string - password: - type: string - permission: - type: string - username: - type: string - required: - - database - - db - - password - - permission - - username - type: object - dto.CaptchaResponse: - properties: - captchaID: - type: string - imagePath: - type: string - type: object - dto.ChangeDBInfo: - properties: - database: - type: string - from: - enum: - - local - - remote - type: string - id: - type: integer - type: - enum: - - mysql - - mariadb - - postgresql - type: string - value: - type: string - required: - - database - - from - - type - - value - type: object - dto.ChangeHostGroup: - properties: - groupID: - type: integer - id: - type: integer - required: - - groupID - - id - type: object - dto.ChangePasswd: - properties: - passwd: - type: string - user: - type: string - type: object - dto.ChangeRedisPass: - properties: - database: - type: string - value: - type: string - required: - - database - type: object - dto.ClamBaseInfo: - properties: - freshIsActive: - type: boolean - freshIsExist: - type: boolean - freshVersion: - type: string - isActive: - type: boolean - isExist: - type: boolean - version: - type: string - type: object - dto.ClamCreate: - properties: - description: - type: string - infectedDir: - type: string - infectedStrategy: - type: string - name: - type: string - path: - type: string - spec: - type: string - status: - type: string - type: object - dto.ClamDelete: - properties: - ids: - items: - type: integer - type: array - removeInfected: - type: boolean - removeRecord: - type: boolean - required: - - ids - type: object - dto.ClamFileReq: - properties: - name: - type: string - tail: - type: string - required: - - name - type: object - dto.ClamLogReq: - properties: - clamName: - type: string - recordName: - type: string - tail: - type: string - type: object - dto.ClamLogSearch: - properties: - clamID: - type: integer - endTime: - type: string - page: - type: integer - pageSize: - type: integer - startTime: - type: string - required: - - page - - pageSize - type: object - dto.ClamUpdate: - properties: - description: - type: string - id: - type: integer - infectedDir: - type: string - infectedStrategy: - type: string - name: - type: string - path: - type: string - spec: - type: string - type: object - dto.ClamUpdateStatus: - properties: - id: - type: integer - status: - type: string - type: object - dto.Clean: - properties: - name: - type: string - size: - type: integer - treeType: - type: string - type: object - dto.CleanLog: - properties: - logType: - enum: - - login - - operation - type: string - required: - - logType - type: object - dto.CommandInfo: - properties: - command: - type: string - groupBelong: - type: string - groupID: - type: integer - id: - type: integer - name: - type: string - type: object - dto.CommandOperate: - properties: - command: - type: string - groupBelong: - type: string - groupID: - type: integer - id: - type: integer - name: - type: string - required: - - command - - name - type: object - dto.CommonBackup: - properties: - detailName: - type: string - name: - type: string - secret: - type: string - type: - enum: - - app - - mysql - - mariadb - - redis - - website - - postgresql - type: string - required: - - type - type: object - dto.CommonRecover: - properties: - detailName: - type: string - file: - type: string - name: - type: string - secret: - type: string - source: - enum: - - OSS - - S3 - - SFTP - - MINIO - - LOCAL - - COS - - KODO - - OneDrive - - WebDAV - type: string - type: - enum: - - app - - mysql - - mariadb - - redis - - website - - postgresql - type: string - required: - - source - - type - type: object - dto.ComposeCreate: - properties: - file: - type: string - from: - enum: - - edit - - path - - template - type: string - name: - type: string - path: - type: string - template: - type: integer - required: - - from - type: object - dto.ComposeOperation: - properties: - name: - type: string - operation: - enum: - - start - - stop - - down - type: string - path: - type: string - withFile: - type: boolean - required: - - name - - operation - - path - type: object - dto.ComposeTemplateCreate: - properties: - content: - type: string - description: - type: string - name: - type: string - required: - - name - type: object - dto.ComposeTemplateInfo: - properties: - content: - type: string - createdAt: - type: string - description: - type: string - id: - type: integer - name: - type: string - type: object - dto.ComposeTemplateUpdate: - properties: - content: - type: string - description: - type: string - id: - type: integer - type: object - dto.ComposeUpdate: - properties: - content: - type: string - name: - type: string - path: - type: string - required: - - content - - name - - path - type: object - dto.ContainerCommit: - properties: - author: - type: string - comment: - type: string - containerID: - type: string - containerName: - type: string - newImageName: - type: string - pause: - type: boolean - required: - - containerID - type: object - dto.ContainerListStats: - properties: - containerID: - type: string - cpuPercent: - type: number - cpuTotalUsage: - type: integer - memoryCache: - type: integer - memoryLimit: - type: integer - memoryPercent: - type: number - memoryUsage: - type: integer - percpuUsage: - type: integer - systemUsage: - type: integer - type: object - dto.ContainerOperate: - properties: - autoRemove: - type: boolean - cmd: - items: - type: string - type: array - containerID: - type: string - cpuShares: - type: integer - entrypoint: - items: - type: string - type: array - env: - items: - type: string - type: array - exposedPorts: - items: - $ref: '#/definitions/dto.PortHelper' - type: array - forcePull: - type: boolean - image: - type: string - ipv4: - type: string - ipv6: - type: string - labels: - items: - type: string - type: array - memory: - type: number - name: - type: string - nanoCPUs: - type: number - network: - type: string - openStdin: - type: boolean - privileged: - type: boolean - publishAllPorts: - type: boolean - restartPolicy: - type: string - tty: - type: boolean - volumes: - items: - $ref: '#/definitions/dto.VolumeHelper' - type: array - required: - - image - - name - type: object - dto.ContainerOperation: - properties: - names: - items: - type: string - type: array - operation: - enum: - - start - - stop - - restart - - kill - - pause - - unpause - - remove - type: string - required: - - names - - operation - type: object - dto.ContainerPrune: - properties: - pruneType: - enum: - - container - - image - - volume - - network - - buildcache - type: string - withTagAll: - type: boolean - required: - - pruneType - type: object - dto.ContainerPruneReport: - properties: - deletedNumber: - type: integer - spaceReclaimed: - type: integer - type: object - dto.ContainerRename: - properties: - name: - type: string - newName: - type: string - required: - - name - - newName - type: object - dto.ContainerStats: - properties: - cache: - type: number - cpuPercent: - type: number - ioRead: - type: number - ioWrite: - type: number - memory: - type: number - networkRX: - type: number - networkTX: - type: number - shotTime: - type: string - type: object - dto.ContainerUpgrade: - properties: - forcePull: - type: boolean - image: - type: string - name: - type: string - required: - - image - - name - type: object - dto.CronjobBatchDelete: - properties: - cleanData: - type: boolean - ids: - items: - type: integer - type: array - required: - - ids - type: object - dto.CronjobClean: - properties: - cleanData: - type: boolean - cronjobID: - type: integer - isDelete: - type: boolean - required: - - cronjobID - type: object - dto.CronjobCreate: - properties: - appID: - type: string - backupAccounts: - type: string - command: - type: string - containerName: - type: string - dbName: - type: string - dbType: - type: string - defaultDownload: - type: string - exclusionRules: - type: string - name: - type: string - retainCopies: - minimum: 1 - type: integer - script: - type: string - secret: - type: string - sourceDir: - type: string - spec: - type: string - type: - type: string - url: - type: string - website: - type: string - required: - - name - - spec - - type - type: object - dto.CronjobDownload: - properties: - backupAccountID: - type: integer - recordID: - type: integer - required: - - backupAccountID - - recordID - type: object - dto.CronjobUpdate: - properties: - appID: - type: string - backupAccounts: - type: string - command: - type: string - containerName: - type: string - dbName: - type: string - dbType: - type: string - defaultDownload: - type: string - exclusionRules: - type: string - id: - type: integer - name: - type: string - retainCopies: - minimum: 1 - type: integer - script: - type: string - secret: - type: string - sourceDir: - type: string - spec: - type: string - url: - type: string - website: - type: string - required: - - id - - name - - spec - type: object - dto.CronjobUpdateStatus: - properties: - id: - type: integer - status: - type: string - required: - - id - - status - type: object - dto.DBBaseInfo: - properties: - containerName: - type: string - name: - type: string - port: - type: integer - type: object - dto.DBConfUpdateByFile: - properties: - database: - type: string - file: - type: string - type: - enum: - - mysql - - mariadb - - postgresql - - redis - type: string - required: - - database - - type - type: object - dto.DaemonJsonConf: - properties: - cgroupDriver: - type: string - experimental: - type: boolean - fixedCidrV6: - type: string - insecureRegistries: - items: - type: string - type: array - ip6Tables: - type: boolean - iptables: - type: boolean - ipv6: - type: boolean - isSwarm: - type: boolean - liveRestore: - type: boolean - logMaxFile: - type: string - logMaxSize: - type: string - registryMirrors: - items: - type: string - type: array - status: - type: string - version: - type: string - type: object - dto.DaemonJsonUpdateByFile: - properties: - file: - type: string - type: object - dto.DashboardBase: - properties: - appInstalledNumber: - type: integer - cpuCores: - type: integer - cpuLogicalCores: - type: integer - cpuModelName: - type: string - cronjobNumber: - type: integer - currentInfo: - $ref: '#/definitions/dto.DashboardCurrent' - databaseNumber: - type: integer - hostname: - type: string - kernelArch: - type: string - kernelVersion: - type: string - os: - type: string - platform: - type: string - platformFamily: - type: string - platformVersion: - type: string - virtualizationSystem: - type: string - websiteNumber: - type: integer - type: object - dto.DashboardCurrent: - properties: - cpuPercent: - items: - type: number - type: array - cpuTotal: - type: integer - cpuUsed: - type: number - cpuUsedPercent: - type: number - diskData: - items: - $ref: '#/definitions/dto.DiskInfo' - type: array - gpuData: - items: - $ref: '#/definitions/dto.GPUInfo' - type: array - ioCount: - type: integer - ioReadBytes: - type: integer - ioReadTime: - type: integer - ioWriteBytes: - type: integer - ioWriteTime: - type: integer - load1: - type: number - load5: - type: number - load15: - type: number - loadUsagePercent: - type: number - memoryAvailable: - type: integer - memoryTotal: - type: integer - memoryUsed: - type: integer - memoryUsedPercent: - type: number - netBytesRecv: - type: integer - netBytesSent: - type: integer - procs: - type: integer - shotTime: - type: string - swapMemoryAvailable: - type: integer - swapMemoryTotal: - type: integer - swapMemoryUsed: - type: integer - swapMemoryUsedPercent: - type: number - timeSinceUptime: - type: string - uptime: - type: integer - type: object - dto.DatabaseCreate: - properties: - address: - type: string - clientCert: - type: string - clientKey: - type: string - description: - type: string - from: - enum: - - local - - remote - type: string - name: - maxLength: 256 - type: string - password: - type: string - port: - type: integer - rootCert: - type: string - skipVerify: - type: boolean - ssl: - type: boolean - type: - type: string - username: - type: string - version: - type: string - required: - - from - - name - - type - - username - - version - type: object - dto.DatabaseDelete: - properties: - deleteBackup: - type: boolean - forceDelete: - type: boolean - id: - type: integer - required: - - id - type: object - dto.DatabaseInfo: - properties: - address: - type: string - clientCert: - type: string - clientKey: - type: string - createdAt: - type: string - description: - type: string - from: - type: string - id: - type: integer - name: - maxLength: 256 - type: string - password: - type: string - port: - type: integer - rootCert: - type: string - skipVerify: - type: boolean - ssl: - type: boolean - type: - type: string - username: - type: string - version: - type: string - type: object - dto.DatabaseItem: - properties: - database: - type: string - from: - type: string - id: - type: integer - name: - type: string - type: object - dto.DatabaseOption: - properties: - address: - type: string - database: - type: string - from: - type: string - id: - type: integer - type: - type: string - version: - type: string - type: object - dto.DatabaseSearch: - properties: - info: - type: string - order: - enum: - - "null" - - ascending - - descending - type: string - orderBy: - enum: - - name - - created_at - type: string - page: - type: integer - pageSize: - type: integer - type: - type: string - required: - - order - - orderBy - - page - - pageSize - type: object - dto.DatabaseUpdate: - properties: - address: - type: string - clientCert: - type: string - clientKey: - type: string - description: - type: string - id: - type: integer - password: - type: string - port: - type: integer - rootCert: - type: string - skipVerify: - type: boolean - ssl: - type: boolean - type: - type: string - username: - type: string - version: - type: string - required: - - type - - username - - version - type: object - dto.DeviceBaseInfo: - properties: - dns: - items: - type: string - type: array - hostname: - type: string - hosts: - items: - $ref: '#/definitions/dto.HostHelper' - type: array - localTime: - type: string - maxSize: - type: integer - ntp: - type: string - swapDetails: - items: - $ref: '#/definitions/dto.SwapHelper' - type: array - swapMemoryAvailable: - type: integer - swapMemoryTotal: - type: integer - swapMemoryUsed: - type: integer - timeZone: - type: string - user: - type: string - type: object - dto.DiskInfo: - properties: - device: - type: string - free: - type: integer - inodesFree: - type: integer - inodesTotal: - type: integer - inodesUsed: - type: integer - inodesUsedPercent: - type: number - path: - type: string - total: - type: integer - type: - type: string - used: - type: integer - usedPercent: - type: number - type: object - dto.DockerOperation: - properties: - operation: - enum: - - start - - restart - - stop - type: string - required: - - operation - type: object - dto.DownloadRecord: - properties: - fileDir: - type: string - fileName: - type: string - source: - enum: - - OSS - - S3 - - SFTP - - MINIO - - LOCAL - - COS - - KODO - - OneDrive - - WebDAV - type: string - required: - - fileDir - - fileName - - source - type: object - dto.Fail2BanBaseInfo: - properties: - banAction: - type: string - banTime: - type: string - findTime: - type: string - isActive: - type: boolean - isEnable: - type: boolean - isExist: - type: boolean - logPath: - type: string - maxRetry: - type: integer - port: - type: integer - version: - type: string - type: object - dto.Fail2BanSearch: - properties: - status: - enum: - - banned - - ignore - type: string - required: - - status - type: object - dto.Fail2BanUpdate: - properties: - key: - enum: - - port - - bantime - - findtime - - maxretry - - banaction - - logpath - - port - type: string - value: - type: string - required: - - key - type: object - dto.FirewallBaseInfo: - properties: - name: - type: string - pingStatus: - type: string - status: - type: string - version: - type: string - type: object - dto.FirewallOperation: - properties: - operation: - enum: - - start - - stop - - restart - - disablePing - - enablePing - type: string - required: - - operation - type: object - dto.ForBuckets: - properties: - accessKey: - type: string - credential: - type: string - type: - type: string - vars: - type: string - required: - - credential - - type - - vars - type: object - dto.ForwardRuleOperate: - properties: - rules: - items: - properties: - num: - type: string - operation: - enum: - - add - - remove - type: string - port: - type: string - protocol: - enum: - - tcp - - udp - - tcp/udp - type: string - targetIP: - type: string - targetPort: - type: string - required: - - operation - - port - - protocol - - targetPort - type: object - type: array - type: object - dto.FtpBaseInfo: - properties: - isActive: - type: boolean - isExist: - type: boolean - type: object - dto.FtpCreate: - properties: - description: - type: string - password: - type: string - path: - type: string - user: - type: string - required: - - password - - path - - user - type: object - dto.FtpLogSearch: - properties: - operation: - type: string - page: - type: integer - pageSize: - type: integer - user: - type: string - required: - - page - - pageSize - type: object - dto.FtpUpdate: - properties: - description: - type: string - id: - type: integer - password: - type: string - path: - type: string - status: - type: string - required: - - password - - path - type: object - dto.GPUInfo: - properties: - fanSpeed: - type: string - gpuUtil: - type: string - index: - type: integer - maxPowerLimit: - type: string - memTotal: - type: string - memUsed: - type: string - memoryUsage: - type: string - performanceState: - type: string - powerDraw: - type: string - powerUsage: - type: string - productName: - type: string - temperature: - type: string - type: object - dto.GenerateLoad: - properties: - encryptionMode: - enum: - - rsa - - ed25519 - - ecdsa - - dsa - type: string - required: - - encryptionMode - type: object - dto.GenerateSSH: - properties: - encryptionMode: - enum: - - rsa - - ed25519 - - ecdsa - - dsa - type: string - password: - type: string - required: - - encryptionMode - type: object - dto.GroupCreate: - properties: - id: - type: integer - name: - type: string - type: - type: string - required: - - name - - type - type: object - dto.GroupInfo: - properties: - id: - type: integer - isDefault: - type: boolean - name: - type: string - type: - type: string - type: object - dto.GroupSearch: - properties: - type: - type: string - required: - - type - type: object - dto.GroupUpdate: - properties: - id: - type: integer - isDefault: - type: boolean - name: - type: string - type: - type: string - required: - - type - type: object - dto.HostConnTest: - properties: - addr: - type: string - authMode: - enum: - - password - - key - type: string - passPhrase: - type: string - password: - type: string - port: - maximum: 65535 - minimum: 1 - type: integer - privateKey: - type: string - user: - type: string - required: - - addr - - port - - user - type: object - dto.HostHelper: - properties: - host: - type: string - ip: - type: string - type: object - dto.HostOperate: - properties: - addr: - type: string - authMode: - enum: - - password - - key - type: string - description: - type: string - groupID: - type: integer - id: - type: integer - name: - type: string - passPhrase: - type: string - password: - type: string - port: - maximum: 65535 - minimum: 1 - type: integer - privateKey: - type: string - rememberPassword: - type: boolean - user: - type: string - required: - - addr - - port - - user - type: object - dto.HostTree: - properties: - children: - items: - $ref: '#/definitions/dto.TreeChild' - type: array - id: - type: integer - label: - type: string - type: object - dto.ImageBuild: - properties: - dockerfile: - type: string - from: - type: string - name: - type: string - tags: - items: - type: string - type: array - required: - - dockerfile - - from - - name - type: object - dto.ImageInfo: - properties: - createdAt: - type: string - id: - type: string - isUsed: - type: boolean - size: - type: string - tags: - items: - type: string - type: array - type: object - dto.ImageLoad: - properties: - path: - type: string - required: - - path - type: object - dto.ImagePull: - properties: - imageName: - type: string - repoID: - type: integer - required: - - imageName - type: object - dto.ImagePush: - properties: - name: - type: string - repoID: - type: integer - tagName: - type: string - required: - - name - - repoID - - tagName - type: object - dto.ImageRepoDelete: - properties: - ids: - items: - type: integer - type: array - required: - - ids - type: object - dto.ImageRepoOption: - properties: - downloadUrl: - type: string - id: - type: integer - name: - type: string - type: object - dto.ImageRepoUpdate: - properties: - auth: - type: boolean - downloadUrl: - type: string - id: - type: integer - password: - maxLength: 256 - type: string - protocol: - type: string - username: - maxLength: 256 - type: string - type: object - dto.ImageSave: - properties: - name: - type: string - path: - type: string - tagName: - type: string - required: - - name - - path - - tagName - type: object - dto.ImageTag: - properties: - sourceID: - type: string - targetName: - type: string - required: - - sourceID - - targetName - type: object - dto.InspectReq: - properties: - id: - type: string - type: - type: string - required: - - id - - type - type: object - dto.LogOption: - properties: - logMaxFile: - type: string - logMaxSize: - type: string - type: object - dto.Login: - properties: - authMethod: - enum: - - jwt - - session - type: string - captcha: - type: string - captchaID: - type: string - ignoreCaptcha: - type: boolean - language: - enum: - - zh - - en - - tw - type: string - name: - type: string - password: - type: string - required: - - authMethod - - language - - name - - password - type: object - dto.MFALogin: - properties: - authMethod: - type: string - code: - type: string - name: - type: string - password: - type: string - required: - - code - - name - - password - type: object - dto.MfaCredential: - properties: - code: - type: string - interval: - type: string - secret: - type: string - required: - - code - - interval - - secret - type: object - dto.MonitorSearch: - properties: - endTime: - type: string - info: - type: string - param: - enum: - - all - - cpu - - memory - - load - - io - - network - type: string - startTime: - type: string - required: - - param - type: object - dto.MysqlDBCreate: - properties: - database: - type: string - description: - type: string - format: - enum: - - utf8mb4 - - utf8 - - gbk - - big5 - type: string - from: - enum: - - local - - remote - type: string - name: - type: string - password: - type: string - permission: - type: string - username: - type: string - required: - - database - - format - - from - - name - - password - - permission - - username - type: object - dto.MysqlDBDelete: - properties: - database: - type: string - deleteBackup: - type: boolean - forceDelete: - type: boolean - id: - type: integer - type: - enum: - - mysql - - mariadb - type: string - required: - - database - - id - - type - type: object - dto.MysqlDBDeleteCheck: - properties: - database: - type: string - id: - type: integer - type: - enum: - - mysql - - mariadb - type: string - required: - - database - - id - - type - type: object - dto.MysqlDBSearch: - properties: - database: - type: string - info: - type: string - order: - enum: - - "null" - - ascending - - descending - type: string - orderBy: - enum: - - name - - created_at - type: string - page: - type: integer - pageSize: - type: integer - required: - - database - - order - - orderBy - - page - - pageSize - type: object - dto.MysqlLoadDB: - properties: - database: - type: string - from: - enum: - - local - - remote - type: string - type: - enum: - - mysql - - mariadb - type: string - required: - - database - - from - - type - type: object - dto.MysqlOption: - properties: - database: - type: string - from: - type: string - id: - type: integer - name: - type: string - type: - type: string - type: object - dto.MysqlStatus: - properties: - Aborted_clients: - type: string - Aborted_connects: - type: string - Bytes_received: - type: string - Bytes_sent: - type: string - Com_commit: - type: string - Com_rollback: - type: string - Connections: - type: string - Created_tmp_disk_tables: - type: string - Created_tmp_tables: - type: string - File: - type: string - Innodb_buffer_pool_pages_dirty: - type: string - Innodb_buffer_pool_read_requests: - type: string - Innodb_buffer_pool_reads: - type: string - Key_read_requests: - type: string - Key_reads: - type: string - Key_write_requests: - type: string - Key_writes: - type: string - Max_used_connections: - type: string - Open_tables: - type: string - Opened_files: - type: string - Opened_tables: - type: string - Position: - type: string - Qcache_hits: - type: string - Qcache_inserts: - type: string - Questions: - type: string - Run: - type: string - Select_full_join: - type: string - Select_range_check: - type: string - Sort_merge_passes: - type: string - Table_locks_waited: - type: string - Threads_cached: - type: string - Threads_connected: - type: string - Threads_created: - type: string - Threads_running: - type: string - Uptime: - type: string - type: object - dto.MysqlVariables: - properties: - binlog_cache_size: - type: string - innodb_buffer_pool_size: - type: string - innodb_log_buffer_size: - type: string - join_buffer_size: - type: string - key_buffer_size: - type: string - long_query_time: - type: string - max_connections: - type: string - max_heap_table_size: - type: string - query_cache_size: - type: string - query_cache_type: - type: string - read_buffer_size: - type: string - read_rnd_buffer_size: - type: string - slow_query_log: - type: string - sort_buffer_size: - type: string - table_open_cache: - type: string - thread_cache_size: - type: string - thread_stack: - type: string - tmp_table_size: - type: string - type: object - dto.MysqlVariablesUpdate: - properties: - database: - type: string - type: - enum: - - mysql - - mariadb - type: string - variables: - items: - $ref: '#/definitions/dto.MysqlVariablesUpdateHelper' - type: array - required: - - database - - type - type: object - dto.MysqlVariablesUpdateHelper: - properties: - param: - type: string - value: {} - type: object - dto.NetworkCreate: - properties: - auxAddress: - items: - $ref: '#/definitions/dto.SettingUpdate' - type: array - auxAddressV6: - items: - $ref: '#/definitions/dto.SettingUpdate' - type: array - driver: - type: string - gateway: - type: string - gatewayV6: - type: string - ipRange: - type: string - ipRangeV6: - type: string - ipv4: - type: boolean - ipv6: - type: boolean - labels: - items: - type: string - type: array - name: - type: string - options: - items: - type: string - type: array - subnet: - type: string - subnetV6: - type: string - required: - - driver - - name - type: object - dto.NginxKey: - enum: - - index - - limit-conn - - ssl - - cache - - http-per - - proxy-cache - type: string - x-enum-varnames: - - Index - - LimitConn - - SSL - - CACHE - - HttpPer - - ProxyCache - dto.OneDriveInfo: - properties: - client_id: - type: string - client_secret: - type: string - redirect_uri: - type: string - type: object - dto.Operate: - properties: - operation: - type: string - required: - - operation - type: object - dto.OperateByID: - properties: - id: - type: integer - required: - - id - type: object - dto.OperationWithName: - properties: - name: - type: string - required: - - name - type: object - dto.OperationWithNameAndType: - properties: - name: - type: string - type: - type: string - required: - - type - type: object - dto.Options: - properties: - option: - type: string - type: object - dto.OsInfo: - properties: - diskSize: - type: integer - kernelArch: - type: string - kernelVersion: - type: string - os: - type: string - platform: - type: string - platformFamily: - type: string - type: object - dto.PageContainer: - properties: - excludeAppStore: - type: boolean - filters: - type: string - name: - type: string - order: - enum: - - "null" - - ascending - - descending - type: string - orderBy: - enum: - - name - - state - - created_at - type: string - page: - type: integer - pageSize: - type: integer - state: - enum: - - all - - created - - running - - paused - - restarting - - removing - - exited - - dead - type: string - required: - - order - - orderBy - - page - - pageSize - - state - type: object - dto.PageCronjob: - properties: - info: - type: string - order: - enum: - - "null" - - ascending - - descending - type: string - orderBy: - enum: - - name - - status - - created_at - type: string - page: - type: integer - pageSize: - type: integer - required: - - order - - orderBy - - page - - pageSize - type: object - dto.PageInfo: - properties: - page: - type: integer - pageSize: - type: integer - required: - - page - - pageSize - type: object - dto.PageResult: - properties: - items: {} - total: - type: integer - type: object - dto.PasswordUpdate: - properties: - newPassword: - type: string - oldPassword: - type: string - required: - - newPassword - - oldPassword - type: object - dto.PortHelper: - properties: - containerPort: - type: string - hostIP: - type: string - hostPort: - type: string - protocol: - type: string - type: object - dto.PortRuleOperate: - properties: - address: - type: string - description: - type: string - operation: - enum: - - add - - remove - type: string - port: - type: string - protocol: - enum: - - tcp - - udp - - tcp/udp - type: string - strategy: - enum: - - accept - - drop - type: string - required: - - operation - - port - - protocol - - strategy - type: object - dto.PortRuleUpdate: - properties: - newRule: - $ref: '#/definitions/dto.PortRuleOperate' - oldRule: - $ref: '#/definitions/dto.PortRuleOperate' - type: object - dto.PortUpdate: - properties: - serverPort: - maximum: 65535 - minimum: 1 - type: integer - required: - - serverPort - type: object - dto.PostgresqlBindUser: - properties: - database: - type: string - name: - type: string - password: - type: string - superUser: - type: boolean - username: - type: string - required: - - database - - name - - password - - username - type: object - dto.PostgresqlDBCreate: - properties: - database: - type: string - description: - type: string - format: - type: string - from: - enum: - - local - - remote - type: string - name: - type: string - password: - type: string - superUser: - type: boolean - username: - type: string - required: - - database - - from - - name - - password - - username - type: object - dto.PostgresqlDBDelete: - properties: - database: - type: string - deleteBackup: - type: boolean - forceDelete: - type: boolean - id: - type: integer - type: - enum: - - postgresql - type: string - required: - - database - - id - - type - type: object - dto.PostgresqlDBDeleteCheck: - properties: - database: - type: string - id: - type: integer - type: - enum: - - postgresql - type: string - required: - - database - - id - - type - type: object - dto.PostgresqlDBSearch: - properties: - database: - type: string - info: - type: string - order: - enum: - - "null" - - ascending - - descending - type: string - orderBy: - enum: - - name - - created_at - type: string - page: - type: integer - pageSize: - type: integer - required: - - database - - order - - orderBy - - page - - pageSize - type: object - dto.PostgresqlLoadDB: - properties: - database: - type: string - from: - enum: - - local - - remote - type: string - type: - enum: - - postgresql - type: string - required: - - database - - from - - type - type: object - dto.ProxyUpdate: - properties: - proxyPasswd: - type: string - proxyPasswdKeep: - type: string - proxyPort: - type: string - proxyType: - type: string - proxyUrl: - type: string - proxyUser: - type: string - type: object - dto.RecordSearch: - properties: - detailName: - type: string - name: - type: string - page: - type: integer - pageSize: - type: integer - type: - type: string - required: - - page - - pageSize - - type - type: object - dto.RecordSearchByCronjob: - properties: - cronjobID: - type: integer - page: - type: integer - pageSize: - type: integer - required: - - cronjobID - - page - - pageSize - type: object - dto.RedisCommand: - properties: - command: - type: string - id: - type: integer - name: - type: string - type: object - dto.RedisConf: - properties: - containerName: - type: string - database: - type: string - maxclients: - type: string - maxmemory: - type: string - name: - type: string - port: - type: integer - requirepass: - type: string - timeout: - type: string - required: - - database - type: object - dto.RedisConfPersistenceUpdate: - properties: - appendfsync: - type: string - appendonly: - type: string - database: - type: string - save: - type: string - type: - enum: - - aof - - rbd - type: string - required: - - database - - type - type: object - dto.RedisConfUpdate: - properties: - database: - type: string - maxclients: - type: string - maxmemory: - type: string - timeout: - type: string - required: - - database - type: object - dto.RedisPersistence: - properties: - appendfsync: - type: string - appendonly: - type: string - database: - type: string - save: - type: string - required: - - database - type: object - dto.RedisStatus: - properties: - connected_clients: - type: string - database: - type: string - instantaneous_ops_per_sec: - type: string - keyspace_hits: - type: string - keyspace_misses: - type: string - latest_fork_usec: - type: string - mem_fragmentation_ratio: - type: string - tcp_port: - type: string - total_commands_processed: - type: string - total_connections_received: - type: string - uptime_in_days: - type: string - used_memory: - type: string - used_memory_peak: - type: string - used_memory_rss: - type: string - required: - - database - type: object - dto.ResourceLimit: - properties: - cpu: - type: integer - memory: - type: integer - type: object - dto.RuleSearch: - properties: - info: - type: string - page: - type: integer - pageSize: - type: integer - status: - type: string - strategy: - type: string - type: - type: string - required: - - page - - pageSize - - type - type: object - dto.SSHConf: - properties: - file: - type: string - type: object - dto.SSHHistory: - properties: - address: - type: string - area: - type: string - authMode: - type: string - date: - type: string - dateStr: - type: string - message: - type: string - port: - type: string - status: - type: string - user: - type: string - type: object - dto.SSHInfo: - properties: - autoStart: - type: boolean - listenAddress: - type: string - message: - type: string - passwordAuthentication: - type: string - permitRootLogin: - type: string - port: - type: string - pubkeyAuthentication: - type: string - status: - type: string - useDNS: - type: string - type: object - dto.SSHLog: - properties: - failedCount: - type: integer - logs: - items: - $ref: '#/definitions/dto.SSHHistory' - type: array - successfulCount: - type: integer - totalCount: - type: integer - type: object - dto.SSHUpdate: - properties: - key: - type: string - newValue: - type: string - oldValue: - type: string - required: - - key - type: object - dto.SSLUpdate: - properties: - cert: - type: string - domain: - type: string - key: - type: string - ssl: - enum: - - enable - - disable - type: string - sslID: - type: integer - sslType: - enum: - - self - - select - - import - - import-paste - - import-local - type: string - required: - - ssl - - sslType - type: object - dto.SearchForTree: - properties: - info: - type: string - type: object - dto.SearchHostWithPage: - properties: - groupID: - type: integer - info: - type: string - page: - type: integer - pageSize: - type: integer - required: - - page - - pageSize - type: object - dto.SearchLgLogWithPage: - properties: - ip: - type: string - page: - type: integer - pageSize: - type: integer - status: - type: string - required: - - page - - pageSize - type: object - dto.SearchOpLogWithPage: - properties: - operation: - type: string - page: - type: integer - pageSize: - type: integer - source: - type: string - status: - type: string - required: - - page - - pageSize - type: object - dto.SearchRecord: - properties: - cronjobID: - type: integer - endTime: - type: string - page: - type: integer - pageSize: - type: integer - startTime: - type: string - status: - type: string - required: - - page - - pageSize - type: object - dto.SearchSSHLog: - properties: - Status: - enum: - - Success - - Failed - - All - type: string - info: - type: string - page: - type: integer - pageSize: - type: integer - required: - - Status - - page - - pageSize - type: object - dto.SearchWithPage: - properties: - info: - type: string - page: - type: integer - pageSize: - type: integer - required: - - page - - pageSize - type: object - dto.SettingInfo: - properties: - allowIPs: - type: string - appStoreLastModified: - type: string - appStoreSyncStatus: - type: string - appStoreVersion: - type: string - bindAddress: - type: string - bindDomain: - type: string - complexityVerification: - type: string - defaultNetwork: - type: string - developerMode: - type: string - dingVars: - type: string - dockerSockPath: - type: string - email: - type: string - emailVars: - type: string - expirationDays: - type: string - expirationTime: - type: string - fileRecycleBin: - type: string - ipv6: - type: string - language: - type: string - lastCleanData: - type: string - lastCleanSize: - type: string - lastCleanTime: - type: string - localTime: - type: string - menuTabs: - type: string - messageType: - type: string - mfaInterval: - type: string - mfaSecret: - type: string - mfaStatus: - type: string - monitorInterval: - type: string - monitorStatus: - type: string - monitorStoreDays: - type: string - noAuthSetting: - type: string - ntpSite: - type: string - panelName: - type: string - port: - type: string - proxyPasswd: - type: string - proxyPasswdKeep: - type: string - proxyPort: - type: string - proxyType: - type: string - proxyUrl: - type: string - proxyUser: - type: string - securityEntrance: - type: string - serverPort: - type: string - sessionTimeout: - type: string - snapshotIgnore: - type: string - ssl: - type: string - sslType: - type: string - systemIP: - type: string - systemVersion: - type: string - theme: - type: string - timeZone: - type: string - userName: - type: string - weChatVars: - type: string - xpackHideMenu: - type: string - type: object - dto.SettingUpdate: - properties: - key: - type: string - value: - type: string - required: - - key - type: object - dto.SnapshotBatchDelete: - properties: - deleteWithFile: - type: boolean - ids: - items: - type: integer - type: array - required: - - ids - type: object - dto.SnapshotCreate: - properties: - defaultDownload: - type: string - description: - maxLength: 256 - type: string - from: - type: string - id: - type: integer - secret: - type: string - required: - - defaultDownload - - from - type: object - dto.SnapshotImport: - properties: - description: - maxLength: 256 - type: string - from: - type: string - names: - items: - type: string - type: array - type: object - dto.SnapshotRecover: - properties: - id: - type: integer - isNew: - type: boolean - reDownload: - type: boolean - secret: - type: string - required: - - id - type: object - dto.SwapHelper: - properties: - isNew: - type: boolean - path: - type: string - size: - type: integer - used: - type: string - required: - - path - type: object - dto.TreeChild: - properties: - id: - type: integer - label: - type: string - type: object - dto.UpdateByFile: - properties: - file: - type: string - type: object - dto.UpdateByNameAndFile: - properties: - file: - type: string - name: - type: string - type: object - dto.UpdateDescription: - properties: - description: - maxLength: 256 - type: string - id: - type: integer - required: - - id - type: object - dto.UpdateFirewallDescription: - properties: - address: - type: string - description: - type: string - port: - type: string - protocol: - type: string - strategy: - enum: - - accept - - drop - type: string - type: - type: string - required: - - strategy - type: object - dto.Upgrade: - properties: - version: - type: string - required: - - version - type: object - dto.UpgradeInfo: - properties: - latestVersion: - type: string - newVersion: - type: string - releaseNote: - type: string - testVersion: - type: string - type: object - dto.UserLoginInfo: - properties: - mfaStatus: - type: string - name: - type: string - token: - type: string - type: object - dto.VolumeCreate: - properties: - driver: - type: string - labels: - items: - type: string - type: array - name: - type: string - options: - items: - type: string - type: array - required: - - driver - - name - type: object - dto.VolumeHelper: - properties: - containerDir: - type: string - mode: - type: string - sourceDir: - type: string - type: - type: string - type: object - files.FileInfo: - properties: - content: - type: string - extension: - type: string - favoriteID: - type: integer - gid: - type: string - group: - type: string - isDetail: - type: boolean - isDir: - type: boolean - isHidden: - type: boolean - isSymlink: - type: boolean - itemTotal: - type: integer - items: - items: - $ref: '#/definitions/files.FileInfo' - type: array - linkPath: - type: string - mimeType: - type: string - modTime: - type: string - mode: - type: string - name: - type: string - path: - type: string - size: - type: integer - type: - type: string - uid: - type: string - updateTime: - type: string - user: - type: string - type: object - mfa.Otp: - properties: - qrImage: - type: string - secret: - type: string - type: object - model.App: - properties: - createdAt: - type: string - crossVersionUpdate: - type: boolean - document: - type: string - github: - type: string - icon: - type: string - id: - type: integer - key: - type: string - lastModified: - type: integer - limit: - type: integer - name: - type: string - readMe: - type: string - recommend: - type: integer - required: - type: string - resource: - type: string - shortDescEn: - type: string - shortDescZh: - type: string - status: - type: string - tags: - items: - type: string - type: array - type: - type: string - updatedAt: - type: string - website: - type: string - type: object - model.AppInstall: - properties: - app: - $ref: '#/definitions/model.App' - appDetailId: - type: integer - appId: - type: integer - containerName: - type: string - createdAt: - type: string - description: - type: string - dockerCompose: - type: string - env: - type: string - httpPort: - type: integer - httpsPort: - type: integer - id: - type: integer - message: - type: string - name: - type: string - param: - type: string - serviceName: - type: string - status: - type: string - updatedAt: - type: string - version: - type: string - type: object - model.Tag: - properties: - createdAt: - type: string - id: - type: integer - key: - type: string - name: - type: string - sort: - type: integer - updatedAt: - type: string - type: object - model.Website: - properties: - IPV6: - type: boolean - accessLog: - type: boolean - alias: - type: string - appInstallId: - type: integer - createdAt: - type: string - defaultServer: - type: boolean - domains: - items: - $ref: '#/definitions/model.WebsiteDomain' - type: array - errorLog: - type: boolean - expireDate: - type: string - ftpId: - type: integer - group: - type: string - httpConfig: - type: string - id: - type: integer - primaryDomain: - type: string - protocol: - type: string - proxy: - type: string - proxyType: - type: string - remark: - type: string - rewrite: - type: string - runtimeID: - type: integer - siteDir: - type: string - status: - type: string - type: - type: string - updatedAt: - type: string - user: - type: string - webSiteGroupId: - type: integer - webSiteSSL: - $ref: '#/definitions/model.WebsiteSSL' - webSiteSSLId: - type: integer - type: object - model.WebsiteAcmeAccount: - properties: - createdAt: - type: string - eabHmacKey: - type: string - eabKid: - type: string - email: - type: string - id: - type: integer - keyType: - type: string - type: - type: string - updatedAt: - type: string - url: - type: string - type: object - model.WebsiteDnsAccount: - properties: - createdAt: - type: string - id: - type: integer - name: - type: string - type: - type: string - updatedAt: - type: string - type: object - model.WebsiteDomain: - properties: - createdAt: - type: string - domain: - type: string - id: - type: integer - port: - type: integer - updatedAt: - type: string - websiteId: - type: integer - type: object - model.WebsiteSSL: - properties: - acmeAccount: - $ref: '#/definitions/model.WebsiteAcmeAccount' - acmeAccountId: - type: integer - autoRenew: - type: boolean - caId: - type: integer - certURL: - type: string - createdAt: - type: string - description: - type: string - dir: - type: string - disableCNAME: - type: boolean - dnsAccount: - $ref: '#/definitions/model.WebsiteDnsAccount' - dnsAccountId: - type: integer - domains: - type: string - execShell: - type: boolean - expireDate: - type: string - id: - type: integer - keyType: - type: string - message: - type: string - nameserver1: - type: string - nameserver2: - type: string - organization: - type: string - pem: - type: string - primaryDomain: - type: string - privateKey: - type: string - provider: - type: string - pushDir: - type: boolean - shell: - type: string - skipDNS: - type: boolean - startDate: - type: string - status: - type: string - type: - type: string - updatedAt: - type: string - websites: - items: - $ref: '#/definitions/model.Website' - type: array - type: object - request.AppInstallCreate: - properties: - advanced: - type: boolean - allowPort: - type: boolean - appDetailId: - type: integer - containerName: - type: string - cpuQuota: - type: number - dockerCompose: - type: string - editCompose: - type: boolean - hostMode: - type: boolean - memoryLimit: - type: number - memoryUnit: - type: string - name: - type: string - params: - additionalProperties: true - type: object - pullImage: - type: boolean - services: - additionalProperties: - type: string - type: object - required: - - appDetailId - - name - type: object - request.AppInstalledIgnoreUpgrade: - properties: - detailID: - type: integer - operate: - enum: - - cancel - - ignore - type: string - required: - - detailID - - operate - type: object - request.AppInstalledInfo: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - request.AppInstalledOperate: - properties: - backup: - type: boolean - backupId: - type: integer - deleteBackup: - type: boolean - deleteDB: - type: boolean - detailId: - type: integer - dockerCompose: - type: string - forceDelete: - type: boolean - installId: - type: integer - operate: - type: string - pullImage: - type: boolean - required: - - installId - - operate - type: object - request.AppInstalledSearch: - properties: - all: - type: boolean - name: - type: string - page: - type: integer - pageSize: - type: integer - sync: - type: boolean - tags: - items: - type: string - type: array - type: - type: string - unused: - type: boolean - update: - type: boolean - required: - - page - - pageSize - type: object - request.AppInstalledUpdate: - properties: - advanced: - type: boolean - allowPort: - type: boolean - containerName: - type: string - cpuQuota: - type: number - dockerCompose: - type: string - editCompose: - type: boolean - hostMode: - type: boolean - installId: - type: integer - memoryLimit: - type: number - memoryUnit: - type: string - params: - additionalProperties: true - type: object - pullImage: - type: boolean - required: - - installId - - params - type: object - request.AppSearch: - properties: - name: - type: string - page: - type: integer - pageSize: - type: integer - recommend: - type: boolean - resource: - type: string - tags: - items: - type: string - type: array - type: - type: string - required: - - page - - pageSize - type: object - request.DirSizeReq: - properties: - path: - type: string - required: - - path - type: object - request.ExposedPort: - properties: - containerPort: - type: integer - hostPort: - type: integer - type: object - request.FavoriteCreate: - properties: - path: - type: string - required: - - path - type: object - request.FavoriteDelete: - properties: - id: - type: integer - required: - - id - type: object - request.FileBatchDelete: - properties: - isDir: - type: boolean - paths: - items: - type: string - type: array - required: - - paths - type: object - request.FileCompress: - properties: - dst: - type: string - files: - items: - type: string - type: array - name: - type: string - replace: - type: boolean - secret: - type: string - type: - type: string - required: - - dst - - files - - name - - type - type: object - request.FileContentReq: - properties: - isDetail: - type: boolean - path: - type: string - required: - - path - type: object - request.FileCreate: - properties: - content: - type: string - isDir: - type: boolean - isLink: - type: boolean - isSymlink: - type: boolean - linkPath: - type: string - mode: - type: integer - path: - type: string - sub: - type: boolean - required: - - path - type: object - request.FileDeCompress: - properties: - dst: - type: string - path: - type: string - secret: - type: string - type: - type: string - required: - - dst - - path - - type - type: object - request.FileDelete: - properties: - forceDelete: - type: boolean - isDir: - type: boolean - path: - type: string - required: - - path - type: object - request.FileDownload: - properties: - compress: - type: boolean - name: - type: string - paths: - items: - type: string - type: array - type: - type: string - required: - - name - - paths - - type - type: object - request.FileEdit: - properties: - content: - type: string - path: - type: string - required: - - path - type: object - request.FileMove: - properties: - cover: - type: boolean - name: - type: string - newPath: - type: string - oldPaths: - items: - type: string - type: array - type: - type: string - required: - - newPath - - oldPaths - - type - type: object - request.FileOption: - properties: - containSub: - type: boolean - dir: - type: boolean - expand: - type: boolean - isDetail: - type: boolean - page: - type: integer - pageSize: - type: integer - path: - type: string - search: - type: string - showHidden: - type: boolean - sortBy: - type: string - sortOrder: - type: string - type: object - request.FilePathCheck: - properties: - path: - type: string - required: - - path - type: object - request.FileReadByLineReq: - properties: - ID: - type: integer - latest: - type: boolean - name: - type: string - page: - type: integer - pageSize: - type: integer - type: - type: string - required: - - page - - pageSize - - type - type: object - request.FileRename: - properties: - newName: - type: string - oldName: - type: string - required: - - newName - - oldName - type: object - request.FileRoleReq: - properties: - group: - type: string - mode: - type: integer - paths: - items: - type: string - type: array - sub: - type: boolean - user: - type: string - required: - - group - - mode - - paths - - user - type: object - request.FileRoleUpdate: - properties: - group: - type: string - path: - type: string - sub: - type: boolean - user: - type: string - required: - - group - - path - - user - type: object - request.FileWget: - properties: - ignoreCertificate: - type: boolean - name: - type: string - path: - type: string - url: - type: string - required: - - name - - path - - url - type: object - request.HostToolConfig: - properties: - content: - type: string - operate: - enum: - - get - - set - type: string - type: - enum: - - supervisord - type: string - required: - - type - type: object - request.HostToolCreate: - properties: - configPath: - type: string - serviceName: - type: string - type: - type: string - required: - - type - type: object - request.HostToolLogReq: - properties: - type: - enum: - - supervisord - type: string - required: - - type - type: object - request.HostToolReq: - properties: - operate: - enum: - - status - - restart - - start - - stop - type: string - type: - enum: - - supervisord - type: string - required: - - type - type: object - request.NewAppInstall: - properties: - advanced: - type: boolean - allowPort: - type: boolean - appDetailID: - type: integer - containerName: - type: string - cpuQuota: - type: number - dockerCompose: - type: string - editCompose: - type: boolean - hostMode: - type: boolean - memoryLimit: - type: number - memoryUnit: - type: string - name: - type: string - params: - additionalProperties: true - type: object - pullImage: - type: boolean - type: object - request.NginxAntiLeechUpdate: - properties: - blocked: - type: boolean - cache: - type: boolean - cacheTime: - type: integer - cacheUint: - type: string - enable: - type: boolean - extends: - type: string - logEnable: - type: boolean - noneRef: - type: boolean - return: - type: string - serverNames: - items: - type: string - type: array - websiteID: - type: integer - required: - - extends - - return - - websiteID - type: object - request.NginxAuthReq: - properties: - websiteID: - type: integer - required: - - websiteID - type: object - request.NginxAuthUpdate: - properties: - operate: - type: string - password: - type: string - remark: - type: string - username: - type: string - websiteID: - type: integer - required: - - operate - - websiteID - type: object - request.NginxCommonReq: - properties: - websiteID: - type: integer - required: - - websiteID - type: object - request.NginxConfigFileUpdate: - properties: - backup: - type: boolean - content: - type: string - required: - - content - type: object - request.NginxConfigUpdate: - properties: - operate: - enum: - - add - - update - - delete - type: string - params: {} - scope: - $ref: '#/definitions/dto.NginxKey' - websiteId: - type: integer - required: - - operate - type: object - request.NginxProxyUpdate: - properties: - content: - type: string - name: - type: string - websiteID: - type: integer - required: - - content - - name - - websiteID - type: object - request.NginxRedirectReq: - properties: - domains: - items: - type: string - type: array - enable: - type: boolean - keepPath: - type: boolean - name: - type: string - operate: - type: string - path: - type: string - redirect: - type: string - redirectRoot: - type: boolean - target: - type: string - type: - type: string - websiteID: - type: integer - required: - - name - - operate - - redirect - - target - - type - - websiteID - type: object - request.NginxRedirectUpdate: - properties: - content: - type: string - name: - type: string - websiteID: - type: integer - required: - - content - - name - - websiteID - type: object - request.NginxRewriteReq: - properties: - name: - type: string - websiteId: - type: integer - required: - - name - - websiteId - type: object - request.NginxRewriteUpdate: - properties: - content: - type: string - name: - type: string - websiteId: - type: integer - required: - - name - - websiteId - type: object - request.NginxScopeReq: - properties: - scope: - $ref: '#/definitions/dto.NginxKey' - websiteId: - type: integer - required: - - scope - type: object - request.NodeModuleReq: - properties: - ID: - type: integer - required: - - ID - type: object - request.NodePackageReq: - properties: - codeDir: - type: string - type: object - request.PHPExtensionsCreate: - properties: - extensions: - type: string - name: - type: string - required: - - extensions - - name - type: object - request.PHPExtensionsDelete: - properties: - id: - type: integer - required: - - id - type: object - request.PHPExtensionsSearch: - properties: - all: - type: boolean - page: - type: integer - pageSize: - type: integer - required: - - page - - pageSize - type: object - request.PHPExtensionsUpdate: - properties: - extensions: - type: string - id: - type: integer - required: - - extensions - - id - type: object - request.PortUpdate: - properties: - key: - type: string - name: - type: string - port: - type: integer - type: object - request.ProcessReq: - properties: - PID: - type: integer - required: - - PID - type: object - request.RecycleBinReduce: - properties: - from: - type: string - name: - type: string - rName: - type: string - required: - - from - - rName - type: object - request.RuntimeCreate: - properties: - appDetailId: - type: integer - clean: - type: boolean - codeDir: - type: string - exposedPorts: - items: - $ref: '#/definitions/request.ExposedPort' - type: array - image: - type: string - install: - type: boolean - name: - type: string - params: - additionalProperties: true - type: object - port: - type: integer - resource: - type: string - source: - type: string - type: - type: string - version: - type: string - type: object - request.RuntimeDelete: - properties: - forceDelete: - type: boolean - id: - type: integer - type: object - request.RuntimeOperate: - properties: - ID: - type: integer - operate: - type: string - type: object - request.RuntimeSearch: - properties: - name: - type: string - page: - type: integer - pageSize: - type: integer - status: - type: string - type: - type: string - required: - - page - - pageSize - type: object - request.RuntimeUpdate: - properties: - clean: - type: boolean - codeDir: - type: string - exposedPorts: - items: - $ref: '#/definitions/request.ExposedPort' - type: array - id: - type: integer - image: - type: string - install: - type: boolean - name: - type: string - params: - additionalProperties: true - type: object - port: - type: integer - rebuild: - type: boolean - source: - type: string - version: - type: string - type: object - request.SearchUploadWithPage: - properties: - page: - type: integer - pageSize: - type: integer - path: - type: string - required: - - page - - pageSize - - path - type: object - request.SupervisorProcessConfig: - properties: - command: - type: string - dir: - type: string - name: - type: string - numprocs: - type: string - operate: - type: string - user: - type: string - type: object - request.SupervisorProcessFileReq: - properties: - content: - type: string - file: - enum: - - out.log - - err.log - - config - type: string - name: - type: string - operate: - enum: - - get - - clear - - update - type: string - required: - - file - - name - - operate - type: object - request.WebsiteAcmeAccountCreate: - properties: - eabHmacKey: - type: string - eabKid: - type: string - email: - type: string - keyType: - enum: - - P256 - - P384 - - "2048" - - "3072" - - "4096" - - "8192" - type: string - type: - enum: - - letsencrypt - - zerossl - - buypass - - google - type: string - required: - - email - - keyType - - type - type: object - request.WebsiteBatchDelReq: - properties: - ids: - items: - type: integer - type: array - required: - - ids - type: object - request.WebsiteCACreate: - properties: - city: - type: string - commonName: - type: string - country: - type: string - keyType: - enum: - - P256 - - P384 - - "2048" - - "3072" - - "4096" - - "8192" - type: string - name: - type: string - organization: - type: string - organizationUint: - type: string - province: - type: string - required: - - commonName - - country - - keyType - - name - - organization - type: object - request.WebsiteCAObtain: - properties: - autoRenew: - type: boolean - description: - type: string - dir: - type: string - domains: - type: string - execShell: - type: boolean - id: - type: integer - keyType: - enum: - - P256 - - P384 - - "2048" - - "3072" - - "4096" - - "8192" - type: string - pushDir: - type: boolean - renew: - type: boolean - shell: - type: string - sslID: - type: integer - time: - type: integer - unit: - type: string - required: - - domains - - id - - keyType - - time - - unit - type: object - request.WebsiteCASearch: - properties: - page: - type: integer - pageSize: - type: integer - required: - - page - - pageSize - type: object - request.WebsiteCommonReq: - properties: - id: - type: integer - required: - - id - type: object - request.WebsiteCreate: - properties: - IPV6: - type: boolean - alias: - type: string - appID: - type: integer - appInstall: - $ref: '#/definitions/request.NewAppInstall' - appInstallID: - type: integer - appType: - enum: - - new - - installed - type: string - ftpPassword: - type: string - ftpUser: - type: string - otherDomains: - type: string - port: - type: integer - primaryDomain: - type: string - proxy: - type: string - proxyType: - type: string - remark: - type: string - runtimeID: - type: integer - type: - type: string - webSiteGroupID: - type: integer - required: - - alias - - primaryDomain - - type - - webSiteGroupID - type: object - request.WebsiteDNSReq: - properties: - acmeAccountId: - type: integer - domains: - items: - type: string - type: array - required: - - acmeAccountId - - domains - type: object - request.WebsiteDefaultUpdate: - properties: - id: - type: integer - type: object - request.WebsiteDelete: - properties: - deleteApp: - type: boolean - deleteBackup: - type: boolean - forceDelete: - type: boolean - id: - type: integer - required: - - id - type: object - request.WebsiteDnsAccountCreate: - properties: - authorization: - additionalProperties: - type: string - type: object - name: - type: string - type: - type: string - required: - - authorization - - name - - type - type: object - request.WebsiteDnsAccountUpdate: - properties: - authorization: - additionalProperties: - type: string - type: object - id: - type: integer - name: - type: string - type: - type: string - required: - - authorization - - id - - name - - type - type: object - request.WebsiteDomainCreate: - properties: - domains: - type: string - websiteID: - type: integer - required: - - domains - - websiteID - type: object - request.WebsiteDomainDelete: - properties: - id: - type: integer - required: - - id - type: object - request.WebsiteHTTPSOp: - properties: - SSLProtocol: - items: - type: string - type: array - algorithm: - type: string - certificate: - type: string - certificatePath: - type: string - enable: - type: boolean - hsts: - type: boolean - httpConfig: - enum: - - HTTPSOnly - - HTTPAlso - - HTTPToHTTPS - type: string - importType: - type: string - privateKey: - type: string - privateKeyPath: - type: string - type: - enum: - - existed - - auto - - manual - type: string - websiteId: - type: integer - websiteSSLId: - type: integer - required: - - websiteId - type: object - request.WebsiteHtmlUpdate: - properties: - content: - type: string - type: - type: string - required: - - content - - type - type: object - request.WebsiteInstallCheckReq: - properties: - InstallIds: - items: - type: integer - type: array - type: object - request.WebsiteLogReq: - properties: - id: - type: integer - logType: - type: string - operate: - type: string - page: - type: integer - pageSize: - type: integer - required: - - id - - logType - - operate - type: object - request.WebsiteNginxUpdate: - properties: - content: - type: string - id: - type: integer - required: - - content - - id - type: object - request.WebsiteOp: - properties: - id: - type: integer - operate: - type: string - required: - - id - type: object - request.WebsitePHPConfigUpdate: - properties: - disableFunctions: - items: - type: string - type: array - id: - type: integer - params: - additionalProperties: - type: string - type: object - scope: - type: string - uploadMaxSize: - type: string - required: - - id - - scope - type: object - request.WebsitePHPFileUpdate: - properties: - content: - type: string - id: - type: integer - type: - type: string - required: - - content - - id - - type - type: object - request.WebsitePHPVersionReq: - properties: - retainConfig: - type: boolean - runtimeID: - type: integer - websiteID: - type: integer - required: - - runtimeID - - websiteID - type: object - request.WebsiteProxyConfig: - properties: - cache: - type: boolean - cacheTime: - type: integer - cacheUnit: - type: string - content: - type: string - enable: - type: boolean - filePath: - type: string - id: - type: integer - match: - type: string - modifier: - type: string - name: - type: string - operate: - type: string - proxyHost: - type: string - proxyPass: - type: string - replaces: - additionalProperties: - type: string - type: object - sni: - type: boolean - required: - - id - - match - - name - - operate - - proxyHost - - proxyPass - type: object - request.WebsiteProxyReq: - properties: - id: - type: integer - required: - - id - type: object - request.WebsiteResourceReq: - properties: - id: - type: integer - required: - - id - type: object - request.WebsiteSSLApply: - properties: - ID: - type: integer - nameservers: - items: - type: string - type: array - skipDNSCheck: - type: boolean - required: - - ID - type: object - request.WebsiteSSLCreate: - properties: - acmeAccountId: - type: integer - apply: - type: boolean - autoRenew: - type: boolean - description: - type: string - dir: - type: string - disableCNAME: - type: boolean - dnsAccountId: - type: integer - execShell: - type: boolean - id: - type: integer - keyType: - type: string - nameserver1: - type: string - nameserver2: - type: string - otherDomains: - type: string - primaryDomain: - type: string - provider: - type: string - pushDir: - type: boolean - shell: - type: string - skipDNS: - type: boolean - required: - - acmeAccountId - - primaryDomain - - provider - type: object - request.WebsiteSSLSearch: - properties: - acmeAccountID: - type: string - page: - type: integer - pageSize: - type: integer - required: - - page - - pageSize - type: object - request.WebsiteSSLUpdate: - properties: - acmeAccountId: - type: integer - apply: - type: boolean - autoRenew: - type: boolean - description: - type: string - dir: - type: string - disableCNAME: - type: boolean - dnsAccountId: - type: integer - execShell: - type: boolean - id: - type: integer - keyType: - type: string - nameserver1: - type: string - nameserver2: - type: string - otherDomains: - type: string - primaryDomain: - type: string - provider: - type: string - pushDir: - type: boolean - shell: - type: string - skipDNS: - type: boolean - required: - - id - - primaryDomain - - provider - type: object - request.WebsiteSSLUpload: - properties: - certificate: - type: string - certificatePath: - type: string - description: - type: string - privateKey: - type: string - privateKeyPath: - type: string - sslID: - type: integer - type: - enum: - - paste - - local - type: string - required: - - type - type: object - request.WebsiteSearch: - properties: - name: - type: string - order: - enum: - - "null" - - ascending - - descending - type: string - orderBy: - enum: - - primary_domain - - type - - status - - created_at - - expire_date - type: string - page: - type: integer - pageSize: - type: integer - websiteGroupId: - type: integer - required: - - order - - orderBy - - page - - pageSize - type: object - request.WebsiteUpdate: - properties: - IPV6: - type: boolean - expireDate: - type: string - id: - type: integer - primaryDomain: - type: string - remark: - type: string - webSiteGroupID: - type: integer - required: - - id - - primaryDomain - type: object - request.WebsiteUpdateDir: - properties: - id: - type: integer - siteDir: - type: string - required: - - id - - siteDir - type: object - request.WebsiteUpdateDirPermission: - properties: - group: - type: string - id: - type: integer - user: - type: string - required: - - group - - id - - user - type: object - response.AppDTO: - properties: - createdAt: - type: string - crossVersionUpdate: - type: boolean - document: - type: string - github: - type: string - icon: - type: string - id: - type: integer - installed: - type: boolean - key: - type: string - lastModified: - type: integer - limit: - type: integer - name: - type: string - readMe: - type: string - recommend: - type: integer - required: - type: string - resource: - type: string - shortDescEn: - type: string - shortDescZh: - type: string - status: - type: string - tags: - items: - $ref: '#/definitions/model.Tag' - type: array - type: - type: string - updatedAt: - type: string - versions: - items: - type: string - type: array - website: - type: string - type: object - response.AppDetailDTO: - properties: - appId: - type: integer - createdAt: - type: string - dockerCompose: - type: string - downloadCallBackUrl: - type: string - downloadUrl: - type: string - enable: - type: boolean - hostMode: - type: boolean - id: - type: integer - ignoreUpgrade: - type: boolean - image: - type: string - lastModified: - type: integer - lastVersion: - type: string - params: {} - status: - type: string - update: - type: boolean - updatedAt: - type: string - version: - type: string - type: object - response.AppInstalledCheck: - properties: - app: - type: string - appInstallId: - type: integer - containerName: - type: string - createdAt: - type: string - httpPort: - type: integer - httpsPort: - type: integer - installPath: - type: string - isExist: - type: boolean - lastBackupAt: - type: string - name: - type: string - status: - type: string - version: - type: string - type: object - response.AppParam: - properties: - edit: - type: boolean - key: - type: string - labelEn: - type: string - labelZh: - type: string - multiple: - type: boolean - required: - type: boolean - rule: - type: string - showValue: - type: string - type: - type: string - value: {} - values: {} - type: object - response.AppService: - properties: - config: {} - from: - type: string - label: - type: string - value: - type: string - type: object - response.FileInfo: - properties: - content: - type: string - extension: - type: string - favoriteID: - type: integer - gid: - type: string - group: - type: string - isDetail: - type: boolean - isDir: - type: boolean - isHidden: - type: boolean - isSymlink: - type: boolean - itemTotal: - type: integer - items: - items: - $ref: '#/definitions/files.FileInfo' - type: array - linkPath: - type: string - mimeType: - type: string - modTime: - type: string - mode: - type: string - name: - type: string - path: - type: string - size: - type: integer - type: - type: string - uid: - type: string - updateTime: - type: string - user: - type: string - type: object - response.FileTree: - properties: - children: - items: - $ref: '#/definitions/response.FileTree' - type: array - extension: - type: string - id: - type: string - isDir: - type: boolean - name: - type: string - path: - type: string - type: object - response.IgnoredApp: - properties: - detailID: - type: integer - icon: - type: string - name: - type: string - version: - type: string - type: object - response.NginxParam: - properties: - name: - type: string - params: - items: - type: string - type: array - type: object - response.NginxStatus: - properties: - accepts: - type: string - active: - type: string - handled: - type: string - reading: - type: string - requests: - type: string - waiting: - type: string - writing: - type: string - type: object - response.PHPConfig: - properties: - disableFunctions: - items: - type: string - type: array - params: - additionalProperties: - type: string - type: object - uploadMaxSize: - type: string - type: object - response.PHPExtensionsDTO: - properties: - createdAt: - type: string - extensions: - type: string - id: - type: integer - name: - type: string - updatedAt: - type: string - type: object - response.WebsiteAcmeAccountDTO: - properties: - createdAt: - type: string - eabHmacKey: - type: string - eabKid: - type: string - email: - type: string - id: - type: integer - keyType: - type: string - type: - type: string - updatedAt: - type: string - url: - type: string - type: object - response.WebsiteCADTO: - properties: - city: - type: string - commonName: - type: string - country: - type: string - createdAt: - type: string - csr: - type: string - id: - type: integer - keyType: - type: string - name: - type: string - organization: - type: string - organizationUint: - type: string - privateKey: - type: string - province: - type: string - updatedAt: - type: string - type: object - response.WebsiteDNSRes: - properties: - domain: - type: string - err: - type: string - resolve: - type: string - value: - type: string - type: object - response.WebsiteDTO: - properties: - IPV6: - type: boolean - accessLog: - type: boolean - accessLogPath: - type: string - alias: - type: string - appInstallId: - type: integer - appName: - type: string - createdAt: - type: string - defaultServer: - type: boolean - domains: - items: - $ref: '#/definitions/model.WebsiteDomain' - type: array - errorLog: - type: boolean - errorLogPath: - type: string - expireDate: - type: string - ftpId: - type: integer - group: - type: string - httpConfig: - type: string - id: - type: integer - primaryDomain: - type: string - protocol: - type: string - proxy: - type: string - proxyType: - type: string - remark: - type: string - rewrite: - type: string - runtimeID: - type: integer - runtimeName: - type: string - siteDir: - type: string - sitePath: - type: string - status: - type: string - type: - type: string - updatedAt: - type: string - user: - type: string - webSiteGroupId: - type: integer - webSiteSSL: - $ref: '#/definitions/model.WebsiteSSL' - webSiteSSLId: - type: integer - type: object - response.WebsiteHTTPS: - properties: - SSL: - $ref: '#/definitions/model.WebsiteSSL' - SSLProtocol: - items: - type: string - type: array - algorithm: - type: string - enable: - type: boolean - hsts: - type: boolean - httpConfig: - type: string - type: object - response.WebsiteLog: - properties: - content: - type: string - enable: - type: boolean - end: - type: boolean - path: - type: string - type: object - response.WebsiteNginxConfig: - properties: - enable: - type: boolean - params: - items: - $ref: '#/definitions/response.NginxParam' - type: array - type: object - response.WebsitePreInstallCheck: - properties: - appName: - type: string - name: - type: string - status: - type: string - version: - type: string - type: object -host: localhost -info: - contact: {} - description: 开源Linux面板 - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - termsOfService: http://swagger.io/terms/ - title: 1Panel - version: "1.0" -paths: - /apps/:key: - get: - consumes: - - application/json - description: 通过 key 获取应用信息 - parameters: - - description: app key - in: path - name: key - required: true - type: string - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.AppDTO' - security: - - ApiKeyAuth: [] - summary: Search app by key - tags: - - App - /apps/checkupdate: - get: - description: 获取应用更新版本 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get app list update - tags: - - App - /apps/detail/:appId/:version/:type: - get: - consumes: - - application/json - description: 通过 appid 获取应用详情 - parameters: - - description: app id - in: path - name: appId - required: true - type: integer - - description: app 版本 - in: path - name: version - required: true - type: string - - description: app 类型 - in: path - name: version - required: true - type: string - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.AppDetailDTO' - security: - - ApiKeyAuth: [] - summary: Search app detail by appid - tags: - - App - /apps/details/:id: - get: - consumes: - - application/json - description: 通过 id 获取应用详情 - parameters: - - description: id - in: path - name: appId - required: true - type: integer - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.AppDetailDTO' - security: - - ApiKeyAuth: [] - summary: Get app detail by id - tags: - - App - /apps/ignored: - get: - consumes: - - application/json - description: 获取忽略的应用版本 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.IgnoredApp' - security: - - ApiKeyAuth: [] - summary: Get Ignore App - tags: - - App - /apps/install: - post: - consumes: - - application/json - description: 安装应用 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.AppInstallCreate' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/model.AppInstall' - security: - - ApiKeyAuth: [] - summary: Install app - tags: - - App - x-panel-log: - BeforeFunctions: - - db: app_installs - input_column: name - input_value: name - isList: false - output_column: app_id - output_value: appId - - db: apps - info: appId - isList: false - output_column: key - output_value: appKey - bodyKeys: - - name - formatEN: Install app [appKey]-[name] - formatZH: 安装应用 [appKey]-[name] - paramKeys: [] - /apps/installed/check: - post: - consumes: - - application/json - description: 检查应用安装情况 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.AppInstalledInfo' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.AppInstalledCheck' - security: - - ApiKeyAuth: [] - summary: Check app installed - tags: - - App - /apps/installed/conf: - post: - consumes: - - application/json - description: 通过 key 获取应用默认配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperationWithNameAndType' - responses: - "200": - description: OK - schema: - type: string - security: - - ApiKeyAuth: [] - summary: Search default config by key - tags: - - App - /apps/installed/conninfo/:key: - get: - consumes: - - application/json - description: 获取应用连接信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperationWithNameAndType' - responses: - "200": - description: OK - schema: - type: string - security: - - ApiKeyAuth: [] - summary: Search app password by key - tags: - - App - /apps/installed/delete/check/:appInstallId: - get: - consumes: - - application/json - description: 删除前检查 - parameters: - - description: App install id - in: path - name: appInstallId - required: true - type: integer - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.AppResource' - type: array - security: - - ApiKeyAuth: [] - summary: Check before delete - tags: - - App - /apps/installed/ignore: - post: - consumes: - - application/json - description: 忽略应用升级版本 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.AppInstalledIgnoreUpgrade' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: ignore App Update - tags: - - App - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - installId - formatEN: Application param update [installId] - formatZH: 忽略应用 [installId] 版本升级 - paramKeys: [] - /apps/installed/list: - get: - consumes: - - application/json - description: 获取已安装应用列表 - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.AppInstallInfo' - type: array - security: - - ApiKeyAuth: [] - summary: List app installed - tags: - - App - /apps/installed/loadport: - post: - consumes: - - application/json - description: 获取应用端口 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperationWithNameAndType' - responses: - "200": - description: OK - schema: - type: integer - security: - - ApiKeyAuth: [] - summary: Search app port by key - tags: - - App - /apps/installed/op: - post: - consumes: - - application/json - description: 操作已安装应用 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.AppInstalledOperate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Operate installed app - tags: - - App - x-panel-log: - BeforeFunctions: - - db: app_installs - input_column: id - input_value: installId - isList: false - output_column: app_id - output_value: appId - - db: app_installs - input_column: id - input_value: installId - isList: false - output_column: name - output_value: appName - - db: apps - input_column: id - input_value: appId - isList: false - output_column: key - output_value: appKey - bodyKeys: - - installId - - operate - formatEN: '[operate] App [appKey][appName]' - formatZH: '[operate] 应用 [appKey][appName]' - paramKeys: [] - /apps/installed/params/:appInstallId: - get: - consumes: - - application/json - description: 通过 install id 获取应用参数 - parameters: - - description: request - in: path - name: appInstallId - required: true - type: string - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.AppParam' - security: - - ApiKeyAuth: [] - summary: Search params by appInstallId - tags: - - App - /apps/installed/params/update: - post: - consumes: - - application/json - description: 修改应用参数 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.AppInstalledUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Change app params - tags: - - App - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - installId - formatEN: Application param update [installId] - formatZH: 应用参数修改 [installId] - paramKeys: [] - /apps/installed/port/change: - post: - consumes: - - application/json - description: 修改应用端口 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.PortUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Change app port - tags: - - App - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - key - - name - - port - formatEN: Application port update [key]-[name] => [port] - formatZH: 应用端口修改 [key]-[name] => [port] - paramKeys: [] - /apps/installed/search: - post: - consumes: - - application/json - description: 分页获取已安装应用列表 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.AppInstalledSearch' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Page app installed - tags: - - App - /apps/installed/sync: - post: - description: 同步已安装应用列表 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Sync app installed - tags: - - App - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: Sync the list of installed apps - formatZH: 同步已安装应用列表 - paramKeys: [] - /apps/installed/update/versions: - post: - consumes: - - application/json - description: 通过 install id 获取应用更新版本 - parameters: - - description: request - in: path - name: appInstallId - required: true - type: integer - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.AppVersion' - type: array - security: - - ApiKeyAuth: [] - summary: Search app update version by install id - tags: - - App - /apps/search: - post: - consumes: - - application/json - description: 获取应用列表 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.AppSearch' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: List apps - tags: - - App - /apps/services/:key: - get: - consumes: - - application/json - description: 通过 key 获取应用 service - parameters: - - description: request - in: path - name: key - required: true - type: string - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/response.AppService' - type: array - security: - - ApiKeyAuth: [] - summary: Search app service by key - tags: - - App - /apps/sync: - post: - description: 同步应用列表 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Sync app list - tags: - - App - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: App store synchronization - formatZH: 应用商店同步 - paramKeys: [] - /auth/captcha: - get: - description: 加载验证码 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.CaptchaResponse' - summary: Load captcha - tags: - - Auth - /auth/demo: - get: - description: 判断是否为demo环境 - responses: - "200": - description: OK - summary: Check System isDemo - tags: - - Auth - /auth/issafety: - get: - description: 获取系统安全登录状态 - responses: - "200": - description: OK - summary: Load safety status - tags: - - Auth - /auth/language: - get: - description: 获取系统语言设置 - responses: - "200": - description: OK - summary: Load System Language - tags: - - Auth - /auth/login: - post: - consumes: - - application/json - description: 用户登录 - parameters: - - description: 安全入口 base64 加密串 - in: header - name: EntranceCode - required: true - type: string - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.Login' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.UserLoginInfo' - summary: User login - tags: - - Auth - /auth/logout: - post: - description: 用户登出 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: User logout - tags: - - Auth - /auth/mfalogin: - post: - consumes: - - application/json - description: 用户 mfa 登录 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.MFALogin' - responses: - "200": - description: OK - headers: - EntranceCode: - description: 安全入口 - type: string - schema: - $ref: '#/definitions/dto.UserLoginInfo' - summary: User login with mfa - tags: - - Auth - /containers: - post: - consumes: - - application/json - description: 创建容器 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ContainerOperate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create container - tags: - - Container - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - - image - formatEN: create container [name][image] - formatZH: 创建容器 [name][image] - paramKeys: [] - /containers/clean/log: - post: - consumes: - - application/json - description: 清理容器日志 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperationWithName' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Clean container log - tags: - - Container - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: clean container [name] logs - formatZH: 清理容器 [name] 日志 - paramKeys: [] - /containers/commit: - post: - consumes: - - application/json - description: 容器提交生成新镜像 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ContainerCommit' - responses: - "200": - description: OK - summary: Commit Container - tags: - - Container - /containers/compose: - post: - consumes: - - application/json - description: 创建容器编排 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ComposeCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create compose - tags: - - Container Compose - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: create compose [name] - formatZH: 创建 compose [name] - paramKeys: [] - /containers/compose/operate: - post: - consumes: - - application/json - description: 容器编排操作 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ComposeOperation' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Operate compose - tags: - - Container Compose - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - - operation - formatEN: compose [operation] [name] - formatZH: compose [operation] [name] - paramKeys: [] - /containers/compose/search: - post: - consumes: - - application/json - description: 获取编排列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchWithPage' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page composes - tags: - - Container Compose - /containers/compose/search/log: - get: - description: docker-compose 日志 - parameters: - - description: compose 文件地址 - in: query - name: compose - type: string - - description: 时间筛选 - in: query - name: since - type: string - - description: 是否追踪 - in: query - name: follow - type: string - - description: 显示行号 - in: query - name: tail - type: string - responses: {} - security: - - ApiKeyAuth: [] - summary: Container Compose logs - tags: - - Container Compose - /containers/compose/test: - post: - consumes: - - application/json - description: 测试 compose 是否可用 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ComposeCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Test compose - tags: - - Container Compose - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: check compose [name] - formatZH: 检测 compose [name] 格式 - paramKeys: [] - /containers/compose/update: - post: - consumes: - - application/json - description: 更新容器编排 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ComposeUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update compose - tags: - - Container Compose - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: update compose information [name] - formatZH: 更新 compose [name] - paramKeys: [] - /containers/daemonjson: - get: - description: 获取 docker 配置信息 - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.DaemonJsonConf' - security: - - ApiKeyAuth: [] - summary: Load docker daemon.json - tags: - - Container Docker - /containers/daemonjson/file: - get: - description: 获取 docker 配置信息(表单) - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - security: - - ApiKeyAuth: [] - summary: Load docker daemon.json - tags: - - Container Docker - /containers/daemonjson/update: - post: - consumes: - - application/json - description: 修改 docker 配置信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SettingUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update docker daemon.json - tags: - - Container Docker - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - key - - value - formatEN: Updated configuration [key] - formatZH: 更新配置 [key] - paramKeys: [] - /containers/daemonjson/update/byfile: - post: - consumes: - - application/json - description: 上传替换 docker 配置文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.DaemonJsonUpdateByFile' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update docker daemon.json by upload file - tags: - - Container Docker - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: Updated configuration file - formatZH: 更新配置文件 - paramKeys: [] - /containers/docker/operate: - post: - consumes: - - application/json - description: Docker 操作 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.DockerOperation' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Operate docker - tags: - - Container Docker - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - operation - formatEN: '[operation] docker service' - formatZH: docker 服务 [operation] - paramKeys: [] - /containers/docker/status: - get: - description: 获取 docker 服务状态 - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - security: - - ApiKeyAuth: [] - summary: Load docker status - tags: - - Container Docker - /containers/download/log: - post: - description: 下载容器日志 - responses: {} - /containers/image: - get: - description: 获取镜像名称列表 - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.Options' - type: array - security: - - ApiKeyAuth: [] - summary: load images options - tags: - - Container Image - /containers/image/all: - get: - description: 获取所有镜像列表 - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.ImageInfo' - type: array - security: - - ApiKeyAuth: [] - summary: List all images - tags: - - Container Image - /containers/image/build: - post: - consumes: - - application/json - description: 构建镜像 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ImageBuild' - responses: - "200": - description: OK - schema: - type: string - security: - - ApiKeyAuth: [] - summary: Build image - tags: - - Container Image - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: build image [name] - formatZH: 构建镜像 [name] - paramKeys: [] - /containers/image/load: - post: - consumes: - - application/json - description: 导入镜像 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ImageLoad' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load image - tags: - - Container Image - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - path - formatEN: load image from [path] - formatZH: 从 [path] 加载镜像 - paramKeys: [] - /containers/image/pull: - post: - consumes: - - application/json - description: 拉取镜像 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ImagePull' - responses: - "200": - description: OK - schema: - type: string - security: - - ApiKeyAuth: [] - summary: Pull image - tags: - - Container Image - x-panel-log: - BeforeFunctions: - - db: image_repos - input_column: id - input_value: repoID - isList: false - output_column: name - output_value: reponame - bodyKeys: - - repoID - - imageName - formatEN: image pull [reponame][imageName] - formatZH: 镜像拉取 [reponame][imageName] - paramKeys: [] - /containers/image/push: - post: - consumes: - - application/json - description: 推送镜像 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ImagePush' - responses: - "200": - description: OK - schema: - type: string - security: - - ApiKeyAuth: [] - summary: Push image - tags: - - Container Image - x-panel-log: - BeforeFunctions: - - db: image_repos - input_column: id - input_value: repoID - isList: false - output_column: name - output_value: reponame - bodyKeys: - - repoID - - tagName - - name - formatEN: push [tagName] to [reponame][name] - formatZH: '[tagName] 推送到 [reponame][name]' - paramKeys: [] - /containers/image/remove: - post: - consumes: - - application/json - description: 删除镜像 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BatchDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete image - tags: - - Container Image - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - names - formatEN: remove image [names] - formatZH: 移除镜像 [names] - paramKeys: [] - /containers/image/save: - post: - consumes: - - application/json - description: 导出镜像 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ImageSave' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Save image - tags: - - Container Image - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - tagName - - path - - name - formatEN: save [tagName] as [path]/[name] - formatZH: 保留 [tagName] 为 [path]/[name] - paramKeys: [] - /containers/image/search: - post: - consumes: - - application/json - description: 获取镜像列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchWithPage' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page images - tags: - - Container Image - /containers/image/tag: - post: - consumes: - - application/json - description: Tag 镜像 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ImageTag' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Tag image - tags: - - Container Image - x-panel-log: - BeforeFunctions: - - db: image_repos - input_column: id - input_value: repoID - isList: false - output_column: name - output_value: reponame - bodyKeys: - - repoID - - targetName - formatEN: tag image [reponame][targetName] - formatZH: tag 镜像 [reponame][targetName] - paramKeys: [] - /containers/info: - post: - consumes: - - application/json - description: 获取容器表单信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperationWithName' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.ContainerOperate' - security: - - ApiKeyAuth: [] - summary: Load container info - tags: - - Container - /containers/inspect: - post: - consumes: - - application/json - description: 容器详情 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.InspectReq' - responses: - "200": - description: OK - schema: - type: string - security: - - ApiKeyAuth: [] - summary: Container inspect - tags: - - Container - /containers/ipv6option/update: - post: - consumes: - - application/json - description: 修改 docker ipv6 配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.LogOption' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update docker daemon.json ipv6 option - tags: - - Container Docker - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: Updated the ipv6 option - formatZH: 更新 ipv6 配置 - paramKeys: [] - /containers/limit: - get: - description: 获取容器限制 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.ResourceLimit' - security: - - ApiKeyAuth: [] - summary: Load container limits - /containers/list: - post: - consumes: - - application/json - description: 获取容器名称 - produces: - - application/json - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: List containers - tags: - - Container - /containers/list/stats: - get: - description: 获取容器列表资源占用 - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.ContainerListStats' - type: array - security: - - ApiKeyAuth: [] - summary: Load container stats - /containers/load/log: - post: - consumes: - - application/json - description: 获取容器操作日志 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperationWithNameAndType' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load container log - tags: - - Container - /containers/logoption/update: - post: - consumes: - - application/json - description: 修改 docker 日志配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.LogOption' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update docker daemon.json log option - tags: - - Container Docker - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: Updated the log option - formatZH: 更新日志配置 - paramKeys: [] - /containers/network: - get: - consumes: - - application/json - description: 获取容器网络列表 - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.Options' - type: array - security: - - ApiKeyAuth: [] - summary: List networks - tags: - - Container Network - post: - consumes: - - application/json - description: 创建容器网络 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.NetworkCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create network - tags: - - Container Network - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: create container network [name] - formatZH: 创建容器网络 name - paramKeys: [] - /containers/network/del: - post: - consumes: - - application/json - description: 删除容器网络 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BatchDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete network - tags: - - Container Network - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - names - formatEN: delete container network [names] - formatZH: 删除容器网络 [names] - paramKeys: [] - /containers/network/search: - post: - consumes: - - application/json - description: 获取容器网络列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchWithPage' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page networks - tags: - - Container Network - /containers/operate: - post: - consumes: - - application/json - description: 容器操作 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ContainerOperation' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Operate Container - tags: - - Container - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - names - - operation - formatEN: container [operation] [names] - formatZH: 容器 [names] 执行 [operation] - paramKeys: [] - /containers/prune: - post: - consumes: - - application/json - description: 容器清理 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ContainerPrune' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.ContainerPruneReport' - security: - - ApiKeyAuth: [] - summary: Clean container - tags: - - Container - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - pruneType - formatEN: clean container [pruneType] - formatZH: 清理容器 [pruneType] - paramKeys: [] - /containers/rename: - post: - consumes: - - application/json - description: 容器重命名 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ContainerRename' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Rename Container - tags: - - Container - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - - newName - formatEN: rename container [name] => [newName] - formatZH: 容器重命名 [name] => [newName] - paramKeys: [] - /containers/repo: - get: - description: 获取镜像仓库列表 - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.ImageRepoOption' - type: array - security: - - ApiKeyAuth: [] - summary: List image repos - tags: - - Container Image-repo - post: - consumes: - - application/json - description: 创建镜像仓库 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ImageRepoDelete' - produces: - - application/json - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create image repo - tags: - - Container Image-repo - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: create image repo [name] - formatZH: 创建镜像仓库 [name] - paramKeys: [] - /containers/repo/del: - post: - consumes: - - application/json - description: 删除镜像仓库 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ImageRepoDelete' - produces: - - application/json - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete image repo - tags: - - Container Image-repo - x-panel-log: - BeforeFunctions: - - db: image_repos - input_column: id - input_value: ids - isList: true - output_column: name - output_value: names - bodyKeys: - - ids - formatEN: delete image repo [names] - formatZH: 删除镜像仓库 [names] - paramKeys: [] - /containers/repo/search: - post: - consumes: - - application/json - description: 获取镜像仓库列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchWithPage' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page image repos - tags: - - Container Image-repo - /containers/repo/status: - get: - consumes: - - application/json - description: 获取 docker 仓库状态 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperateByID' - produces: - - application/json - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load repo status - tags: - - Container Image-repo - /containers/repo/update: - post: - consumes: - - application/json - description: 更新镜像仓库 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ImageRepoUpdate' - produces: - - application/json - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update image repo - tags: - - Container Image-repo - x-panel-log: - BeforeFunctions: - - db: image_repos - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: update image repo information [name] - formatZH: 更新镜像仓库 [name] - paramKeys: [] - /containers/search: - post: - consumes: - - application/json - description: 获取容器列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PageContainer' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page containers - tags: - - Container - /containers/search/log: - post: - description: 容器日志 - parameters: - - description: 容器名称 - in: query - name: container - type: string - - description: 时间筛选 - in: query - name: since - type: string - - description: 是否追踪 - in: query - name: follow - type: string - - description: 显示行号 - in: query - name: tail - type: string - responses: {} - security: - - ApiKeyAuth: [] - summary: Container logs - tags: - - Container - /containers/stats/:id: - get: - description: 容器监控信息 - parameters: - - description: 容器id - in: path - name: id - required: true - type: integer - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.ContainerStats' - security: - - ApiKeyAuth: [] - summary: Container stats - tags: - - Container - /containers/template: - get: - description: 获取容器编排模版列表 - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.ComposeTemplateInfo' - type: array - security: - - ApiKeyAuth: [] - summary: List compose templates - tags: - - Container Compose-template - post: - consumes: - - application/json - description: 创建容器编排模版 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ComposeTemplateCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create compose template - tags: - - Container Compose-template - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: create compose template [name] - formatZH: 创建 compose 模版 [name] - paramKeys: [] - /containers/template/del: - post: - consumes: - - application/json - description: 删除容器编排模版 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BatchDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete compose template - tags: - - Container Compose-template - x-panel-log: - BeforeFunctions: - - db: compose_templates - input_column: id - input_value: ids - isList: true - output_column: name - output_value: names - bodyKeys: - - ids - formatEN: delete compose template [names] - formatZH: 删除 compose 模版 [names] - paramKeys: [] - /containers/template/search: - post: - consumes: - - application/json - description: 获取容器编排模版列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchWithPage' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page compose templates - tags: - - Container Compose-template - /containers/template/update: - post: - consumes: - - application/json - description: 更新容器编排模版 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ComposeTemplateUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update compose template - tags: - - Container Compose-template - x-panel-log: - BeforeFunctions: - - db: compose_templates - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: update compose template information [name] - formatZH: 更新 compose 模版 [name] - paramKeys: [] - /containers/update: - post: - consumes: - - application/json - description: 更新容器 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ContainerOperate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update container - tags: - - Container - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - - image - formatEN: update container [name][image] - formatZH: 更新容器 [name][image] - paramKeys: [] - /containers/upgrade: - post: - consumes: - - application/json - description: 更新容器镜像 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ContainerUpgrade' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Upgrade container - tags: - - Container - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - - image - formatEN: upgrade container image [name][image] - formatZH: 更新容器镜像 [name][image] - paramKeys: [] - /containers/volume: - get: - consumes: - - application/json - description: 获取容器存储卷列表 - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.Options' - type: array - security: - - ApiKeyAuth: [] - summary: List volumes - tags: - - Container Volume - post: - consumes: - - application/json - description: 创建容器存储卷 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.VolumeCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create volume - tags: - - Container Volume - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: create container volume [name] - formatZH: 创建容器存储卷 [name] - paramKeys: [] - /containers/volume/del: - post: - consumes: - - application/json - description: 删除容器存储卷 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BatchDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete volume - tags: - - Container Volume - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - names - formatEN: delete container volume [names] - formatZH: 删除容器存储卷 [names] - paramKeys: [] - /containers/volume/search: - post: - consumes: - - application/json - description: 获取容器存储卷分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchWithPage' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page volumes - tags: - - Container Volume - /cronjobs: - post: - consumes: - - application/json - description: 创建计划任务 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.CronjobCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create cronjob - tags: - - Cronjob - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - type - - name - formatEN: create cronjob [type][name] - formatZH: 创建计划任务 [type][name] - paramKeys: [] - /cronjobs/del: - post: - consumes: - - application/json - description: 删除计划任务 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.CronjobBatchDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete cronjob - tags: - - Cronjob - x-panel-log: - BeforeFunctions: - - db: cronjobs - input_column: id - input_value: ids - isList: true - output_column: name - output_value: names - bodyKeys: - - ids - formatEN: delete cronjob [names] - formatZH: 删除计划任务 [names] - paramKeys: [] - /cronjobs/download: - post: - consumes: - - application/json - description: 下载计划任务记录 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.CronjobDownload' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Download cronjob records - tags: - - Cronjob - x-panel-log: - BeforeFunctions: - - db: job_records - input_column: id - input_value: recordID - isList: false - output_column: file - output_value: file - bodyKeys: - - recordID - formatEN: download the cronjob record [file] - formatZH: 下载计划任务记录 [file] - paramKeys: [] - /cronjobs/handle: - post: - consumes: - - application/json - description: 手动执行计划任务 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperateByID' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Handle cronjob once - tags: - - Cronjob - x-panel-log: - BeforeFunctions: - - db: cronjobs - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: manually execute the cronjob [name] - formatZH: 手动执行计划任务 [name] - paramKeys: [] - /cronjobs/records/clean: - post: - consumes: - - application/json - description: 清空计划任务记录 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.CronjobClean' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Clean job records - tags: - - Cronjob - x-panel-log: - BeforeFunctions: - - db: cronjobs - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: clean cronjob [name] records - formatZH: 清空计划任务记录 [name] - paramKeys: [] - /cronjobs/records/log: - post: - consumes: - - application/json - description: 获取计划任务记录日志 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperateByID' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load Cronjob record log - tags: - - Cronjob - /cronjobs/search: - post: - consumes: - - application/json - description: 获取计划任务分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PageCronjob' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page cronjobs - tags: - - Cronjob - /cronjobs/search/records: - post: - consumes: - - application/json - description: 获取计划任务记录 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchRecord' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page job records - tags: - - Cronjob - /cronjobs/status: - post: - consumes: - - application/json - description: 更新计划任务状态 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.CronjobUpdateStatus' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update cronjob status - tags: - - Cronjob - x-panel-log: - BeforeFunctions: - - db: cronjobs - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - - status - formatEN: change the status of cronjob [name] to [status]. - formatZH: 修改计划任务 [name] 状态为 [status] - paramKeys: [] - /cronjobs/update: - post: - consumes: - - application/json - description: 更新计划任务 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.CronjobUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update cronjob - tags: - - Cronjob - x-panel-log: - BeforeFunctions: - - db: cronjobs - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: update cronjob [name] - formatZH: 更新计划任务 [name] - paramKeys: [] - /dashboard/base/:ioOption/:netOption: - get: - consumes: - - application/json - description: 获取首页基础数据 - parameters: - - description: request - in: path - name: ioOption - required: true - type: string - - description: request - in: path - name: netOption - required: true - type: string - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.DashboardBase' - security: - - ApiKeyAuth: [] - summary: Load dashboard base info - tags: - - Dashboard - /dashboard/base/os: - get: - consumes: - - application/json - description: 获取服务器基础数据 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.OsInfo' - security: - - ApiKeyAuth: [] - summary: Load os info - tags: - - Dashboard - /dashboard/current/:ioOption/:netOption: - get: - consumes: - - application/json - description: 获取首页实时数据 - parameters: - - description: request - in: path - name: ioOption - required: true - type: string - - description: request - in: path - name: netOption - required: true - type: string - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.DashboardCurrent' - security: - - ApiKeyAuth: [] - summary: Load dashboard current info - tags: - - Dashboard - /dashboard/system/restart/:operation: - post: - consumes: - - application/json - description: 重启服务器/面板 - parameters: - - description: request - in: path - name: operation - required: true - type: string - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: System restart - tags: - - Dashboard - /databases: - post: - consumes: - - application/json - description: 创建 mysql 数据库 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.MysqlDBCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create mysql database - tags: - - Database Mysql - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: create mysql database [name] - formatZH: 创建 mysql 数据库 [name] - paramKeys: [] - /databases/bind: - post: - consumes: - - application/json - description: 绑定 mysql 数据库用户 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BindUser' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Bind user of mysql database - tags: - - Database Mysql - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - database - - username - formatEN: bind mysql database [database] [username] - formatZH: 绑定 mysql 数据库名 [database] [username] - paramKeys: [] - /databases/change/access: - post: - consumes: - - application/json - description: 修改 mysql 访问权限 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ChangeDBInfo' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Change mysql access - tags: - - Database Mysql - x-panel-log: - BeforeFunctions: - - db: database_mysqls - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: Update database [name] access - formatZH: 更新数据库 [name] 访问权限 - paramKeys: [] - /databases/change/password: - post: - consumes: - - application/json - description: 修改 mysql 密码 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ChangeDBInfo' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Change mysql password - tags: - - Database Mysql - x-panel-log: - BeforeFunctions: - - db: database_mysqls - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: Update database [name] password - formatZH: 更新数据库 [name] 密码 - paramKeys: [] - /databases/common/info: - post: - consumes: - - application/json - description: 获取数据库基础信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperationWithNameAndType' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.DBBaseInfo' - security: - - ApiKeyAuth: [] - summary: Load base info - tags: - - Database Common - /databases/common/load/file: - post: - consumes: - - application/json - description: 获取数据库配置文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperationWithNameAndType' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load Database conf - tags: - - Database Common - /databases/common/update/conf: - post: - consumes: - - application/json - description: 上传替换配置文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.DBConfUpdateByFile' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update conf by upload file - tags: - - Database Common - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - type - - database - formatEN: update the [type] [database] database configuration information - formatZH: 更新 [type] 数据库 [database] 配置信息 - paramKeys: [] - /databases/db: - post: - consumes: - - application/json - description: 创建远程数据库 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.DatabaseCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create database - tags: - - Database - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - - type - formatEN: create database [name][type] - formatZH: 创建远程数据库 [name][type] - paramKeys: [] - /databases/db/:name: - get: - description: 获取远程数据库 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.DatabaseInfo' - security: - - ApiKeyAuth: [] - summary: Get databases - tags: - - Database - /databases/db/check: - post: - consumes: - - application/json - description: 检测远程数据库连接性 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.DatabaseCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Check database - tags: - - Database - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - - type - formatEN: check if database [name][type] is connectable - formatZH: 检测远程数据库 [name][type] 连接性 - paramKeys: [] - /databases/db/del: - post: - consumes: - - application/json - description: 删除远程数据库 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.DatabaseDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete database - tags: - - Database - x-panel-log: - BeforeFunctions: - - db: databases - input_column: id - input_value: ids - isList: true - output_column: name - output_value: names - bodyKeys: - - ids - formatEN: delete database [names] - formatZH: 删除远程数据库 [names] - paramKeys: [] - /databases/db/item/:type: - get: - description: 获取数据库列表 - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.DatabaseItem' - type: array - security: - - ApiKeyAuth: [] - summary: List databases - tags: - - Database - /databases/db/list/:type: - get: - description: 获取远程数据库列表 - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.DatabaseOption' - type: array - security: - - ApiKeyAuth: [] - summary: List databases - tags: - - Database - /databases/db/search: - post: - consumes: - - application/json - description: 获取远程数据库列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.DatabaseSearch' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page databases - tags: - - Database - /databases/db/update: - post: - consumes: - - application/json - description: 更新远程数据库 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.DatabaseUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update database - tags: - - Database - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: update database [name] - formatZH: 更新远程数据库 [name] - paramKeys: [] - /databases/del: - post: - consumes: - - application/json - description: 删除 mysql 数据库 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.MysqlDBDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete mysql database - tags: - - Database Mysql - x-panel-log: - BeforeFunctions: - - db: database_mysqls - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: delete mysql database [name] - formatZH: 删除 mysql 数据库 [name] - paramKeys: [] - /databases/del/check: - post: - consumes: - - application/json - description: Mysql 数据库删除前检查 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.MysqlDBDeleteCheck' - responses: - "200": - description: OK - schema: - items: - type: string - type: array - security: - - ApiKeyAuth: [] - summary: Check before delete mysql database - tags: - - Database Mysql - /databases/description/update: - post: - consumes: - - application/json - description: 更新 mysql 数据库库描述信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.UpdateDescription' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update mysql database description - tags: - - Database Mysql - x-panel-log: - BeforeFunctions: - - db: database_mysqls - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - - description - formatEN: The description of the mysql database [name] is modified => [description] - formatZH: mysql 数据库 [name] 描述信息修改 [description] - paramKeys: [] - /databases/load: - post: - consumes: - - application/json - description: 从服务器获取 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.MysqlLoadDB' - responses: {} - security: - - ApiKeyAuth: [] - summary: Load mysql database from remote - tags: - - Database Mysql - /databases/options: - get: - consumes: - - application/json - description: 获取 mysql 数据库列表 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PageInfo' - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.MysqlOption' - type: array - security: - - ApiKeyAuth: [] - summary: List mysql database names - tags: - - Database Mysql - /databases/pg: - post: - consumes: - - application/json - description: 创建 postgresql 数据库 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PostgresqlDBCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create postgresql database - tags: - - Database Postgresql - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: create postgresql database [name] - formatZH: 创建 postgresql 数据库 [name] - paramKeys: [] - /databases/pg/:database/load: - post: - consumes: - - application/json - description: 从服务器获取 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PostgresqlLoadDB' - responses: {} - security: - - ApiKeyAuth: [] - summary: Load postgresql database from remote - tags: - - Database Postgresql - /databases/pg/bind: - post: - consumes: - - application/json - description: 绑定 postgresql 数据库用户 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PostgresqlBindUser' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Bind postgresql user - tags: - - Database Postgresql - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - - username - formatEN: bind postgresql database [name] user [username] - formatZH: 绑定 postgresql 数据库 [name] 用户 [username] - paramKeys: [] - /databases/pg/del: - post: - consumes: - - application/json - description: 删除 postgresql 数据库 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PostgresqlDBDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete postgresql database - tags: - - Database Postgresql - x-panel-log: - BeforeFunctions: - - db: database_postgresqls - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: delete postgresql database [name] - formatZH: 删除 postgresql 数据库 [name] - paramKeys: [] - /databases/pg/del/check: - post: - consumes: - - application/json - description: Postgresql 数据库删除前检查 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PostgresqlDBDeleteCheck' - responses: - "200": - description: OK - schema: - items: - type: string - type: array - security: - - ApiKeyAuth: [] - summary: Check before delete postgresql database - tags: - - Database Postgresql - /databases/pg/description: - post: - consumes: - - application/json - description: 更新 postgresql 数据库库描述信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.UpdateDescription' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update postgresql database description - tags: - - Database Postgresql - x-panel-log: - BeforeFunctions: - - db: database_postgresqls - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - - description - formatEN: The description of the postgresql database [name] is modified => - [description] - formatZH: postgresql 数据库 [name] 描述信息修改 [description] - paramKeys: [] - /databases/pg/password: - post: - consumes: - - application/json - description: 修改 postgresql 密码 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ChangeDBInfo' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Change postgresql password - tags: - - Database Postgresql - x-panel-log: - BeforeFunctions: - - db: database_postgresqls - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: Update database [name] password - formatZH: 更新数据库 [name] 密码 - paramKeys: [] - /databases/pg/privileges: - post: - consumes: - - application/json - description: 修改 postgresql 用户权限 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ChangeDBInfo' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Change postgresql privileges - tags: - - Database Postgresql - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - database - - username - formatEN: Update [user] privileges of database [database] - formatZH: 更新数据库 [database] 用户 [username] 权限 - paramKeys: [] - /databases/pg/search: - post: - consumes: - - application/json - description: 获取 postgresql 数据库列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PostgresqlDBSearch' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page postgresql databases - tags: - - Database Postgresql - /databases/redis/conf: - post: - consumes: - - application/json - description: 获取 redis 配置信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperationWithName' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.RedisConf' - security: - - ApiKeyAuth: [] - summary: Load redis conf - tags: - - Database Redis - /databases/redis/conf/update: - post: - consumes: - - application/json - description: 更新 redis 配置信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.RedisConfUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update redis conf - tags: - - Database Redis - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: update the redis database configuration information - formatZH: 更新 redis 数据库配置信息 - paramKeys: [] - /databases/redis/install/cli: - post: - description: 安装 redis cli - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Install redis-cli - tags: - - Database Redis - /databases/redis/password: - post: - consumes: - - application/json - description: 更新 redis 密码 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ChangeRedisPass' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Change redis password - tags: - - Database Redis - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: change the password of the redis database - formatZH: 修改 redis 数据库密码 - paramKeys: [] - /databases/redis/persistence/conf: - post: - consumes: - - application/json - description: 获取 redis 持久化配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperationWithName' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.RedisPersistence' - security: - - ApiKeyAuth: [] - summary: Load redis persistence conf - tags: - - Database Redis - /databases/redis/persistence/update: - post: - consumes: - - application/json - description: 更新 redis 持久化配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.RedisConfPersistenceUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update redis persistence conf - tags: - - Database Redis - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: redis database persistence configuration update - formatZH: redis 数据库持久化配置更新 - paramKeys: [] - /databases/redis/status: - post: - consumes: - - application/json - description: 获取 redis 状态信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperationWithName' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.RedisStatus' - security: - - ApiKeyAuth: [] - summary: Load redis status info - tags: - - Database Redis - /databases/remote: - post: - consumes: - - application/json - description: 获取 mysql 远程访问权限 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperationWithNameAndType' - responses: - "200": - description: OK - schema: - type: boolean - security: - - ApiKeyAuth: [] - summary: Load mysql remote access - tags: - - Database Mysql - /databases/search: - post: - consumes: - - application/json - description: 获取 mysql 数据库列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.MysqlDBSearch' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page mysql databases - tags: - - Database Mysql - /databases/status: - post: - consumes: - - application/json - description: 获取 mysql 状态信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperationWithNameAndType' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.MysqlStatus' - security: - - ApiKeyAuth: [] - summary: Load mysql status info - tags: - - Database Mysql - /databases/variables: - post: - consumes: - - application/json - description: 获取 mysql 性能参数信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperationWithNameAndType' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.MysqlVariables' - security: - - ApiKeyAuth: [] - summary: Load mysql variables info - tags: - - Database Mysql - /databases/variables/update: - post: - consumes: - - application/json - description: mysql 性能调优 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.MysqlVariablesUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update mysql variables - tags: - - Database Mysql - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: adjust mysql database performance parameters - formatZH: 调整 mysql 数据库性能参数 - paramKeys: [] - /db/remote/del/check: - post: - consumes: - - application/json - description: Mysql 远程数据库删除前检查 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperateByID' - responses: - "200": - description: OK - schema: - items: - type: string - type: array - security: - - ApiKeyAuth: [] - summary: Check before delete remote database - tags: - - Database - /files: - post: - consumes: - - application/json - description: 创建文件/文件夹 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create file - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - path - formatEN: Create dir or file [path] - formatZH: 创建文件/文件夹 [path] - paramKeys: [] - /files/batch/del: - post: - consumes: - - application/json - description: 批量删除文件/文件夹 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileBatchDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Batch delete file - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - paths - formatEN: Batch delete dir or file [paths] - formatZH: 批量删除文件/文件夹 [paths] - paramKeys: [] - /files/batch/role: - post: - consumes: - - application/json - description: 批量修改文件权限和用户/组 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileRoleReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Batch change file mode and owner - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - paths - - mode - - user - - group - formatEN: Batch change file mode and owner [paths] => [mode]/[user]/[group] - formatZH: 批量修改文件权限和用户/组 [paths] => [mode]/[user]/[group] - paramKeys: [] - /files/check: - post: - consumes: - - application/json - description: 检测文件是否存在 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FilePathCheck' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Check file exist - tags: - - File - /files/chunkdownload: - post: - consumes: - - application/json - description: 分片下载下载文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileDownload' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Chunk Download file - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: Download file [name] - formatZH: 下载文件 [name] - paramKeys: [] - /files/chunkupload: - post: - description: 分片上传文件 - parameters: - - description: request - in: formData - name: file - required: true - type: file - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: ChunkUpload file - tags: - - File - /files/compress: - post: - consumes: - - application/json - description: 压缩文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileCompress' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Compress file - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: Compress file [name] - formatZH: 压缩文件 [name] - paramKeys: [] - /files/content: - post: - consumes: - - application/json - description: 获取文件内容 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileContentReq' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.FileInfo' - security: - - ApiKeyAuth: [] - summary: Load file content - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - path - formatEN: Load file content [path] - formatZH: 获取文件内容 [path] - paramKeys: [] - /files/decompress: - post: - consumes: - - application/json - description: 解压文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileDeCompress' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Decompress file - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - path - formatEN: Decompress file [path] - formatZH: 解压 [path] - paramKeys: [] - /files/del: - post: - consumes: - - application/json - description: 删除文件/文件夹 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete file - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - path - formatEN: Delete dir or file [path] - formatZH: 删除文件/文件夹 [path] - paramKeys: [] - /files/download: - get: - consumes: - - application/json - description: 下载文件 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Download file - tags: - - File - /files/favorite: - post: - consumes: - - application/json - description: 创建收藏 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FavoriteCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create favorite - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - path - formatEN: 收藏文件/文件夹 [path] - formatZH: 收藏文件/文件夹 [path] - paramKeys: [] - /files/favorite/del: - post: - consumes: - - application/json - description: 删除收藏 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FavoriteDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete favorite - tags: - - File - x-panel-log: - BeforeFunctions: - - db: favorites - input_column: id - input_value: id - isList: false - output_column: path - output_value: path - bodyKeys: - - id - formatEN: delete avorite [path] - formatZH: 删除收藏 [path] - paramKeys: [] - /files/favorite/search: - post: - consumes: - - application/json - description: 获取收藏列表 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PageInfo' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: List favorites - tags: - - File - /files/mode: - post: - consumes: - - application/json - description: 修改文件权限 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Change file mode - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - path - - mode - formatEN: Change mode [paths] => [mode] - formatZH: 修改权限 [paths] => [mode] - paramKeys: [] - /files/move: - post: - consumes: - - application/json - description: 移动文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileMove' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Move file - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - oldPaths - - newPath - formatEN: Move [oldPaths] => [newPath] - formatZH: 移动文件 [oldPaths] => [newPath] - paramKeys: [] - /files/owner: - post: - consumes: - - application/json - description: 修改文件用户/组 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileRoleUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Change file owner - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - path - - user - - group - formatEN: Change owner [paths] => [user]/[group] - formatZH: 修改用户/组 [paths] => [user]/[group] - paramKeys: [] - /files/read: - post: - description: 按行读取日志文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileReadByLineReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Read file by Line - tags: - - File - /files/recycle/clear: - post: - consumes: - - application/json - description: 清空回收站文件 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Clear RecycleBin files - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: 清空回收站 - formatZH: 清空回收站 - paramKeys: [] - /files/recycle/reduce: - post: - consumes: - - application/json - description: 还原回收站文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.RecycleBinReduce' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Reduce RecycleBin files - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: Reduce RecycleBin file [name] - formatZH: 还原回收站文件 [name] - paramKeys: [] - /files/recycle/search: - post: - consumes: - - application/json - description: 获取回收站文件列表 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PageInfo' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: List RecycleBin files - tags: - - File - /files/recycle/status: - get: - consumes: - - application/json - description: 获取回收站状态 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get RecycleBin status - tags: - - File - /files/rename: - post: - consumes: - - application/json - description: 修改文件名称 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileRename' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Change file name - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - oldName - - newName - formatEN: Rename [oldName] => [newName] - formatZH: 重命名 [oldName] => [newName] - paramKeys: [] - /files/save: - post: - consumes: - - application/json - description: 更新文件内容 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileEdit' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update file content - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - path - formatEN: Update file content [path] - formatZH: 更新文件内容 [path] - paramKeys: [] - /files/search: - post: - consumes: - - application/json - description: 获取文件列表 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileOption' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.FileInfo' - security: - - ApiKeyAuth: [] - summary: List files - tags: - - File - /files/size: - post: - consumes: - - application/json - description: 获取文件夹大小 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.DirSizeReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load file size - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - path - formatEN: Load file size [path] - formatZH: 获取文件夹大小 [path] - paramKeys: [] - /files/tree: - post: - consumes: - - application/json - description: 加载文件树 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileOption' - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/response.FileTree' - type: array - security: - - ApiKeyAuth: [] - summary: Load files tree - tags: - - File - /files/upload: - post: - description: 上传文件 - parameters: - - description: request - in: formData - name: file - required: true - type: file - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Upload file - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - path - formatEN: Upload file [path] - formatZH: 上传文件 [path] - paramKeys: [] - /files/upload/search: - post: - consumes: - - application/json - description: 分页获取上传文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.SearchUploadWithPage' - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/response.FileInfo' - type: array - security: - - ApiKeyAuth: [] - summary: Page file - tags: - - File - /files/wget: - post: - consumes: - - application/json - description: 下载远端文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.FileWget' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Wget file - tags: - - File - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - url - - path - - name - formatEN: Download url => [path]/[name] - formatZH: 下载 url => [path]/[name] - paramKeys: [] - /groups: - post: - consumes: - - application/json - description: 创建系统组 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.GroupCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create group - tags: - - System Group - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - - type - formatEN: create group [name][type] - formatZH: 创建组 [name][type] - paramKeys: [] - /groups/del: - post: - consumes: - - application/json - description: 删除系统组 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperateByID' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete group - tags: - - System Group - x-panel-log: - BeforeFunctions: - - db: groups - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - - db: groups - input_column: id - input_value: id - isList: false - output_column: type - output_value: type - bodyKeys: - - id - formatEN: delete group [type][name] - formatZH: 删除组 [type][name] - paramKeys: [] - /groups/search: - post: - consumes: - - application/json - description: 查询系统组 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.GroupSearch' - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.GroupInfo' - type: array - security: - - ApiKeyAuth: [] - summary: List groups - tags: - - System Group - /groups/update: - post: - consumes: - - application/json - description: 更新系统组 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.GroupUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update group - tags: - - System Group - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - - type - formatEN: update group [name][type] - formatZH: 更新组 [name][type] - paramKeys: [] - /host/conffile/update: - post: - consumes: - - application/json - description: 上传文件更新 SSH 配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SSHConf' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update host SSH setting by file - tags: - - SSH - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: update SSH conf - formatZH: 修改 SSH 配置文件 - paramKeys: [] - /host/ssh/conf: - get: - description: 获取 SSH 配置文件 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load host SSH conf - tags: - - SSH - /host/ssh/generate: - post: - consumes: - - application/json - description: 生成 SSH 密钥 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.GenerateSSH' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Generate host SSH secret - tags: - - SSH - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: generate SSH secret - formatZH: '生成 SSH 密钥 ' - paramKeys: [] - /host/ssh/log: - post: - consumes: - - application/json - description: 获取 SSH 登录日志 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchSSHLog' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.SSHLog' - security: - - ApiKeyAuth: [] - summary: Load host SSH logs - tags: - - SSH - /host/ssh/operate: - post: - consumes: - - application/json - description: 修改 SSH 服务状态 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.Operate' - responses: {} - security: - - ApiKeyAuth: [] - summary: Operate SSH - tags: - - SSH - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - operation - formatEN: '[operation] SSH' - formatZH: '[operation] SSH ' - paramKeys: [] - /host/ssh/search: - post: - description: 加载 SSH 配置信息 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.SSHInfo' - security: - - ApiKeyAuth: [] - summary: Load host SSH setting info - tags: - - SSH - /host/ssh/secret: - post: - consumes: - - application/json - description: 获取 SSH 密钥 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.GenerateLoad' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load host SSH secret - tags: - - SSH - /host/ssh/update: - post: - consumes: - - application/json - description: 更新 SSH 配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SSHUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update host SSH setting - tags: - - SSH - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - key - - value - formatEN: update SSH setting [key] => [value] - formatZH: 修改 SSH 配置 [key] => [value] - paramKeys: [] - /host/tool: - post: - consumes: - - application/json - description: 获取主机工具状态 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.HostToolReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get tool - tags: - - Host tool - /host/tool/config: - post: - consumes: - - application/json - description: 操作主机工具配置文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.HostToolConfig' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get tool config - tags: - - Host tool - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - operate - formatEN: '[operate] tool config' - formatZH: '[operate] 主机工具配置文件 ' - paramKeys: [] - /host/tool/create: - post: - consumes: - - application/json - description: 创建主机工具配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.HostToolCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create Host tool Config - tags: - - Host tool - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - type - formatEN: create [type] config - formatZH: 创建 [type] 配置 - paramKeys: [] - /host/tool/log: - post: - consumes: - - application/json - description: 获取主机工具日志 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.HostToolLogReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get tool - tags: - - Host tool - /host/tool/operate: - post: - consumes: - - application/json - description: 操作主机工具 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.HostToolReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Operate tool - tags: - - Host tool - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - operate - - type - formatEN: '[operate] [type]' - formatZH: '[operate] [type] ' - paramKeys: [] - /host/tool/supervisor/process: - get: - consumes: - - application/json - description: 获取 Supervisor 进程配置 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get Supervisor process config - tags: - - Host tool - post: - consumes: - - application/json - description: 操作守护进程 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.SupervisorProcessConfig' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create Supervisor process - tags: - - Host tool - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - operate - formatEN: '[operate] process' - formatZH: '[operate] 守护进程 ' - paramKeys: [] - /host/tool/supervisor/process/file: - post: - consumes: - - application/json - description: 操作 Supervisor 进程文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.SupervisorProcessFileReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get Supervisor process config - tags: - - Host tool - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - operate - formatEN: '[operate] Supervisor Process Config file' - formatZH: '[operate] Supervisor 进程文件 ' - paramKeys: [] - /hosts: - post: - consumes: - - application/json - description: 创建主机 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.HostOperate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create host - tags: - - Host - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - - addr - formatEN: create host [name][addr] - formatZH: 创建主机 [name][addr] - paramKeys: [] - /hosts/command: - get: - description: 获取快速命令列表 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.CommandInfo' - security: - - ApiKeyAuth: [] - summary: List commands - tags: - - Command - post: - consumes: - - application/json - description: 创建快速命令 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.CommandOperate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create command - tags: - - Command - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - - command - formatEN: create quick command [name][command] - formatZH: 创建快捷命令 [name][command] - paramKeys: [] - /hosts/command/del: - post: - consumes: - - application/json - description: 删除快速命令 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BatchDeleteReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete command - tags: - - Command - x-panel-log: - BeforeFunctions: - - db: commands - input_column: id - input_value: ids - isList: true - output_column: name - output_value: names - bodyKeys: - - ids - formatEN: delete quick command [names] - formatZH: 删除快捷命令 [names] - paramKeys: [] - /hosts/command/redis: - get: - description: 获取 redis 快速命令列表 - responses: - "200": - description: OK - schema: - type: Array - security: - - ApiKeyAuth: [] - summary: List redis commands - tags: - - Redis Command - post: - consumes: - - application/json - description: 保存 Redis 快速命令 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.RedisCommand' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Save redis command - tags: - - Redis Command - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - - command - formatEN: save quick command for redis [name][command] - formatZH: 保存 redis 快捷命令 [name][command] - paramKeys: [] - /hosts/command/redis/del: - post: - consumes: - - application/json - description: 删除 redis 快速命令 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BatchDeleteReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete redis command - tags: - - Redis Command - x-panel-log: - BeforeFunctions: - - db: redis_commands - input_column: id - input_value: ids - isList: true - output_column: name - output_value: names - bodyKeys: - - ids - formatEN: delete quick command of redis [names] - formatZH: 删除 redis 快捷命令 [names] - paramKeys: [] - /hosts/command/redis/search: - post: - consumes: - - application/json - description: 获取 redis 快速命令列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchWithPage' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page redis commands - tags: - - Redis Command - /hosts/command/search: - post: - consumes: - - application/json - description: 获取快速命令列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchWithPage' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page commands - tags: - - Command - /hosts/command/tree: - get: - consumes: - - application/json - description: 获取快速命令树 - responses: - "200": - description: OK - schema: - type: Array - security: - - ApiKeyAuth: [] - summary: Tree commands - tags: - - Command - /hosts/command/update: - post: - consumes: - - application/json - description: 更新快速命令 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.CommandOperate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update command - tags: - - Command - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: update quick command [name] - formatZH: 更新快捷命令 [name] - paramKeys: [] - /hosts/del: - post: - consumes: - - application/json - description: 删除主机 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BatchDeleteReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete host - tags: - - Host - x-panel-log: - BeforeFunctions: - - db: hosts - input_column: id - input_value: ids - isList: true - output_column: addr - output_value: addrs - bodyKeys: - - ids - formatEN: delete host [addrs] - formatZH: 删除主机 [addrs] - paramKeys: [] - /hosts/firewall/base: - get: - description: 获取防火墙基础信息 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.FirewallBaseInfo' - security: - - ApiKeyAuth: [] - summary: Load firewall base info - tags: - - Firewall - /hosts/firewall/batch: - post: - consumes: - - application/json - description: 批量删除防火墙规则 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BatchRuleOperate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create group - tags: - - Firewall - /hosts/firewall/forward: - post: - consumes: - - application/json - description: 更新防火墙端口转发规则 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ForwardRuleOperate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create group - tags: - - Firewall - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - source_port - formatEN: update port forward rules [source_port] - formatZH: 更新端口转发规则 [source_port] - paramKeys: [] - /hosts/firewall/ip: - post: - consumes: - - application/json - description: 创建防火墙 IP 规则 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.AddrRuleOperate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create group - tags: - - Firewall - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - strategy - - address - formatEN: create address rules [strategy][address] - formatZH: 添加 ip 规则 [strategy] [address] - paramKeys: [] - /hosts/firewall/operate: - post: - consumes: - - application/json - description: 修改防火墙状态 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.FirewallOperation' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page firewall status - tags: - - Firewall - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - operation - formatEN: '[operation] firewall' - formatZH: '[operation] 防火墙' - paramKeys: [] - /hosts/firewall/port: - post: - consumes: - - application/json - description: 创建防火墙端口规则 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PortRuleOperate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create group - tags: - - Firewall - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - port - - strategy - formatEN: create port rules [strategy][port] - formatZH: 添加端口规则 [strategy] [port] - paramKeys: [] - /hosts/firewall/search: - post: - consumes: - - application/json - description: 获取防火墙规则列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.RuleSearch' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page firewall rules - tags: - - Firewall - /hosts/firewall/update/addr: - post: - consumes: - - application/json - description: 更新 ip 防火墙规则 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.AddrRuleUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create group - tags: - - Firewall - /hosts/firewall/update/description: - post: - consumes: - - application/json - description: 更新防火墙描述 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.UpdateFirewallDescription' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update rule description - tags: - - Firewall - /hosts/firewall/update/port: - post: - consumes: - - application/json - description: 更新端口防火墙规则 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PortRuleUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create group - tags: - - Firewall - /hosts/monitor/clean: - post: - description: 清空监控数据 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Clean monitor datas - tags: - - Monitor - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: clean monitor datas - formatZH: 清空监控数据 - paramKeys: [] - /hosts/monitor/search: - post: - description: 获取监控数据 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.MonitorSearch' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load monitor datas - tags: - - Monitor - /hosts/search: - post: - consumes: - - application/json - description: 获取主机列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchHostWithPage' - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.HostTree' - type: array - security: - - ApiKeyAuth: [] - summary: Page host - tags: - - Host - /hosts/test/byid/:id: - post: - consumes: - - application/json - description: 测试主机连接 - parameters: - - description: request - in: path - name: id - required: true - type: integer - responses: - "200": - description: OK - schema: - type: boolean - security: - - ApiKeyAuth: [] - summary: Test host conn by host id - tags: - - Host - /hosts/test/byinfo: - post: - consumes: - - application/json - description: 测试主机连接 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.HostConnTest' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Test host conn by info - tags: - - Host - /hosts/tree: - post: - consumes: - - application/json - description: 加载主机树 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchForTree' - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.HostTree' - type: array - security: - - ApiKeyAuth: [] - summary: Load host tree - tags: - - Host - /hosts/update: - post: - consumes: - - application/json - description: 更新主机 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.HostOperate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update host - tags: - - Host - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - - addr - formatEN: update host [name][addr] - formatZH: 更新主机信息 [name][addr] - paramKeys: [] - /hosts/update/group: - post: - consumes: - - application/json - description: 切换分组 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ChangeHostGroup' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update host group - tags: - - Host - x-panel-log: - BeforeFunctions: - - db: hosts - input_column: id - input_value: id - isList: false - output_column: addr - output_value: addr - bodyKeys: - - id - - group - formatEN: change host [addr] group => [group] - formatZH: 切换主机[addr]分组 => [group] - paramKeys: [] - /logs/clean: - post: - consumes: - - application/json - description: 清空操作日志 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.CleanLog' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Clean operation logs - tags: - - Logs - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - logType - formatEN: Clean the [logType] log information - formatZH: 清空 [logType] 日志信息 - paramKeys: [] - /logs/login: - post: - consumes: - - application/json - description: 获取系统登录日志列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchLgLogWithPage' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page login logs - tags: - - Logs - /logs/operation: - post: - consumes: - - application/json - description: 获取系统操作日志列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchOpLogWithPage' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page operation logs - tags: - - Logs - /logs/system: - post: - description: 获取系统日志 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load system logs - tags: - - Logs - /logs/system/files: - get: - description: 获取系统日志文件列表 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load system log files - tags: - - Logs - /openresty: - get: - description: 获取 OpenResty 配置信息 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.FileInfo' - security: - - ApiKeyAuth: [] - summary: Load OpenResty conf - tags: - - OpenResty - /openresty/clear: - post: - description: 清理 OpenResty 代理缓存 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Clear OpenResty proxy cache - tags: - - OpenResty - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: Clear nginx proxy cache - formatZH: 清理 Openresty 代理缓存 - paramKeys: [] - /openresty/file: - post: - consumes: - - application/json - description: 上传更新 OpenResty 配置文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NginxConfigFileUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update OpenResty conf by upload file - tags: - - OpenResty - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: Update nginx conf - formatZH: 更新 nginx 配置 - paramKeys: [] - /openresty/scope: - post: - consumes: - - application/json - description: 获取部分 OpenResty 配置信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NginxScopeReq' - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/response.NginxParam' - type: array - security: - - ApiKeyAuth: [] - summary: Load partial OpenResty conf - tags: - - OpenResty - /openresty/status: - get: - description: 获取 OpenResty 状态信息 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.NginxStatus' - security: - - ApiKeyAuth: [] - summary: Load OpenResty status info - tags: - - OpenResty - /openresty/update: - post: - consumes: - - application/json - description: 更新 OpenResty 配置信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NginxConfigUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update OpenResty conf - tags: - - OpenResty - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: websiteId - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - websiteId - formatEN: Update nginx conf [domain] - formatZH: 更新 nginx 配置 [domain] - paramKeys: [] - /process/stop: - post: - description: 停止进程 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.ProcessReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Stop Process - tags: - - Process - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - PID - formatEN: 结束进程 [PID] - formatZH: 结束进程 [PID] - paramKeys: [] - /runtimes: - post: - consumes: - - application/json - description: 创建运行环境 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.RuntimeCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create runtime - tags: - - Runtime - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: Create runtime [name] - formatZH: 创建运行环境 [name] - paramKeys: [] - /runtimes/:id: - get: - consumes: - - application/json - description: 获取运行环境 - parameters: - - description: request - in: path - name: id - required: true - type: string - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get runtime - tags: - - Runtime - /runtimes/del: - post: - consumes: - - application/json - description: 删除运行环境 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.RuntimeDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete runtime - tags: - - Website - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - id - formatEN: Delete website [name] - formatZH: 删除网站 [name] - paramKeys: [] - /runtimes/node/modules: - post: - consumes: - - application/json - description: 获取 Node 项目的 modules - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NodeModuleReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get Node modules - tags: - - Runtime - /runtimes/node/modules/operate: - post: - consumes: - - application/json - description: 操作 Node 项目 modules - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NodeModuleReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Operate Node modules - tags: - - Runtime - /runtimes/node/package: - post: - consumes: - - application/json - description: 获取 Node 项目的 scripts - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NodePackageReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get Node package scripts - tags: - - Runtime - /runtimes/operate: - post: - consumes: - - application/json - description: 操作运行环境 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.RuntimeOperate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Operate runtime - tags: - - Runtime - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - id - formatEN: Operate runtime [name] - formatZH: 操作运行环境 [name] - paramKeys: [] - /runtimes/php/extensions: - post: - consumes: - - application/json - description: Create Extensions - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.PHPExtensionsCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create Extensions - tags: - - PHP Extensions - /runtimes/php/extensions/del: - post: - consumes: - - application/json - description: Delete Extensions - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.PHPExtensionsDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete Extensions - tags: - - PHP Extensions - /runtimes/php/extensions/search: - post: - consumes: - - application/json - description: Page Extensions - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.PHPExtensionsSearch' - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/response.PHPExtensionsDTO' - type: array - security: - - ApiKeyAuth: [] - summary: Page Extensions - tags: - - PHP Extensions - /runtimes/php/extensions/update: - post: - consumes: - - application/json - description: Update Extensions - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.PHPExtensionsUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update Extensions - tags: - - PHP Extensions - /runtimes/search: - post: - consumes: - - application/json - description: 获取运行环境列表 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.RuntimeSearch' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: List runtimes - tags: - - Runtime - /runtimes/sync: - post: - consumes: - - application/json - description: 同步运行环境状态 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Sync runtime status - tags: - - Runtime - /runtimes/update: - post: - consumes: - - application/json - description: 更新运行环境 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.RuntimeUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update runtime - tags: - - Runtime - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: Update runtime [name] - formatZH: 更新运行环境 [name] - paramKeys: [] - /settings/backup: - post: - consumes: - - application/json - description: 创建备份账号 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BackupOperate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create backup account - tags: - - Backup Account - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - type - formatEN: create backup account [type] - formatZH: 创建备份账号 [type] - paramKeys: [] - /settings/backup/backup: - post: - consumes: - - application/json - description: 备份系统数据 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.CommonBackup' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Backup system data - tags: - - Backup Account - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - type - - name - - detailName - formatEN: backup [type] data [name][detailName] - formatZH: 备份 [type] 数据 [name][detailName] - paramKeys: [] - /settings/backup/del: - post: - consumes: - - application/json - description: 删除备份账号 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperateByID' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete backup account - tags: - - Backup Account - x-panel-log: - BeforeFunctions: - - db: backup_accounts - input_column: id - input_value: id - isList: false - output_column: type - output_value: types - bodyKeys: - - id - formatEN: delete backup account [types] - formatZH: 删除备份账号 [types] - paramKeys: [] - /settings/backup/onedrive: - get: - consumes: - - application/json - description: 获取 OneDrive 信息 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.OneDriveInfo' - security: - - ApiKeyAuth: [] - summary: Load OneDrive info - tags: - - Backup Account - /settings/backup/record/del: - post: - consumes: - - application/json - description: 删除备份记录 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BatchDeleteReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete backup record - tags: - - Backup Account - x-panel-log: - BeforeFunctions: - - db: backup_records - input_column: id - input_value: ids - isList: true - output_column: file_name - output_value: files - bodyKeys: - - ids - formatEN: delete backup records [files] - formatZH: 删除备份记录 [files] - paramKeys: [] - /settings/backup/record/download: - post: - consumes: - - application/json - description: 下载备份记录 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.DownloadRecord' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Download backup record - tags: - - Backup Account - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - source - - fileName - formatEN: download backup records [source][fileName] - formatZH: 下载备份记录 [source][fileName] - paramKeys: [] - /settings/backup/record/search: - post: - consumes: - - application/json - description: 获取备份记录列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.RecordSearch' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Page backup records - tags: - - Backup Account - /settings/backup/record/search/bycronjob: - post: - consumes: - - application/json - description: 通过计划任务获取备份记录列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.RecordSearchByCronjob' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Page backup records by cronjob - tags: - - Backup Account - /settings/backup/recover: - post: - consumes: - - application/json - description: 恢复系统数据 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.CommonRecover' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Recover system data - tags: - - Backup Account - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - type - - name - - detailName - - file - formatEN: recover [type] data [name][detailName] from [file] - formatZH: 从 [file] 恢复 [type] 数据 [name][detailName] - paramKeys: [] - /settings/backup/recover/byupload: - post: - consumes: - - application/json - description: 从上传恢复系统数据 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.CommonRecover' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Recover system data by upload - tags: - - Backup Account - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - type - - name - - detailName - - file - formatEN: recover [type] data [name][detailName] from [file] - formatZH: 从 [file] 恢复 [type] 数据 [name][detailName] - paramKeys: [] - /settings/backup/refresh/onedrive: - post: - description: 刷新 OneDrive token - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Refresh OneDrive token - tags: - - Backup Account - /settings/backup/search: - get: - description: 获取备份账号列表 - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/dto.BackupInfo' - type: array - security: - - ApiKeyAuth: [] - summary: List backup accounts - tags: - - Backup Account - post: - consumes: - - application/json - description: 获取 bucket 列表 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ForBuckets' - responses: - "200": - description: OK - schema: - items: - type: string - type: array - security: - - ApiKeyAuth: [] - summary: List buckets - tags: - - Backup Account - /settings/backup/search/files: - post: - consumes: - - application/json - description: 获取备份账号内文件列表 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BackupSearchFile' - responses: - "200": - description: OK - schema: - items: - type: string - type: array - security: - - ApiKeyAuth: [] - summary: List files from backup accounts - tags: - - Backup Account - /settings/backup/update: - post: - consumes: - - application/json - description: 更新备份账号信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BackupOperate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update backup account - tags: - - Backup Account - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - type - formatEN: update backup account [types] - formatZH: 更新备份账号 [types] - paramKeys: [] - /settings/basedir: - get: - description: 获取安装根目录 - responses: - "200": - description: OK - schema: - type: string - security: - - ApiKeyAuth: [] - summary: Load local backup dir - tags: - - System Setting - /settings/bind/update: - post: - consumes: - - application/json - description: 更新系统监听信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BindInfo' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update system bind info - tags: - - System Setting - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - ipv6 - - bindAddress - formatEN: 'update system bind info => ipv6: [ipv6], 监听 IP: [bindAddress]' - formatZH: '修改系统监听信息 => ipv6: [ipv6], 监听 IP: [bindAddress]' - paramKeys: [] - /settings/expired/handle: - post: - consumes: - - application/json - description: 重置过期系统登录密码 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PasswordUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Reset system password expired - tags: - - System Setting - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: reset an expired Password - formatZH: 重置过期密码 - paramKeys: [] - /settings/interface: - get: - consumes: - - application/json - description: 获取系统地址信息 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load system address - tags: - - System Setting - /settings/menu/update: - post: - consumes: - - application/json - description: 隐藏高级功能菜单 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SettingUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update system setting - tags: - - System Setting - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: Hide advanced feature menu. - formatZH: 隐藏高级功能菜单 - paramKeys: [] - /settings/mfa: - post: - consumes: - - application/json - description: 获取 mfa 信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.MfaCredential' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/mfa.Otp' - security: - - ApiKeyAuth: [] - summary: Load mfa info - tags: - - System Setting - /settings/mfa/bind: - post: - consumes: - - application/json - description: Mfa 绑定 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.MfaCredential' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Bind mfa - tags: - - System Setting - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: bind mfa - formatZH: mfa 绑定 - paramKeys: [] - /settings/password/update: - post: - consumes: - - application/json - description: 更新系统登录密码 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PasswordUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update system password - tags: - - System Setting - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: update system password - formatZH: 修改系统密码 - paramKeys: [] - /settings/port/update: - post: - consumes: - - application/json - description: 更新系统端口 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PortUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update system port - tags: - - System Setting - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - serverPort - formatEN: update system port => [serverPort] - formatZH: 修改系统端口 => [serverPort] - paramKeys: [] - /settings/proxy/update: - post: - consumes: - - application/json - description: 服务器代理配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ProxyUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update proxy setting - tags: - - System Setting - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - proxyUrl - - proxyPort - formatEN: set proxy [proxyPort]:[proxyPort]. - formatZH: 服务器代理配置 [proxyPort]:[proxyPort] - paramKeys: [] - /settings/search: - post: - description: 加载系统配置信息 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.SettingInfo' - security: - - ApiKeyAuth: [] - summary: Load system setting info - tags: - - System Setting - /settings/search/available: - get: - description: 获取系统可用状态 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load system available status - tags: - - System Setting - /settings/snapshot: - post: - consumes: - - application/json - description: 创建系统快照 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SnapshotCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create system snapshot - tags: - - System Setting - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - from - - description - formatEN: Create system backup [description] to [from] - formatZH: 创建系统快照 [description] 到 [from] - paramKeys: [] - /settings/snapshot/del: - post: - consumes: - - application/json - description: 删除系统快照 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SnapshotBatchDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete system backup - tags: - - System Setting - x-panel-log: - BeforeFunctions: - - db: snapshots - input_column: id - input_value: ids - isList: true - output_column: name - output_value: name - bodyKeys: - - ids - formatEN: Delete system backup [name] - formatZH: 删除系统快照 [name] - paramKeys: [] - /settings/snapshot/description/update: - post: - consumes: - - application/json - description: 更新快照描述信息 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.UpdateDescription' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update snapshot description - tags: - - System Setting - x-panel-log: - BeforeFunctions: - - db: snapshots - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - - description - formatEN: The description of the snapshot [name] is modified => [description] - formatZH: 快照 [name] 描述信息修改 [description] - paramKeys: [] - /settings/snapshot/import: - post: - consumes: - - application/json - description: 导入已有快照 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SnapshotImport' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Import system snapshot - tags: - - System Setting - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - from - - names - formatEN: Sync system snapshots [names] from [from] - formatZH: 从 [from] 同步系统快照 [names] - paramKeys: [] - /settings/snapshot/recover: - post: - consumes: - - application/json - description: 从系统快照恢复 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SnapshotRecover' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Recover system backup - tags: - - System Setting - x-panel-log: - BeforeFunctions: - - db: snapshots - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: Recover from system backup [name] - formatZH: 从系统快照 [name] 恢复 - paramKeys: [] - /settings/snapshot/rollback: - post: - consumes: - - application/json - description: 从系统快照回滚 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SnapshotRecover' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Rollback system backup - tags: - - System Setting - x-panel-log: - BeforeFunctions: - - db: snapshots - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: Rollback from system backup [name] - formatZH: 从系统快照 [name] 回滚 - paramKeys: [] - /settings/snapshot/search: - post: - consumes: - - application/json - description: 获取系统快照列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchWithPage' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page system snapshot - tags: - - System Setting - /settings/snapshot/status: - post: - consumes: - - application/json - description: 获取快照状态 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperateByID' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load Snapshot status - tags: - - System Setting - /settings/ssl/download: - post: - description: 下载证书 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Download system cert - tags: - - System Setting - /settings/ssl/info: - get: - description: 获取证书信息 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.SettingInfo' - security: - - ApiKeyAuth: [] - summary: Load system cert info - tags: - - System Setting - /settings/ssl/update: - post: - consumes: - - application/json - description: 修改系统 ssl 登录 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SSLUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update system ssl - tags: - - System Setting - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - ssl - formatEN: update system ssl => [ssl] - formatZH: 修改系统 ssl => [ssl] - paramKeys: [] - /settings/update: - post: - consumes: - - application/json - description: 更新系统配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SettingUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update system setting - tags: - - System Setting - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - key - - value - formatEN: update system setting [key] => [value] - formatZH: 修改系统配置 [key] => [value] - paramKeys: [] - /settings/upgrade: - get: - consumes: - - application/json - description: 获取版本 release notes - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.Upgrade' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load release notes by version - tags: - - System Setting - post: - consumes: - - application/json - description: 系统更新 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.Upgrade' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Upgrade - tags: - - System Setting - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - version - formatEN: upgrade system => [version] - formatZH: 更新系统 => [version] - paramKeys: [] - /toolbox/clam: - post: - consumes: - - application/json - description: 创建扫描规则 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ClamCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create clam - tags: - - Clam - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - - path - formatEN: create clam [name][path] - formatZH: 创建扫描规则 [name][path] - paramKeys: [] - /toolbox/clam/base: - get: - consumes: - - application/json - description: 获取 Clam 基础信息 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.ClamBaseInfo' - security: - - ApiKeyAuth: [] - summary: Load clam base info - tags: - - Clam - /toolbox/clam/del: - post: - consumes: - - application/json - description: 删除扫描规则 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ClamDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete clam - tags: - - Clam - x-panel-log: - BeforeFunctions: - - db: clams - input_column: id - input_value: ids - isList: true - output_column: name - output_value: names - bodyKeys: - - ids - formatEN: delete clam [names] - formatZH: 删除扫描规则 [names] - paramKeys: [] - /toolbox/clam/file/search: - post: - consumes: - - application/json - description: 获取扫描文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ClamFileReq' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Load clam file - tags: - - Clam - /toolbox/clam/file/update: - post: - consumes: - - application/json - description: 更新病毒扫描配置文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.UpdateByNameAndFile' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update clam file - tags: - - Clam - /toolbox/clam/handle: - post: - consumes: - - application/json - description: 执行病毒扫描 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperateByID' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Handle clam scan - tags: - - Clam - x-panel-log: - BeforeFunctions: - - db: clams - input_column: id - input_value: id - isList: true - output_column: name - output_value: name - bodyKeys: - - id - formatEN: handle clam scan [name] - formatZH: 执行病毒扫描 [name] - paramKeys: [] - /toolbox/clam/operate: - post: - consumes: - - application/json - description: 修改 Clam 状态 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.Operate' - responses: {} - security: - - ApiKeyAuth: [] - summary: Operate Clam - tags: - - Clam - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - operation - formatEN: '[operation] FTP' - formatZH: '[operation] Clam' - paramKeys: [] - /toolbox/clam/record/clean: - post: - consumes: - - application/json - description: 清空扫描报告 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperateByID' - responses: {} - security: - - ApiKeyAuth: [] - summary: Clean clam record - tags: - - Clam - x-panel-log: - BeforeFunctions: - - db: clams - input_column: id - input_value: id - isList: true - output_column: name - output_value: name - bodyKeys: - - id - formatEN: clean clam record [name] - formatZH: 清空扫描报告 [name] - paramKeys: [] - /toolbox/clam/record/log: - post: - consumes: - - application/json - description: 获取扫描结果详情 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ClamLogReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load clam record detail - tags: - - Clam - /toolbox/clam/record/search: - post: - consumes: - - application/json - description: 获取扫描结果列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ClamLogSearch' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page clam record - tags: - - Clam - /toolbox/clam/search: - post: - consumes: - - application/json - description: 获取扫描规则列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchWithPage' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page clam - tags: - - Clam - /toolbox/clam/status/update: - post: - consumes: - - application/json - description: 修改扫描规则状态 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ClamUpdateStatus' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update clam status - tags: - - Clam - x-panel-log: - BeforeFunctions: - - db: clams - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - - status - formatEN: change the status of clam [name] to [status]. - formatZH: 修改扫描规则 [name] 状态为 [status] - paramKeys: [] - /toolbox/clam/update: - post: - consumes: - - application/json - description: 修改扫描规则 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ClamUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update clam - tags: - - Clam - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - - path - formatEN: update clam [name][path] - formatZH: 修改扫描规则 [name][path] - paramKeys: [] - /toolbox/clean: - post: - consumes: - - application/json - description: 清理系统垃圾文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - items: - $ref: '#/definitions/dto.Clean' - type: array - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Clean system - tags: - - Device - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: Clean system junk files - formatZH: 清理系统垃圾文件 - paramKeys: [] - /toolbox/device/base: - post: - description: 获取设备基础信息 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.DeviceBaseInfo' - security: - - ApiKeyAuth: [] - summary: Load device base info - tags: - - Device - /toolbox/device/check/dns: - post: - consumes: - - application/json - description: 检查系统 DNS 配置可用性 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SettingUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Check device DNS conf - tags: - - Device - /toolbox/device/conf: - post: - consumes: - - application/json - description: 获取系统配置文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.OperationWithName' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: load conf - tags: - - Device - /toolbox/device/update/byconf: - post: - consumes: - - application/json - description: 通过文件修改配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.UpdateByNameAndFile' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update device conf by file - tags: - - Device - /toolbox/device/update/conf: - post: - consumes: - - application/json - description: 修改系统参数 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SettingUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update device - tags: - - Device - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - key - - value - formatEN: update device conf [key] => [value] - formatZH: 修改主机参数 [key] => [value] - paramKeys: [] - /toolbox/device/update/host: - post: - description: 修改系统 hosts - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update device hosts - tags: - - Device - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - key - - value - formatEN: update device host [key] => [value] - formatZH: 修改主机 Host [key] => [value] - paramKeys: [] - /toolbox/device/update/passwd: - post: - consumes: - - application/json - description: 修改系统密码 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.ChangePasswd' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update device passwd - tags: - - Device - /toolbox/device/update/swap: - post: - consumes: - - application/json - description: 修改系统 Swap - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SwapHelper' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update device swap - tags: - - Device - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - operate - - path - formatEN: '[operate] device swap [path]' - formatZH: '[operate] 主机 swap [path]' - paramKeys: [] - /toolbox/device/zone/options: - get: - consumes: - - application/json - description: 获取系统可用时区选项 - responses: - "200": - description: OK - schema: - type: Array - security: - - ApiKeyAuth: [] - summary: list time zone options - tags: - - Device - /toolbox/fail2ban/base: - get: - description: 获取 Fail2ban 基础信息 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.Fail2BanBaseInfo' - security: - - ApiKeyAuth: [] - summary: Load fail2ban base info - tags: - - Fail2ban - /toolbox/fail2ban/load/conf: - get: - consumes: - - application/json - description: 获取 fail2ban 配置文件 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load fail2ban conf - tags: - - Fail2ban - /toolbox/fail2ban/operate: - post: - consumes: - - application/json - description: 修改 Fail2ban 状态 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.Operate' - responses: {} - security: - - ApiKeyAuth: [] - summary: Operate fail2ban - tags: - - Fail2ban - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - operation - formatEN: '[operation] Fail2ban' - formatZH: '[operation] Fail2ban' - paramKeys: [] - /toolbox/fail2ban/operate/sshd: - post: - consumes: - - application/json - description: 配置 sshd - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.Operate' - responses: {} - security: - - ApiKeyAuth: [] - summary: Operate sshd of fail2ban - tags: - - Fail2ban - /toolbox/fail2ban/search: - post: - consumes: - - application/json - description: 获取 Fail2ban ip - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.Fail2BanSearch' - responses: - "200": - description: OK - schema: - type: Array - security: - - ApiKeyAuth: [] - summary: Page fail2ban ip list - tags: - - Fail2ban - /toolbox/fail2ban/update: - post: - consumes: - - application/json - description: 修改 Fail2ban 配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.Fail2BanUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update fail2ban conf - tags: - - Fail2ban - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - key - - value - formatEN: update fail2ban conf [key] => [value] - formatZH: 修改 Fail2ban 配置 [key] => [value] - paramKeys: [] - /toolbox/fail2ban/update/byconf: - post: - consumes: - - application/json - description: 通过文件修改 fail2ban 配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.UpdateByFile' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update fail2ban conf by file - tags: - - Fail2ban - /toolbox/ftp: - post: - consumes: - - application/json - description: 创建 FTP 账户 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.FtpCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create FTP user - tags: - - FTP - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - user - - path - formatEN: create FTP [user][path] - formatZH: 创建 FTP 账户 [user][path] - paramKeys: [] - /toolbox/ftp/base: - get: - description: 获取 FTP 基础信息 - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.FtpBaseInfo' - security: - - ApiKeyAuth: [] - summary: Load FTP base info - tags: - - FTP - /toolbox/ftp/del: - post: - consumes: - - application/json - description: 删除 FTP 账户 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BatchDeleteReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete FTP user - tags: - - FTP - x-panel-log: - BeforeFunctions: - - db: ftps - input_column: id - input_value: ids - isList: true - output_column: user - output_value: users - bodyKeys: - - ids - formatEN: delete FTP users [users] - formatZH: 删除 FTP 账户 [users] - paramKeys: [] - /toolbox/ftp/log/search: - post: - consumes: - - application/json - description: 获取 FTP 操作日志 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.FtpLogSearch' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Load FTP operation log - tags: - - FTP - /toolbox/ftp/operate: - post: - consumes: - - application/json - description: 修改 FTP 状态 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.Operate' - responses: {} - security: - - ApiKeyAuth: [] - summary: Operate FTP - tags: - - FTP - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - operation - formatEN: '[operation] FTP' - formatZH: '[operation] FTP' - paramKeys: [] - /toolbox/ftp/search: - post: - consumes: - - application/json - description: 获取 FTP 账户列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SearchWithPage' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page FTP user - tags: - - FTP - /toolbox/ftp/sync: - post: - consumes: - - application/json - description: 同步 FTP 账户 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BatchDeleteReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Sync FTP user - tags: - - FTP - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: sync FTP users - formatZH: 同步 FTP 账户 - paramKeys: [] - /toolbox/ftp/update: - post: - consumes: - - application/json - description: 修改 FTP 账户 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.FtpUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update FTP user - tags: - - FTP - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - user - - path - formatEN: update FTP [user][path] - formatZH: 修改 FTP 账户 [user][path] - paramKeys: [] - /toolbox/scan: - post: - description: 扫描系统垃圾文件 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Scan system - tags: - - Device - x-panel-log: - BeforeFunctions: [] - bodyKeys: [] - formatEN: scan System Junk Files - formatZH: 扫描系统垃圾文件 - paramKeys: [] - /websites: - post: - consumes: - - application/json - description: 创建网站 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create website - tags: - - Website - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - primaryDomain - formatEN: Create website [primaryDomain] - formatZH: 创建网站 [primaryDomain] - paramKeys: [] - /websites/:id: - get: - consumes: - - application/json - description: 通过 id 查询网站 - parameters: - - description: request - in: path - name: id - required: true - type: integer - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.WebsiteDTO' - security: - - ApiKeyAuth: [] - summary: Search website by id - tags: - - Website - /websites/:id/config/:type: - get: - consumes: - - application/json - description: 通过 id 查询网站 nginx - parameters: - - description: request - in: path - name: id - required: true - type: integer - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.FileInfo' - security: - - ApiKeyAuth: [] - summary: Search website nginx by id - tags: - - Website Nginx - /websites/:id/https: - get: - consumes: - - application/json - description: 获取 https 配置 - parameters: - - description: request - in: path - name: id - required: true - type: integer - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.WebsiteHTTPS' - security: - - ApiKeyAuth: [] - summary: Load https conf - tags: - - Website HTTPS - post: - consumes: - - application/json - description: 更新 https 配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteHTTPSOp' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.WebsiteHTTPS' - security: - - ApiKeyAuth: [] - summary: Update https conf - tags: - - Website HTTPS - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: websiteId - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - websiteId - formatEN: Update website https [domain] conf - formatZH: 更新网站 [domain] https 配置 - paramKeys: [] - /websites/acme: - post: - consumes: - - application/json - description: 创建网站 acme - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteAcmeAccountCreate' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.WebsiteAcmeAccountDTO' - security: - - ApiKeyAuth: [] - summary: Create website acme account - tags: - - Website Acme - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - email - formatEN: Create website acme [email] - formatZH: 创建网站 acme [email] - paramKeys: [] - /websites/acme/del: - post: - consumes: - - application/json - description: 删除网站 acme - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteResourceReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete website acme account - tags: - - Website Acme - x-panel-log: - BeforeFunctions: - - db: website_acme_accounts - input_column: id - input_value: id - isList: false - output_column: email - output_value: email - bodyKeys: - - id - formatEN: Delete website acme [email] - formatZH: 删除网站 acme [email] - paramKeys: [] - /websites/acme/search: - post: - consumes: - - application/json - description: 获取网站 acme 列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PageInfo' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page website acme accounts - tags: - - Website Acme - /websites/auths: - post: - consumes: - - application/json - description: 获取密码访问配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NginxAuthReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get AuthBasic conf - tags: - - Website - /websites/auths/update: - post: - consumes: - - application/json - description: 更新密码访问配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NginxAuthUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get AuthBasic conf - tags: - - Website - /websites/ca: - post: - consumes: - - application/json - description: 创建网站 ca - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteCACreate' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/request.WebsiteCACreate' - security: - - ApiKeyAuth: [] - summary: Create website ca - tags: - - Website CA - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: Create website ca [name] - formatZH: 创建网站 ca [name] - paramKeys: [] - /websites/ca/{id}: - get: - consumes: - - application/json - description: 获取网站 ca - parameters: - - description: id - in: path - name: id - required: true - type: integer - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.WebsiteCADTO' - security: - - ApiKeyAuth: [] - summary: Get website ca - tags: - - Website CA - /websites/ca/del: - post: - consumes: - - application/json - description: 删除网站 ca - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteCommonReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete website ca - tags: - - Website CA - x-panel-log: - BeforeFunctions: - - db: website_cas - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: Delete website ca [name] - formatZH: 删除网站 ca [name] - paramKeys: [] - /websites/ca/download: - post: - consumes: - - application/json - description: 下载 CA 证书文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteResourceReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Download CA file - tags: - - Website CA - x-panel-log: - BeforeFunctions: - - db: website_cas - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: download ca file [name] - formatZH: 下载 CA 证书文件 [name] - paramKeys: [] - /websites/ca/obtain: - post: - consumes: - - application/json - description: 自签 SSL 证书 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteCAObtain' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Obtain SSL - tags: - - Website CA - x-panel-log: - BeforeFunctions: - - db: website_cas - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: Obtain SSL [name] - formatZH: 自签 SSL 证书 [name] - paramKeys: [] - /websites/ca/renew: - post: - consumes: - - application/json - description: 续签 SSL 证书 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteCAObtain' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Obtain SSL - tags: - - Website CA - x-panel-log: - BeforeFunctions: - - db: website_cas - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: Obtain SSL [name] - formatZH: 自签 SSL 证书 [name] - paramKeys: [] - /websites/ca/search: - post: - consumes: - - application/json - description: 获取网站 ca 列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteCASearch' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page website ca - tags: - - Website CA - /websites/check: - post: - consumes: - - application/json - description: 网站创建前检查 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteInstallCheckReq' - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/response.WebsitePreInstallCheck' - type: array - security: - - ApiKeyAuth: [] - summary: Check before create website - tags: - - Website - /websites/config: - post: - consumes: - - application/json - description: 获取 nginx 配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NginxScopeReq' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.WebsiteNginxConfig' - security: - - ApiKeyAuth: [] - summary: Load nginx conf - tags: - - Website Nginx - /websites/config/update: - post: - consumes: - - application/json - description: 更新 nginx 配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NginxConfigUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update nginx conf - tags: - - Website Nginx - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: websiteId - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - websiteId - formatEN: Nginx conf update [domain] - formatZH: nginx 配置修改 [domain] - paramKeys: [] - /websites/default/html/:type: - get: - consumes: - - application/json - description: 获取默认 html - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.FileInfo' - security: - - ApiKeyAuth: [] - summary: Get default html - tags: - - Website - /websites/default/html/update: - post: - consumes: - - application/json - description: 更新默认 html - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteHtmlUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update default html - tags: - - Website - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - type - formatEN: Update default html - formatZH: 更新默认 html - paramKeys: [] - /websites/default/server: - post: - consumes: - - application/json - description: 操作网站日志 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteDefaultUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Change default server - tags: - - Website - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: id - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - id - - operate - formatEN: Change default server => [domain] - formatZH: 修改默认 server => [domain] - paramKeys: [] - /websites/del: - post: - consumes: - - application/json - description: 删除网站 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete website - tags: - - Website - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: id - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - id - formatEN: Delete website [domain] - formatZH: 删除网站 [domain] - paramKeys: [] - /websites/dir: - post: - consumes: - - application/json - description: 获取网站目录配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteCommonReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get website dir - tags: - - Website - /websites/dir/permission: - post: - consumes: - - application/json - description: 更新网站目录权限 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteUpdateDirPermission' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update Site Dir permission - tags: - - Website - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: id - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - id - formatEN: Update domain [domain] dir permission - formatZH: 更新网站 [domain] 目录权限 - paramKeys: [] - /websites/dir/update: - post: - consumes: - - application/json - description: 更新网站目录 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteUpdateDir' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update Site Dir - tags: - - Website - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: id - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - id - formatEN: Update domain [domain] dir - formatZH: 更新网站 [domain] 目录 - paramKeys: [] - /websites/dns: - post: - consumes: - - application/json - description: 创建网站 dns - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteDnsAccountCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create website dns account - tags: - - Website DNS - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: Create website dns [name] - formatZH: 创建网站 dns [name] - paramKeys: [] - /websites/dns/del: - post: - consumes: - - application/json - description: 删除网站 dns - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteResourceReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete website dns account - tags: - - Website DNS - x-panel-log: - BeforeFunctions: - - db: website_dns_accounts - input_column: id - input_value: id - isList: false - output_column: name - output_value: name - bodyKeys: - - id - formatEN: Delete website dns [name] - formatZH: 删除网站 dns [name] - paramKeys: [] - /websites/dns/search: - post: - consumes: - - application/json - description: 获取网站 dns 列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.PageInfo' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page website dns accounts - tags: - - Website DNS - /websites/dns/update: - post: - consumes: - - application/json - description: 更新网站 dns - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteDnsAccountUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update website dns account - tags: - - Website DNS - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - name - formatEN: Update website dns [name] - formatZH: 更新网站 dns [name] - paramKeys: [] - /websites/domains: - post: - consumes: - - application/json - description: 创建网站域名 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteDomainCreate' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/model.WebsiteDomain' - security: - - ApiKeyAuth: [] - summary: Create website domain - tags: - - Website Domain - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - domain - formatEN: Create domain [domain] - formatZH: 创建域名 [domain] - paramKeys: [] - /websites/domains/:websiteId: - get: - consumes: - - application/json - description: 通过网站 id 查询域名 - parameters: - - description: request - in: path - name: websiteId - required: true - type: integer - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/model.WebsiteDomain' - type: array - security: - - ApiKeyAuth: [] - summary: Search website domains by websiteId - tags: - - Website Domain - /websites/domains/del: - post: - consumes: - - application/json - description: 删除网站域名 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteDomainDelete' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete website domain - tags: - - Website Domain - x-panel-log: - BeforeFunctions: - - db: website_domains - input_column: id - input_value: id - isList: false - output_column: domain - output_value: domain - bodyKeys: - - id - formatEN: Delete domain [domain] - formatZH: 删除域名 [domain] - paramKeys: [] - /websites/leech: - post: - consumes: - - application/json - description: 获取防盗链配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NginxCommonReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get AntiLeech conf - tags: - - Website - /websites/leech/update: - post: - consumes: - - application/json - description: 更新防盗链配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NginxAntiLeechUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update AntiLeech - tags: - - Website - /websites/list: - get: - description: 获取网站列表 - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/response.WebsiteDTO' - type: array - security: - - ApiKeyAuth: [] - summary: List websites - tags: - - Website - /websites/log: - post: - consumes: - - application/json - description: 操作网站日志 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteLogReq' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.WebsiteLog' - security: - - ApiKeyAuth: [] - summary: Operate website log - tags: - - Website - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: id - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - id - - operate - formatEN: '[domain][operate] logs' - formatZH: '[domain][operate] 日志' - paramKeys: [] - /websites/nginx/update: - post: - consumes: - - application/json - description: 更新 网站 nginx 配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteNginxUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update website nginx conf - tags: - - Website Nginx - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: id - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - id - formatEN: '[domain] Nginx conf update' - formatZH: '[domain] Nginx 配置修改' - paramKeys: [] - /websites/operate: - post: - consumes: - - application/json - description: 操作网站 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteOp' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Operate website - tags: - - Website - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: id - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - id - - operate - formatEN: '[operate] website [domain]' - formatZH: '[operate] 网站 [domain]' - paramKeys: [] - /websites/options: - get: - description: 获取网站列表 - responses: - "200": - description: OK - schema: - items: - type: string - type: array - security: - - ApiKeyAuth: [] - summary: List website names - tags: - - Website - /websites/php/config: - post: - consumes: - - application/json - description: 更新 网站 PHP 配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsitePHPConfigUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update website php conf - tags: - - Website PHP - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: id - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - id - formatEN: '[domain] PHP conf update' - formatZH: '[domain] PHP 配置修改' - paramKeys: [] - /websites/php/config/:id: - get: - consumes: - - application/json - description: 获取网站 php 配置 - parameters: - - description: request - in: path - name: id - required: true - type: integer - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.PHPConfig' - security: - - ApiKeyAuth: [] - summary: Load website php conf - tags: - - Website - /websites/php/update: - post: - consumes: - - application/json - description: 更新 php 配置文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsitePHPFileUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update php conf - tags: - - Website PHP - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: websiteId - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - websiteId - formatEN: Nginx conf update [domain] - formatZH: php 配置修改 [domain] - paramKeys: [] - /websites/php/version: - post: - consumes: - - application/json - description: 变更 php 版本 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsitePHPVersionReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update php version - tags: - - Website PHP - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: websiteId - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - websiteId - formatEN: php version update [domain] - formatZH: php 版本变更 [domain] - paramKeys: [] - /websites/proxies: - post: - consumes: - - application/json - description: 获取反向代理配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteProxyReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get proxy conf - tags: - - Website - /websites/proxies/update: - post: - consumes: - - application/json - description: 修改反向代理配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteProxyConfig' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update proxy conf - tags: - - Website - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: id - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - id - formatEN: Update domain [domain] proxy config - formatZH: '修改网站 [domain] 反向代理配置 ' - paramKeys: [] - /websites/proxy/file: - post: - consumes: - - application/json - description: 更新反向代理文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NginxProxyUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update proxy file - tags: - - Website - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: websiteID - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - websiteID - formatEN: Nginx conf proxy file update [domain] - formatZH: 更新反向代理文件 [domain] - paramKeys: [] - /websites/redirect: - post: - consumes: - - application/json - description: 获取重定向配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteProxyReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get redirect conf - tags: - - Website - /websites/redirect/file: - post: - consumes: - - application/json - description: 更新重定向文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NginxRedirectUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update redirect file - tags: - - Website - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: websiteID - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - websiteID - formatEN: Nginx conf redirect file update [domain] - formatZH: 更新重定向文件 [domain] - paramKeys: [] - /websites/redirect/update: - post: - consumes: - - application/json - description: 修改重定向配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NginxRedirectReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update redirect conf - tags: - - Website - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: websiteID - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - websiteID - formatEN: Update domain [domain] redirect config - formatZH: '修改网站 [domain] 重定向理配置 ' - paramKeys: [] - /websites/rewrite: - post: - consumes: - - application/json - description: 获取伪静态配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NginxRewriteReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Get rewrite conf - tags: - - Website - /websites/rewrite/update: - post: - consumes: - - application/json - description: 更新伪静态配置 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.NginxRewriteUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update rewrite conf - tags: - - Website - x-panel-log: - BeforeFunctions: - - db: websites - input_column: id - input_value: websiteID - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - websiteID - formatEN: Nginx conf rewrite update [domain] - formatZH: 伪静态配置修改 [domain] - paramKeys: [] - /websites/search: - post: - consumes: - - application/json - description: 获取网站列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteSearch' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/dto.PageResult' - security: - - ApiKeyAuth: [] - summary: Page websites - tags: - - Website - /websites/ssl: - post: - consumes: - - application/json - description: 创建网站 ssl - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteSSLCreate' - responses: - "200": - description: OK - schema: - $ref: '#/definitions/request.WebsiteSSLCreate' - security: - - ApiKeyAuth: [] - summary: Create website ssl - tags: - - Website SSL - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - primaryDomain - formatEN: Create website ssl [primaryDomain] - formatZH: 创建网站 ssl [primaryDomain] - paramKeys: [] - /websites/ssl/:id: - get: - consumes: - - application/json - description: 通过 id 查询 ssl - parameters: - - description: request - in: path - name: id - required: true - type: integer - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Search website ssl by id - tags: - - Website SSL - /websites/ssl/del: - post: - consumes: - - application/json - description: 删除网站 ssl - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteBatchDelReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Delete website ssl - tags: - - Website SSL - x-panel-log: - BeforeFunctions: - - db: website_ssls - input_column: id - input_value: ids - isList: true - output_column: primary_domain - output_value: domain - bodyKeys: - - ids - formatEN: Delete ssl [domain] - formatZH: 删除 ssl [domain] - paramKeys: [] - /websites/ssl/download: - post: - consumes: - - application/json - description: 下载证书文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteResourceReq' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Download SSL file - tags: - - Website SSL - x-panel-log: - BeforeFunctions: - - db: website_ssls - input_column: id - input_value: id - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - id - formatEN: download ssl file [domain] - formatZH: 下载证书文件 [domain] - paramKeys: [] - /websites/ssl/obtain: - post: - consumes: - - application/json - description: 申请证书 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteSSLApply' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Apply ssl - tags: - - Website SSL - x-panel-log: - BeforeFunctions: - - db: website_ssls - input_column: id - input_value: ID - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - ID - formatEN: apply ssl [domain] - formatZH: 申请证书 [domain] - paramKeys: [] - /websites/ssl/resolve: - post: - consumes: - - application/json - description: 解析网站 ssl - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteDNSReq' - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/response.WebsiteDNSRes' - type: array - security: - - ApiKeyAuth: [] - summary: Resolve website ssl - tags: - - Website SSL - /websites/ssl/search: - post: - consumes: - - application/json - description: 获取网站 ssl 列表分页 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteSSLSearch' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Page website ssl - tags: - - Website SSL - /websites/ssl/update: - post: - consumes: - - application/json - description: 更新 ssl - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteSSLUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update ssl - tags: - - Website SSL - x-panel-log: - BeforeFunctions: - - db: website_ssls - input_column: id - input_value: id - isList: false - output_column: primary_domain - output_value: domain - bodyKeys: - - id - formatEN: Update ssl config [domain] - formatZH: 更新证书设置 [domain] - paramKeys: [] - /websites/ssl/upload: - post: - consumes: - - application/json - description: 上传 ssl - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteSSLUpload' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Upload ssl - tags: - - Website SSL - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - type - formatEN: Upload ssl [type] - formatZH: 上传 ssl [type] - paramKeys: [] - /websites/ssl/website/:websiteId: - get: - consumes: - - application/json - description: 通过网站 id 查询 ssl - parameters: - - description: request - in: path - name: websiteId - required: true - type: integer - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Search website ssl by website id - tags: - - Website SSL - /websites/update: - post: - consumes: - - application/json - description: 更新网站 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteUpdate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Update website - tags: - - Website - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - primaryDomain - formatEN: Update website [primaryDomain] - formatZH: 更新网站 [primaryDomain] - paramKeys: [] -swagger: "2.0" diff --git a/core/cmd/server/main.go b/core/cmd/server/main.go deleted file mode 100644 index fbfa86301..000000000 --- a/core/cmd/server/main.go +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "fmt" - "os" - - _ "net/http/pprof" - - "github.com/1Panel-dev/1Panel/core/cmd/server/cmd" - _ "github.com/1Panel-dev/1Panel/core/cmd/server/docs" -) - -// @title 1Panel -// @version 1.0 -// @description 开源Linux面板 -// @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/v1 - -//go:generate swag init -o ./docs -g main.go -d ../../backend -g ../cmd/server/main.go -func main() { - if err := cmd.RootCmd.Execute(); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} diff --git a/core/go.mod b/core/go.mod deleted file mode 100644 index 3ef520d39..000000000 --- a/core/go.mod +++ /dev/null @@ -1,105 +0,0 @@ -module github.com/1Panel-dev/1Panel/core - -go 1.22.4 - -require ( - github.com/dgraph-io/badger/v4 v4.2.0 - github.com/fsnotify/fsnotify v1.7.0 - github.com/gin-contrib/gzip v1.0.1 - github.com/gin-gonic/gin v1.10.0 - github.com/glebarez/sqlite v1.11.0 - github.com/go-gormigrate/gormigrate/v2 v2.1.2 - github.com/go-playground/validator/v10 v10.22.0 - github.com/golang-jwt/jwt/v4 v4.5.0 - github.com/google/uuid v1.6.0 - github.com/jinzhu/copier v0.4.0 - github.com/mojocn/base64Captcha v1.3.6 - github.com/nicksnyder/go-i18n/v2 v2.4.0 - github.com/pkg/errors v0.9.1 - github.com/robfig/cron/v3 v3.0.1 - github.com/sirupsen/logrus v1.9.3 - github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e - github.com/spf13/cobra v1.8.1 - github.com/spf13/viper v1.19.0 - github.com/swaggo/files v1.0.1 - github.com/swaggo/gin-swagger v1.6.0 - github.com/swaggo/swag v1.16.3 - github.com/xlzd/gotp v0.1.0 - golang.org/x/sys v0.22.0 - golang.org/x/term v0.22.0 - golang.org/x/text v0.16.0 - gopkg.in/yaml.v3 v3.0.1 - gorm.io/gorm v1.25.11 -) - -require ( - github.com/KyleBanks/depth v1.2.1 // indirect - github.com/PuerkitoBio/purell v1.1.1 // indirect - github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect - github.com/bytedance/sonic v1.11.6 // indirect - github.com/bytedance/sonic/loader v0.1.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cloudwego/base64x v0.1.4 // indirect - github.com/cloudwego/iasm v0.2.0 // indirect - github.com/dgraph-io/ristretto v0.1.1 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/gin-contrib/sse v0.1.0 // indirect - github.com/glebarez/go-sqlite v1.21.2 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.19.6 // indirect - github.com/go-openapi/spec v0.20.4 // indirect - github.com/go-openapi/swag v0.19.15 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/goccy/go-json v0.10.2 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect - github.com/golang/glog v1.0.0 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/golang/snappy v0.0.3 // indirect - github.com/google/flatbuffers v1.12.1 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.5 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.2 // indirect - github.com/klauspost/cpuid/v2 v2.2.7 // indirect - github.com/leodido/go-urn v1.4.0 // indirect - github.com/magiconair/properties v1.8.7 // indirect - github.com/mailru/easyjson v0.7.6 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.2.2 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - github.com/sagikazarmark/locafero v0.4.0 // indirect - github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.11.0 // indirect - github.com/spf13/cast v1.6.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/subosito/gotenv v1.6.0 // indirect - github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.2.12 // indirect - go.opencensus.io v0.24.0 // indirect - go.uber.org/atomic v1.9.0 // indirect - go.uber.org/multierr v1.9.0 // indirect - golang.org/x/arch v0.8.0 // indirect - golang.org/x/crypto v0.23.0 // indirect - golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/image v0.13.0 // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect - google.golang.org/protobuf v1.34.1 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - modernc.org/libc v1.22.5 // indirect - modernc.org/mathutil v1.5.0 // indirect - modernc.org/memory v1.5.0 // indirect - modernc.org/sqlite v1.23.1 // indirect -) diff --git a/core/go.sum b/core/go.sum deleted file mode 100644 index 81555b5bc..000000000 --- a/core/go.sum +++ /dev/null @@ -1,393 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= -github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= -github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= -github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= -github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= -github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= -github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= -github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= -github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= -github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= -github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/gin-contrib/gzip v1.0.1 h1:HQ8ENHODeLY7a4g1Au/46Z92bdGFl74OhxcZble9WJE= -github.com/gin-contrib/gzip v1.0.1/go.mod h1:njt428fdUNRvjuJf16tZMYZ2Yl+WQB53X5wmhDwXvC4= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= -github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= -github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= -github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= -github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw= -github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ= -github.com/go-gormigrate/gormigrate/v2 v2.1.2 h1:F/d1hpHbRAvKezziV2CC5KUE82cVe9zTgHSBoOOZ4CY= -github.com/go-gormigrate/gormigrate/v2 v2.1.2/go.mod h1:9nHVX6z3FCMCQPA7PThGcA55t22yKQfK/Dnsf5i7hUo= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M= -github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= -github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao= -github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= -github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= -github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= -github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= -github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= -github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= -github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= -github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= -github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= -github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mojocn/base64Captcha v1.3.6 h1:gZEKu1nsKpttuIAQgWHO+4Mhhls8cAKyiV2Ew03H+Tw= -github.com/mojocn/base64Captcha v1.3.6/go.mod h1:i5CtHvm+oMbj1UzEPXaA8IH/xHFZ3DGY3Wh3dBpZ28E= -github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM= -github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= -github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= -github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= -github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= -github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= -github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= -github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= -github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= -github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= -github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= -github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= -github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg= -github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M= -github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo= -github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg= -github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk= -github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= -github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= -github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/xlzd/gotp v0.1.0 h1:37blvlKCh38s+fkem+fFh7sMnceltoIEBYTVXyoa5Po= -github.com/xlzd/gotp v0.1.0/go.mod h1:ndLJ3JKzi3xLmUProq4LLxCuECL93dG9WASNLpHz8qg= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= -golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= -golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg= -golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg= -gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE= -modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY= -modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= -modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= -modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM= -modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk= -nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/core/init/router/router.go b/core/init/router/router.go index bc302f6d1..56ffcd4f7 100644 --- a/core/init/router/router.go +++ b/core/init/router/router.go @@ -4,8 +4,8 @@ import ( "fmt" "net/http" - "github.com/1Panel-dev/1Panel/core/cmd/server/docs" - "github.com/1Panel-dev/1Panel/core/cmd/server/web" + "github.com/1Panel-dev/1Panel/cmd/server/docs" + "github.com/1Panel-dev/1Panel/cmd/server/web" "github.com/1Panel-dev/1Panel/core/global" "github.com/1Panel-dev/1Panel/core/i18n" "github.com/1Panel-dev/1Panel/core/middleware" diff --git a/core/init/viper/viper.go b/core/init/viper/viper.go index 8e38c1ce4..bcce2018d 100644 --- a/core/init/viper/viper.go +++ b/core/init/viper/viper.go @@ -7,7 +7,7 @@ import ( "path" "strings" - "github.com/1Panel-dev/1Panel/core/cmd/server/conf" + "github.com/1Panel-dev/1Panel/cmd/server/conf" "github.com/1Panel-dev/1Panel/core/configs" "github.com/1Panel-dev/1Panel/core/global" "github.com/1Panel-dev/1Panel/core/utils/cmd" diff --git a/core/middleware/operation.go b/core/middleware/operation.go index a357649b1..535b24960 100644 --- a/core/middleware/operation.go +++ b/core/middleware/operation.go @@ -10,9 +10,9 @@ import ( "strings" "time" + "github.com/1Panel-dev/1Panel/cmd/server/docs" "github.com/1Panel-dev/1Panel/core/app/model" "github.com/1Panel-dev/1Panel/core/app/service" - "github.com/1Panel-dev/1Panel/core/cmd/server/docs" "github.com/1Panel-dev/1Panel/core/constant" "github.com/1Panel-dev/1Panel/core/global" "github.com/1Panel-dev/1Panel/core/utils/copier" diff --git a/go.mod b/go.mod index 7d4bd19ad..4c551c158 100644 --- a/go.mod +++ b/go.mod @@ -1,287 +1,105 @@ module github.com/1Panel-dev/1Panel -go 1.22.3 +go 1.22.4 require ( - github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible - github.com/aws/aws-sdk-go v1.50.20 - github.com/compose-spec/compose-go/v2 v2.0.2 - github.com/creack/pty v1.1.21 github.com/dgraph-io/badger/v4 v4.2.0 - github.com/docker/compose/v2 v2.26.1 - github.com/docker/docker v26.0.2+incompatible - github.com/docker/go-connections v0.5.0 github.com/fsnotify/fsnotify v1.7.0 - github.com/gin-contrib/gzip v0.0.6 - github.com/gin-gonic/gin v1.9.1 - github.com/glebarez/sqlite v1.10.0 - github.com/go-acme/lego/v4 v4.17.4 - github.com/go-gormigrate/gormigrate/v2 v2.1.1 - github.com/go-playground/validator/v10 v10.18.0 - github.com/go-redis/redis v6.15.9+incompatible - github.com/go-sql-driver/mysql v1.7.1 - github.com/goh-chunlin/go-onedrive v1.1.1 + github.com/gin-contrib/gzip v1.0.1 + github.com/gin-gonic/gin v1.10.0 + github.com/glebarez/sqlite v1.11.0 + github.com/go-gormigrate/gormigrate/v2 v2.1.2 + github.com/go-playground/validator/v10 v10.22.0 github.com/golang-jwt/jwt/v4 v4.5.0 github.com/google/uuid v1.6.0 - github.com/gorilla/websocket v1.5.1 - github.com/jackc/pgx/v5 v5.5.4 github.com/jinzhu/copier v0.4.0 - github.com/jinzhu/gorm v1.9.16 - github.com/joho/godotenv v1.5.1 - github.com/klauspost/compress v1.17.6 - github.com/mholt/archiver/v4 v4.0.0-alpha.8 - github.com/minio/minio-go/v7 v7.0.67 github.com/mojocn/base64Captcha v1.3.6 github.com/nicksnyder/go-i18n/v2 v2.4.0 - github.com/opencontainers/image-spec v1.1.0 github.com/pkg/errors v0.9.1 - github.com/pkg/sftp v1.13.6 - github.com/qiniu/go-sdk/v7 v7.19.0 github.com/robfig/cron/v3 v3.0.1 - github.com/shirou/gopsutil/v3 v3.24.1 github.com/sirupsen/logrus v1.9.3 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e - github.com/spf13/afero v1.11.0 - github.com/spf13/cobra v1.8.0 - github.com/spf13/viper v1.18.2 - github.com/studio-b12/gowebdav v0.9.0 - github.com/subosito/gotenv v1.6.0 + github.com/spf13/cobra v1.8.1 + github.com/spf13/viper v1.19.0 github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 github.com/swaggo/swag v1.16.3 - github.com/tencentyun/cos-go-sdk-v5 v0.7.46 github.com/xlzd/gotp v0.1.0 - golang.org/x/crypto v0.24.0 - golang.org/x/net v0.26.0 - golang.org/x/oauth2 v0.21.0 - golang.org/x/sys v0.21.0 - golang.org/x/term v0.21.0 + golang.org/x/sys v0.22.0 + golang.org/x/term v0.22.0 golang.org/x/text v0.16.0 - gopkg.in/ini.v1 v1.67.0 gopkg.in/yaml.v3 v3.0.1 - gorm.io/gorm v1.25.7 + gorm.io/gorm v1.25.11 ) require ( - github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect - github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/KyleBanks/depth v1.2.1 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/Microsoft/hcsshim v0.11.4 // indirect - github.com/aliyun/alibaba-cloud-sdk-go v1.62.712 // indirect - github.com/andybalholm/brotli v1.1.0 // indirect - github.com/aws/aws-sdk-go-v2 v1.27.2 // indirect - github.com/aws/aws-sdk-go-v2/config v1.27.18 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.18 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 // indirect - github.com/aws/smithy-go v1.20.2 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/bodgit/plumbing v1.3.0 // indirect - github.com/bodgit/sevenzip v1.5.0 // indirect - github.com/bodgit/windows v1.0.1 // indirect - github.com/bytedance/sonic v1.11.0 // indirect - github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/PuerkitoBio/purell v1.1.1 // indirect + github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect + github.com/bytedance/sonic v1.11.6 // indirect + github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect - github.com/chenzhuoyu/iasm v0.9.1 // indirect - github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28 // indirect - github.com/cloudflare/cloudflare-go v0.97.0 // indirect - github.com/containerd/console v1.0.4 // indirect - github.com/containerd/containerd v1.7.13 // indirect - github.com/containerd/continuity v0.4.3 // indirect - github.com/containerd/log v0.1.0 // indirect - github.com/containerd/ttrpc v1.2.3 // indirect - github.com/containerd/typeurl/v2 v2.1.1 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect - github.com/distribution/reference v0.5.0 // indirect - github.com/docker/buildx v0.13.1 // indirect - github.com/docker/cli v26.0.0+incompatible // indirect - github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker-credential-helpers v0.8.1 // indirect - github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect - github.com/docker/go-metrics v0.0.1 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fvbommel/sortorder v1.1.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/sse v0.1.0 // indirect - github.com/glebarez/go-sqlite v1.22.0 // indirect - github.com/go-jose/go-jose/v4 v4.0.2 // indirect - github.com/go-logr/logr v1.4.1 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/go-openapi/jsonpointer v0.20.2 // indirect - github.com/go-openapi/jsonreference v0.20.4 // indirect - github.com/go-openapi/spec v0.20.14 // indirect - github.com/go-openapi/swag v0.22.9 // indirect + github.com/glebarez/go-sqlite v1.21.2 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.19.6 // indirect + github.com/go-openapi/spec v0.20.4 // indirect + github.com/go-openapi/swag v0.19.15 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/goccy/go-json v0.10.3 // indirect - github.com/gofrs/flock v0.8.1 // indirect - github.com/gogo/googleapis v1.4.1 // indirect + github.com/goccy/go-json v0.10.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect - github.com/golang/glog v1.2.0 // indirect + github.com/golang/glog v1.0.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/google/flatbuffers v23.5.26+incompatible // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/go-querystring v1.1.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/gorilla/mux v1.8.1 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect - github.com/h2non/filetype v1.1.3 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-retryablehttp v0.7.7 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/snappy v0.0.3 // indirect + github.com/google/flatbuffers v1.12.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/imdario/mergo v0.3.16 // indirect - github.com/in-toto/in-toto-golang v0.9.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect - github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/cpuid/v2 v2.2.6 // indirect - github.com/klauspost/pgzip v1.2.6 // indirect - github.com/kr/fs v0.1.0 // indirect + github.com/klauspost/compress v1.17.2 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/leodido/go-urn v1.4.0 // indirect - github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mailru/easyjson v0.7.7 // indirect + github.com/mailru/easyjson v0.7.6 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-shellwords v1.0.12 // indirect - github.com/miekg/dns v1.1.59 // indirect - github.com/miekg/pkcs11 v1.1.1 // indirect - github.com/minio/md5-simd v1.1.2 // indirect - github.com/minio/sha256-simd v1.0.1 // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/moby/buildkit v0.14.1 // indirect - github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/locker v1.0.1 // indirect - github.com/moby/patternmatcher v0.6.0 // indirect - github.com/moby/sys/sequential v0.5.0 // indirect - github.com/moby/sys/signal v0.7.0 // indirect - github.com/moby/sys/user v0.1.0 // indirect - github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/morikuni/aec v1.0.0 // indirect - github.com/mozillazg/go-httpheader v0.4.0 // indirect - github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect - github.com/ncruces/go-strftime v0.1.9 // indirect - github.com/nrdcg/dnspod-go v0.4.0 // indirect - github.com/nrdcg/namesilo v0.2.1 // indirect - github.com/nwaples/rardecode/v2 v2.0.0-beta.2 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect - github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.1.1 // indirect - github.com/pierrec/lz4/v4 v4.1.21 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect - github.com/prometheus/client_golang v1.18.0 // indirect - github.com/prometheus/client_model v0.6.0 // indirect - github.com/prometheus/common v0.47.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - github.com/rs/xid v1.5.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect - github.com/shibumi/go-pathspec v1.3.0 // indirect - github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/testify v1.9.0 // indirect - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.898 // indirect - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.898 // indirect - github.com/therootcompany/xz v1.0.1 // indirect - github.com/theupdateframework/notary v0.7.0 // indirect - github.com/tklauser/go-sysconf v0.3.13 // indirect - github.com/tklauser/numcpus v0.7.0 // indirect - github.com/tonistiigi/fsutil v0.0.0-20240301111122-7525a1af2bb5 // indirect - github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect - github.com/tonistiigi/vt100 v0.0.0-20230623042737-f9a4f7ef6531 // indirect + github.com/subosito/gotenv v1.6.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect - github.com/ulikunitz/xz v0.5.11 // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect - github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect - github.com/xeipuuv/gojsonschema v1.2.0 // indirect - github.com/yusufpapurcu/wmi v1.2.4 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.48.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect - go.opentelemetry.io/otel v1.24.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.1 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.23.1 // indirect - go.opentelemetry.io/otel/metric v1.24.0 // indirect - go.opentelemetry.io/otel/sdk v1.23.1 // indirect - go.opentelemetry.io/otel/trace v1.24.0 // indirect - go.opentelemetry.io/proto/otlp v1.1.0 // indirect - go.uber.org/atomic v1.11.0 // indirect - go.uber.org/multierr v1.11.0 // indirect - go4.org v0.0.0-20230225012048-214862532bf5 // indirect - golang.org/x/arch v0.7.0 // indirect - golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect - golang.org/x/image v0.18.0 // indirect - golang.org/x/mod v0.18.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.22.0 // indirect - google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect - google.golang.org/grpc v1.63.1 // indirect - google.golang.org/protobuf v1.34.2 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/arch v0.8.0 // indirect + golang.org/x/crypto v0.23.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/image v0.13.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect + google.golang.org/protobuf v1.34.1 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/apimachinery v0.29.2 // indirect - k8s.io/apiserver v0.29.2 // indirect - k8s.io/client-go v0.29.2 // indirect - k8s.io/klog/v2 v2.120.1 // indirect - k8s.io/utils v0.0.0-20240102154912-e7106e64919e // indirect - modernc.org/libc v1.41.0 // indirect - modernc.org/mathutil v1.6.0 // indirect - modernc.org/memory v1.7.2 // indirect - modernc.org/sqlite v1.29.1 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect -) - -replace ( - github.com/containerd/containerd => github.com/containerd/containerd v1.7.13 - github.com/cucumber/godog => github.com/cucumber/godog v0.12.6 - github.com/docker/buildx => github.com/docker/buildx v0.12.0-rc2.0.20231219140829-617f538cb315 - github.com/moby/buildkit => github.com/moby/buildkit v0.13.0-beta3 - golang.org/x/net => golang.org/x/net v0.23.0 - k8s.io/api => k8s.io/api v0.29.2 - k8s.io/apimachinery => k8s.io/apimachinery v0.29.2 - k8s.io/client-go => k8s.io/client-go v0.29.2 + modernc.org/libc v1.22.5 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.5.0 // indirect + modernc.org/sqlite v1.23.1 // indirect ) diff --git a/go.sum b/go.sum index beec247c6..81555b5bc 100644 --- a/go.sum +++ b/go.sum @@ -1,755 +1,222 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= -github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= -github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= -github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= -github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= -github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= -github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= -github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.712 h1:lM7JnA9dEdDFH9XOgRNQMDTQnOjlLkDTNA7c0aWTQ30= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.712/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= -github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g= -github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= -github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc= -github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA= -github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= -github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= -github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= -github.com/aws/aws-sdk-go v1.50.20 h1:xfAnSDVf/azIWTVQXQODp89bubvCS85r70O3nuQ4dnE= -github.com/aws/aws-sdk-go v1.50.20/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.27.2 h1:pLsTXqX93rimAOZG2FIYraDQstZaaGVVN4tNw65v0h8= -github.com/aws/aws-sdk-go-v2 v1.27.2/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= -github.com/aws/aws-sdk-go-v2/config v1.27.18 h1:wFvAnwOKKe7QAyIxziwSKjmer9JBMH1vzIL6W+fYuKk= -github.com/aws/aws-sdk-go-v2/config v1.27.18/go.mod h1:0xz6cgdX55+kmppvPm2IaKzIXOheGJhAufacPJaXZ7c= -github.com/aws/aws-sdk-go-v2/credentials v1.17.18 h1:D/ALDWqK4JdY3OFgA2thcPO1c9aYTT5STS/CvnkqY1c= -github.com/aws/aws-sdk-go-v2/credentials v1.17.18/go.mod h1:JuitCWq+F5QGUrmMPsk945rop6bB57jdscu+Glozdnc= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 h1:dDgptDO9dxeFkXy+tEgVkzSClHZje/6JkPW5aZyEvrQ= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5/go.mod h1:gjvE2KBUgUQhcv89jqxrIxH9GaKs1JbZzWejj/DaHGA= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 h1:cy8ahBJuhtM8GTTSyOkfy6WVPV1IE+SS5/wfXUYuulw= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9/go.mod h1:CZBXGLaJnEZI6EVNcPd7a6B5IC5cA/GkRWtu9fp3S6Y= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 h1:A4SYk07ef04+vxZToz9LWvAXl9LW0NClpPpMsi31cz0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9/go.mod h1:5jJcHuwDagxN+ErjQ3PU3ocf6Ylc/p9x+BLO/+X4iXw= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 h1:o4T+fKxA3gTMcluBNZZXE9DNaMkJuUL1O3mffCUjoJo= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11/go.mod h1:84oZdJ+VjuJKs9v1UTC9NaodRZRseOXCTgku+vQJWR8= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 h1:gEYM2GSpr4YNWc6hCd5nod4+d4kd9vWIAWrmGuLdlMw= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.11/go.mod h1:gVvwPdPNYehHSP9Rs7q27U1EU+3Or2ZpXvzAYJNh63w= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 h1:iXjh3uaH3vsVcnyZX7MqCoCfcyxIrVE9iOQruRaWPrQ= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5/go.mod h1:5ZXesEuy/QcO0WUnt+4sDkxhdXRHTu2yG0uCSH8B6os= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 h1:M/1u4HBpwLuMtjlxuI2y6HoVLzF5e2mfxHCg7ZVMYmk= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.12/go.mod h1:kcfd+eTdEi/40FIbLq4Hif3XMXnl5b/+t/KTfLt9xIk= -github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= -github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20150223135152-b965b613227f/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw= -github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bodgit/plumbing v1.3.0 h1:pf9Itz1JOQgn7vEOE7v7nlEfBykYqvUYioC61TwWCFU= -github.com/bodgit/plumbing v1.3.0/go.mod h1:JOTb4XiRu5xfnmdnDJo6GmSbSbtSyufrsyZFByMtKEs= -github.com/bodgit/sevenzip v1.5.0 h1:QESwnPUnhqftOgbi6wIiWm1WEkrT4puHukt5a2psEcw= -github.com/bodgit/sevenzip v1.5.0/go.mod h1:+E74G6pfBX8IMaVybsKMgGTTTBcbHU8ssPTJ9mLUr38= -github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4= -github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM= -github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0 h1:s7+5BfS4WFJoVF9pnB8kBk03S7pZXRdKamnV0FOl5Sc= -github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= -github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= -github.com/bytedance/sonic v1.11.0 h1:FwNNv6Vu4z2Onf1++LNzxB/QhitD8wuTdpZzMTGITWo= -github.com/bytedance/sonic v1.11.0/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= +github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= +github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= -github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= -github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= -github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= -github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= -github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= -github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28 h1:LdXxtjzvZYhhUaonAaAKArG3pyC67kGL3YY+6hGG8G4= -github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e85keuznYcH5rqI438v41pKcBl4ZxQ= -github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= -github.com/cloudflare/cloudflare-go v0.97.0 h1:feZRGiRF1EbljnNIYdt8014FnOLtC3CCvgkLXu915ks= -github.com/cloudflare/cloudflare-go v0.97.0/go.mod h1:JXRwuTfHpe5xFg8xytc2w0XC6LcrFsBVMS4WlVaiGg8= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= -github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= -github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4= -github.com/compose-spec/compose-go/v2 v2.0.2 h1:zhXMV7VWI00Su0LdKt8/sxeXxcjLWhmGmpEyw+ZYznI= -github.com/compose-spec/compose-go/v2 v2.0.2/go.mod h1:bEPizBkIojlQ20pi2vNluBa58tevvj0Y18oUSHPyfdc= -github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= -github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= -github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= -github.com/containerd/containerd v1.7.13 h1:wPYKIeGMN8vaggSKuV1X0wZulpMz4CrgEsZdaCyB6Is= -github.com/containerd/containerd v1.7.13/go.mod h1:zT3up6yTRfEUa6+GsITYIJNgSVL9NQ4x4h1RPzk0Wu4= -github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= -github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= -github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= -github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o= -github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= -github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/containerd/nydus-snapshotter v0.13.1 h1:5XNkCZ9ivLXCcyx3Jbbfh/fntkcls69uBg0x9VE8zlk= -github.com/containerd/nydus-snapshotter v0.13.1/go.mod h1:XWAz9ytsjBuKPVXDKP3xoMlcSKNsGnjXlEup6DuzUIo= -github.com/containerd/stargz-snapshotter v0.14.3 h1:OTUVZoPSPs8mGgmQUE1dqw3WX/3nrsmsurW7UPLWl1U= -github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= -github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= -github.com/containerd/ttrpc v1.2.3 h1:4jlhbXIGvijRtNC8F/5CpuJZ7yKOBFGFOOXg1bkISz0= -github.com/containerd/ttrpc v1.2.3/go.mod h1:ieWsXucbb8Mj9PH0rXCw1i8IunRbbAiDkpXkbfflWBM= -github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4= -github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0= -github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= -github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73 h1:OGNva6WhsKst5OZf7eZOklDztV3hwtTHovdrLHV+MsA= -github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= -github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/buildx v0.12.0-rc2.0.20231219140829-617f538cb315 h1:UZxx9xBADdf/9UmSdEUi+pdJoPKpgcf9QUAY5gEIYmY= -github.com/docker/buildx v0.12.0-rc2.0.20231219140829-617f538cb315/go.mod h1:X8ZHhuW6ncwtoJ36TlU+gyaROTcBkTE01VHYmTStQCE= -github.com/docker/cli v26.0.0+incompatible h1:90BKrx1a1HKYpSnnBFR6AgDq/FqkHxwlUyzJVPxD30I= -github.com/docker/cli v26.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/compose/v2 v2.26.1 h1:27fAR5jVzNUYwY/9ppIjrPqGYLW5HtOTq2aYGBMCtA0= -github.com/docker/compose/v2 v2.26.1/go.mod h1:5iVCMlr18ab0NlMxIPdtTgThTkzb34Z/zj15N7KSW+s= -github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= -github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v26.0.2+incompatible h1:yGVmKUFGgcxA6PXWAokO0sQL22BrQ67cgVjko8tGdXE= -github.com/docker/docker v26.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo= -github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= -github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= -github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= -github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= -github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= -github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= -github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY= -github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= -github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= -github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= -github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= -github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= -github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= -github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= +github.com/gin-contrib/gzip v1.0.1 h1:HQ8ENHODeLY7a4g1Au/46Z92bdGFl74OhxcZble9WJE= +github.com/gin-contrib/gzip v1.0.1/go.mod h1:njt428fdUNRvjuJf16tZMYZ2Yl+WQB53X5wmhDwXvC4= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= -github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= -github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= -github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ= -github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc= -github.com/glebarez/sqlite v1.10.0 h1:u4gt8y7OND/cCei/NMHmfbLxF6xP2wgKcT/BJf2pYkc= -github.com/glebarez/sqlite v1.10.0/go.mod h1:IJ+lfSOmiekhQsFTJRx/lHtGYmCdtAiTaf5wI9u5uHA= -github.com/go-acme/lego/v4 v4.17.4 h1:h0nePd3ObP6o7kAkndtpTzCw8shOZuWckNYeUQwo36Q= -github.com/go-acme/lego/v4 v4.17.4/go.mod h1:dU94SvPNqimEeb7EVilGGSnS0nU1O5Exir0pQ4QFL4U= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gormigrate/gormigrate/v2 v2.1.1 h1:eGS0WTFRV30r103lU8JNXY27KbviRnqqIDobW3EV3iY= -github.com/go-gormigrate/gormigrate/v2 v2.1.1/go.mod h1:L7nJ620PFDKei9QOhJzqA8kRCk+E3UbV2f5gv+1ndLc= -github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk= -github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= -github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= -github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= -github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= -github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do= -github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw= -github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE= -github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= +github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= +github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw= +github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ= +github.com/go-gormigrate/gormigrate/v2 v2.1.2 h1:F/d1hpHbRAvKezziV2CC5KUE82cVe9zTgHSBoOOZ4CY= +github.com/go-gormigrate/gormigrate/v2 v2.1.2/go.mod h1:9nHVX6z3FCMCQPA7PThGcA55t22yKQfK/Dnsf5i7hUo= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs= +github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= +github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M= +github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.8.0/go.mod h1:9JhgTzTaE31GZDpH/HSvHiRJrJ3iKAgqqH0Bl/Ocjdk= -github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= -github.com/go-playground/validator/v10 v10.18.0 h1:BvolUXjp4zuvkZ5YN5t7ebzbhlUtPsPm2S9NAZ5nl9U= -github.com/go-playground/validator/v10 v10.18.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= -github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= -github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= -github.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= -github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= -github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= -github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= -github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao= +github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/goh-chunlin/go-onedrive v1.1.1 h1:HGtHk5iG0MZ92zYUtaY04czfZPBIJUr12UuFc+PW8m4= -github.com/goh-chunlin/go-onedrive v1.1.1/go.mod h1:N8qIGHD7tryO734epiBKk5oXcpGwxKET/u3LuBHciTs= -github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= -github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= -github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93 h1:jc2UWq7CbdszqeH6qu1ougXMIUBfSy8Pbh/anURYbGI= -github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= -github.com/google/flatbuffers v23.5.26+incompatible h1:M9dgRyhJemaM4Sw8+66GHBu8ioaQmyPLg1b8VwK5WJg= -github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= +github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= -github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= -github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= -github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= -github.com/h2non/filetype v1.1.1/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= -github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= -github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= -github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= -github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= -github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= -github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/in-toto/in-toto-golang v0.9.0 h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ9EBM1XU= -github.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3lUTQd+eF9HdeMo= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= -github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= -github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8= -github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= -github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= -github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= -github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo= -github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o= -github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs= -github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= -github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= -github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= -github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= +github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= -github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= -github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4= -github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed h1:036IscGBfJsFIgJQzlui7nK1Ncm0tp2ktmPj8xO4N/0= -github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= -github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= -github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= -github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= -github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= -github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mholt/archiver/v4 v4.0.0-alpha.8 h1:tRGQuDVPh66WCOelqe6LIGh0gwmfwxUrSSDunscGsRM= -github.com/mholt/archiver/v4 v4.0.0-alpha.8/go.mod h1:5f7FUYGXdJWUjESffJaYR4R60VhnHxb2X3T1teMyv5A= -github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs= -github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk= -github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= -github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= -github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.67 h1:BeBvZWAS+kRJm1vGTMJYVjKUNoo0FoEt/wUWdUtfmh8= -github.com/minio/minio-go/v7 v7.0.67/go.mod h1:+UXocnUeZ3wHvVh5s95gcrA4YjMIbccT6ubB+1m054A= -github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= -github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/moby/buildkit v0.13.0-beta3 h1:eefOGE6SsWYHFfymc09Q7VU5i3L9vUs8ZCZVCDXWNOo= -github.com/moby/buildkit v0.13.0-beta3/go.mod h1:tSWWhq1EDM0eB3ngMNDiH2hOOW9fXTyn2uXuOraCLlE= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= -github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= -github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= -github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= -github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= -github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= -github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= -github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= -github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI= -github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= -github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= -github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mojocn/base64Captcha v1.3.6 h1:gZEKu1nsKpttuIAQgWHO+4Mhhls8cAKyiV2Ew03H+Tw= github.com/mojocn/base64Captcha v1.3.6/go.mod h1:i5CtHvm+oMbj1UzEPXaA8IH/xHFZ3DGY3Wh3dBpZ28E= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60= -github.com/mozillazg/go-httpheader v0.4.0 h1:aBn6aRXtFzyDLZ4VIRLsZbbJloagQfMnCiYgOq6hK4w= -github.com/mozillazg/go-httpheader v0.4.0/go.mod h1:PuT8h0pw6efvp8ZeUec1Rs7dwjK08bt6gKSReGMqtdA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 h1:o6uBwrhM5C8Ll3MAAxrQxRHEu7FkapwTuI2WmL1rw4g= -github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8= -github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= -github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM= github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nrdcg/dnspod-go v0.4.0 h1:c/jn1mLZNKF3/osJ6mz3QPxTudvPArXTjpkmYj0uK6U= -github.com/nrdcg/dnspod-go v0.4.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgPTGKr6KQ= -github.com/nrdcg/namesilo v0.2.1 h1:kLjCjsufdW/IlC+iSfAqj0iQGgKjlbUUeDJio5Y6eMg= -github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw= -github.com/nwaples/rardecode/v2 v2.0.0-beta.2 h1:e3mzJFJs4k83GXBEiTaQ5HgSc/kOK8q0rDaRO0MPaOk= -github.com/nwaples/rardecode/v2 v2.0.0-beta.2/go.mod h1:yntwv/HfMc/Hbvtq9I19D1n58te3h6KsqCf3GxyfBGY= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= -github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= -github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= -github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= -github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= -github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= -github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg= -github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= -github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= -github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= -github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= -github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= -github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= -github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo= -github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= -github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= -github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= -github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= -github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= -github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.47.0 h1:p5Cz0FNHo7SnWOmWmoRozVcjEp0bIVU8cV7OShpjL1k= -github.com/prometheus/common v0.47.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= -github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/qiniu/dyn v1.3.0/go.mod h1:E8oERcm8TtwJiZvkQPbcAh0RL8jO1G0VXJMW3FAWdkk= -github.com/qiniu/go-sdk/v7 v7.19.0 h1:k3AzDPil8QHIQnki6xXt4YRAjE52oRoBUXQ4bV+Wc5U= -github.com/qiniu/go-sdk/v7 v7.19.0/go.mod h1:nqoYCNo53ZlGA521RvRethvxUDvXKt4gtYXOwye868w= -github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= -github.com/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbmfHkLguCE9laoZCUzEEpIZXA= -github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU= -github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI= -github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE= -github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI= -github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU= -github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= -github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= -github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= -github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= -github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spdx/tools-golang v0.5.1 h1:fJg3SVOGG+eIva9ZUBm/hvyA7PIPVFjRxUKe6fdAgwE= -github.com/spdx/tools-golang v0.5.1/go.mod h1:/DRDQuBfB37HctM29YtrX1v+bXiVmT2OpQDalRmX9aU= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= -github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= -github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= -github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -758,8 +225,6 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/studio-b12/gowebdav v0.9.0 h1:1j1sc9gQnNxbXXM4M/CebPOX4aXYtr7MojAVcN4dHjU= -github.com/studio-b12/gowebdav v0.9.0/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= @@ -768,388 +233,124 @@ github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+z github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo= github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg= github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.563/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.898 h1:ERwcXqhc94L9cFxtiI0pvt7IJtlHl/p/Jayl3mLw+ms= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.898/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.898 h1:LoYv5u+gUoFpU/AmIuTRG/2KiEkdm9gCC0dTvk8WITQ= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.898/go.mod h1:c1j6YQ+vCbeA8kJ59Im4UnMd1GxovlpPBDhGZoewfn8= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.563/go.mod h1:uom4Nvi9W+Qkom0exYiJ9VWJjXwyxtPYTkKkaLMlfE0= -github.com/tencentyun/cos-go-sdk-v5 v0.7.46 h1:IeTiMR8qZ7iQWhAGb1niw5vt0T1TfAwPeB8Gn/oTkuk= -github.com/tencentyun/cos-go-sdk-v5 v0.7.46/go.mod h1:DH9US8nB+AJXqwu/AMOrCFN1COv3dpytXuJWHgdg7kE= -github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw= -github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY= -github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c= -github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= -github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4= -github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4= -github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY= -github.com/tonistiigi/fsutil v0.0.0-20240301111122-7525a1af2bb5 h1:oZS8KCqAg62sxJkEq/Ppzqrb6EooqzWtL8Oaex7bc5c= -github.com/tonistiigi/fsutil v0.0.0-20240301111122-7525a1af2bb5/go.mod h1:vbbYqJlnswsbJqWUcJN8fKtBhnEgldDrcagTgnBVKKM= -github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0= -github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk= -github.com/tonistiigi/vt100 v0.0.0-20230623042737-f9a4f7ef6531 h1:Y/M5lygoNPKwVNLMPXgVfsRT40CSFKXCxuU8LoHySjs= -github.com/tonistiigi/vt100 v0.0.0-20230623042737-f9a4f7ef6531/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= -github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= -github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= -github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= -github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= -github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xlzd/gotp v0.1.0 h1:37blvlKCh38s+fkem+fFh7sMnceltoIEBYTVXyoa5Po= github.com/xlzd/gotp v0.1.0/go.mod h1:ndLJ3JKzi3xLmUProq4LLxCuECL93dG9WASNLpHz8qg= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= -github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 h1:P+/g8GpuJGYbOp2tAdKrIPUX9JO02q8Q0YNlHolpibA= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.48.0 h1:ZeW4++xt1VrFSdnd0pFXz0PkrjLb89/VPOUOyPDJG/g= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.48.0/go.mod h1:ZdzuQW6m/OEtOLWWJs+k5ddZXsUq9xs2vx+ZT9G9eJ0= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.1 h1:o8iWeVFa1BcLtVEV0LzrCxV2/55tB3xLxADr6Kyoey4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.1/go.mod h1:SEVfdK4IoBnbT2FXNM/k8yC08MrfbhWk3U4ljM8B3HE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.23.1 h1:cfuy3bXmLJS7M1RZmAL6SuhGtKUp2KEsrm00OlAXkq4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.23.1/go.mod h1:22jr92C6KwlwItJmQzfixzQM3oyyuYLCfHiMY+rpsPU= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/sdk v1.23.1 h1:O7JmZw0h76if63LQdsBMKQDWNb5oEcOThG9IrxscV+E= -go.opentelemetry.io/otel/sdk v1.23.1/go.mod h1:LzdEVR5am1uKOOwfBWFef2DCi1nu3SA8XQxx2IerWFk= -go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= -go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= -go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc= -go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= -golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= -golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg= golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk= -golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= -golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 h1:rIo7ocm2roD9DcFIX67Ym8icoGCKSARAiPljFhh5suQ= -google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.63.1 h1:pNClQmvdlyNUiwFETOux/PYqfhmA7BrswEdGRnib1fA= -google.golang.org/grpc v1.63.1/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1158,88 +359,35 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII= -gopkg.in/cenkalti/backoff.v2 v2.2.1/go.mod h1:S0QdOvT2AlerfSBkp0O+dk+bbIMaNbEmVk876gPCthU= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1 h1:d4KQkxAaAiRY2h5Zqis161Pv91A37uZyJOx73duwUwM= -gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1/go.mod h1:WbjuEoo1oadwzQ4apSDU+JTvmllEHtsNHS6y7vFc7iw= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/gorm v1.25.7 h1:VsD6acwRjz2zFxGO50gPO6AkNs7KKnvfzUjHQhZDz/A= -gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= -gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= -gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg= +gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A= -k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0= -k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8= -k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= -k8s.io/apiserver v0.29.2 h1:+Z9S0dSNr+CjnVXQePG8TcBWHr3Q7BmAr7NraHvsMiQ= -k8s.io/apiserver v0.29.2/go.mod h1:B0LieKVoyU7ykQvPFm7XSdIHaCHSzCzQWPFa5bqbeMQ= -k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg= -k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA= -k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= -k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= -k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ= -k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk= -modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY= -modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= -modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= -modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= -modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= -modernc.org/sqlite v1.29.1 h1:19GY2qvWB4VPw0HppFlZCPAbmxFU41r+qjKZQdQ1ryA= -modernc.org/sqlite v1.29.1/go.mod h1:hG41jCYxOAOoO6BRK66AdRlmOcDzXf7qnwlwjUIOqa0= +modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE= +modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= +modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM= +modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=