diff --git a/backend/app/api/v1/app_install.go b/backend/app/api/v1/app_install.go index 59baebc77..3b134f956 100644 --- a/backend/app/api/v1/app_install.go +++ b/backend/app/api/v1/app_install.go @@ -1,8 +1,6 @@ package v1 import ( - "reflect" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" @@ -25,7 +23,14 @@ func (b *BaseApi) SearchAppInstalled(c *gin.Context) { if err := helper.CheckBindAndValidate(&req, c); err != nil { return } - if !reflect.DeepEqual(req.PageInfo, dto.PageInfo{}) { + if req.All { + list, err := appInstallService.SearchForWebsite(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, list) + } else { total, list, err := appInstallService.Page(req) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) @@ -35,13 +40,6 @@ func (b *BaseApi) SearchAppInstalled(c *gin.Context) { Items: list, Total: total, }) - } else { - list, err := appInstallService.SearchForWebsite(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, list) } } diff --git a/backend/app/api/v1/website.go b/backend/app/api/v1/website.go index c341414b4..ab151c27f 100644 --- a/backend/app/api/v1/website.go +++ b/backend/app/api/v1/website.go @@ -195,71 +195,6 @@ func (b *BaseApi) GetWebsiteNginx(c *gin.Context) { helper.SuccessWithData(c, fileInfo) } -// @Tags Website Domain -// @Summary Search website domains by websiteId -// @Description 通过网站 id 查询域名 -// @Accept json -// @Param websiteId path integer true "request" -// @Success 200 {array} model.WebsiteDomain -// @Security ApiKeyAuth -// @Router /websites/domains/:websiteId [get] -func (b *BaseApi) GetWebDomains(c *gin.Context) { - websiteId, err := helper.GetIntParamByKey(c, "websiteId") - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) - return - } - list, err := websiteService.GetWebsiteDomain(websiteId) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, list) -} - -// @Tags Website Domain -// @Summary Delete website domain -// @Description 删除网站域名 -// @Accept json -// @Param request body request.WebsiteDomainDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/domains/del [post] -// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_domains","output_column":"domain","output_value":"domain"}],"formatZH":"删除域名 [domain]","formatEN":"Delete domain [domain]"} -func (b *BaseApi) DeleteWebDomain(c *gin.Context) { - var req request.WebsiteDomainDelete - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - if err := websiteService.DeleteWebsiteDomain(req.ID); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website Domain -// @Summary Create website domain -// @Description 创建网站域名 -// @Accept json -// @Param request body request.WebsiteDomainCreate true "request" -// @Success 200 {object} model.WebsiteDomain -// @Security ApiKeyAuth -// @Router /websites/domains [post] -// @x-panel-log {"bodyKeys":["domain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建域名 [domain]","formatEN":"Create domain [domain]"} -func (b *BaseApi) CreateWebDomain(c *gin.Context) { - var req request.WebsiteDomainCreate - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - domain, err := websiteService.CreateWebsiteDomain(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, domain) -} - // @Tags Website Nginx // @Summary Load nginx conf // @Description 获取 nginx 配置 diff --git a/backend/app/api/v1/website_domain.go b/backend/app/api/v1/website_domain.go new file mode 100644 index 000000000..d50433435 --- /dev/null +++ b/backend/app/api/v1/website_domain.go @@ -0,0 +1,73 @@ +package v1 + +import ( + "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" + "github.com/1Panel-dev/1Panel/backend/app/dto/request" + "github.com/1Panel-dev/1Panel/backend/constant" + "github.com/gin-gonic/gin" +) + +// @Tags Website Domain +// @Summary Delete website domain +// @Description 删除网站域名 +// @Accept json +// @Param request body request.WebsiteDomainDelete true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /websites/domains/del [post] +// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_domains","output_column":"domain","output_value":"domain"}],"formatZH":"删除域名 [domain]","formatEN":"Delete domain [domain]"} +func (b *BaseApi) DeleteWebDomain(c *gin.Context) { + var req request.WebsiteDomainDelete + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + if err := websiteService.DeleteWebsiteDomain(req.ID); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} + +// @Tags Website Domain +// @Summary Create website domain +// @Description 创建网站域名 +// @Accept json +// @Param request body request.WebsiteDomainCreate true "request" +// @Success 200 {object} model.WebsiteDomain +// @Security ApiKeyAuth +// @Router /websites/domains [post] +// @x-panel-log {"bodyKeys":["domain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建域名 [domain]","formatEN":"Create domain [domain]"} +func (b *BaseApi) CreateWebDomain(c *gin.Context) { + var req request.WebsiteDomainCreate + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + domain, err := websiteService.CreateWebsiteDomain(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, domain) +} + +// @Tags Website Domain +// @Summary Search website domains by websiteId +// @Description 通过网站 id 查询域名 +// @Accept json +// @Param websiteId path integer true "request" +// @Success 200 {array} model.WebsiteDomain +// @Security ApiKeyAuth +// @Router /websites/domains/:websiteId [get] +func (b *BaseApi) GetWebDomains(c *gin.Context) { + websiteId, err := helper.GetIntParamByKey(c, "websiteId") + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) + return + } + list, err := websiteService.GetWebsiteDomain(websiteId) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, list) +} diff --git a/backend/app/dto/request/app.go b/backend/app/dto/request/app.go index 08a88bec8..d64eeb959 100644 --- a/backend/app/dto/request/app.go +++ b/backend/app/dto/request/app.go @@ -40,6 +40,7 @@ type AppInstalledSearch struct { Tags []string `json:"tags"` Update bool `json:"update"` Unused bool `json:"unused"` + All bool `json:"all"` } type AppInstalledInfo struct { diff --git a/backend/app/dto/request/website.go b/backend/app/dto/request/website.go index a8bfe46ea..99c819a96 100644 --- a/backend/app/dto/request/website.go +++ b/backend/app/dto/request/website.go @@ -45,7 +45,7 @@ type NewAppInstall struct { } type WebsiteInstallCheckReq struct { - InstallIds []uint `json:"InstallIds" validate:"required"` + InstallIds []uint `json:"InstallIds"` } type WebsiteUpdate struct { diff --git a/backend/app/service/website.go b/backend/app/service/website.go index 85c6285b6..cd78c5f79 100644 --- a/backend/app/service/website.go +++ b/backend/app/service/website.go @@ -186,20 +186,6 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error) return err } defaultHttpPort := nginxInstall.HttpPort - if len(primaryDomainArray) > 1 { - portStr := primaryDomainArray[1] - portN, err := strconv.Atoi(portStr) - if err != nil { - return err - } - if exist, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithDomain(primaryDomain), websiteDomainRepo.WithPort(portN)); len(exist) > 0 { - return buserr.New(constant.ErrDomainIsExist) - } - } else { - if exist, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithDomain(primaryDomain), websiteDomainRepo.WithPort(defaultHttpPort)); len(exist) > 0 { - return buserr.New(constant.ErrDomainIsExist) - } - } var ( domains []model.WebsiteDomain @@ -224,6 +210,13 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error) } } + for _, domain := range domains { + if exist, _ := websiteDomainRepo.GetFirst(websiteDomainRepo.WithDomain(domain.Domain), websiteDomainRepo.WithPort(domain.Port)); exist.ID > 0 { + website, _ := websiteRepo.GetFirst(commonRepo.WithByID(exist.WebsiteID)) + return buserr.WithName(constant.ErrDomainIsUsed, website.PrimaryDomain) + } + } + for port := range ports { if existPorts, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithPort(port)); len(existPorts) == 0 { errMap := make(map[string]interface{}) @@ -516,8 +509,9 @@ func (w WebsiteService) CreateWebsiteDomain(create request.WebsiteDomainCreate) } } - if existDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithDomain(create.Domain), websiteDomainRepo.WithPort(create.Port)); len(existDomains) > 0 { - return domainModel, buserr.WithDetail(constant.ErrDomainIsExist, create.Domain, nil) + if existDomain, _ := websiteDomainRepo.GetFirst(websiteDomainRepo.WithDomain(create.Domain), websiteDomainRepo.WithPort(create.Port)); existDomain.ID > 0 { + website, _ := websiteRepo.GetFirst(commonRepo.WithByID(existDomain.WebsiteID)) + return domainModel, buserr.WithName(constant.ErrDomainIsUsed, website.PrimaryDomain) } website, err := websiteRepo.GetFirst(commonRepo.WithByID(create.WebsiteID)) diff --git a/backend/constant/errs.go b/backend/constant/errs.go index 79a456bae..11606f860 100644 --- a/backend/constant/errs.go +++ b/backend/constant/errs.go @@ -71,6 +71,7 @@ var ( ErrUsernameIsNotExist = "ErrUsernameIsNotExist" ErrBackupMatch = "ErrBackupMatch" ErrBackupExist = "ErrBackupExist" + ErrDomainIsUsed = "ErrDomainIsUsed" ) // ssl diff --git a/backend/i18n/lang/en.yaml b/backend/i18n/lang/en.yaml index ff0e294b9..985ce19fc 100644 --- a/backend/i18n/lang/en.yaml +++ b/backend/i18n/lang/en.yaml @@ -75,6 +75,7 @@ ErrBackupMatch: 'the backup file does not match the current partial data of the ErrBackupExist: 'the backup file corresponds to a portion of the original data that does not exist: {{ .detail}}"' ErrPHPResource: 'The local runtime does not support switching!' ErrPathPermission: 'A folder with non-1000:1000 permissions was detected in the index directory, which may cause Access denied errors when accessing the website.' +ErrDomainIsUsed: "Domain is already used by website {{ .name }}" #ssl ErrSSLCannotDelete: "The certificate is being used by the website and cannot be removed" diff --git a/backend/i18n/lang/zh-Hant.yaml b/backend/i18n/lang/zh-Hant.yaml index 9ce558c2a..38f1680aa 100644 --- a/backend/i18n/lang/zh-Hant.yaml +++ b/backend/i18n/lang/zh-Hant.yaml @@ -75,6 +75,7 @@ ErrBackupMatch: '該備份文件與當前網站部分數據不匹配: {{ .detail ErrBackupExist: '該備份文件對應部分原數據不存在: {{ .detail}}"' ErrPHPResource: '本地運行環境不支持切換!' ErrPathPermission: 'index 目錄下檢測到非 1000:1000 權限文件夾,可能導致網站訪問 Access denied 錯誤' +ErrDomainIsUsed: "域名已被網站【{{ .name }}】使用" #ssl ErrSSLCannotDelete: "證書正在被網站使用,無法刪除" diff --git a/backend/i18n/lang/zh.yaml b/backend/i18n/lang/zh.yaml index c6a492dcc..eab7adcc4 100644 --- a/backend/i18n/lang/zh.yaml +++ b/backend/i18n/lang/zh.yaml @@ -75,6 +75,7 @@ ErrBackupMatch: '该备份文件与当前网站部分数据不匹配 {{ .detail} ErrBackupExist: '该备份文件对应部分源数据不存在 {{ .detail}}"' ErrPHPResource: '本地运行环境不支持切换!' ErrPathPermission: 'index 目录下检测到非 1000:1000 权限文件夹,可能导致网站访问 Access denied 错误' +ErrDomainIsUsed: "域名已被网站【{{ .name }}】使用" #ssl ErrSSLCannotDelete: "证书正在被网站使用,无法删除" diff --git a/frontend/src/api/interface/app.ts b/frontend/src/api/interface/app.ts index 657358479..074c5149c 100644 --- a/frontend/src/api/interface/app.ts +++ b/frontend/src/api/interface/app.ts @@ -161,9 +161,10 @@ export namespace App { deleteBackup?: boolean; } - export interface AppInstalledSearch { + export interface AppInstalledSearch extends ReqPage { type: string; unused?: boolean; + all?: boolean; } export interface AppService { diff --git a/frontend/src/views/website/website/create/index.vue b/frontend/src/views/website/website/create/index.vue index f3a080ed9..42202da24 100644 --- a/frontend/src/views/website/website/create/index.vue +++ b/frontend/src/views/website/website/create/index.vue @@ -458,7 +458,7 @@ const changeType = (type: string) => { }; const searchAppInstalled = () => { - GetAppInstalled({ type: 'website', unused: true }).then((res) => { + GetAppInstalled({ type: 'website', unused: true, all: true, page: 1, pageSize: 100 }).then((res) => { appInstalles.value = res.data; if (res.data && res.data.length > 0) { website.value.appInstallId = res.data[0].id;