From fb90fae87f0d6fc3433363d9b27245b1fc6815ea Mon Sep 17 00:00:00 2001 From: zhengkunwang223 Date: Sun, 20 Nov 2022 18:32:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0https=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/v1/website.go | 28 ++++ backend/app/api/v1/website_ssl.go | 42 +++--- backend/app/dto/website.go | 20 +++ backend/app/dto/website_ssl.go | 6 +- backend/app/repo/website_ssl.go | 9 ++ backend/app/service/website.go | 49 ++++++ backend/app/service/website_ssl.go | 52 +++---- backend/app/service/website_utils.go | 25 +++- backend/router/ro_website.go | 2 + backend/router/ro_website_ssl.go | 1 - frontend/src/api/interface/website.ts | 16 ++ frontend/src/api/modules/website.ts | 12 ++ frontend/src/lang/modules/zh.ts | 1 + .../src/views/website/ssl/create/index.vue | 1 + .../website/config/basic/https/index.vue | 139 ++++++++++++++++++ .../website/website/config/basic/index.vue | 5 +- 16 files changed, 346 insertions(+), 62 deletions(-) create mode 100644 frontend/src/views/website/website/config/basic/https/index.vue diff --git a/backend/app/api/v1/website.go b/backend/app/api/v1/website.go index efb4ea3ee..177ba6b4a 100644 --- a/backend/app/api/v1/website.go +++ b/backend/app/api/v1/website.go @@ -166,3 +166,31 @@ func (b *BaseApi) UpdateNginxConfig(c *gin.Context) { } helper.SuccessWithData(c, nil) } + +func (b *BaseApi) GetHTTPSConfig(c *gin.Context) { + id, err := helper.GetParamID(c) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) + return + } + res, err := websiteService.GetWebsiteHTTPS(id) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, res) +} + +func (b *BaseApi) UpdateHTTPSConfig(c *gin.Context) { + var req dto.WebsiteHTTPSOp + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + res, err := websiteService.OpWebsiteHTTPS(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, res) +} diff --git a/backend/app/api/v1/website_ssl.go b/backend/app/api/v1/website_ssl.go index 2a5e3f78f..18f962fec 100644 --- a/backend/app/api/v1/website_ssl.go +++ b/backend/app/api/v1/website_ssl.go @@ -5,23 +5,33 @@ import ( "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/gin-gonic/gin" + "reflect" ) func (b *BaseApi) PageWebsiteSSL(c *gin.Context) { - var req dto.PageInfo + var req dto.WebsiteSSLSearch if err := c.ShouldBindJSON(&req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - total, accounts, err := websiteSSLService.Page(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return + if !reflect.DeepEqual(req.PageInfo, dto.PageInfo{}) { + total, accounts, err := websiteSSLService.Page(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, dto.PageResult{ + Total: total, + Items: accounts, + }) + } else { + list, err := websiteSSLService.Search() + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, list) } - helper.SuccessWithData(c, dto.PageResult{ - Total: total, - Items: accounts, - }) } func (b *BaseApi) CreateWebsiteSSL(c *gin.Context) { @@ -51,20 +61,6 @@ func (b *BaseApi) RenewWebsiteSSL(c *gin.Context) { helper.SuccessWithData(c, nil) } -func (b *BaseApi) ApplyWebsiteSSL(c *gin.Context) { - var req dto.WebsiteSSLApply - if err := c.ShouldBindJSON(&req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - res, err := websiteSSLService.Apply(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, res) -} - func (b *BaseApi) GetDNSResolve(c *gin.Context) { var req dto.WebsiteDNSReq if err := c.ShouldBindJSON(&req); err != nil { diff --git a/backend/app/dto/website.go b/backend/app/dto/website.go index 59210c663..e93c897aa 100644 --- a/backend/app/dto/website.go +++ b/backend/app/dto/website.go @@ -69,3 +69,23 @@ type WebSiteDomainCreate struct { Port int `json:"port"` Domain string `json:"domain"` } + +type WebsiteHTTPS struct { + Enable bool `json:"enable"` + SSL model.WebSiteSSL `json:"SSL"` +} + +type SSlType string + +const ( + SSLExisted SSlType = "existed" + SSLAuto SSlType = "auto" + SSLManual SSlType = "manual" +) + +type WebsiteHTTPSOp struct { + WebsiteID uint `json:"websiteId"` + Enable bool `json:"enable"` + WebsiteSSLID uint `json:"websiteSSLId"` + Type SSlType `json:"type"` +} diff --git a/backend/app/dto/website_ssl.go b/backend/app/dto/website_ssl.go index 06160ff13..3ef56980b 100644 --- a/backend/app/dto/website_ssl.go +++ b/backend/app/dto/website_ssl.go @@ -14,6 +14,10 @@ const ( Http = "http" ) +type WebsiteSSLSearch struct { + PageInfo +} + type WebsiteSSLCreate struct { PrimaryDomain string `json:"primaryDomain" validate:"required"` OtherDomains string `json:"otherDomains"` @@ -24,7 +28,7 @@ type WebsiteSSLCreate struct { type WebsiteSSLApply struct { WebsiteID uint `json:"websiteId" validate:"required"` - SSLID uint `json:"SSLId" validate:"required"` + Enable bool `json:"enable" validate:"required"` } type WebsiteDNSReq struct { diff --git a/backend/app/repo/website_ssl.go b/backend/app/repo/website_ssl.go index 74c20f626..ad412c6a8 100644 --- a/backend/app/repo/website_ssl.go +++ b/backend/app/repo/website_ssl.go @@ -33,6 +33,15 @@ func (w WebsiteSSLRepo) GetFirst(opts ...DBOption) (model.WebSiteSSL, error) { return website, nil } +func (w WebsiteSSLRepo) List(opts ...DBOption) ([]model.WebSiteSSL, error) { + var websites []model.WebSiteSSL + db := getDb(opts...).Model(&model.WebSiteSSL{}) + if err := db.Find(&websites).Error; err != nil { + return websites, err + } + return websites, nil +} + func (w WebsiteSSLRepo) Create(ctx context.Context, ssl *model.WebSiteSSL) error { return getTx(ctx).Create(ssl).Error } diff --git a/backend/app/service/website.go b/backend/app/service/website.go index 390cb63f1..435c771d7 100644 --- a/backend/app/service/website.go +++ b/backend/app/service/website.go @@ -271,3 +271,52 @@ func (w WebsiteService) GetWebsiteNginxConfig(websiteId uint) (dto.FileInfo, err } return dto.FileInfo{FileInfo: *info}, nil } + +func (w WebsiteService) GetWebsiteHTTPS(websiteId uint) (dto.WebsiteHTTPS, error) { + website, err := websiteRepo.GetFirst(commonRepo.WithByID(websiteId)) + if err != nil { + return dto.WebsiteHTTPS{}, err + } + var res dto.WebsiteHTTPS + if website.WebSiteSSLID == 0 { + res.Enable = false + return res, nil + } + websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(website.WebSiteSSLID)) + if err != nil { + return dto.WebsiteHTTPS{}, err + } + res.SSL = websiteSSL + res.Enable = true + return res, nil +} + +func (w WebsiteService) OpWebsiteHTTPS(req dto.WebsiteHTTPSOp) (dto.WebsiteHTTPS, error) { + website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID)) + if err != nil { + return dto.WebsiteHTTPS{}, err + } + + var res dto.WebsiteHTTPS + res.Enable = req.Enable + ssl, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(req.WebsiteSSLID)) + if err != nil { + return dto.WebsiteHTTPS{}, err + } + + if req.Type == dto.SSLExisted { + website.WebSiteSSLID = ssl.ID + if err := websiteRepo.Save(context.TODO(), &website); err != nil { + return dto.WebsiteHTTPS{}, err + } + res.SSL = ssl + } + + if req.Enable { + if err := applySSL(website, ssl); err != nil { + return dto.WebsiteHTTPS{}, err + } + } + + return res, nil +} diff --git a/backend/app/service/website_ssl.go b/backend/app/service/website_ssl.go index d42a79da0..2428d31e9 100644 --- a/backend/app/service/website_ssl.go +++ b/backend/app/service/website_ssl.go @@ -7,15 +7,17 @@ import ( "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/model" "github.com/1Panel-dev/1Panel/backend/utils/ssl" - "path" "strings" ) type WebSiteSSLService struct { } -func (w WebSiteSSLService) Page(search dto.PageInfo) (int64, []dto.WebsiteSSLDTO, error) { +func (w WebSiteSSLService) Page(search dto.WebsiteSSLSearch) (int64, []dto.WebsiteSSLDTO, error) { total, sslList, err := websiteSSLRepo.Page(search.Page, search.PageSize, commonRepo.WithOrderBy("created_at desc")) + if err != nil { + return 0, nil, err + } var sslDTOs []dto.WebsiteSSLDTO for _, ssl := range sslList { sslDTOs = append(sslDTOs, dto.WebsiteSSLDTO{ @@ -25,6 +27,20 @@ func (w WebSiteSSLService) Page(search dto.PageInfo) (int64, []dto.WebsiteSSLDTO return total, sslDTOs, err } +func (w WebSiteSSLService) Search() ([]dto.WebsiteSSLDTO, error) { + sslList, err := websiteSSLRepo.List() + if err != nil { + return nil, err + } + var sslDTOs []dto.WebsiteSSLDTO + for _, ssl := range sslList { + sslDTOs = append(sslDTOs, dto.WebsiteSSLDTO{ + WebSiteSSL: ssl, + }) + } + return sslDTOs, err +} + func (w WebSiteSSLService) Create(create dto.WebsiteSSLCreate) (dto.WebsiteSSLCreate, error) { var res dto.WebsiteSSLCreate @@ -142,38 +158,6 @@ func (w WebSiteSSLService) Renew(sslId uint) error { return websiteSSLRepo.Save(websiteSSL) } -func (w WebSiteSSLService) Apply(apply dto.WebsiteSSLApply) (dto.WebsiteSSLApply, error) { - websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(apply.SSLID)) - if err != nil { - return dto.WebsiteSSLApply{}, err - } - website, err := websiteRepo.GetFirst(commonRepo.WithByID(apply.WebsiteID)) - if err != nil { - return dto.WebsiteSSLApply{}, err - } - if err := createPemFile(websiteSSL); err != nil { - return dto.WebsiteSSLApply{}, err - } - nginxParams := getNginxParamsFromStaticFile(dto.SSL) - for i, param := range nginxParams { - if param.Name == "ssl_certificate" { - nginxParams[i].Params = []string{path.Join("/etc/nginx/ssl", websiteSSL.PrimaryDomain, "fullchain.pem")} - } - if param.Name == "ssl_certificate_key" { - nginxParams[i].Params = []string{path.Join("/etc/nginx/ssl", websiteSSL.PrimaryDomain, "privkey.pem")} - } - } - if err := updateNginxConfig(website, nginxParams, dto.SSL); err != nil { - return dto.WebsiteSSLApply{}, err - } - website.WebSiteSSLID = websiteSSL.ID - if err := websiteRepo.Save(context.TODO(), &website); err != nil { - return dto.WebsiteSSLApply{}, err - } - - return apply, nil -} - func (w WebSiteSSLService) GetDNSResolve(req dto.WebsiteDNSReq) (dto.WebsiteDNSRes, error) { acmeAccount, err := websiteAcmeRepo.GetFirst(commonRepo.WithByID(req.AcmeAccountID)) if err != nil { diff --git a/backend/app/service/website_utils.go b/backend/app/service/website_utils.go index 5d5270052..a9add4b5e 100644 --- a/backend/app/service/website_utils.go +++ b/backend/app/service/website_utils.go @@ -308,7 +308,7 @@ func deleteNginxConfig(website model.WebSite, keys []string) error { return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxConfig.ContainerName) } -func createPemFile(websiteSSL model.WebSiteSSL) error { +func createPemFile(website model.WebSite, websiteSSL model.WebSiteSSL) error { nginxApp, err := appRepo.GetFirst(appRepo.WithKey("nginx")) if err != nil { return err @@ -318,7 +318,7 @@ func createPemFile(websiteSSL model.WebSiteSSL) error { return err } - configDir := path.Join(constant.AppInstallDir, "nginx", nginxInstall.Name, "ssl", websiteSSL.PrimaryDomain) + configDir := path.Join(constant.AppInstallDir, "nginx", nginxInstall.Name, "ssl", website.Alias) fileOp := files.NewFileOp() if !fileOp.Stat(configDir) { @@ -350,6 +350,27 @@ func createPemFile(websiteSSL model.WebSiteSSL) error { return nil } +func applySSL(website model.WebSite, websiteSSL model.WebSiteSSL) error { + + if err := createPemFile(website, websiteSSL); err != nil { + return err + } + nginxParams := getNginxParamsFromStaticFile(dto.SSL) + for i, param := range nginxParams { + if param.Name == "ssl_certificate" { + nginxParams[i].Params = []string{path.Join("/etc/nginx/ssl", website.Alias, "fullchain.pem")} + } + if param.Name == "ssl_certificate_key" { + nginxParams[i].Params = []string{path.Join("/etc/nginx/ssl", website.Alias, "privkey.pem")} + } + } + if err := updateNginxConfig(website, nginxParams, dto.SSL); err != nil { + return err + } + + return nil +} + func getParamArray(key string, param interface{}) []string { var res []string switch p := param.(type) { diff --git a/backend/router/ro_website.go b/backend/router/ro_website.go index 5aa14b76a..6153aa1a8 100644 --- a/backend/router/ro_website.go +++ b/backend/router/ro_website.go @@ -26,5 +26,7 @@ func (a *WebsiteRouter) InitWebsiteRouter(Router *gin.RouterGroup) { groupRouter.POST("/domains", baseApi.CreateWebDomain) groupRouter.POST("/config", baseApi.GetNginxConfig) groupRouter.POST("/config/update", baseApi.UpdateNginxConfig) + groupRouter.GET("/:id/https", baseApi.GetHTTPSConfig) + groupRouter.POST("/:id/https", baseApi.UpdateHTTPSConfig) } } diff --git a/backend/router/ro_website_ssl.go b/backend/router/ro_website_ssl.go index e3cf0fdf3..2b338b78f 100644 --- a/backend/router/ro_website_ssl.go +++ b/backend/router/ro_website_ssl.go @@ -18,7 +18,6 @@ func (a *WebsiteSSLRouter) InitWebsiteSSLRouter(Router *gin.RouterGroup) { groupRouter.POST("/search", baseApi.PageWebsiteSSL) groupRouter.POST("/renew", baseApi.RenewWebsiteSSL) groupRouter.POST("", baseApi.CreateWebsiteSSL) - groupRouter.POST("/apply", baseApi.ApplyWebsiteSSL) groupRouter.POST("/resolve", baseApi.GetDNSResolve) groupRouter.DELETE("/:id", baseApi.DeleteWebsiteSSL) groupRouter.GET("/:websiteId", baseApi.GetWebsiteSSL) diff --git a/frontend/src/api/interface/website.ts b/frontend/src/api/interface/website.ts index 0666a32cc..22f3e1dbf 100644 --- a/frontend/src/api/interface/website.ts +++ b/frontend/src/api/interface/website.ts @@ -165,4 +165,20 @@ export namespace WebSite { value: string; type: string; } + + export interface SSLReq { + name?: string; + } + + export interface HTTPSReq { + websiteId: number; + enable: boolean; + websiteSSLId: number; + type: string; + } + + export interface HTTPSConfig { + enable: boolean; + SSL: SSL; + } } diff --git a/frontend/src/api/modules/website.ts b/frontend/src/api/modules/website.ts index e6f92de79..30da5acb9 100644 --- a/frontend/src/api/modules/website.ts +++ b/frontend/src/api/modules/website.ts @@ -95,6 +95,10 @@ export const SearchSSL = (req: ReqPage) => { return http.post>(`/websites/ssl/search`, req); }; +export const ListSSL = (req: WebSite.SSLReq) => { + return http.post(`/websites/ssl/search`, req); +}; + export const CreateSSL = (req: WebSite.SSLCreate) => { return http.post(`/websites/ssl`, req); }; @@ -118,3 +122,11 @@ export const RenewSSL = (req: WebSite.SSLRenew) => { export const GetDnsResolve = (req: WebSite.DNSResolveReq) => { return http.post(`/websites/ssl/resolve`, req); }; + +export const GetHTTPSConfig = (id: number) => { + return http.get(`/websites/${id}/https`); +}; + +export const UpdateHTTPSConfig = (req: WebSite.HTTPSReq) => { + return http.post(`/websites/${req.websiteId}/https`, req); +}; diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index e93231ad9..489b375ba 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -739,5 +739,6 @@ export default { renewHelper: '确定续签证书?', renewSuccess: '续签证书', config: '配置', + enableHTTPS: '启用HTTPS', }, }; diff --git a/frontend/src/views/website/ssl/create/index.vue b/frontend/src/views/website/ssl/create/index.vue index 89d84082b..042630815 100644 --- a/frontend/src/views/website/ssl/create/index.vue +++ b/frontend/src/views/website/ssl/create/index.vue @@ -185,6 +185,7 @@ const submit = async (formEl: FormInstance | undefined) => { loading.value = true; CreateSSL(ssl.value) .then(() => { + handleClose(); ElMessage.success(i18n.global.t('commons.msg.createSuccess')); }) .finally(() => { diff --git a/frontend/src/views/website/website/config/basic/https/index.vue b/frontend/src/views/website/website/config/basic/https/index.vue new file mode 100644 index 000000000..93f40099e --- /dev/null +++ b/frontend/src/views/website/website/config/basic/https/index.vue @@ -0,0 +1,139 @@ + + diff --git a/frontend/src/views/website/website/config/basic/index.vue b/frontend/src/views/website/website/config/basic/index.vue index 823b511c2..630de2d69 100644 --- a/frontend/src/views/website/website/config/basic/index.vue +++ b/frontend/src/views/website/website/config/basic/index.vue @@ -9,7 +9,9 @@ - + + + @@ -23,6 +25,7 @@ import Doamin from './domain/index.vue'; import Default from './default-doc/index.vue'; import LimitConn from './limit-conn/index.vue'; import Other from './other/index.vue'; +import HTTPS from './https/index.vue'; const props = defineProps({ id: {