diff --git a/agent/app/api/v2/agents.go b/agent/app/api/v2/agents.go index 44d69b200..efed902cf 100644 --- a/agent/app/api/v2/agents.go +++ b/agent/app/api/v2/agents.go @@ -124,7 +124,7 @@ func (b *BaseApi) PageAgents(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } - total, list, err := agentService.Page(req) + total, list, err := agentService.Page(req, helper.IsDemoRequest(c)) if err != nil { helper.BadRequest(c, err) return @@ -447,7 +447,7 @@ func (b *BaseApi) PageAgentAccounts(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } - total, list, err := agentService.PageAccounts(req) + total, list, err := agentService.PageAccounts(req, helper.IsDemoRequest(c)) if err != nil { helper.BadRequest(c, err) return diff --git a/agent/app/api/v2/alert.go b/agent/app/api/v2/alert.go index 90c4480be..109bce509 100644 --- a/agent/app/api/v2/alert.go +++ b/agent/app/api/v2/alert.go @@ -268,7 +268,7 @@ func (b *BaseApi) PageAlertConfig(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } - total, configs, err := alertService.PageAlertConfig(req) + total, configs, err := alertService.PageAlertConfig(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/app.go b/agent/app/api/v2/app.go index cc2aa54fc..b090c6840 100644 --- a/agent/app/api/v2/app.go +++ b/agent/app/api/v2/app.go @@ -120,7 +120,7 @@ func (b *BaseApi) GetAppDetail(c *gin.Context) { } version := c.Param("version") appType := c.Param("type") - appDetailDTO, err := appService.GetAppDetail(appID, version, appType) + appDetailDTO, err := appService.GetAppDetail(appID, version, appType, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/app_ignore_upgrade.go b/agent/app/api/v2/app_ignore_upgrade.go index 48073a401..e377fc794 100644 --- a/agent/app/api/v2/app_ignore_upgrade.go +++ b/agent/app/api/v2/app_ignore_upgrade.go @@ -14,7 +14,7 @@ import ( // @Security Timestamp // @Router /apps/ignored/detail [get] func (b *BaseApi) ListAppIgnored(c *gin.Context) { - res, err := appIgnoreUpgradeService.List() + res, err := appIgnoreUpgradeService.List(helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/app_install.go b/agent/app/api/v2/app_install.go index 1ced903ce..ccec6cc00 100644 --- a/agent/app/api/v2/app_install.go +++ b/agent/app/api/v2/app_install.go @@ -21,6 +21,7 @@ func (b *BaseApi) SearchAppInstalled(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } + req.ReadOnly = helper.IsDemoRequest(c) if req.All { list, err := appInstallService.SearchForWebsite(req) if err != nil { @@ -73,6 +74,7 @@ func (b *BaseApi) CheckAppInstalled(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } + req.ReadOnly = helper.IsDemoRequest(c) checkData, err := appInstallService.CheckExist(req) if err != nil { helper.InternalServer(c, err) @@ -115,7 +117,7 @@ func (b *BaseApi) LoadConnInfo(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } - conn, err := appInstallService.LoadConnInfo(req) + conn, err := appInstallService.LoadConnInfo(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return @@ -137,7 +139,7 @@ func (b *BaseApi) DeleteCheck(c *gin.Context) { helper.BadRequest(c, err) return } - checkData, err := appInstallService.DeleteCheck(appInstallId) + checkData, err := appInstallService.DeleteCheck(appInstallId, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return @@ -277,7 +279,7 @@ func (b *BaseApi) GetParams(c *gin.Context) { helper.BadRequest(c, err) return } - content, err := appInstallService.GetParams(appInstallId) + content, err := appInstallService.GetParams(appInstallId, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return @@ -341,7 +343,7 @@ func (b *BaseApi) GetAppInstallInfo(c *gin.Context) { helper.BadRequest(c, err) return } - info, err := appInstallService.GetAppInstallInfo(appInstallId) + info, err := appInstallService.GetAppInstallInfo(appInstallId, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/backup.go b/agent/app/api/v2/backup.go index 4cb19e9f1..17fb7ee24 100644 --- a/agent/app/api/v2/backup.go +++ b/agent/app/api/v2/backup.go @@ -209,7 +209,7 @@ func (b *BaseApi) SearchBackup(c *gin.Context) { return } - total, list, err := backupService.SearchWithPage(req) + total, list, err := backupService.SearchWithPage(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/clam.go b/agent/app/api/v2/clam.go index 00144ea22..912a3c1f7 100644 --- a/agent/app/api/v2/clam.go +++ b/agent/app/api/v2/clam.go @@ -106,7 +106,7 @@ func (b *BaseApi) SearchClam(c *gin.Context) { // @Security Timestamp // @Router /toolbox/clam/base [post] func (b *BaseApi) LoadClamBaseInfo(c *gin.Context) { - info, err := clamService.LoadBaseInfo() + info, err := clamService.LoadBaseInfo(helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/compose_template.go b/agent/app/api/v2/compose_template.go index c19ff805a..08be28eb4 100644 --- a/agent/app/api/v2/compose_template.go +++ b/agent/app/api/v2/compose_template.go @@ -65,7 +65,7 @@ func (b *BaseApi) SearchComposeTemplate(c *gin.Context) { return } - total, list, err := composeTemplateService.SearchWithPage(req) + total, list, err := composeTemplateService.SearchWithPage(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return @@ -85,7 +85,7 @@ func (b *BaseApi) SearchComposeTemplate(c *gin.Context) { // @Security Timestamp // @Router /containers/template [get] func (b *BaseApi) ListComposeTemplate(c *gin.Context) { - list, err := composeTemplateService.List() + list, err := composeTemplateService.List(helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/container.go b/agent/app/api/v2/container.go index f24e84338..e1f3ce529 100644 --- a/agent/app/api/v2/container.go +++ b/agent/app/api/v2/container.go @@ -273,7 +273,7 @@ func (b *BaseApi) SearchCompose(c *gin.Context) { return } - total, list, err := containerService.PageCompose(req) + total, list, err := containerService.PageCompose(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return @@ -387,7 +387,7 @@ func (b *BaseApi) ContainerInfo(c *gin.Context) { return } - data, err := containerService.ContainerInfo(req) + data, err := containerService.ContainerInfo(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/cronjob.go b/agent/app/api/v2/cronjob.go index 8d02a6b0e..ebba75c0d 100644 --- a/agent/app/api/v2/cronjob.go +++ b/agent/app/api/v2/cronjob.go @@ -144,7 +144,7 @@ func (b *BaseApi) SearchCronjob(c *gin.Context) { return } - total, list, err := cronjobService.SearchWithPage(req) + total, list, err := cronjobService.SearchWithPage(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/database.go b/agent/app/api/v2/database.go index 6e16478c8..3447c337d 100644 --- a/agent/app/api/v2/database.go +++ b/agent/app/api/v2/database.go @@ -78,7 +78,7 @@ func (b *BaseApi) SearchDatabase(c *gin.Context) { return } - total, list, err := databaseService.SearchWithPage(req) + total, list, err := databaseService.SearchWithPage(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return @@ -147,7 +147,7 @@ func (b *BaseApi) GetDatabase(c *gin.Context) { helper.BadRequest(c, err) return } - data, err := databaseService.Get(name) + data, err := databaseService.Get(name, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/database_mongodb.go b/agent/app/api/v2/database_mongodb.go index 2d00c2adb..0749d0c6f 100644 --- a/agent/app/api/v2/database_mongodb.go +++ b/agent/app/api/v2/database_mongodb.go @@ -54,7 +54,7 @@ func (b *BaseApi) SearchMongodb(c *gin.Context) { return } - total, list, err := mongodbService.SearchWithPage(req) + total, list, err := mongodbService.SearchWithPage(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/database_mysql.go b/agent/app/api/v2/database_mysql.go index f467deee2..3f4b3a75f 100644 --- a/agent/app/api/v2/database_mysql.go +++ b/agent/app/api/v2/database_mysql.go @@ -53,7 +53,7 @@ func (b *BaseApi) ListMysqlUsers(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } - data, err := mysqlService.ListUsers(req) + data, err := mysqlService.ListUsers(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/database_postgresql.go b/agent/app/api/v2/database_postgresql.go index e92e44868..a9e28dca9 100644 --- a/agent/app/api/v2/database_postgresql.go +++ b/agent/app/api/v2/database_postgresql.go @@ -151,7 +151,7 @@ func (b *BaseApi) SearchPostgresql(c *gin.Context) { return } - total, list, err := postgresqlService.SearchWithPage(req) + total, list, err := postgresqlService.SearchWithPage(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/file.go b/agent/app/api/v2/file.go index 4b592850a..730403df2 100644 --- a/agent/app/api/v2/file.go +++ b/agent/app/api/v2/file.go @@ -148,7 +148,7 @@ func (b *BaseApi) FileAISearch(c *gin.Context) { if strings.TrimSpace(req.ResponseLanguage) == "" { req.ResponseLanguage = strings.TrimSpace(c.GetHeader("Accept-Language")) } - res, err := fileService.AISearch(req) + res, err := fileService.AISearch(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return @@ -1633,7 +1633,7 @@ func (b *BaseApi) SearchFileShare(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } - total, list, err := fileShareService.Page(req) + total, list, err := fileShareService.Page(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return @@ -1657,7 +1657,7 @@ func (b *BaseApi) GetFileShareDetail(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } - info, err := fileShareService.GetByPath(req.Path) + info, err := fileShareService.GetByPath(req.Path, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return @@ -1676,7 +1676,7 @@ func (b *BaseApi) GetPublicFileShareInfo(c *gin.Context) { helper.BadRequest(c, errors.New("code is required")) return } - info, err := fileShareService.GetPublicByCode(code) + info, err := fileShareService.GetPublicByCode(code, helper.IsDemoRequest(c)) if err != nil { if be, ok := err.(buserr.BusinessError); ok { helper.ErrorWithDetail(c, http.StatusBadRequest, be.Msg, be) @@ -1729,7 +1729,7 @@ func (b *BaseApi) GetFileShareQRCode(c *gin.Context) { helper.BadRequest(c, errors.New("code is required")) return } - if _, err := fileShareService.GetByCode(code); err != nil { + if _, err := fileShareService.GetByCode(code, helper.IsDemoRequest(c)); err != nil { if be, ok := err.(buserr.BusinessError); ok { helper.ErrorWithDetail(c, http.StatusBadRequest, be.Msg, be) return @@ -1811,7 +1811,7 @@ func (b *BaseApi) CheckFileShare(c *gin.Context) { helper.BadRequest(c, errors.New("code is required")) return } - if err := fileShareService.Check(code, password); err != nil { + if err := fileShareService.Check(code, password, helper.IsDemoRequest(c)); err != nil { if be, ok := err.(buserr.BusinessError); ok { helper.ErrorWithDetail(c, http.StatusBadRequest, be.Msg, be) return @@ -1836,7 +1836,7 @@ func (b *BaseApi) DownloadFileShare(c *gin.Context) { helper.BadRequest(c, errors.New("code is required")) return } - filePath, displayName, err := fileShareService.PrepareDownload(code, password) + filePath, displayName, err := fileShareService.PrepareDownload(code, password, helper.IsDemoRequest(c)) if err != nil { if be, ok := err.(buserr.BusinessError); ok { helper.ErrorWithDetail(c, http.StatusBadRequest, be.Msg, be) diff --git a/agent/app/api/v2/ftp.go b/agent/app/api/v2/ftp.go index a8e83cf80..d8806927e 100644 --- a/agent/app/api/v2/ftp.go +++ b/agent/app/api/v2/ftp.go @@ -87,7 +87,7 @@ func (b *BaseApi) SearchFtp(c *gin.Context) { return } - total, list, err := ftpService.SearchWithPage(req) + total, list, err := ftpService.SearchWithPage(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/helper/helper.go b/agent/app/api/v2/helper/helper.go index b36ff3f1b..8301a46e2 100644 --- a/agent/app/api/v2/helper/helper.go +++ b/agent/app/api/v2/helper/helper.go @@ -48,6 +48,10 @@ func BadRequest(ctx *gin.Context, err error) { ErrorWithDetail(ctx, http.StatusBadRequest, "ErrInvalidParams", err) } +func IsDemoRequest(ctx *gin.Context) bool { + return global.CONF.Base.IsDemo || ctx.GetHeader(constant.DemoModeHeader) == strconv.FormatBool(true) +} + func SuccessWithData(ctx *gin.Context, data interface{}) { if data == nil { data = gin.H{} diff --git a/agent/app/api/v2/host.go b/agent/app/api/v2/host.go index 0ec247f9f..972117b9e 100644 --- a/agent/app/api/v2/host.go +++ b/agent/app/api/v2/host.go @@ -100,7 +100,7 @@ func (b *BaseApi) SearchHost(c *gin.Context) { return } - total, list, err := hostService.SearchWithPage(req) + total, list, err := hostService.SearchWithPage(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/image_repo.go b/agent/app/api/v2/image_repo.go index a8f3df23c..7e9f9d693 100644 --- a/agent/app/api/v2/image_repo.go +++ b/agent/app/api/v2/image_repo.go @@ -21,7 +21,7 @@ func (b *BaseApi) SearchRepo(c *gin.Context) { return } - total, list, err := imageRepoService.Page(req) + total, list, err := imageRepoService.Page(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/mcp_server.go b/agent/app/api/v2/mcp_server.go index f1ecbdbcd..864789ac7 100644 --- a/agent/app/api/v2/mcp_server.go +++ b/agent/app/api/v2/mcp_server.go @@ -19,7 +19,7 @@ func (b *BaseApi) PageMcpServers(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } - list := mcpServerService.Page(req) + list := mcpServerService.Page(req, helper.IsDemoRequest(c)) helper.SuccessWithData(c, list) } diff --git a/agent/app/api/v2/runtime.go b/agent/app/api/v2/runtime.go index fbe22a9e4..794de5584 100644 --- a/agent/app/api/v2/runtime.go +++ b/agent/app/api/v2/runtime.go @@ -20,6 +20,7 @@ func (b *BaseApi) SearchRuntimes(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } + req.ReadOnly = helper.IsDemoRequest(c) total, items, err := runtimeService.Page(req) if err != nil { helper.InternalServer(c, err) @@ -132,7 +133,7 @@ func (b *BaseApi) GetRuntime(c *gin.Context) { helper.BadRequest(c, err) return } - res, err := runtimeService.Get(id) + res, err := runtimeService.Get(id, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return @@ -529,7 +530,7 @@ func (b *BaseApi) GetPHPContainerConfig(c *gin.Context) { helper.BadRequest(c, err) return } - data, err := runtimeService.GetPHPContainerConfig(id) + data, err := runtimeService.GetPHPContainerConfig(id, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/setting.go b/agent/app/api/v2/setting.go index c6343e228..c80b293d6 100644 --- a/agent/app/api/v2/setting.go +++ b/agent/app/api/v2/setting.go @@ -191,7 +191,7 @@ func (b *BaseApi) LoadBaseDir(c *gin.Context) { // @Security Timestamp // @Router /settings/ssh/conn [get] func (b *BaseApi) LoadLocalConn(c *gin.Context) { - helper.SuccessWithData(c, settingService.GetLocalConn()) + helper.SuccessWithData(c, settingService.GetLocalConn(helper.IsDemoRequest(c))) } // @Tags System Setting diff --git a/agent/app/api/v2/ssh.go b/agent/app/api/v2/ssh.go index 6dbd1011a..ee17d6b47 100644 --- a/agent/app/api/v2/ssh.go +++ b/agent/app/api/v2/ssh.go @@ -144,7 +144,7 @@ func (b *BaseApi) SearchRootCert(c *gin.Context) { return } - total, data, err := sshService.SearchRootCerts(req) + total, data, err := sshService.SearchRootCerts(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/tensorrt_llm.go b/agent/app/api/v2/tensorrt_llm.go index e28fd4f8d..3d65a7285 100644 --- a/agent/app/api/v2/tensorrt_llm.go +++ b/agent/app/api/v2/tensorrt_llm.go @@ -19,7 +19,7 @@ func (b *BaseApi) PageTensorRTLLMs(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } - list := tensorrtLLMService.Page(req) + list := tensorrtLLMService.Page(req, helper.IsDemoRequest(c)) helper.SuccessWithData(c, list) } diff --git a/agent/app/api/v2/terminal.go b/agent/app/api/v2/terminal.go index 0260cb1f1..df2d343ad 100644 --- a/agent/app/api/v2/terminal.go +++ b/agent/app/api/v2/terminal.go @@ -98,7 +98,7 @@ func prepareTerminalSession(c *gin.Context) (*websocket.Conn, int, int, bool) { return nil, 0, 0, false } - if global.CONF.Base.IsDemo { + if helper.IsDemoRequest(c) { if wshandleError(wsConn, errors.New(" demo server, prohibit this operation!")) { return nil, 0, 0, false } diff --git a/agent/app/api/v2/website.go b/agent/app/api/v2/website.go index e9c8dd4ae..652fa6cec 100644 --- a/agent/app/api/v2/website.go +++ b/agent/app/api/v2/website.go @@ -255,7 +255,7 @@ func (b *BaseApi) GetHTTPSConfig(c *gin.Context) { helper.BadRequest(c, err) return } - res, err := websiteService.GetWebsiteHTTPS(id) + res, err := websiteService.GetWebsiteHTTPS(id, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return @@ -1080,7 +1080,7 @@ func (b *BaseApi) GetWebsiteResource(c *gin.Context) { helper.BadRequest(c, err) return } - res, err := websiteService.GetWebsiteResource(id) + res, err := websiteService.GetWebsiteResource(id, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/website_acme_account.go b/agent/app/api/v2/website_acme_account.go index 79fa4deaf..9852d873d 100644 --- a/agent/app/api/v2/website_acme_account.go +++ b/agent/app/api/v2/website_acme_account.go @@ -20,7 +20,7 @@ func (b *BaseApi) PageWebsiteAcmeAccount(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } - total, accounts, err := websiteAcmeAccountService.Page(req) + total, accounts, err := websiteAcmeAccountService.Page(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/website_ca.go b/agent/app/api/v2/website_ca.go index 183517ba9..5a58baf7e 100644 --- a/agent/app/api/v2/website_ca.go +++ b/agent/app/api/v2/website_ca.go @@ -24,7 +24,7 @@ func (b *BaseApi) PageWebsiteCA(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } - total, cas, err := websiteCAService.Page(req) + total, cas, err := websiteCAService.Page(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return @@ -70,7 +70,7 @@ func (b *BaseApi) GetWebsiteCA(c *gin.Context) { if err != nil { return } - res, err := websiteCAService.GetCA(id) + res, err := websiteCAService.GetCA(id, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/website_dns_account.go b/agent/app/api/v2/website_dns_account.go index 21010122d..3ded62d8c 100644 --- a/agent/app/api/v2/website_dns_account.go +++ b/agent/app/api/v2/website_dns_account.go @@ -20,7 +20,7 @@ func (b *BaseApi) PageWebsiteDnsAccount(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } - total, accounts, err := websiteDnsAccountService.Page(req) + total, accounts, err := websiteDnsAccountService.Page(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/api/v2/website_ssl.go b/agent/app/api/v2/website_ssl.go index a32104d96..ff4e53407 100644 --- a/agent/app/api/v2/website_ssl.go +++ b/agent/app/api/v2/website_ssl.go @@ -28,7 +28,7 @@ func (b *BaseApi) PageWebsiteSSL(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } - total, accounts, err := websiteSSLService.Page(req) + total, accounts, err := websiteSSLService.Page(req, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return @@ -159,7 +159,7 @@ func (b *BaseApi) GetWebsiteSSLByWebsiteId(c *gin.Context) { helper.BadRequest(c, err) return } - websiteSSL, err := websiteSSLService.GetWebsiteSSL(websiteId) + websiteSSL, err := websiteSSLService.GetWebsiteSSL(websiteId, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return @@ -181,7 +181,7 @@ func (b *BaseApi) GetWebsiteSSLById(c *gin.Context) { helper.BadRequest(c, err) return } - websiteSSL, err := websiteSSLService.GetSSL(id) + websiteSSL, err := websiteSSLService.GetSSL(id, helper.IsDemoRequest(c)) if err != nil { helper.InternalServer(c, err) return diff --git a/agent/app/dto/request/app.go b/agent/app/dto/request/app.go index f2519636d..fa345316f 100644 --- a/agent/app/dto/request/app.go +++ b/agent/app/dto/request/app.go @@ -62,11 +62,13 @@ type AppInstalledSearch struct { All bool `json:"all"` Sync bool `json:"sync"` CheckUpdate bool `json:"checkUpdate"` + ReadOnly bool `json:"-"` } type AppInstalledInfo struct { - Key string `json:"key" validate:"required"` - Name string `json:"name"` + Key string `json:"key" validate:"required"` + Name string `json:"name"` + ReadOnly bool `json:"-"` } type AppBackupSearch struct { diff --git a/agent/app/dto/request/runtime.go b/agent/app/dto/request/runtime.go index 88f07b1a4..72c67a3f8 100644 --- a/agent/app/dto/request/runtime.go +++ b/agent/app/dto/request/runtime.go @@ -6,9 +6,10 @@ import ( type RuntimeSearch struct { dto.PageInfo - Type string `json:"type"` - Name string `json:"name"` - Status string `json:"status"` + Type string `json:"type"` + Name string `json:"name"` + Status string `json:"status"` + ReadOnly bool `json:"-"` } type RuntimeCreate struct { diff --git a/agent/app/service/agents.go b/agent/app/service/agents.go index e6ada78f5..4cc8d0cdf 100644 --- a/agent/app/service/agents.go +++ b/agent/app/service/agents.go @@ -38,7 +38,7 @@ type IAgentService interface { BatchUpgrade(req dto.AgentBatchUpgradeReq) ([]dto.AgentBatchUpgradeResult, error) BatchInstallSkill(req dto.AgentBatchSkillInstallReq) ([]dto.AgentBatchSkillInstallResult, error) BatchOperate(req dto.AgentBatchOperateReq) ([]dto.AgentBatchOperateResult, error) - Page(req dto.SearchWithPage) (int64, []dto.AgentItem, error) + Page(req dto.SearchWithPage, readOnly bool) (int64, []dto.AgentItem, error) DeleteCheck(req dto.AgentIDReq) ([]dto.AppResource, error) Delete(req dto.AgentDeleteReq) error ResetToken(req dto.AgentTokenResetReq) error @@ -76,7 +76,7 @@ type IAgentService interface { CreateAccount(req dto.AgentAccountCreateReq) error UpdateAccount(req dto.AgentAccountUpdateReq) error SyncAgentsByAccount(account *model.AgentAccount) error - PageAccounts(req dto.AgentAccountSearch) (int64, []dto.AgentAccountInfo, error) + PageAccounts(req dto.AgentAccountSearch, readOnly ...bool) (int64, []dto.AgentAccountInfo, error) CountAccountsByProviders(req dto.AgentAccountProviderCountReq) (map[string]int64, error) GetAccountModels(req dto.AgentAccountModelReq) ([]dto.AgentAccountModel, error) DiscoverAccountModels(req dto.AgentAccountModelDiscoverReq) ([]dto.AgentAccountModel, error) @@ -745,7 +745,7 @@ func setAgentWebUIParams(params map[string]interface{}, agentType, appVersion st params["PANEL_APP_PORT_HTTP"] = webUIPort } -func (a AgentService) Page(req dto.SearchWithPage) (int64, []dto.AgentItem, error) { +func (a AgentService) Page(req dto.SearchWithPage, readOnly bool) (int64, []dto.AgentItem, error) { var opts []repo.DBOption if strings.TrimSpace(req.Info) != "" { opts = append(opts, repo.WithByLikeName(req.Info)) @@ -760,11 +760,19 @@ func (a AgentService) Page(req dto.SearchWithPage) (int64, []dto.AgentItem, erro appInstall, _ := appInstallRepo.GetFirst(repo.WithByID(item.AppInstallID)) appInstalls = append(appInstalls, appInstall) } - syncAgentAppInstalls(appInstalls) + readOnlyMode := isDemoReadOnly(readOnly) + if !readOnlyMode { + syncAgentAppInstalls(appInstalls) + } for index, item := range list { appInstall := appInstalls[index] envMap := readInstallEnv(appInstall.Env) agentItem := buildAgentItem(&item, &appInstall, envMap) + if readOnlyMode { + agentItem.Token = "" + agentItem.APIKey = "" + agentItem.DashboardPassword = "" + } agentItem.Upgradable = checkAgentUpgradable(appInstall) items = append(items, agentItem) } @@ -1128,7 +1136,7 @@ func (a AgentService) UpdateAccount(req dto.AgentAccountUpdateReq) error { return nil } -func (a AgentService) PageAccounts(req dto.AgentAccountSearch) (int64, []dto.AgentAccountInfo, error) { +func (a AgentService) PageAccounts(req dto.AgentAccountSearch, readOnly ...bool) (int64, []dto.AgentAccountInfo, error) { var opts []repo.DBOption if strings.TrimSpace(req.Provider) != "" { opts = append(opts, repo.WithByProvider(req.Provider)) @@ -1149,7 +1157,7 @@ func (a AgentService) PageAccounts(req dto.AgentAccountSearch) (int64, []dto.Age items := make([]dto.AgentAccountInfo, 0, len(list)) for _, item := range list { apiKey := "" - if item.RememberAPIKey { + if item.RememberAPIKey && !isDemoReadOnly(readOnly...) { apiKey = item.APIKey } items = append(items, dto.AgentAccountInfo{ diff --git a/agent/app/service/alert.go b/agent/app/service/alert.go index 5b7f5e7d1..6b6a1a2fc 100644 --- a/agent/app/service/alert.go +++ b/agent/app/service/alert.go @@ -51,7 +51,7 @@ type IAlertService interface { GetCronJobs(req dto.CronJobReq) ([]dto.CronJobDTO, error) GetAlertConfig(req dto.AlertConfigQuery) ([]model.AlertConfig, error) - PageAlertConfig(req dto.AlertConfigPageReq) (int64, []model.AlertConfig, error) + PageAlertConfig(req dto.AlertConfigPageReq, readOnly ...bool) (int64, []model.AlertConfig, error) UpdateAlertConfig(req dto.AlertConfigUpdate, operator string) error DeleteAlertConfig(id uint) error TestAlertConfig(req dto.AlertConfigTest) (bool, error) @@ -497,7 +497,7 @@ func (a AlertService) GetAlertConfig(req dto.AlertConfigQuery) ([]model.AlertCon return configs, err } -func (a AlertService) PageAlertConfig(req dto.AlertConfigPageReq) (int64, []model.AlertConfig, error) { +func (a AlertService) PageAlertConfig(req dto.AlertConfigPageReq, readOnly ...bool) (int64, []model.AlertConfig, error) { opts := []repo.DBOption{ alertRepo.WithByTypeNotIn([]string{"common"}), repo.WithOrderDesc("created_at"), @@ -505,7 +505,25 @@ func (a AlertService) PageAlertConfig(req dto.AlertConfigPageReq) (int64, []mode if len(req.ExcludeTypes) > 0 { opts = append(opts, alertRepo.WithByTypeNotIn(req.ExcludeTypes)) } - return alertRepo.PageAlertConfig(req.Page, req.PageSize, opts...) + total, configs, err := alertRepo.PageAlertConfig(req.Page, req.PageSize, opts...) + if err != nil || !isDemoReadOnly(readOnly...) { + return total, configs, err + } + for i := range configs { + var value interface{} + if err := json.Unmarshal([]byte(configs[i].Config), &value); err != nil { + configs[i].Config = "" + continue + } + redactSensitiveData(value) + data, err := json.Marshal(value) + if err != nil { + configs[i].Config = "" + continue + } + configs[i].Config = string(data) + } + return total, configs, nil } func (a AlertService) UpdateAlertConfig(req dto.AlertConfigUpdate, operator string) error { diff --git a/agent/app/service/app.go b/agent/app/service/app.go index 63d538bfc..a784c91ed 100644 --- a/agent/app/service/app.go +++ b/agent/app/service/app.go @@ -48,7 +48,7 @@ type IAppService interface { PageApp(ctx *gin.Context, req request.AppSearch) (*response.AppRes, error) GetAppTags(ctx *gin.Context) ([]response.TagDTO, error) GetApp(ctx *gin.Context, key string) (*response.AppDTO, error) - GetAppDetail(appId uint, version, appType string) (response.AppDetailDTO, error) + GetAppDetail(appId uint, version, appType string, readOnly ...bool) (response.AppDetailDTO, error) Install(req request.AppInstallCreate, executeScript bool) (*model.AppInstall, error) SyncAppListFromRemote(taskID string) error GetAppUpdate() (*response.AppUpdateRes, error) @@ -231,7 +231,7 @@ func (a AppService) GetAppDetailByKey(appKey, version string) (response.AppDetai return appDetailDTO, nil } -func (a AppService) GetAppDetail(appID uint, version, appType string) (response.AppDetailDTO, error) { +func (a AppService) GetAppDetail(appID uint, version, appType string, readOnly ...bool) (response.AppDetailDTO, error) { var ( appDetailDTO response.AppDetailDTO opts []repo.DBOption @@ -243,6 +243,7 @@ func (a AppService) GetAppDetail(appID uint, version, appType string) (response. } appDetailDTO.AppDetail = detail appDetailDTO.Enable = true + readOnlyMode := isDemoReadOnly(readOnly...) if appType == "runtime" { app, err := appRepo.GetFirst(repo.WithByID(appID)) @@ -252,42 +253,46 @@ func (a AppService) GetAppDetail(appID uint, version, appType string) (response. fileOp := files.NewFileOp() versionPath := filepath.Join(app.GetAppResourcePath(), detail.Version) - if !fileOp.Stat(versionPath) || detail.Update { + versionExists := fileOp.Stat(versionPath) + if (!versionExists || detail.Update) && !readOnlyMode { if err = downloadApp(app, detail, nil, nil); err != nil && !fileOp.Stat(versionPath) { return appDetailDTO, err } + versionExists = fileOp.Stat(versionPath) } - switch app.Type { - case constant.RuntimePHP: - paramsPath := filepath.Join(versionPath, "data.yml") - if !fileOp.Stat(paramsPath) { - return appDetailDTO, buserr.WithDetail("ErrFileNotExist", paramsPath, nil) - } - param, err := fileOp.GetContent(paramsPath) - if err != nil { - return appDetailDTO, err - } - paramMap := make(map[string]interface{}) - if err = yaml.Unmarshal(param, ¶mMap); err != nil { - return appDetailDTO, err - } - appDetailDTO.Params = paramMap["additionalProperties"] - composePath := filepath.Join(versionPath, "docker-compose.yml") - if !fileOp.Stat(composePath) { - return appDetailDTO, buserr.WithDetail("ErrFileNotExist", composePath, nil) - } - 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 + if versionExists { + switch app.Type { + case constant.RuntimePHP: + paramsPath := filepath.Join(versionPath, "data.yml") + if !fileOp.Stat(paramsPath) { + return appDetailDTO, buserr.WithDetail("ErrFileNotExist", paramsPath, nil) + } + param, err := fileOp.GetContent(paramsPath) + if err != nil { + return appDetailDTO, err + } + paramMap := make(map[string]interface{}) + if err = yaml.Unmarshal(param, ¶mMap); err != nil { + return appDetailDTO, err + } + appDetailDTO.Params = paramMap["additionalProperties"] + composePath := filepath.Join(versionPath, "docker-compose.yml") + if !fileOp.Stat(composePath) { + return appDetailDTO, buserr.WithDetail("ErrFileNotExist", composePath, nil) + } + 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 + } } } } @@ -299,7 +304,7 @@ func (a AppService) GetAppDetail(appID uint, version, appType string) (response. appDetailDTO.Params = paramMap } - if appDetailDTO.DockerCompose == "" { + if appDetailDTO.DockerCompose == "" && !readOnlyMode { filename := filepath.Base(appDetailDTO.DownloadUrl) dockerComposeUrl := fmt.Sprintf("%s%s", strings.TrimSuffix(appDetailDTO.DownloadUrl, filename), "docker-compose.yml") statusCode, composeRes, err := req_helper.HandleRequest(dockerComposeUrl, http.MethodGet, constant.TimeOut20s) diff --git a/agent/app/service/app_ingore_upgrade.go b/agent/app/service/app_ingore_upgrade.go index 720b6a071..46251b5f5 100644 --- a/agent/app/service/app_ingore_upgrade.go +++ b/agent/app/service/app_ingore_upgrade.go @@ -13,7 +13,7 @@ type AppIgnoreUpgradeService struct { } type IAppIgnoreUpgradeService interface { - List() ([]response.AppIgnoreUpgradeDTO, error) + List(readOnly ...bool) ([]response.AppIgnoreUpgradeDTO, error) CreateAppIgnore(req request.AppIgnoreUpgradeReq) error Delete(req request.ReqWithID) error } @@ -22,7 +22,7 @@ func NewIAppIgnoreUpgradeService() IAppIgnoreUpgradeService { return AppIgnoreUpgradeService{} } -func (a AppIgnoreUpgradeService) List() ([]response.AppIgnoreUpgradeDTO, error) { +func (a AppIgnoreUpgradeService) List(readOnly ...bool) ([]response.AppIgnoreUpgradeDTO, error) { var res []response.AppIgnoreUpgradeDTO ignores, err := appIgnoreUpgradeRepo.List() if err != nil { @@ -37,14 +37,18 @@ func (a AppIgnoreUpgradeService) List() ([]response.AppIgnoreUpgradeDTO, error) } app, err := appRepo.GetFirst(repo.WithByID(ignore.AppID)) if errors.Is(err, gorm.ErrRecordNotFound) { - _ = appIgnoreUpgradeRepo.Delete(repo.WithByID(ignore.ID)) + if !isDemoReadOnly(readOnly...) { + _ = appIgnoreUpgradeRepo.Delete(repo.WithByID(ignore.ID)) + } continue } dto.Name = app.Name if ignore.Scope == "version" { appDetail, err := appDetailRepo.GetFirst(repo.WithByID(ignore.AppDetailID)) if errors.Is(err, gorm.ErrRecordNotFound) { - _ = appIgnoreUpgradeRepo.Delete(repo.WithByID(ignore.ID)) + if !isDemoReadOnly(readOnly...) { + _ = appIgnoreUpgradeRepo.Delete(repo.WithByID(ignore.ID)) + } continue } dto.Version = appDetail.Version diff --git a/agent/app/service/app_install.go b/agent/app/service/app_install.go index df5145c9f..2300961ab 100644 --- a/agent/app/service/app_install.go +++ b/agent/app/service/app_install.go @@ -42,21 +42,21 @@ 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) + LoadConnInfo(req dto.OperationWithNameAndType, readOnly ...bool) (response.DatabaseConn, error) SearchForWebsite(req request.AppInstalledSearch) ([]response.AppInstallDTO, error) Operate(req request.AppInstalledOperate) error Update(req request.AppInstalledUpdate) error SyncAll(systemInit bool) error GetServices(key string) ([]response.AppService, error) GetUpdateVersions(req request.AppUpdateVersion) ([]dto.AppVersion, error) - GetParams(id uint) (*response.AppConfig, error) + GetParams(id uint, readOnly ...bool) (*response.AppConfig, error) ChangeAppPort(req request.PortUpdate) error GetDefaultConfigByKey(key, name string) (string, error) - DeleteCheck(installId uint) ([]dto.AppResource, error) + DeleteCheck(installId uint, readOnly ...bool) ([]dto.AppResource, error) UpdateAppConfig(req request.AppConfigUpdate) error GetInstallList() ([]dto.AppInstallInfo, error) - GetAppInstallInfo(appInstallID uint) (*response.AppInstallInfo, error) + GetAppInstallInfo(appInstallID uint, readOnly ...bool) (*response.AppInstallInfo, error) UpdateSort(req request.AppInstallSort) error } @@ -123,7 +123,7 @@ func (a *AppInstallService) Page(req request.AppInstalledSearch) (int64, []respo } } - installDTOs, _ := handleInstalled(installs, req.Update, req.Sync, req.CheckUpdate) + installDTOs, _ := handleInstalled(installs, req.Update, req.Sync && !req.ReadOnly, req.CheckUpdate, req.ReadOnly) if req.Update { total = int64(len(installDTOs)) } @@ -151,8 +151,10 @@ func (a *AppInstallService) CheckExist(req request.AppInstalledInfo) (*response. if reflect.DeepEqual(appInstall, model.AppInstall{}) { return res, nil } - if err = syncAppInstallStatus(&appInstall, false); err != nil { - return nil, err + if !req.ReadOnly { + if err = syncAppInstallStatus(&appInstall, false); err != nil { + return nil, err + } } res.ContainerName = appInstall.ContainerName @@ -182,7 +184,7 @@ func (a *AppInstallService) LoadPort(req dto.OperationWithNameAndType) (int64, e return app.Port, nil } -func (a *AppInstallService) LoadConnInfo(req dto.OperationWithNameAndType) (response.DatabaseConn, error) { +func (a *AppInstallService) LoadConnInfo(req dto.OperationWithNameAndType, readOnly ...bool) (response.DatabaseConn, error) { var data response.DatabaseConn app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name) if err != nil { @@ -191,6 +193,9 @@ func (a *AppInstallService) LoadConnInfo(req dto.OperationWithNameAndType) (resp data.Status = app.Status data.Username = app.UserName data.Password = app.Password + if isDemoReadOnly(readOnly...) { + data.Password = "" + } data.ServiceName = app.ServiceName data.Port = app.Port data.ContainerName = app.ContainerName @@ -240,7 +245,7 @@ func (a *AppInstallService) SearchForWebsite(req request.AppInstalledSearch) ([] } } - return handleInstalled(installs, false, true, false) + return handleInstalled(installs, false, !req.ReadOnly, false, req.ReadOnly) } func (a *AppInstallService) Operate(req request.AppInstalledOperate) error { @@ -664,7 +669,7 @@ func (a *AppInstallService) ChangeAppPort(req request.PortUpdate) error { return nil } -func (a *AppInstallService) DeleteCheck(installID uint) ([]dto.AppResource, error) { +func (a *AppInstallService) DeleteCheck(installID uint, readOnly ...bool) ([]dto.AppResource, error) { var res []dto.AppResource appInstall, err := appInstallRepo.GetFirst(repo.WithByID(installID)) if err != nil { @@ -685,7 +690,7 @@ func (a *AppInstallService) DeleteCheck(installID uint) ([]dto.AppResource, erro Type: "app", Name: linkInstall.Name, }) - } else { + } else if !isDemoReadOnly(readOnly...) { _ = appInstallResourceRepo.DeleteBy(context.Background(), appInstallResourceRepo.WithAppInstallId(resource.AppInstallId)) } } @@ -723,7 +728,7 @@ func (a *AppInstallService) GetDefaultConfigByKey(key, name string) (string, err return string(contentByte), nil } -func (a *AppInstallService) GetParams(id uint) (*response.AppConfig, error) { +func (a *AppInstallService) GetParams(id uint, readOnly ...bool) (*response.AppConfig, error) { var ( params []response.AppParam appForm dto.AppForm @@ -818,8 +823,14 @@ func (a *AppInstallService) GetParams(id uint) (*response.AppConfig, error) { } } + readOnlyMode := isDemoReadOnly(readOnly...) + if readOnlyMode { + redactSensitiveAppParams(params) + } config := getAppCommonConfig(envs) - config.DockerCompose = install.DockerCompose + if !readOnlyMode { + config.DockerCompose = install.DockerCompose + } res.Params = params if config.ContainerName == "" { config.ContainerName = install.ContainerName @@ -829,8 +840,10 @@ func (a *AppInstallService) GetParams(id uint) (*response.AppConfig, error) { res.RestartPolicy = getRestartPolicy(install.DockerCompose) res.WebUI = install.WebUI res.Type = install.App.Type - if rawCompose, err := getUpgradeCompose(install, detail); err == nil { - res.RawCompose = rawCompose + if !readOnlyMode { + if rawCompose, err := getUpgradeCompose(install, detail); err == nil { + res.RawCompose = rawCompose + } } return &res, nil } @@ -958,20 +971,25 @@ func updateInstallInfoInDB(appKey, appName, param string, value interface{}) err return nil } -func (a *AppInstallService) GetAppInstallInfo(installID uint) (*response.AppInstallInfo, error) { +func (a *AppInstallService) GetAppInstallInfo(installID uint, readOnly ...bool) (*response.AppInstallInfo, error) { appInstall, _ := appInstallRepo.GetFirst(repo.WithByID(installID)) if appInstall.ID == 0 { return &response.AppInstallInfo{ Status: constant.StatusDeleted, }, nil } - _ = syncAppInstallStatus(&appInstall, false) + if !isDemoReadOnly(readOnly...) { + _ = syncAppInstallStatus(&appInstall, false) + } appInstall, _ = appInstallRepo.GetFirst(repo.WithByID(installID)) var envMap map[string]interface{} err := json.Unmarshal([]byte(appInstall.Env), &envMap) if err != nil { return nil, err } + if isDemoReadOnly(readOnly...) { + redactSensitiveValues(envMap) + } res := &response.AppInstallInfo{ ID: appInstall.ID, Name: appInstall.Name, diff --git a/agent/app/service/app_utils.go b/agent/app/service/app_utils.go index a3c213bb6..8988d7c43 100644 --- a/agent/app/service/app_utils.go +++ b/agent/app/service/app_utils.go @@ -53,6 +53,62 @@ var ( Delete DatabaseOp = "delete" ) +func isDemoReadOnly(readOnly ...bool) bool { + return global.CONF.Base.IsDemo || len(readOnly) > 0 && readOnly[0] +} + +func normalizeConfigKey(key string) string { + return strings.ToLower(strings.NewReplacer("_", "", "-", "", ".", "", " ", "").Replace(key)) +} + +func isSensitiveConfigKey(key string) bool { + normalized := normalizeConfigKey(key) + for _, marker := range []string{"password", "passwd", "passphrase", "secret", "token", "credential", "privatekey", "authorization"} { + if strings.Contains(normalized, marker) { + return true + } + } + return normalized == "key" || strings.HasSuffix(normalized, "key") +} + +func redactSensitiveValues(values map[string]interface{}) { + redactSensitiveData(values) +} + +func redactSensitiveData(value interface{}) { + switch data := value.(type) { + case map[string]interface{}: + for key, item := range data { + if isSensitiveConfigKey(key) { + data[key] = "" + } else { + redactSensitiveData(item) + } + } + case []interface{}: + for _, item := range data { + redactSensitiveData(item) + } + } +} + +func redactSensitiveAppParams(params []response.AppParam) { + for i := range params { + if strings.EqualFold(params[i].Type, "password") || isSensitiveConfigKey(params[i].Key) { + params[i].Value = "" + params[i].ShowValue = "" + } + } +} + +func redactSensitiveEnvironments(environments []request.Environment) { + for i := range environments { + if isSensitiveConfigKey(environments[i].Key) { + environments[i].Value = "" + } + } +} + func checkPort(key string, params map[string]interface{}) (int, error) { port, ok := params[key] if ok { @@ -1387,7 +1443,9 @@ func synAppInstall(containers map[string]container.Summary, appInstall *model.Ap } appInstall.Status = constant.StatusError appInstall.Message = buserr.WithName("ErrContainerNotFound", strings.Join(containerNames, ",")).Error() - _ = appInstallRepo.Save(context.Background(), appInstall) + if !global.CONF.Base.IsDemo { + _ = appInstallRepo.Save(context.Background(), appInstall) + } return } notFoundNames := make([]string, 0) @@ -1446,10 +1504,12 @@ func synAppInstall(containers map[string]container.Summary, appInstall *model.Ap appInstall.Message = msg appInstall.Status = constant.StatusUnHealthy } - _ = appInstallRepo.Save(context.Background(), appInstall) + if !global.CONF.Base.IsDemo { + _ = appInstallRepo.Save(context.Background(), appInstall) + } } -func handleInstalled(appInstallList []model.AppInstall, updated, sync, checkUpdate bool) ([]response.AppInstallDTO, error) { +func handleInstalled(appInstallList []model.AppInstall, updated, sync, checkUpdate, readOnly bool) ([]response.AppInstallDTO, error) { var ( res []response.AppInstallDTO containersMap map[string]container.Summary @@ -1480,6 +1540,9 @@ func handleInstalled(appInstallList []model.AppInstall, updated, sync, checkUpda resourceKeys := getAppInstallResourceKeys(installed.ID) envMap := make(map[string]interface{}) _ = json.Unmarshal([]byte(installed.Env), &envMap) + if isDemoReadOnly(readOnly) { + redactSensitiveValues(envMap) + } installDTO := response.AppInstallDTO{ ID: installed.ID, Name: installed.Name, @@ -1524,7 +1587,9 @@ func handleInstalled(appInstallList []model.AppInstall, updated, sync, checkUpda continue } - installDTO.DockerCompose = installed.DockerCompose + if !isDemoReadOnly(readOnly) { + installDTO.DockerCompose = installed.DockerCompose + } installDTO.IsEdit = isEditCompose(installed) details, err := appDetailRepo.GetBy(appDetailRepo.WithAppId(installed.App.ID)) diff --git a/agent/app/service/backup.go b/agent/app/service/backup.go index 3a50f22ee..a7466b980 100644 --- a/agent/app/service/backup.go +++ b/agent/app/service/backup.go @@ -33,7 +33,7 @@ type IBackupService interface { CheckUsed(name string, isPublic bool) error LoadBackupOptions() ([]dto.BackupOption, error) - SearchWithPage(search dto.SearchPageWithType) (int64, interface{}, error) + SearchWithPage(search dto.SearchPageWithType, readOnly ...bool) (int64, interface{}, error) Create(backupDto dto.BackupOperate) error CheckConn(req dto.BackupOperate) dto.BackupCheckRes GetBuckets(backupDto dto.ForBuckets) ([]interface{}, error) @@ -80,7 +80,7 @@ func (u *BackupService) GetLocalDir() (string, error) { return account.BackupPath, nil } -func (u *BackupService) SearchWithPage(req dto.SearchPageWithType) (int64, interface{}, error) { +func (u *BackupService) SearchWithPage(req dto.SearchPageWithType, readOnly ...bool) (int64, interface{}, error) { options := []repo.DBOption{repo.WithOrderDesc("created_at")} if len(req.Type) != 0 { options = append(options, repo.WithByType(req.Type)) @@ -128,11 +128,36 @@ func (u *BackupService) SearchWithPage(req dto.SearchPageWithType) (int64, inter itemVars, _ := json.Marshal(varMap) item.Vars = string(itemVars) } + if isDemoReadOnly(readOnly...) { + item.AccessKey = "" + item.Credential = "" + item.Vars = sanitizeBackupVars(item.Vars) + } data = append(data, item) } return count, data, nil } +func sanitizeBackupVars(vars string) string { + if vars == "" { + return vars + } + var values map[string]interface{} + if err := json.Unmarshal([]byte(vars), &values); err != nil { + return "" + } + for key := range values { + if isSensitiveConfigKey(key) || normalizeConfigKey(key) == "code" { + delete(values, key) + } + } + data, err := json.Marshal(values) + if err != nil { + return "" + } + return string(data) +} + func (u *BackupService) CheckConn(req dto.BackupOperate) dto.BackupCheckRes { var res dto.BackupCheckRes var backup model.BackupAccount diff --git a/agent/app/service/clam.go b/agent/app/service/clam.go index 444e25562..a3d7165cf 100644 --- a/agent/app/service/clam.go +++ b/agent/app/service/clam.go @@ -33,7 +33,7 @@ type ClamService struct { } type IClamService interface { - LoadBaseInfo() (dto.ClamBaseInfo, error) + LoadBaseInfo(readOnly bool) (dto.ClamBaseInfo, error) Operate(operate string) error SearchWithPage(search dto.SearchClamWithPage) (int64, interface{}, error) Create(req dto.ClamCreate, operator string) error @@ -53,7 +53,7 @@ func NewIClamService() IClamService { return &ClamService{} } -func (c *ClamService) LoadBaseInfo() (dto.ClamBaseInfo, error) { +func (c *ClamService) LoadBaseInfo(readOnly bool) (dto.ClamBaseInfo, error) { var baseInfo dto.ClamBaseInfo baseInfo.Version = "-" baseInfo.FreshVersion = "-" @@ -96,7 +96,7 @@ func (c *ClamService) LoadBaseInfo() (dto.ClamBaseInfo, error) { baseInfo.Version = strings.TrimPrefix(version, "ClamAV ") } } - } else { + } else if !readOnly && !global.CONF.Base.IsDemo { _ = clam.CheckWithStopAll(false, clamRepo) } if baseInfo.FreshIsActive { diff --git a/agent/app/service/compose_template.go b/agent/app/service/compose_template.go index a5d6b6b1f..f1447eb11 100644 --- a/agent/app/service/compose_template.go +++ b/agent/app/service/compose_template.go @@ -11,8 +11,8 @@ import ( type ComposeTemplateService struct{} type IComposeTemplateService interface { - List() ([]dto.ComposeTemplateInfo, error) - SearchWithPage(search dto.SearchWithPage) (int64, interface{}, error) + List(readOnly ...bool) ([]dto.ComposeTemplateInfo, error) + SearchWithPage(search dto.SearchWithPage, readOnly ...bool) (int64, interface{}, error) Create(req dto.ComposeTemplateCreate) error Update(id uint, upMap map[string]interface{}) error Batch(req dto.ComposeTemplateBatch) error @@ -23,7 +23,7 @@ func NewIComposeTemplateService() IComposeTemplateService { return &ComposeTemplateService{} } -func (u *ComposeTemplateService) List() ([]dto.ComposeTemplateInfo, error) { +func (u *ComposeTemplateService) List(readOnly ...bool) ([]dto.ComposeTemplateInfo, error) { composes, err := composeRepo.List() if err != nil { return nil, buserr.New("ErrRecordNotFound") @@ -34,12 +34,15 @@ func (u *ComposeTemplateService) List() ([]dto.ComposeTemplateInfo, error) { if err := copier.Copy(&item, &compose); err != nil { return nil, buserr.WithDetail("ErrStructTransform", err.Error(), nil) } + if isDemoReadOnly(readOnly...) { + item.Content = "" + } dtoLists = append(dtoLists, item) } return dtoLists, err } -func (u *ComposeTemplateService) SearchWithPage(req dto.SearchWithPage) (int64, interface{}, error) { +func (u *ComposeTemplateService) SearchWithPage(req dto.SearchWithPage, readOnly ...bool) (int64, interface{}, error) { total, composes, err := composeRepo.Page(req.Page, req.PageSize, repo.WithByLikeName(req.Info)) var dtoComposeTemplates []dto.ComposeTemplateInfo for _, compose := range composes { @@ -47,6 +50,9 @@ func (u *ComposeTemplateService) SearchWithPage(req dto.SearchWithPage) (int64, if err := copier.Copy(&item, &compose); err != nil { return 0, nil, buserr.WithDetail("ErrStructTransform", err.Error(), nil) } + if isDemoReadOnly(readOnly...) { + item.Content = "" + } dtoComposeTemplates = append(dtoComposeTemplates, item) } return total, dtoComposeTemplates, err diff --git a/agent/app/service/container.go b/agent/app/service/container.go index 2cc7d6564..e9905331d 100644 --- a/agent/app/service/container.go +++ b/agent/app/service/container.go @@ -65,7 +65,7 @@ type IContainerService interface { PageVolume(req dto.SearchWithPage) (int64, interface{}, error) ListVolume() ([]dto.Options, error) - PageCompose(req dto.SearchWithPage) (int64, interface{}, error) + PageCompose(req dto.SearchWithPage, readOnly ...bool) (int64, interface{}, error) LoadComposeEnv(name string) (string, error) CreateCompose(req dto.ComposeCreate) error ComposeOperation(req dto.ComposeOperation) error @@ -77,7 +77,7 @@ type IContainerService interface { ContainerCreate(req dto.ContainerOperate, inThread bool) error ContainerUpdate(req dto.ContainerOperate) error ContainerUpgrade(req dto.ContainerUpgrade) error - ContainerInfo(req dto.OperationWithName) (*dto.ContainerOperate, error) + ContainerInfo(req dto.OperationWithName, readOnly ...bool) (*dto.ContainerOperate, error) ContainerListStats() ([]dto.ContainerListStats, error) ContainerItemStats(req dto.OperationWithName) (dto.ContainerItemStats, error) LoadResourceLimit() (*dto.ResourceLimit, error) @@ -568,7 +568,7 @@ func (u *ContainerService) ContainerCreate(req dto.ContainerOperate, inThread bo return taskItem.Execute() } -func (u *ContainerService) ContainerInfo(req dto.OperationWithName) (*dto.ContainerOperate, error) { +func (u *ContainerService) ContainerInfo(req dto.OperationWithName, readOnly ...bool) (*dto.ContainerOperate, error) { client, err := docker.NewDockerClient() if err != nil { return nil, err @@ -612,6 +612,9 @@ func (u *ContainerService) ContainerInfo(req dto.OperationWithName) (*dto.Contai data.Tty = oldContainer.Config.Tty data.Entrypoint = oldContainer.Config.Entrypoint data.Env = oldContainer.Config.Env + if isDemoReadOnly(readOnly...) { + data.Env = nil + } data.CPUShares = oldContainer.HostConfig.CPUShares for key, val := range oldContainer.Config.Labels { data.Labels = append(data.Labels, fmt.Sprintf("%s=%s", key, val)) diff --git a/agent/app/service/container_compose.go b/agent/app/service/container_compose.go index faa6227ca..fddaf708e 100644 --- a/agent/app/service/container_compose.go +++ b/agent/app/service/container_compose.go @@ -35,7 +35,7 @@ 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) { +func (u *ContainerService) PageCompose(req dto.SearchWithPage, readOnly ...bool) (int64, interface{}, error) { var ( records []dto.ComposeInfo BackDatas []dto.ComposeInfo @@ -187,7 +187,10 @@ func (u *ContainerService) PageCompose(req dto.SearchWithPage) (int64, interface } BackDatas = records[start:end] } - listItem := loadEnv(BackDatas) + listItem := BackDatas + if !isDemoReadOnly(readOnly...) { + listItem = loadEnv(BackDatas) + } return int64(total), listItem, nil } diff --git a/agent/app/service/cronjob.go b/agent/app/service/cronjob.go index 896abbfbb..92219d940 100644 --- a/agent/app/service/cronjob.go +++ b/agent/app/service/cronjob.go @@ -25,7 +25,7 @@ import ( type CronjobService struct{} type ICronjobService interface { - SearchWithPage(search dto.PageCronjob) (int64, interface{}, error) + SearchWithPage(search dto.PageCronjob, readOnly ...bool) (int64, interface{}, error) SearchRecords(search dto.SearchRecord) (int64, interface{}, error) Create(cronjobDto dto.CronjobOperate, operator string) error LoadNextHandle(spec string) ([]string, error) @@ -50,7 +50,7 @@ func NewICronjobService() ICronjobService { return &CronjobService{} } -func (u *CronjobService) SearchWithPage(search dto.PageCronjob) (int64, interface{}, error) { +func (u *CronjobService) SearchWithPage(search dto.PageCronjob, readOnly ...bool) (int64, interface{}, error) { total, cronjobs, err := cronjobRepo.Page(search.Page, search.PageSize, repo.WithByGroups(search.GroupIDs), @@ -83,6 +83,9 @@ func (u *CronjobService) SearchWithPage(search dto.PageCronjob) (int64, interfac if cronjob.Type == "snapshot" && len(cronjob.SnapshotRule) != 0 { _ = json.Unmarshal([]byte(cronjob.SnapshotRule), &item.SnapshotRule) } + if isDemoReadOnly(readOnly...) { + item.Secret = "" + } dtoCronjobs = append(dtoCronjobs, item) } return total, dtoCronjobs, err diff --git a/agent/app/service/database.go b/agent/app/service/database.go index f2071ee02..40f59de6d 100644 --- a/agent/app/service/database.go +++ b/agent/app/service/database.go @@ -24,8 +24,8 @@ import ( type DatabaseService struct{} type IDatabaseService interface { - Get(name string) (dto.DatabaseInfo, error) - SearchWithPage(search dto.DatabaseSearch) (int64, interface{}, error) + Get(name string, readOnly ...bool) (dto.DatabaseInfo, error) + SearchWithPage(search dto.DatabaseSearch, readOnly ...bool) (int64, interface{}, error) CheckDatabase(req dto.DatabaseCreate) bool Create(req dto.DatabaseCreate) error Update(req dto.DatabaseUpdate) error @@ -39,7 +39,7 @@ func NewIDatabaseService() IDatabaseService { return &DatabaseService{} } -func (u *DatabaseService) SearchWithPage(search dto.DatabaseSearch) (int64, interface{}, error) { +func (u *DatabaseService) SearchWithPage(search dto.DatabaseSearch, readOnly ...bool) (int64, interface{}, error) { total, dbs, err := databaseRepo.Page(search.Page, search.PageSize, databaseRepo.WithTypeList(search.Type), repo.WithByLikeName(search.Info), @@ -52,12 +52,16 @@ func (u *DatabaseService) SearchWithPage(search dto.DatabaseSearch) (int64, inte if err := copier.Copy(&item, &db); err != nil { return 0, nil, buserr.WithDetail("ErrStructTransform", err.Error(), nil) } + if isDemoReadOnly(readOnly...) { + item.Password = "" + item.ClientKey = "" + } datas = append(datas, item) } return total, datas, err } -func (u *DatabaseService) Get(name string) (dto.DatabaseInfo, error) { +func (u *DatabaseService) Get(name string, readOnly ...bool) (dto.DatabaseInfo, error) { var data dto.DatabaseInfo remote, err := databaseRepo.Get(repo.WithByName(name)) if err != nil { @@ -66,6 +70,10 @@ func (u *DatabaseService) Get(name string) (dto.DatabaseInfo, error) { if err := copier.Copy(&data, &remote); err != nil { return data, buserr.WithDetail("ErrStructTransform", err.Error(), nil) } + if isDemoReadOnly(readOnly...) { + data.Password = "" + data.ClientKey = "" + } return data, nil } diff --git a/agent/app/service/database_mongodb.go b/agent/app/service/database_mongodb.go index 2e61aab9e..9509de177 100644 --- a/agent/app/service/database_mongodb.go +++ b/agent/app/service/database_mongodb.go @@ -23,7 +23,7 @@ import ( type MongodbService struct{} type IMongodbService interface { - SearchWithPage(search dto.MongodbDBSearch) (int64, interface{}, error) + SearchWithPage(search dto.MongodbDBSearch, readOnly ...bool) (int64, interface{}, error) Create(ctx context.Context, req dto.MongodbDBCreate) (*model.DatabaseMongodb, error) LoadFromRemote(req dto.MongodbLoadDB) error UpdateDescription(req dto.UpdateDescription) error @@ -40,7 +40,7 @@ func NewIMongodbService() IMongodbService { return &MongodbService{} } -func (u *MongodbService) SearchWithPage(search dto.MongodbDBSearch) (int64, interface{}, error) { +func (u *MongodbService) SearchWithPage(search dto.MongodbDBSearch, readOnly ...bool) (int64, interface{}, error) { total, mongodbs, err := mongodbRepo.Page( search.Page, search.PageSize, @@ -54,6 +54,9 @@ func (u *MongodbService) SearchWithPage(search dto.MongodbDBSearch) (int64, inte if err := copier.Copy(&item, &mongodb); err != nil { return 0, nil, buserr.WithDetail("ErrStructTransform", err.Error(), nil) } + if isDemoReadOnly(readOnly...) { + item.Password = "" + } dtoMongodbs = append(dtoMongodbs, item) } return total, dtoMongodbs, err diff --git a/agent/app/service/database_mysql.go b/agent/app/service/database_mysql.go index 2e7aa5988..ad02ad8bf 100644 --- a/agent/app/service/database_mysql.go +++ b/agent/app/service/database_mysql.go @@ -46,7 +46,7 @@ type IMysqlService interface { DeleteCheck(req dto.MysqlDBDeleteCheck) ([]dto.DBResource, error) Delete(ctx context.Context, req dto.MysqlDBDelete) error - ListUsers(req dto.MysqlUserSearch) ([]dto.MysqlUser, error) + ListUsers(req dto.MysqlUserSearch, readOnly ...bool) ([]dto.MysqlUser, error) ListGrants(req dto.MysqlUserSearch) ([]dto.MysqlGrant, error) ListGrantSummary(req dto.MysqlGrantSummarySearch) (map[string][]dto.MysqlUser, error) CreateUser(req dto.MysqlUserCreate) error @@ -506,7 +506,7 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode return &createItem, nil } -func (u *MysqlService) ListUsers(req dto.MysqlUserSearch) ([]dto.MysqlUser, error) { +func (u *MysqlService) ListUsers(req dto.MysqlUserSearch, readOnly ...bool) ([]dto.MysqlUser, error) { dbType, err := resolveDatabaseUserType(req.Database) if err != nil { return nil, err @@ -520,10 +520,14 @@ func (u *MysqlService) ListUsers(req dto.MysqlUserSearch) ([]dto.MysqlUser, erro if isMysqlSystemUser(user.Username) { continue } + password := user.Password + if isDemoReadOnly(readOnly...) { + password = "" + } res = append(res, dto.MysqlUser{ Username: user.Username, Host: user.Host, - Password: user.Password, + Password: password, Description: user.Description, IsDelete: user.IsDelete, }) diff --git a/agent/app/service/database_postgresql.go b/agent/app/service/database_postgresql.go index 9bf6eca8c..68cf64ef2 100644 --- a/agent/app/service/database_postgresql.go +++ b/agent/app/service/database_postgresql.go @@ -26,7 +26,7 @@ import ( type PostgresqlService struct{} type IPostgresqlService interface { - SearchWithPage(search dto.PostgresqlDBSearch) (int64, interface{}, error) + SearchWithPage(search dto.PostgresqlDBSearch, readOnly ...bool) (int64, interface{}, error) ListDBOption() ([]dto.PostgresqlOption, error) BindUser(req dto.PostgresqlBindUser) error Create(ctx context.Context, req dto.PostgresqlDBCreate) (*model.DatabasePostgresql, error) @@ -42,7 +42,7 @@ func NewIPostgresqlService() IPostgresqlService { return &PostgresqlService{} } -func (u *PostgresqlService) SearchWithPage(search dto.PostgresqlDBSearch) (int64, interface{}, error) { +func (u *PostgresqlService) SearchWithPage(search dto.PostgresqlDBSearch, readOnly ...bool) (int64, interface{}, error) { total, postgresqls, err := postgresqlRepo.Page(search.Page, search.PageSize, postgresqlRepo.WithByPostgresqlName(search.Database), repo.WithByLikeName(search.Info), @@ -54,6 +54,9 @@ func (u *PostgresqlService) SearchWithPage(search dto.PostgresqlDBSearch) (int64 if err := copier.Copy(&item, &pg); err != nil { return 0, nil, buserr.WithDetail("ErrStructTransform", err.Error(), nil) } + if isDemoReadOnly(readOnly...) { + item.Password = "" + } dtoPostgresqls = append(dtoPostgresqls, item) } return total, dtoPostgresqls, err diff --git a/agent/app/service/file.go b/agent/app/service/file.go index f3212fbfe..7dec86b3c 100644 --- a/agent/app/service/file.go +++ b/agent/app/service/file.go @@ -87,7 +87,7 @@ type IFileService interface { ConvertLog(req dto.PageInfo) (int64, []response.FileConvertLog, error) BatchGetRemarks(req request.FileRemarkBatch) map[string]string SetRemark(req request.FileRemarkUpdate) error - AISearch(req request.FileAISearch) (*response.FileAISearchResult, error) + AISearch(req request.FileAISearch, readOnly ...bool) (*response.FileAISearchResult, error) } const ( @@ -1560,7 +1560,7 @@ func (f *FileService) ConvertLog(req dto.PageInfo) (total int64, data []response return total, data, nil } -func (f *FileService) AISearch(req request.FileAISearch) (*response.FileAISearchResult, error) { +func (f *FileService) AISearch(req request.FileAISearch, readOnly ...bool) (*response.FileAISearchResult, error) { root := filepath.Clean(strings.TrimSpace(req.Path)) if root == "" { return nil, buserr.WithDetail("ErrInvalidParams", "path is required", nil) @@ -1613,10 +1613,15 @@ func (f *FileService) AISearch(req request.FileAISearch) (*response.FileAISearch return nil, buserr.WithDetail("ErrFileAISearchBadPattern", err.Error(), nil) } - cfg, timeout, err := terminalai.LoadFileAIRuntimeConfig() - aiEnabled := err == nil - if err != nil && !errors.Is(err, os.ErrNotExist) { - return nil, err + var cfg terminalai.GeneratorConfig + var timeout time.Duration + aiEnabled := false + if !isDemoReadOnly(readOnly...) { + cfg, timeout, err = terminalai.LoadFileAIRuntimeConfig() + aiEnabled = err == nil + if err != nil && !errors.Is(err, os.ErrNotExist) { + return nil, err + } } items, truncated, err := files.CollectDirInventory(root, containSub, maxItems) diff --git a/agent/app/service/file_share.go b/agent/app/service/file_share.go index 8b0ed91ad..87b3d89a1 100644 --- a/agent/app/service/file_share.go +++ b/agent/app/service/file_share.go @@ -37,14 +37,14 @@ var fileShareCodeRegexp = regexp.MustCompile(`^[A-Za-z0-9]{10,16}$`) type IFileShareService interface { Create(req request.FileShareCreate) (*response.FileShareInfo, error) - Page(req dto.PageInfo) (int64, []response.FileShareInfo, error) - GetByPath(path string) (*response.FileShareInfo, error) - GetByCode(code string) (*response.FileShareInfo, error) - GetPublicByCode(code string) (*response.FileSharePublicInfo, error) + Page(req dto.PageInfo, readOnly ...bool) (int64, []response.FileShareInfo, error) + GetByPath(path string, readOnly ...bool) (*response.FileShareInfo, error) + GetByCode(code string, readOnly ...bool) (*response.FileShareInfo, error) + GetPublicByCode(code string, readOnly ...bool) (*response.FileSharePublicInfo, error) DeleteByPath(path string) error SharePathCodeMap() (map[string]string, error) - Check(code, password string) error - PrepareDownload(code, password string) (filePath, fileName string, err error) + Check(code, password string, readOnly ...bool) error + PrepareDownload(code, password string, readOnly ...bool) (filePath, fileName string, err error) } func NewIFileShareService() IFileShareService { @@ -212,14 +212,14 @@ func (s *FileShareService) Create(req request.FileShareCreate) (*response.FileSh return &res, nil } -func (s *FileShareService) Page(req dto.PageInfo) (int64, []response.FileShareInfo, error) { +func (s *FileShareService) Page(req dto.PageInfo, readOnly ...bool) (int64, []response.FileShareInfo, error) { items, err := fileShareRepo.All() if err != nil { return 0, nil, err } result := make([]response.FileShareInfo, 0, len(items)) for _, item := range items { - if err := s.pruneInvalidShare(item); err != nil { + if err := s.pruneInvalidShare(item, readOnly...); err != nil { return 0, nil, err } if item.ExpiresUnix > 0 && time.Now().Unix() > item.ExpiresUnix { @@ -239,7 +239,7 @@ func (s *FileShareService) Page(req dto.PageInfo) (int64, []response.FileShareIn return int64(total), result[start:end], nil } -func (s *FileShareService) GetByPath(path string) (*response.FileShareInfo, error) { +func (s *FileShareService) GetByPath(path string, readOnly ...bool) (*response.FileShareInfo, error) { item, err := fileShareRepo.GetFirst(fileShareRepo.WithByPath(strings.TrimSpace(path))) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -247,7 +247,7 @@ func (s *FileShareService) GetByPath(path string) (*response.FileShareInfo, erro } return nil, err } - if err := s.pruneInvalidShare(item); err != nil { + if err := s.pruneInvalidShare(item, readOnly...); err != nil { return nil, err } if item.ExpiresUnix > 0 && time.Now().Unix() > item.ExpiresUnix { @@ -258,7 +258,7 @@ func (s *FileShareService) GetByPath(path string) (*response.FileShareInfo, erro return &info, nil } -func (s *FileShareService) GetByCode(code string) (*response.FileShareInfo, error) { +func (s *FileShareService) GetByCode(code string, readOnly ...bool) (*response.FileShareInfo, error) { item, err := fileShareRepo.GetFirst(fileShareRepo.WithByCode(strings.TrimSpace(code))) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -266,7 +266,7 @@ func (s *FileShareService) GetByCode(code string) (*response.FileShareInfo, erro } return nil, err } - if err := s.pruneInvalidShare(item); err != nil { + if err := s.pruneInvalidShare(item, readOnly...); err != nil { return nil, err } if item.ExpiresUnix > 0 && time.Now().Unix() > item.ExpiresUnix { @@ -276,7 +276,7 @@ func (s *FileShareService) GetByCode(code string) (*response.FileShareInfo, erro return &info, nil } -func (s *FileShareService) GetPublicByCode(code string) (*response.FileSharePublicInfo, error) { +func (s *FileShareService) GetPublicByCode(code string, readOnly ...bool) (*response.FileSharePublicInfo, error) { item, err := fileShareRepo.GetFirst(fileShareRepo.WithByCode(strings.TrimSpace(code))) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -284,7 +284,7 @@ func (s *FileShareService) GetPublicByCode(code string) (*response.FileSharePubl } return nil, err } - if err := s.pruneInvalidShare(item); err != nil { + if err := s.pruneInvalidShare(item, readOnly...); err != nil { return nil, err } if item.ExpiresUnix > 0 && time.Now().Unix() > item.ExpiresUnix { @@ -324,32 +324,38 @@ func (s *FileShareService) SharePathCodeMap() (map[string]string, error) { return result, nil } -func (s *FileShareService) Check(code, password string) error { - _, err := s.check(code, password) +func (s *FileShareService) Check(code, password string, readOnly ...bool) error { + _, err := s.check(code, password, readOnly...) return err } -func (s *FileShareService) PrepareDownload(code, password string) (string, string, error) { - item, err := s.check(code, password) +func (s *FileShareService) PrepareDownload(code, password string, readOnly ...bool) (string, string, error) { + item, err := s.check(code, password, readOnly...) if err != nil { return "", "", err } return item.Path, item.FileName, nil } -func (s *FileShareService) pruneInvalidShare(item model.FileShare) error { +func (s *FileShareService) pruneInvalidShare(item model.FileShare, readOnly ...bool) error { now := time.Now().Unix() if item.ExpiresUnix > 0 && now > item.ExpiresUnix { + if isDemoReadOnly(readOnly...) { + return nil + } return fileShareRepo.Delete(repo.WithByID(item.ID)) } info, err := os.Stat(item.Path) if err != nil || info.IsDir() { + if isDemoReadOnly(readOnly...) { + return nil + } return fileShareRepo.Delete(repo.WithByID(item.ID)) } return nil } -func (s *FileShareService) check(code, password string) (*model.FileShare, error) { +func (s *FileShareService) check(code, password string, readOnly ...bool) (*model.FileShare, error) { code = strings.TrimSpace(code) password = strings.TrimSpace(password) if code == "" { @@ -366,7 +372,9 @@ func (s *FileShareService) check(code, password string) (*model.FileShare, error now := time.Now().Unix() if item.ExpiresUnix > 0 && now > item.ExpiresUnix { - _ = fileShareRepo.Delete(repo.WithByID(item.ID)) + if !isDemoReadOnly(readOnly...) { + _ = fileShareRepo.Delete(repo.WithByID(item.ID)) + } return nil, buserr.New("ErrFileShareExpired") } if item.PasswordHash != "" { @@ -377,7 +385,9 @@ func (s *FileShareService) check(code, password string) (*model.FileShare, error info, err := os.Stat(item.Path) if err != nil || info.IsDir() { - _ = fileShareRepo.Delete(repo.WithByID(item.ID)) + if !isDemoReadOnly(readOnly...) { + _ = fileShareRepo.Delete(repo.WithByID(item.ID)) + } return nil, buserr.New("ErrFileSharePath") } diff --git a/agent/app/service/ftp.go b/agent/app/service/ftp.go index 35fd186ed..b16d43d0f 100644 --- a/agent/app/service/ftp.go +++ b/agent/app/service/ftp.go @@ -21,7 +21,7 @@ type FtpService struct{} type IFtpService interface { LoadBaseInfo() (dto.FtpBaseInfo, error) - SearchWithPage(search dto.SearchWithPage) (int64, interface{}, error) + SearchWithPage(search dto.SearchWithPage, readOnly ...bool) (int64, interface{}, error) Operate(operation string) error Create(req dto.FtpCreate) (uint, error) CreateWebsite(req dto.FtpCreate) (uint, error) @@ -74,7 +74,7 @@ func (u *FtpService) Operate(operation string) error { return client.Operate(operation) } -func (f *FtpService) SearchWithPage(req dto.SearchWithPage) (int64, interface{}, error) { +func (f *FtpService) SearchWithPage(req dto.SearchWithPage, readOnly ...bool) (int64, interface{}, error) { total, lists, err := ftpRepo.Page(req.Page, req.PageSize, ftpRepo.WithLikeUser(req.Info), repo.WithOrderDesc("created_at")) if err != nil { return 0, nil, err @@ -85,7 +85,11 @@ func (f *FtpService) SearchWithPage(req dto.SearchWithPage) (int64, interface{}, if err := copier.Copy(&item, &user); err != nil { return 0, nil, buserr.WithDetail("ErrStructTransform", err.Error(), nil) } - item.Password, _ = encrypt.StringDecrypt(item.Password) + if isDemoReadOnly(readOnly...) { + item.Password = "" + } else { + item.Password, _ = encrypt.StringDecrypt(item.Password) + } users = append(users, item) } return total, users, err diff --git a/agent/app/service/host.go b/agent/app/service/host.go index 8633f59ea..12bfa640c 100644 --- a/agent/app/service/host.go +++ b/agent/app/service/host.go @@ -21,7 +21,7 @@ type IHostService interface { TestByInfo(req dto.HostConnTest) bool GetHostByID(id uint) (*dto.HostInfo, error) SearchForTree(search dto.SearchForTree) ([]dto.HostTree, error) - SearchWithPage(search dto.SearchPageWithGroup) (int64, interface{}, error) + SearchWithPage(search dto.SearchPageWithGroup, readOnly ...bool) (int64, interface{}, error) Create(req dto.HostOperate) (*dto.HostInfo, error) Update(id uint, upMap map[string]interface{}) (*dto.HostInfo, error) Delete(id []uint) error @@ -111,7 +111,7 @@ func (u *HostService) TestLocalConn(id uint) bool { return true } -func (u *HostService) SearchWithPage(req dto.SearchPageWithGroup) (int64, interface{}, error) { +func (u *HostService) SearchWithPage(req dto.SearchPageWithGroup, readOnly ...bool) (int64, interface{}, error) { var options []repo.DBOption if len(req.Info) != 0 { options = append(options, hostRepo.WithByInfo(req.Info)) @@ -155,6 +155,11 @@ func (u *HostService) SearchWithPage(req dto.SearchPageWithGroup) (int64, interf } } } + if isDemoReadOnly(readOnly...) { + item.Password = "" + item.PrivateKey = "" + item.PassPhrase = "" + } dtoHosts = append(dtoHosts, item) } return total, dtoHosts, err diff --git a/agent/app/service/image_repo.go b/agent/app/service/image_repo.go index a663a11dc..f91d215f7 100644 --- a/agent/app/service/image_repo.go +++ b/agent/app/service/image_repo.go @@ -24,7 +24,7 @@ import ( type ImageRepoService struct{} type IImageRepoService interface { - Page(search dto.SearchWithPage) (int64, interface{}, error) + Page(search dto.SearchWithPage, readOnly ...bool) (int64, interface{}, error) List() ([]dto.ImageRepoOption, error) Login(req dto.OperateByID) error Create(req dto.ImageRepoCreate) error @@ -36,10 +36,13 @@ func NewIImageRepoService() IImageRepoService { return &ImageRepoService{} } -func (u *ImageRepoService) Page(req dto.SearchWithPage) (int64, interface{}, error) { +func (u *ImageRepoService) Page(req dto.SearchWithPage, readOnly ...bool) (int64, interface{}, error) { total, ops, err := imageRepoRepo.Page(req.Page, req.PageSize, repo.WithByLikeName(req.Info), repo.WithOrderDesc("created_at")) var dtoOps []dto.ImageRepoInfo for _, op := range ops { + if isDemoReadOnly(readOnly...) { + op.Password = "" + } var item dto.ImageRepoInfo if err := copier.Copy(&item, &op); err != nil { return 0, nil, buserr.WithDetail("ErrStructTransform", err.Error(), nil) diff --git a/agent/app/service/mcp_server.go b/agent/app/service/mcp_server.go index 4e6abb303..a63916d37 100644 --- a/agent/app/service/mcp_server.go +++ b/agent/app/service/mcp_server.go @@ -48,7 +48,7 @@ const ( ) type IMcpServerService interface { - Page(req request.McpServerSearch) response.McpServersRes + Page(req request.McpServerSearch, readOnly ...bool) response.McpServersRes Detail(req request.McpServerDetail) (response.McpServerDTO, error) Create(create request.McpServerCreate) error Update(req request.McpServerUpdate) error @@ -65,7 +65,7 @@ func NewIMcpServerService() IMcpServerService { return &McpServerService{} } -func (m McpServerService) Page(req request.McpServerSearch) response.McpServersRes { +func (m McpServerService) Page(req request.McpServerSearch, readOnly ...bool) response.McpServersRes { var ( res response.McpServersRes items []response.McpServerDTO @@ -74,6 +74,10 @@ func (m McpServerService) Page(req request.McpServerSearch) response.McpServersR total, data, _ := mcpServerRepo.Page(req.PageInfo.Page, req.PageInfo.PageSize) for _, item := range data { normalizeMcpServerGateway(&item) + if isDemoReadOnly(readOnly...) { + item.DockerCompose = "" + item.Env = "" + } items = append(items, response.McpServerDTO{ McpServer: item, Environments: make([]request.Environment, 0), diff --git a/agent/app/service/runtime.go b/agent/app/service/runtime.go index 3d60040f0..61fe95021 100644 --- a/agent/app/service/runtime.go +++ b/agent/app/service/runtime.go @@ -48,7 +48,7 @@ type IRuntimeService interface { 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) + Get(id uint, readOnly ...bool) (res *response.RuntimeDTO, err error) GetNodePackageRunScript(req request.NodePackageReq) ([]response.PackageScripts, error) OperateRuntime(req request.RuntimeOperate) error GetNodeModules(req request.NodeModuleReq) ([]response.NodeModule, error) @@ -70,7 +70,7 @@ type IRuntimeService interface { GetFPMConfig(id uint) (*request.FPMConfig, error) UpdatePHPContainer(req request.PHPContainerConfig) error - GetPHPContainerConfig(id uint) (*request.PHPContainerConfig, error) + GetPHPContainerConfig(id uint, readOnly ...bool) (*request.PHPContainerConfig, error) GetSupervisorProcess(id uint) ([]response.SupervisorProcessConfig, error) OperateSupervisorProcess(req request.PHPSupervisorProcessConfig) error @@ -332,8 +332,11 @@ func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.Runt if len(runtimes) == 0 { return 0, res, nil } - if err = SyncRuntimesStatus(runtimes); err != nil { - return 0, nil, err + readOnlyMode := isDemoReadOnly(req.ReadOnly) + if !readOnlyMode { + if err = SyncRuntimesStatus(runtimes); err != nil { + return 0, nil, err + } } for _, runtime := range runtimes { if runtime.Resource == constant.ResourceLocal { @@ -347,7 +350,7 @@ func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.Runt } detail, _ := appDetailRepo.GetFirst(repo.WithByID(runtime.AppDetailID)) if detail.AppId == 0 { - appID, appDetailID := handleRuntimeDetailID(runtime) + appID, appDetailID := handleRuntimeDetailID(runtime, !readOnlyMode) runtimeDTO.AppDetailID = appDetailID runtimeDTO.AppID = appID } else { @@ -358,6 +361,9 @@ func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.Runt runtimeDTO.Params[k] = v } } + if readOnlyMode { + redactSensitiveValues(runtimeDTO.Params) + } runtimeDTO.ExposedPorts, _ = loadComposeExposedPortsFromEnv(envs, "", false) res = append(res, runtimeDTO) } @@ -538,7 +544,7 @@ func deleteRuntimeImages(runtime *model.Runtime, taskItem *task.Task) { } } -func (r *RuntimeService) Get(id uint) (*response.RuntimeDTO, error) { +func (r *RuntimeService) Get(id uint, readOnly ...bool) (*response.RuntimeDTO, error) { runtime, err := runtimeRepo.GetFirst(context.Background(), repo.WithByID(id)) if err != nil { return nil, err @@ -627,6 +633,11 @@ func (r *RuntimeService) Get(id uint) (*response.RuntimeDTO, error) { return nil, err } } + if isDemoReadOnly(readOnly...) { + redactSensitiveValues(res.Params) + redactSensitiveAppParams(res.AppParams) + redactSensitiveEnvironments(res.Environments) + } return &res, nil } @@ -1348,7 +1359,7 @@ func (r *RuntimeService) UpdatePHPContainer(req request.PHPContainerConfig) erro return nil } -func (r *RuntimeService) GetPHPContainerConfig(id uint) (*request.PHPContainerConfig, error) { +func (r *RuntimeService) GetPHPContainerConfig(id uint, readOnly ...bool) (*request.PHPContainerConfig, error) { runtime, err := runtimeRepo.GetFirst(context.Background(), repo.WithByID(id)) if err != nil { return nil, err @@ -1365,6 +1376,9 @@ func (r *RuntimeService) GetPHPContainerConfig(id uint) (*request.PHPContainerCo Volumes: runtimeDTO.Volumes, ExtraHosts: runtimeDTO.ExtraHosts, } + if isDemoReadOnly(readOnly...) { + redactSensitiveEnvironments(res.Environments) + } return res, nil } diff --git a/agent/app/service/runtime_utils.go b/agent/app/service/runtime_utils.go index 16e3f2665..7df830979 100644 --- a/agent/app/service/runtime_utils.go +++ b/agent/app/service/runtime_utils.go @@ -245,7 +245,9 @@ func SyncRuntimesStatus(runtimes []model.Runtime) error { case "restarting": runtimes[index].Status = constant.StatusRestarting } - _ = runtimeRepo.Save(&runtimes[index]) + if !global.CONF.Base.IsDemo { + _ = runtimeRepo.Save(&runtimes[index]) + } delete(runtimeContainer, contain.Names[0]) } } @@ -295,6 +297,9 @@ func SyncRuntimeContainerStatus(runtime *model.Runtime) error { } } + if global.CONF.Base.IsDemo { + return nil + } return runtimeRepo.Save(runtime) } @@ -1148,7 +1153,7 @@ func getOperation(operate, pkgManager string) string { return ops[1] } -func handleRuntimeDetailID(runtime model.Runtime) (uint, uint) { +func handleRuntimeDetailID(runtime model.Runtime, persist bool) (uint, uint) { app, _ := appRepo.GetFirst(appRepo.WithKey(runtime.Type)) if app.ID == 0 { return 0, 0 @@ -1158,6 +1163,8 @@ func handleRuntimeDetailID(runtime model.Runtime) (uint, uint) { return 0, 0 } runtime.AppDetailID = appDetail.ID - _ = runtimeRepo.Save(&runtime) + if persist && !global.CONF.Base.IsDemo { + _ = runtimeRepo.Save(&runtime) + } return app.ID, appDetail.ID } diff --git a/agent/app/service/setting.go b/agent/app/service/setting.go index 4b453618d..847bc0278 100644 --- a/agent/app/service/setting.go +++ b/agent/app/service/setting.go @@ -40,7 +40,7 @@ type ISettingService interface { SaveConnInfo(req dto.SSHConnData) error SetDefaultIsConn(req dto.SSHDefaultConn) error GetSystemProxy() (*dto.SystemProxy, error) - GetLocalConn() dto.SSHConnData + GetLocalConn(readOnly ...bool) dto.SSHConnData GetLocalConnForSSH() (dto.SSHConnData, error) SaveDescription(req dto.CommonDescription) error @@ -311,8 +311,14 @@ func (u *SettingService) loadLocalConn() dto.SSHConnData { return data } -func (u *SettingService) GetLocalConn() dto.SSHConnData { +func (u *SettingService) GetLocalConn(readOnly ...bool) dto.SSHConnData { data := u.loadLocalConn() + if isDemoReadOnly(readOnly...) { + data.Password = "" + data.PrivateKey = "" + data.PassPhrase = "" + return data + } if len(data.Password) != 0 { data.Password = base64.StdEncoding.EncodeToString([]byte(data.Password)) } diff --git a/agent/app/service/ssh.go b/agent/app/service/ssh.go index 24dee35dc..7edada825 100644 --- a/agent/app/service/ssh.go +++ b/agent/app/service/ssh.go @@ -57,7 +57,7 @@ type ISSHService interface { SyncRootCert() error CreateRootCert(req dto.RootCertOperate) error EditRootCert(req dto.RootCertOperate) error - SearchRootCerts(req dto.SearchWithPage) (int64, interface{}, error) + SearchRootCerts(req dto.SearchWithPage, readOnly ...bool) (int64, interface{}, error) DeleteRootCerts(req dto.ForceDelete) error } @@ -585,7 +585,7 @@ func (u *SSHService) EditRootCert(req dto.RootCertOperate) error { return hostRepo.SaveCert(&cert) } -func (u *SSHService) SearchRootCerts(req dto.SearchWithPage) (int64, interface{}, error) { +func (u *SSHService) SearchRootCerts(req dto.SearchWithPage, readOnly ...bool) (int64, interface{}, error) { total, records, err := hostRepo.PageCert(req.Page, req.PageSize) if err != nil { return 0, nil, err @@ -597,12 +597,15 @@ func (u *SSHService) SearchRootCerts(req dto.SearchWithPage) (int64, interface{} if err == nil && len(publicItem) != 0 { publicBase64 = base64.StdEncoding.EncodeToString(publicItem) } - privateItem, _ := os.ReadFile(records[i].PrivateKeyPath) var privateBase64 string - if err == nil && len(publicItem) != 0 { - privateBase64 = base64.StdEncoding.EncodeToString(privateItem) + var passPhrase string + if !isDemoReadOnly(readOnly...) { + privateItem, _ := os.ReadFile(records[i].PrivateKeyPath) + if len(privateItem) != 0 { + privateBase64 = base64.StdEncoding.EncodeToString(privateItem) + } + passPhrase, _ = encrypt.StringDecryptWithBase64(records[i].PassPhrase) } - passPhrase, _ := encrypt.StringDecryptWithBase64(records[i].PassPhrase) datas = append(datas, dto.RootCert{ ID: records[i].ID, CreatedAt: records[i].CreatedAt, diff --git a/agent/app/service/tensorrt_llm.go b/agent/app/service/tensorrt_llm.go index 5fbf68cb0..81ffd7c26 100644 --- a/agent/app/service/tensorrt_llm.go +++ b/agent/app/service/tensorrt_llm.go @@ -28,7 +28,7 @@ import ( type TensorRTLLMService struct{} type ITensorRTLLMService interface { - Page(req request.TensorRTLLMSearch) response.TensorRTLLMsRes + Page(req request.TensorRTLLMSearch, readOnly bool) response.TensorRTLLMsRes Create(create request.TensorRTLLMCreate) error Update(req request.TensorRTLLMUpdate) error Delete(id uint) error @@ -39,18 +39,23 @@ func NewITensorRTLLMService() ITensorRTLLMService { return &TensorRTLLMService{} } -func (t TensorRTLLMService) Page(req request.TensorRTLLMSearch) response.TensorRTLLMsRes { +func (t TensorRTLLMService) Page(req request.TensorRTLLMSearch, readOnly bool) response.TensorRTLLMsRes { var ( res response.TensorRTLLMsRes items []response.TensorRTLLMDTO ) + readOnlyMode := isDemoReadOnly(readOnly) total, data, _ := tensorrtLLMRepo.Page(req.PageInfo.Page, req.PageInfo.PageSize) for _, item := range data { - _ = syncTensorRTLLMContainerStatus(&item) + _ = syncTensorRTLLMContainerStatus(&item, readOnlyMode) serverDTO := response.TensorRTLLMDTO{ TensorRTLLM: item, } + if readOnlyMode { + serverDTO.DockerCompose = "" + serverDTO.Env = "" + } envs, _ := gotenv.Unmarshal(item.Env) serverDTO.Version = envs["VERSION"] serverDTO.ModelDir = envs["MODEL_PATH"] @@ -63,6 +68,9 @@ func (t TensorRTLLMService) Page(req request.TensorRTLLMSearch) response.TensorR composeByte, err := files.NewFileOp().GetContent(path.Join(global.Dir.TensorRTLLMDir, item.Name, "docker-compose.yml")) if err == nil { serverDTO.Environments, _ = getDockerComposeEnvironments(composeByte) + if readOnlyMode { + redactSensitiveEnvironments(serverDTO.Environments) + } } volumes, err := getDockerComposeVolumes(composeByte) if err == nil { @@ -323,10 +331,10 @@ func startTensorRTLLM(tensorrtLLM *model.TensorRTLLM) { tensorrtLLM.Status = constant.StatusRunning tensorrtLLM.Message = "" } - _ = syncTensorRTLLMContainerStatus(tensorrtLLM) + _ = syncTensorRTLLMContainerStatus(tensorrtLLM, false) } -func syncTensorRTLLMContainerStatus(tensorrtLLM *model.TensorRTLLM) error { +func syncTensorRTLLMContainerStatus(tensorrtLLM *model.TensorRTLLM, readOnly bool) error { containerNames := []string{tensorrtLLM.ContainerName} cli, err := docker.NewClient() if err != nil { @@ -342,6 +350,9 @@ func syncTensorRTLLMContainerStatus(tensorrtLLM *model.TensorRTLLM) error { return nil } tensorrtLLM.Status = constant.StatusStopped + if readOnly || global.CONF.Base.IsDemo { + return nil + } return tensorrtLLMRepo.Save(tensorrtLLM) } container := containers[0] @@ -359,6 +370,9 @@ func syncTensorRTLLMContainerStatus(tensorrtLLM *model.TensorRTLLM) error { tensorrtLLM.Status = constant.StatusStopped } } + if readOnly || global.CONF.Base.IsDemo { + return nil + } return tensorrtLLMRepo.Save(tensorrtLLM) } diff --git a/agent/app/service/website.go b/agent/app/service/website.go index 5b88b2fd6..b0dc76309 100644 --- a/agent/app/service/website.go +++ b/agent/app/service/website.go @@ -94,7 +94,7 @@ type IWebsiteService interface { GetWebsiteNginxConfig(websiteId uint, configType string) (*response.FileInfo, error) UpdateNginxConfigFile(req request.WebsiteNginxUpdate) error - GetWebsiteHTTPS(websiteId uint) (response.WebsiteHTTPS, error) + GetWebsiteHTTPS(websiteId uint, readOnly ...bool) (response.WebsiteHTTPS, error) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteHTTPSOp) (*response.WebsiteHTTPS, error) LoadWebsiteDirConfig(req request.WebsiteCommonReq) (*response.WebsiteDirConfig, error) @@ -117,7 +117,7 @@ type IWebsiteService interface { SetRealIPConfig(req request.WebsiteRealIP) error GetRealIPConfig(websiteID uint) (*response.WebsiteRealIP, error) - GetWebsiteResource(websiteID uint) ([]response.Resource, error) + GetWebsiteResource(websiteID uint, readOnly ...bool) ([]response.Resource, error) ListDatabases() ([]response.Database, error) ChangeDatabase(req request.ChangeDatabase) error @@ -914,7 +914,7 @@ func (w WebsiteService) GetWebsiteNginxConfig(websiteID uint, configType string) return &response.FileInfo{FileInfo: *info}, nil } -func (w WebsiteService) GetWebsiteHTTPS(websiteId uint) (response.WebsiteHTTPS, error) { +func (w WebsiteService) GetWebsiteHTTPS(websiteId uint, readOnly ...bool) (response.WebsiteHTTPS, error) { website, err := websiteRepo.GetFirst(repo.WithByID(websiteId)) if err != nil { return response.WebsiteHTTPS{}, err @@ -938,6 +938,10 @@ func (w WebsiteService) GetWebsiteHTTPS(websiteId uint) (response.WebsiteHTTPS, return response.WebsiteHTTPS{}, err } res.SSL = *websiteSSL + if isDemoReadOnly(readOnly...) { + res.SSL.PrivateKey = "" + res.SSL.AcmeAccount.EabHmacKey = "" + } res.Enable = true if website.HttpConfig != "" { res.HttpConfig = website.HttpConfig @@ -2238,7 +2242,7 @@ func (w WebsiteService) GetRealIPConfig(websiteID uint) (*response.WebsiteRealIP return res, err } -func (w WebsiteService) GetWebsiteResource(websiteID uint) ([]response.Resource, error) { +func (w WebsiteService) GetWebsiteResource(websiteID uint, readOnly ...bool) ([]response.Resource, error) { website, err := websiteRepo.GetFirst(repo.WithByID(websiteID)) if err != nil { return nil, err @@ -2307,6 +2311,11 @@ func (w WebsiteService) GetWebsiteResource(websiteID uint) ([]response.Resource, } } } + if isDemoReadOnly(readOnly...) { + for i := range res { + res[i].Detail = nil + } + } return res, nil } diff --git a/agent/app/service/website_acme_account.go b/agent/app/service/website_acme_account.go index f29fbb99a..57ce36714 100644 --- a/agent/app/service/website_acme_account.go +++ b/agent/app/service/website_acme_account.go @@ -14,7 +14,7 @@ type WebsiteAcmeAccountService struct { } type IWebsiteAcmeAccountService interface { - Page(search dto.PageInfo) (int64, []response.WebsiteAcmeAccountDTO, error) + Page(search dto.PageInfo, readOnly ...bool) (int64, []response.WebsiteAcmeAccountDTO, error) Create(create request.WebsiteAcmeAccountCreate) (*response.WebsiteAcmeAccountDTO, error) Delete(id uint) error Update(update request.WebsiteAcmeAccountUpdate) (*response.WebsiteAcmeAccountDTO, error) @@ -24,10 +24,13 @@ func NewIWebsiteAcmeAccountService() IWebsiteAcmeAccountService { return &WebsiteAcmeAccountService{} } -func (w WebsiteAcmeAccountService) Page(search dto.PageInfo) (int64, []response.WebsiteAcmeAccountDTO, error) { +func (w WebsiteAcmeAccountService) Page(search dto.PageInfo, readOnly ...bool) (int64, []response.WebsiteAcmeAccountDTO, error) { total, accounts, err := websiteAcmeRepo.Page(search.Page, search.PageSize, repo.WithOrderDesc("created_at")) var accountDTOs []response.WebsiteAcmeAccountDTO for _, account := range accounts { + if isDemoReadOnly(readOnly...) { + account.EabHmacKey = "" + } accountDTOs = append(accountDTOs, response.WebsiteAcmeAccountDTO{ WebsiteAcmeAccount: account, }) diff --git a/agent/app/service/website_ca.go b/agent/app/service/website_ca.go index 0052e7fac..b4c702ee0 100644 --- a/agent/app/service/website_ca.go +++ b/agent/app/service/website_ca.go @@ -37,9 +37,9 @@ type WebsiteCAService struct { } type IWebsiteCAService interface { - Page(search request.WebsiteCASearch) (int64, []response.WebsiteCADTO, error) + Page(search request.WebsiteCASearch, readOnly ...bool) (int64, []response.WebsiteCADTO, error) Create(create request.WebsiteCACreate) (*request.WebsiteCACreate, error) - GetCA(id uint) (*response.WebsiteCADTO, error) + GetCA(id uint, readOnly ...bool) (*response.WebsiteCADTO, error) Delete(id uint) error ObtainSSL(req request.WebsiteCAObtain) (*model.WebsiteSSL, error) DownloadFile(id uint) (*os.File, error) @@ -49,13 +49,16 @@ func NewIWebsiteCAService() IWebsiteCAService { return &WebsiteCAService{} } -func (w WebsiteCAService) Page(search request.WebsiteCASearch) (int64, []response.WebsiteCADTO, error) { +func (w WebsiteCAService) Page(search request.WebsiteCASearch, readOnly ...bool) (int64, []response.WebsiteCADTO, error) { total, cas, err := websiteCARepo.Page(search.Page, search.PageSize, repo.WithOrderDesc("created_at")) if err != nil { return 0, nil, err } var caDTOs []response.WebsiteCADTO for _, ca := range cas { + if isDemoReadOnly(readOnly...) { + ca.PrivateKey = "" + } caDTOs = append(caDTOs, response.WebsiteCADTO{ WebsiteCA: ca, }) @@ -125,12 +128,15 @@ func (w WebsiteCAService) Create(create request.WebsiteCACreate) (*request.Websi return &create, nil } -func (w WebsiteCAService) GetCA(id uint) (*response.WebsiteCADTO, error) { +func (w WebsiteCAService) GetCA(id uint, readOnly ...bool) (*response.WebsiteCADTO, error) { res := &response.WebsiteCADTO{} ca, err := websiteCARepo.GetFirst(repo.WithByID(id)) if err != nil { return nil, err } + if isDemoReadOnly(readOnly...) { + ca.PrivateKey = "" + } res.WebsiteCA = ca certBlock, _ := pem.Decode([]byte(ca.CSR)) if certBlock == nil { diff --git a/agent/app/service/website_dns_account.go b/agent/app/service/website_dns_account.go index 6260a2270..0bf71a79d 100644 --- a/agent/app/service/website_dns_account.go +++ b/agent/app/service/website_dns_account.go @@ -16,7 +16,7 @@ type WebsiteDnsAccountService struct { } type IWebsiteDnsAccountService interface { - Page(search dto.PageInfo) (int64, []response.WebsiteDnsAccountDTO, error) + Page(search dto.PageInfo, readOnly ...bool) (int64, []response.WebsiteDnsAccountDTO, error) Create(create request.WebsiteDnsAccountCreate) (request.WebsiteDnsAccountCreate, error) Update(update request.WebsiteDnsAccountUpdate) (request.WebsiteDnsAccountUpdate, error) Delete(id uint) error @@ -26,12 +26,14 @@ func NewIWebsiteDnsAccountService() IWebsiteDnsAccountService { return &WebsiteDnsAccountService{} } -func (w WebsiteDnsAccountService) Page(search dto.PageInfo) (int64, []response.WebsiteDnsAccountDTO, error) { +func (w WebsiteDnsAccountService) Page(search dto.PageInfo, readOnly ...bool) (int64, []response.WebsiteDnsAccountDTO, error) { total, accounts, err := websiteDnsRepo.Page(search.Page, search.PageSize, repo.WithOrderDesc("created_at")) var accountDTOs []response.WebsiteDnsAccountDTO for _, account := range accounts { auth := make(map[string]string) - _ = json.Unmarshal([]byte(account.Authorization), &auth) + if !isDemoReadOnly(readOnly...) { + _ = json.Unmarshal([]byte(account.Authorization), &auth) + } accountDTOs = append(accountDTOs, response.WebsiteDnsAccountDTO{ WebsiteDnsAccount: account, Authorization: auth, diff --git a/agent/app/service/website_ssl.go b/agent/app/service/website_ssl.go index f90628fc5..76511bdd1 100644 --- a/agent/app/service/website_ssl.go +++ b/agent/app/service/website_ssl.go @@ -95,12 +95,12 @@ func newWebsiteSSLLegoClient(ctx context.Context, acmeAccount *model.WebsiteAcme } type IWebsiteSSLService interface { - Page(search request.WebsiteSSLSearch) (int64, []response.WebsiteSSLDTO, error) - GetSSL(id uint) (*response.WebsiteSSLDTO, error) + Page(search request.WebsiteSSLSearch, readOnly ...bool) (int64, []response.WebsiteSSLDTO, error) + GetSSL(id uint, readOnly ...bool) (*response.WebsiteSSLDTO, error) Search(req request.WebsiteSSLListReq) ([]response.WebsiteSSLDTO, error) Create(create request.WebsiteSSLCreate) (request.WebsiteSSLCreate, error) GetDNSResolve(req request.WebsiteDNSReq) ([]response.WebsiteDNSRes, error) - GetWebsiteSSL(websiteId uint) (response.WebsiteSSLDTO, error) + GetWebsiteSSL(websiteId uint, readOnly ...bool) (response.WebsiteSSLDTO, error) Delete(ids []uint) error Update(update request.WebsiteSSLUpdate) error Upload(req request.WebsiteSSLUpload) error @@ -116,7 +116,7 @@ func NewIWebsiteSSLService() IWebsiteSSLService { return &WebsiteSSLService{} } -func (w WebsiteSSLService) Page(search request.WebsiteSSLSearch) (int64, []response.WebsiteSSLDTO, error) { +func (w WebsiteSSLService) Page(search request.WebsiteSSLSearch, readOnly ...bool) (int64, []response.WebsiteSSLDTO, error) { var ( result []response.WebsiteSSLDTO opts []repo.DBOption @@ -134,6 +134,10 @@ func (w WebsiteSSLService) Page(search request.WebsiteSSLSearch) (int64, []respo return 0, nil, err } for _, model := range sslList { + if isDemoReadOnly(readOnly...) { + model.PrivateKey = "" + model.AcmeAccount.EabHmacKey = "" + } result = append(result, response.WebsiteSSLDTO{ WebsiteSSL: model, LogPath: path.Join(global.Dir.SSLLogDir, fmt.Sprintf("%s-ssl-%d.log", model.PrimaryDomain, model.ID)), @@ -142,12 +146,16 @@ func (w WebsiteSSLService) Page(search request.WebsiteSSLSearch) (int64, []respo return total, result, err } -func (w WebsiteSSLService) GetSSL(id uint) (*response.WebsiteSSLDTO, error) { +func (w WebsiteSSLService) GetSSL(id uint, readOnly ...bool) (*response.WebsiteSSLDTO, error) { var res response.WebsiteSSLDTO websiteSSL, err := websiteSSLRepo.GetFirst(repo.WithByID(id)) if err != nil { return nil, err } + if isDemoReadOnly(readOnly...) { + websiteSSL.PrivateKey = "" + websiteSSL.AcmeAccount.EabHmacKey = "" + } res.WebsiteSSL = *websiteSSL return &res, nil } @@ -682,7 +690,7 @@ func (w WebsiteSSLService) GetDNSResolve(req request.WebsiteDNSReq) ([]response. return res, nil } -func (w WebsiteSSLService) GetWebsiteSSL(websiteId uint) (response.WebsiteSSLDTO, error) { +func (w WebsiteSSLService) GetWebsiteSSL(websiteId uint, readOnly ...bool) (response.WebsiteSSLDTO, error) { var res response.WebsiteSSLDTO website, err := websiteRepo.GetFirst(repo.WithByID(websiteId)) if err != nil { @@ -692,6 +700,10 @@ func (w WebsiteSSLService) GetWebsiteSSL(websiteId uint) (response.WebsiteSSLDTO if err != nil { return res, err } + if isDemoReadOnly(readOnly...) { + websiteSSL.PrivateKey = "" + websiteSSL.AcmeAccount.EabHmacKey = "" + } res.WebsiteSSL = *websiteSSL return res, nil } diff --git a/agent/constant/common.go b/agent/constant/common.go index 347a23ff7..e323a1f2e 100644 --- a/agent/constant/common.go +++ b/agent/constant/common.go @@ -22,6 +22,7 @@ const ( TypeComposeCreate = "compose-create" InterruptedMsg = "the task was interrupted due to the restart of the 1panel service" + DemoModeHeader = "X-Panel-Demo-Mode" ) const ( diff --git a/core/app/auth/auth.go b/core/app/auth/auth.go index 825c1edb4..c83a6c138 100644 --- a/core/app/auth/auth.go +++ b/core/app/auth/auth.go @@ -49,8 +49,10 @@ func Login(c *gin.Context, info dto.Login, entrance string) (*dto.UserLoginInfo, if err != nil { return nil, "", err } - if err = settingRepo.Update("Language", info.Language); err != nil { - return nil, "", err + if !global.CONF.Base.IsDemo { + if err = settingRepo.Update("Language", info.Language); err != nil { + return nil, "", err + } } if mfaSetting.Value == constant.StatusEnable { return BeginMFALogin(c, nameSetting.Value, entrance, mfaSetting.Value), "", nil diff --git a/core/app/service/setting.go b/core/app/service/setting.go index 687a78ab6..9f34ff0e3 100644 --- a/core/app/service/setting.go +++ b/core/app/service/setting.go @@ -99,13 +99,17 @@ func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) { } if info.Edition == "" { info.Edition = "cn" - _ = settingRepo.UpdateOrCreate("Edition", info.Edition) + if !global.CONF.Base.IsDemo { + _ = settingRepo.UpdateOrCreate("Edition", info.Edition) + } } if info.MenuAccordion == "" { info.MenuAccordion = constant.StatusDisable - _ = settingRepo.UpdateOrCreate("MenuAccordion", info.MenuAccordion) + if !global.CONF.Base.IsDemo { + _ = settingRepo.UpdateOrCreate("MenuAccordion", info.MenuAccordion) + } } - if info.ProxyPasswdKeep != constant.StatusEnable { + if global.CONF.Base.IsDemo || info.ProxyPasswdKeep != constant.StatusEnable { info.ProxyPasswd = "" } else { info.ProxyPasswd, _ = encrypt.StringDecrypt(info.ProxyPasswd) @@ -142,11 +146,15 @@ func (u *SettingService) GetSettingBaseInfo() (*dto.SettingBaseInfo, error) { } if info.Edition == "" { info.Edition = "cn" - _ = settingRepo.UpdateOrCreate("Edition", info.Edition) + if !global.CONF.Base.IsDemo { + _ = settingRepo.UpdateOrCreate("Edition", info.Edition) + } } if info.MenuAccordion == "" { info.MenuAccordion = constant.StatusDisable - _ = settingRepo.UpdateOrCreate("MenuAccordion", info.MenuAccordion) + if !global.CONF.Base.IsDemo { + _ = settingRepo.UpdateOrCreate("MenuAccordion", info.MenuAccordion) + } } return &info, err @@ -516,6 +524,9 @@ func (u *SettingService) LoadFromCert() (*dto.SSLInfo, error) { data.SSLID = uint(id) data.Timeout = ssl.ExpireDate.Format(constant.DateTimeLayout) } + if global.CONF.Base.IsDemo { + data.Key = "" + } return &data, nil } diff --git a/core/constant/common.go b/core/constant/common.go index 7385960dc..30f952866 100644 --- a/core/constant/common.go +++ b/core/constant/common.go @@ -13,6 +13,7 @@ const ( DefaultDate = "1970-01-01" DateTimeLayout = "2006-01-02 15:04:05" // or use time.DateTime while go version >= 1.20 DateTimeSlimLayout = "20060102150405" + DemoModeHeader = "X-Panel-Demo-Mode" OrderDesc = "descending" OrderAsc = "ascending" diff --git a/core/init/router/proxy.go b/core/init/router/proxy.go index 3be526474..834dae4bd 100644 --- a/core/init/router/proxy.go +++ b/core/init/router/proxy.go @@ -50,6 +50,7 @@ func Proxy() gin.HandlerFunc { if userName := middleware.LoadOperationUser(c); userName != "" { c.Request.Header.Set("X-Panel-User", url.QueryEscape(userName)) } + c.Request.Header.Set(constant.DemoModeHeader, strconv.FormatBool(global.CONF.Base.IsDemo)) if reqPath == "/api/v2/hosts/terminal/local" && (currentNode == "local" || len(currentNode) == 0) { proxyLocalAgent(c) diff --git a/core/middleware/demo_handle.go b/core/middleware/demo_handle.go index 431bc2b2c..cc9309e30 100644 --- a/core/middleware/demo_handle.go +++ b/core/middleware/demo_handle.go @@ -3,62 +3,184 @@ package middleware import ( "net/http" "strings" + "sync" "github.com/1Panel-dev/1Panel/core/app/dto" "github.com/1Panel-dev/1Panel/core/buserr" "github.com/gin-gonic/gin" ) -var whiteUrlList = map[string]struct{}{ - "/api/v2/dashboard/app/launcher/option": {}, - "/api/v2/websites/config": {}, - "/api/v2/websites/waf/config": {}, - "/api/v2/files/size": {}, - "/api/v2/runtimes/sync": {}, - "/api/v2/toolbox/device/base": {}, - "/api/v2/files/user/group": {}, - "/api/v2/files/mount": {}, - "/api/v2/hosts/ssh/log": {}, - "/api/v2/toolbox/clam/base": {}, - "/api/v2/backups/record/size": {}, +var ( + demoRouteMu sync.RWMutex - "/api/v2/core/auth/login": {}, - "/api/v2/core/logs/login": {}, - "/api/v2/core/logs/operation": {}, - "/api/v2/core/auth/logout": {}, + demoReadOnlyPostRoutes = map[string]struct{}{ + "/api/v2/dashboard/app/launcher/option": {}, + "/api/v2/websites/config": {}, + "/api/v2/websites/waf/config": {}, + "/api/v2/websites/options": {}, + "/api/v2/websites/rewrite": {}, + "/api/v2/websites/dir": {}, + "/api/v2/websites/proxies": {}, + "/api/v2/websites/auths": {}, + "/api/v2/websites/leech": {}, + "/api/v2/websites/redirect": {}, + "/api/v2/files/size": {}, + "/api/v2/files/tree": {}, + "/api/v2/toolbox/device/base": {}, + "/api/v2/files/user/group": {}, + "/api/v2/files/mount": {}, + "/api/v2/hosts/ssh/log": {}, + "/api/v2/toolbox/clam/base": {}, + "/api/v2/backups/record/size": {}, + "/api/v2/containers/info": {}, + "/api/v2/containers/list": {}, + "/api/v2/containers/list/byimage": {}, + "/api/v2/containers/users": {}, + "/api/v2/containers/files/size": {}, + "/api/v2/logs/system/read": {}, + "/api/v2/logs/tasks/read": {}, - "/api/v2/apps/installed/loadport": {}, - "/api/v2/apps/installed/check": {}, - "/api/v2/apps/installed/conninfo": {}, - "/api/v2/databases/load/file": {}, - "/api/v2/databases/variables": {}, - "/api/v2/databases/status": {}, - "/api/v2/databases/baseinfo": {}, + "/api/v2/core/auth/login": {}, + "/api/v2/core/auth/mfalogin": {}, + "/api/v2/core/auth/passkey/begin": {}, + "/api/v2/core/auth/passkey/finish": {}, + "/api/v2/core/logs/login": {}, + "/api/v2/core/logs/operation": {}, + "/api/v2/core/auth/logout": {}, + "/api/v2/core/settings/search/base": {}, - "/api/v2/xpack/waf/attack/stat": {}, - "/api/v2/xpack/waf/config/website": {}, - "/api/v2/xpack/waf/relation/stat": {}, + "/api/v2/apps/installed/loadport": {}, + "/api/v2/apps/installed/check": {}, + "/api/v2/apps/installed/conninfo": {}, + "/api/v2/databases/common/info": {}, + "/api/v2/databases/common/load/file": {}, + "/api/v2/databases/load/file": {}, + "/api/v2/databases/variables": {}, + "/api/v2/databases/status": {}, + "/api/v2/databases/baseinfo": {}, + "/api/v2/backups/search/files": {}, + "/api/v2/backups/record/search/bycronjob": {}, + "/api/v2/cronjobs/search/records": {}, - "/api/v2/xpack/monitor/stat": {}, - "/api/v2/xpack/monitor/visitors": {}, - "/api/v2/xpack/monitor/visitors/loc": {}, - "/api/v2/xpack/monitor/qps": {}, - "/api/v2/xpack/monitor/logs/stat": {}, - "/api/v2/xpack/monitor/websites": {}, - "/api/v2/xpack/monitor/trend": {}, - "/api/v2/xpack/monitor/rank": {}, - "/api/v2/xpack/waf/cdn": {}, + "/api/v2/xpack/waf/attack/stat": {}, + "/api/v2/xpack/waf/config/website": {}, + "/api/v2/xpack/waf/relation/stat": {}, - "/api/v2/core/nodes/list": {}, + "/api/v2/xpack/monitor/stat": {}, + "/api/v2/xpack/monitor/visitors": {}, + "/api/v2/xpack/monitor/visitors/loc": {}, + "/api/v2/xpack/monitor/qps": {}, + "/api/v2/xpack/monitor/logs/stat": {}, + "/api/v2/xpack/monitor/websites": {}, + "/api/v2/xpack/monitor/trend": {}, + "/api/v2/xpack/monitor/rank": {}, + "/api/v2/xpack/waf/cdn": {}, + "/api/v2/xpack/tampers/search/log": {}, + "/api/v2/xpack/tampers/search/file": {}, + + "/api/v2/core/nodes/list": {}, + "/api/v2/core/xpack/nodes/search/upgrade/logs": {}, + } + + demoBlockedGetRoutes = map[string]struct{}{ + "/api/v2/containers/exec": {}, + "/api/v2/core/script/run": {}, + "/api/v2/files/download": {}, + "/api/v2/hosts/terminal/local": {}, + "/api/v2/hosts/terminal/ssh": {}, + "/api/v2/hosts/terminal/container": {}, + "/api/v2/process/:pid": {}, + } +) + +const demoReadOnlyContextKey = "DEMO_READ_ONLY_REQUEST" + +func RegisterDemoReadOnlyPostRoutes(paths ...string) { + demoRouteMu.Lock() + defer demoRouteMu.Unlock() + for _, routePath := range paths { + if routePath != "" { + demoReadOnlyPostRoutes[routePath] = struct{}{} + } + } +} + +func RegisterDemoBlockedGetRoutes(paths ...string) { + demoRouteMu.Lock() + defer demoRouteMu.Unlock() + for _, routePath := range paths { + if routePath != "" { + demoBlockedGetRoutes[routePath] = struct{}{} + } + } +} + +func demoRequestPath(c *gin.Context) string { + if routePath := c.FullPath(); routePath != "" { + return routePath + } + return c.Request.URL.Path +} + +func isDemoSearchRoute(routePath string) bool { + return strings.HasSuffix(routePath, "/search") || strings.HasSuffix(routePath, "/ai-search") +} + +func isDemoReadOnlyPost(routePath string) bool { + if isDemoSearchRoute(routePath) { + return true + } + demoRouteMu.RLock() + defer demoRouteMu.RUnlock() + for pattern := range demoReadOnlyPostRoutes { + if matchDemoRoute(pattern, routePath) { + return true + } + } + return false +} + +func isDemoBlockedGet(routePath string) bool { + demoRouteMu.RLock() + defer demoRouteMu.RUnlock() + for pattern := range demoBlockedGetRoutes { + if matchDemoRoute(pattern, routePath) { + return true + } + } + return false +} + +func matchDemoRoute(pattern, routePath string) bool { + if pattern == routePath { + return true + } + patternParts := strings.Split(strings.Trim(pattern, "/"), "/") + pathParts := strings.Split(strings.Trim(routePath, "/"), "/") + if len(patternParts) != len(pathParts) { + return false + } + for i := range patternParts { + if strings.HasPrefix(patternParts[i], ":") { + continue + } + if patternParts[i] != pathParts[i] { + return false + } + } + return true } func DemoHandle() gin.HandlerFunc { return func(c *gin.Context) { - if strings.Contains(c.Request.URL.Path, "search") || (c.Request.Method == http.MethodGet && c.Request.URL.Path != "/api/v2/containers/exec") { + routePath := demoRequestPath(c) + if c.Request.Method == http.MethodGet && !isDemoBlockedGet(routePath) { + c.Set(demoReadOnlyContextKey, true) c.Next() return } - if _, ok := whiteUrlList[c.Request.URL.Path]; ok { + if c.Request.Method == http.MethodPost && isDemoReadOnlyPost(routePath) { + c.Set(demoReadOnlyContextKey, true) c.Next() return } diff --git a/core/middleware/operation.go b/core/middleware/operation.go index 47fb6d379..0d42efd17 100644 --- a/core/middleware/operation.go +++ b/core/middleware/operation.go @@ -36,7 +36,7 @@ func OperationLog() gin.HandlerFunc { return func(c *gin.Context) { c.Request.Header.Del(headerNeedOperationResolve) - if strings.Contains(c.Request.URL.Path, "search") || c.Request.Method == http.MethodGet { + if c.GetBool(demoReadOnlyContextKey) || strings.Contains(c.Request.URL.Path, "search") || c.Request.Method == http.MethodGet { c.Next() return } diff --git a/core/utils/req_helper/proxy_local/req_to_local.go b/core/utils/req_helper/proxy_local/req_to_local.go index df202ce92..920faf4a2 100644 --- a/core/utils/req_helper/proxy_local/req_to_local.go +++ b/core/utils/req_helper/proxy_local/req_to_local.go @@ -10,11 +10,14 @@ import ( "net/http" "net/url" "os" + "strconv" "strings" "github.com/gin-gonic/gin" "github.com/1Panel-dev/1Panel/core/app/dto" + "github.com/1Panel-dev/1Panel/core/constant" + "github.com/1Panel-dev/1Panel/core/global" "github.com/1Panel-dev/1Panel/core/i18n" ) @@ -82,6 +85,7 @@ func (c *ReusableClient) Request(reqUrl, reqMethod string, body io.Reader, ctx * } } } + req.Header.Set(constant.DemoModeHeader, strconv.FormatBool(global.CONF.Base.IsDemo)) resp, err := c.client.Do(req) if err != nil {