diff --git a/backend/app/api/v1/app.go b/backend/app/api/v1/app.go index 425f21d21..2e83ae84e 100644 --- a/backend/app/api/v1/app.go +++ b/backend/app/api/v1/app.go @@ -7,7 +7,6 @@ import ( "github.com/1Panel-dev/1Panel/backend/global" "github.com/gin-gonic/gin" "reflect" - "strconv" ) func (b *BaseApi) SearchApp(c *gin.Context) { @@ -35,13 +34,13 @@ func (b *BaseApi) SyncApp(c *gin.Context) { } func (b *BaseApi) GetApp(c *gin.Context) { - idStr := c.Param("id") - u64, err := strconv.ParseUint(idStr, 10, 32) + + id, err := helper.GetParamID(c) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - appDTO, err := appService.GetApp(uint(u64)) + appDTO, err := appService.GetApp(id) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -49,14 +48,15 @@ func (b *BaseApi) GetApp(c *gin.Context) { helper.SuccessWithData(c, appDTO) } func (b *BaseApi) GetAppDetail(c *gin.Context) { - idStr := c.Param("appid") - u64, err := strconv.ParseUint(idStr, 10, 32) + + appId, err := helper.GetIntParamByKey(c, "appId") if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) return } + version := c.Param("version") - appDetailDTO, err := appService.GetAppDetail(uint(u64), version) + appDetailDTO, err := appService.GetAppDetail(appId, version) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -175,17 +175,13 @@ func (b *BaseApi) GetServices(c *gin.Context) { func (b *BaseApi) GetUpdateVersions(c *gin.Context) { - appInstallId := c.Param("appInstallId") - if appInstallId == "" { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, nil) - return - } - id, err := strconv.Atoi(appInstallId) + appInstallId, err := helper.GetIntParamByKey(c, "appInstallId") if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) return } - versions, err := appService.GetUpdateVersions(uint(id)) + + versions, err := appService.GetUpdateVersions(appInstallId) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return diff --git a/backend/app/api/v1/helper/helper.go b/backend/app/api/v1/helper/helper.go index 796d79a02..2d5918723 100644 --- a/backend/app/api/v1/helper/helper.go +++ b/backend/app/api/v1/helper/helper.go @@ -1,6 +1,7 @@ package helper import ( + "fmt" "net/http" "strconv" @@ -85,3 +86,12 @@ func GetParamID(c *gin.Context) (uint, error) { intNum, _ := strconv.Atoi(idParam) return uint(intNum), nil } + +func GetIntParamByKey(c *gin.Context, key string) (uint, error) { + idParam, ok := c.Params.Get(key) + if !ok { + return 0, fmt.Errorf("error %s in path", key) + } + intNum, _ := strconv.Atoi(idParam) + return uint(intNum), nil +} diff --git a/backend/app/api/v1/website.go b/backend/app/api/v1/website.go index 648673eca..a9a65f63e 100644 --- a/backend/app/api/v1/website.go +++ b/backend/app/api/v1/website.go @@ -51,3 +51,34 @@ func (b *BaseApi) DeleteWebSite(c *gin.Context) { } helper.SuccessWithData(c, nil) } + +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) +} + +func (b *BaseApi) DeleteWebDomain(c *gin.Context) { + + id, err := helper.GetParamID(c) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) + return + } + + if err := websiteService.DeleteWebsiteDomain(id); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} diff --git a/backend/app/api/v1/website_group.go b/backend/app/api/v1/website_group.go index 9f0d04144..5991555ac 100644 --- a/backend/app/api/v1/website_group.go +++ b/backend/app/api/v1/website_group.go @@ -5,7 +5,6 @@ import ( "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/gin-gonic/gin" - "strconv" ) func (b *BaseApi) GetWebGroups(c *gin.Context) { @@ -45,17 +44,13 @@ func (b *BaseApi) UpdateWebGroup(c *gin.Context) { func (b *BaseApi) DeleteWebGroup(c *gin.Context) { - groupId := c.Param("groupId") - if groupId == "" { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, nil) - return - } - id, err := strconv.Atoi(groupId) + groupId, err := helper.GetIntParamByKey(c, "groupId") if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) return } - if err := websiteGroupService.DeleteGroup(uint(id)); err != nil { + + if err := websiteGroupService.DeleteGroup(groupId); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } diff --git a/backend/app/dto/website.go b/backend/app/dto/website.go index 8e4183aa5..c3fd83dd5 100644 --- a/backend/app/dto/website.go +++ b/backend/app/dto/website.go @@ -18,7 +18,7 @@ type WebSiteCreate struct { Type string `json:"type" validate:"required"` Alias string `json:"alias" validate:"required"` Remark string `json:"remark"` - Domains []string `json:"domains"` + OtherDomains string `json:"otherDomains"` AppType AppType `json:"appType" validate:"required"` AppInstall NewAppInstall `json:"appInstall"` AppID uint `json:"appID"` @@ -41,3 +41,18 @@ type WebSiteDel struct { type WebSiteDTO struct { model.WebSite } + +type WebSiteGroupCreate struct { + Name string +} + +type WebSiteGroupUpdate struct { + ID uint + Name string +} + +type WebSiteDomainCreate struct { +} + +type WebSiteDomainDel struct { +} diff --git a/backend/app/dto/website_group.go b/backend/app/dto/website_group.go deleted file mode 100644 index 37ba914d3..000000000 --- a/backend/app/dto/website_group.go +++ /dev/null @@ -1,10 +0,0 @@ -package dto - -type WebSiteGroupCreate struct { - Name string -} - -type WebSiteGroupUpdate struct { - ID uint - Name string -} diff --git a/backend/app/repo/common.go b/backend/app/repo/common.go index eedf2c374..103afba34 100644 --- a/backend/app/repo/common.go +++ b/backend/app/repo/common.go @@ -71,12 +71,13 @@ func (c *CommonRepo) WithIdsNotIn(ids []uint) DBOption { } func getTx(ctx context.Context, opts ...DBOption) *gorm.DB { - if ctx == nil || ctx.Value(constant.DB) == nil { - return getDb() - } - tx := ctx.Value(constant.DB).(*gorm.DB) - for _, opt := range opts { - tx = opt(tx) + tx, ok := ctx.Value(constant.DB).(*gorm.DB) + if ok { + for _, opt := range opts { + tx = opt(tx) + } + } else { + return getDb(opts...) } return tx } diff --git a/backend/app/repo/website.go b/backend/app/repo/website.go index 883c24163..d60c8e7b1 100644 --- a/backend/app/repo/website.go +++ b/backend/app/repo/website.go @@ -3,12 +3,19 @@ package repo import ( "context" "github.com/1Panel-dev/1Panel/backend/app/model" + "gorm.io/gorm" "gorm.io/gorm/clause" ) type WebSiteRepo struct { } +func (w WebSiteRepo) WithAppInstallId(appInstallId uint) DBOption { + return func(db *gorm.DB) *gorm.DB { + return db.Where("app_install_id = ?", appInstallId) + } +} + func (w WebSiteRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebSite, error) { var websites []model.WebSite db := getDb(opts...).Model(&model.WebSite{}) diff --git a/backend/app/repo/website_domain.go b/backend/app/repo/website_domain.go index 33d35962d..5f2a47d9b 100644 --- a/backend/app/repo/website_domain.go +++ b/backend/app/repo/website_domain.go @@ -15,6 +15,17 @@ func (w WebSiteDomainRepo) WithWebSiteId(websiteId uint) DBOption { return db.Where("web_site_id = ?", websiteId) } } + +func (w WebSiteDomainRepo) WithPort(port int) DBOption { + return func(db *gorm.DB) *gorm.DB { + return db.Where("port = ?", port) + } +} +func (w WebSiteDomainRepo) WithDomain(domain string) DBOption { + return func(db *gorm.DB) *gorm.DB { + return db.Where("domain = ?", domain) + } +} func (w WebSiteDomainRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebSiteDomain, error) { var domains []model.WebSiteDomain db := getDb(opts...).Model(&model.WebSiteDomain{}) diff --git a/backend/app/service/website.go b/backend/app/service/website.go index db39a3b6a..e3d228c66 100644 --- a/backend/app/service/website.go +++ b/backend/app/service/website.go @@ -1,12 +1,15 @@ package service import ( + "context" + "fmt" "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/model" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/pkg/errors" "gorm.io/gorm" "reflect" + "strings" "time" ) @@ -28,6 +31,7 @@ func (w WebsiteService) PageWebSite(req dto.WebSiteReq) (int64, []dto.WebSiteDTO } func (w WebsiteService) CreateWebsite(create dto.WebSiteCreate) error { + defaultDate, _ := time.Parse(constant.DateLayout, constant.DefaultDate) website := &model.WebSite{ PrimaryDomain: create.PrimaryDomain, @@ -54,7 +58,9 @@ func (w WebsiteService) CreateWebsite(create dto.WebSiteCreate) error { } var domains []model.WebSiteDomain domains = append(domains, model.WebSiteDomain{Domain: website.PrimaryDomain, WebSiteID: website.ID, Port: 80}) - for _, domain := range create.Domains { + + otherDomainArray := strings.Split(create.OtherDomains, "\n") + for _, domain := range otherDomainArray { domainModel, err := getDomain(domain, website.ID) if err != nil { tx.Rollback() @@ -93,6 +99,10 @@ func (w WebsiteService) DeleteWebSite(req dto.WebSiteDel) error { tx, ctx := getTxAndContext() if req.DeleteApp { + websites, _ := websiteRepo.GetBy(websiteRepo.WithAppInstallId(website.AppInstallID)) + if len(websites) > 1 { + return errors.New("other website use this app") + } appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { return err @@ -115,3 +125,43 @@ func (w WebsiteService) DeleteWebSite(req dto.WebSiteDel) error { tx.Commit() return nil } + +func (w WebsiteService) CreateWebsiteDomain() { + +} + +func (w WebsiteService) GetWebsiteDomain(websiteId uint) ([]model.WebSiteDomain, error) { + return websiteDomainRepo.GetBy(websiteDomainRepo.WithWebSiteId(websiteId)) +} + +func (w WebsiteService) DeleteWebsiteDomain(domainId uint) error { + + webSiteDomain, err := websiteDomainRepo.GetFirst(commonRepo.WithByID(domainId)) + if err != nil { + return err + } + + if websiteDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebSiteId(webSiteDomain.WebSiteID)); len(websiteDomains) == 1 { + return fmt.Errorf("can not delete last domain") + } + website, err := websiteRepo.GetFirst(commonRepo.WithByID(webSiteDomain.WebSiteID)) + if err != nil { + return err + } + var ports []int + if oldDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebSiteId(webSiteDomain.WebSiteID), websiteDomainRepo.WithPort(webSiteDomain.Port)); len(oldDomains) == 1 { + ports = append(ports, webSiteDomain.Port) + } + + var domains []string + if oldDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebSiteId(webSiteDomain.WebSiteID), websiteDomainRepo.WithDomain(webSiteDomain.Domain)); len(oldDomains) == 1 { + domains = append(domains, webSiteDomain.Domain) + } + if len(ports) > 0 || len(domains) > 0 { + if err := deleteListenAndServerName(website, ports, domains); err != nil { + return err + } + } + + return websiteDomainRepo.DeleteBy(context.TODO(), commonRepo.WithByID(domainId)) +} diff --git a/backend/app/service/website_utils.go b/backend/app/service/website_utils.go index cbee90775..a4479aa50 100644 --- a/backend/app/service/website_utils.go +++ b/backend/app/service/website_utils.go @@ -11,6 +11,7 @@ import ( "github.com/1Panel-dev/1Panel/cmd/server/nginx_conf" "github.com/pkg/errors" "gorm.io/gorm" + "os" "path" "strconv" "strings" @@ -67,7 +68,7 @@ func configDefaultNginx(website *model.WebSite, domains []model.WebSiteDomain) e var serverNames []string for _, domain := range domains { serverNames = append(serverNames, domain.Domain) - server.UpdateListen(string(rune(domain.Port)), false) + server.UpdateListen(strconv.Itoa(domain.Port), false) } server.UpdateServerName(serverNames) proxy := fmt.Sprintf("http://%s:%d", appInstall.ServiceName, appInstall.HttpPort) @@ -121,6 +122,50 @@ func delNginxConfig(website model.WebSite) error { return opNginx(nginxInstall.ContainerName, "reload") } -func delApp() error { +func nginxCheckAndReload(oldContent string, filePath string, containerName string) error { + + if err := opNginx(containerName, "check"); err != nil { + _ = files.NewFileOp().WriteFile(filePath, strings.NewReader(oldContent), 0644) + return err + } + + if err := opNginx(containerName, "reload"); err != nil { + _ = files.NewFileOp().WriteFile(filePath, strings.NewReader(oldContent), 0644) + return err + } + return nil } + +func deleteListenAndServerName(website model.WebSite, ports []int, domains []string) error { + + nginxApp, err := appRepo.GetFirst(appRepo.WithKey("nginx")) + if err != nil { + return err + } + nginxInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithAppId(nginxApp.ID)) + if err != nil { + return err + } + + configPath := path.Join(constant.AppInstallDir, "nginx", nginxInstall.Name, "conf", "conf.d", website.PrimaryDomain+".conf") + content, err := os.ReadFile(configPath) + if err != nil { + return err + } + config := parser.NewStringParser(string(content)).Parse() + server := config.FindServers()[0] + for _, port := range ports { + server.DeleteListen(strconv.Itoa(port)) + } + for _, domain := range domains { + server.DeleteServerName(domain) + } + + config.FilePath = configPath + if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { + return err + } + return nginxCheckAndReload(string(content), configPath, nginxInstall.ContainerName) + +} diff --git a/backend/router/ro_app.go b/backend/router/ro_app.go index f81a645aa..695190363 100644 --- a/backend/router/ro_app.go +++ b/backend/router/ro_app.go @@ -18,7 +18,7 @@ func (a *AppRouter) InitAppRouter(Router *gin.RouterGroup) { appRouter.POST("/sync", baseApi.SyncApp) appRouter.POST("/search", baseApi.SearchApp) appRouter.GET("/:id", baseApi.GetApp) - appRouter.GET("/detail/:appid/:version", baseApi.GetAppDetail) + appRouter.GET("/detail/:appId/:version", baseApi.GetAppDetail) appRouter.POST("/install", baseApi.InstallApp) appRouter.GET("/installed/:appInstallId/versions", baseApi.GetUpdateVersions) appRouter.POST("/installed", baseApi.SearchInstalled) diff --git a/backend/router/ro_website.go b/backend/router/ro_website.go index 665a862db..4272f5c96 100644 --- a/backend/router/ro_website.go +++ b/backend/router/ro_website.go @@ -18,5 +18,7 @@ func (a *WebsiteRouter) InitWebsiteRouter(Router *gin.RouterGroup) { groupRouter.POST("", baseApi.CreateWebsite) groupRouter.POST("/search", baseApi.PageWebsite) groupRouter.POST("/del", baseApi.DeleteWebSite) + groupRouter.GET("/domains/:websiteId", baseApi.GetWebDomains) + groupRouter.DELETE("/domains/:id", baseApi.DeleteWebDomain) } } diff --git a/backend/utils/nginx/components/server.go b/backend/utils/nginx/components/server.go index 8b3a98992..568ce44d4 100644 --- a/backend/utils/nginx/components/server.go +++ b/backend/utils/nginx/components/server.go @@ -74,17 +74,44 @@ func (s *Server) UpdateListen(bind string, defaultServer bool, params ...string) listen.DefaultServer = DefaultServer } var newListens []*ServerListen + exist := false for _, li := range s.Listens { if li.Bind == bind { + exist = true newListens = append(newListens, listen) } else { newListens = append(newListens, li) } } + if !exist { + newListens = append(newListens, listen) + } s.Listens = newListens } +func (s *Server) DeleteListen(bind string) { + var newListens []*ServerListen + for _, li := range s.Listens { + if li.Bind != bind { + newListens = append(newListens, li) + } + } + s.Listens = newListens +} + +func (s *Server) DeleteServerName(name string) { + var names []string + dirs := s.FindDirectives("server_name") + params := dirs[0].GetParameters() + for _, param := range params { + if param != name { + names = append(names, param) + } + } + s.UpdateServerName(names) +} + func (s *Server) UpdateServerName(names []string) { serverNameDirective := Directive{ Name: "server_name", diff --git a/frontend/src/api/interface/website.ts b/frontend/src/api/interface/website.ts index c39d238de..15e14cc77 100644 --- a/frontend/src/api/interface/website.ts +++ b/frontend/src/api/interface/website.ts @@ -35,7 +35,6 @@ export namespace WebSite { type: string; alias: string; remark: string; - domains: string[]; appType: string; appInstallID: number; webSiteGroupID: number; @@ -51,4 +50,10 @@ export namespace WebSite { name: string; id?: number; } + + export interface Domain { + name: string; + port: number; + id: number; + } } diff --git a/frontend/src/api/modules/website.ts b/frontend/src/api/modules/website.ts index c2449efc7..b19d4a946 100644 --- a/frontend/src/api/modules/website.ts +++ b/frontend/src/api/modules/website.ts @@ -29,3 +29,11 @@ export const UpdateGroup = (req: WebSite.GroupOp) => { export const DeleteGroup = (id: number) => { return http.delete(`/websites/groups/${id}`); }; + +export const ListDomains = (id: number) => { + return http.get(`/websites/domains/${id}`); +}; + +export const DeleteDomain = (id: number) => { + return http.delete(`/websites/domains/${id}`); +}; diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 83f5f35c6..c0103e37f 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -682,5 +682,8 @@ export default { deleteApp: '删除应用', deleteBackup: '删除备份', domain: '域名', + domainHelper: '一行一个域名,支持*和IP地址,支持域名:端口', + port: '端口', + addDomain: '新增域名', }, }; diff --git a/frontend/src/routers/modules/website.ts b/frontend/src/routers/modules/website.ts index 4165ea114..d4b5130a3 100644 --- a/frontend/src/routers/modules/website.ts +++ b/frontend/src/routers/modules/website.ts @@ -19,16 +19,17 @@ const webSiteRouter = { }, }, { - path: '/websites/projects/config', + path: '/websites/:id/config', name: 'WebsiteConfig', component: () => import('@/views/website/project/config/index.vue'), hidden: true, + props: true, meta: { activeMenu: '/websites', }, }, { - path: '/websites/config', + path: '/websites/nginx', name: 'Config', component: () => import('@/views/website/config/index.vue'), meta: { diff --git a/frontend/src/views/website/project/config/basic/domain/index.vue b/frontend/src/views/website/project/config/basic/domain/index.vue new file mode 100644 index 000000000..ca8fd69b5 --- /dev/null +++ b/frontend/src/views/website/project/config/basic/domain/index.vue @@ -0,0 +1,60 @@ + + + diff --git a/frontend/src/views/website/project/config/basic/index.vue b/frontend/src/views/website/project/config/basic/index.vue new file mode 100644 index 000000000..ec52c5bee --- /dev/null +++ b/frontend/src/views/website/project/config/basic/index.vue @@ -0,0 +1,31 @@ + + + diff --git a/frontend/src/views/website/project/config/index.vue b/frontend/src/views/website/project/config/index.vue index df0725dac..116dbe2eb 100644 --- a/frontend/src/views/website/project/config/index.vue +++ b/frontend/src/views/website/project/config/index.vue @@ -2,24 +2,7 @@ - - - - - - - - - Config - Role - Task - Task - Task - Task - Task - + 优化 反代 @@ -33,5 +16,17 @@ diff --git a/frontend/src/views/website/project/create/index.vue b/frontend/src/views/website/project/create/index.vue index f33ed059a..a886c9abe 100644 --- a/frontend/src/views/website/project/create/index.vue +++ b/frontend/src/views/website/project/create/index.vue @@ -86,7 +86,12 @@ - + @@ -123,7 +128,6 @@ const website = ref({ type: 'deployment', alias: '', remark: '', - domains: [], appType: 'installed', appInstallID: 0, webSiteGroupID: 1, diff --git a/frontend/src/views/website/project/index.vue b/frontend/src/views/website/project/index.vue index a4fbe44b1..68a5e815e 100644 --- a/frontend/src/views/website/project/index.vue +++ b/frontend/src/views/website/project/index.vue @@ -9,7 +9,7 @@ @@ -66,8 +66,8 @@ const search = async () => { }); }; -const openConfig = () => { - router.push({ name: 'WebsiteConfig' }); +const openConfig = (id: number) => { + router.push({ name: 'WebsiteConfig', params: { id: id } }); }; const buttons = [