From c9ff245222e13c829b79e5c7c7979e4bd620654a Mon Sep 17 00:00:00 2001 From: zhengkunwang223 Date: Mon, 5 Dec 2022 15:50:53 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BF=AE=E6=94=B9=E8=AF=81=E4=B9=A6=20?= =?UTF-8?q?=E8=B4=A6=E5=8F=B7=E7=AD=89=E5=88=A0=E9=99=A4=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/model/website_acme_account.go | 2 +- backend/app/model/website_ssl.go | 25 ++-- backend/app/repo/website.go | 41 ++++-- backend/app/repo/website_acme_account.go | 22 ++- backend/app/repo/website_ssl.go | 36 ++++- backend/app/service/entry.go | 6 +- backend/app/service/website_acme_account.go | 5 + backend/app/service/website_dns_account.go | 7 +- backend/app/service/website_ssl.go | 4 + backend/constant/errs.go | 6 + backend/i18n/lang/en.yaml | 6 +- backend/i18n/lang/zh.yaml | 7 +- frontend/src/lang/modules/zh.ts | 5 + .../src/views/app-store/installed/index.vue | 3 +- .../src/views/website/ssl/create/index.vue | 4 +- .../views/website/ssl/dns-account/index.vue | 2 +- frontend/src/views/website/ssl/index.vue | 136 +++++++++--------- .../website/config/basic/other/index.vue | 2 +- frontend/src/views/website/website/index.vue | 2 +- 19 files changed, 208 insertions(+), 113 deletions(-) diff --git a/backend/app/model/website_acme_account.go b/backend/app/model/website_acme_account.go index 0dc807cb6..f03696a0b 100644 --- a/backend/app/model/website_acme_account.go +++ b/backend/app/model/website_acme_account.go @@ -4,7 +4,7 @@ type WebsiteAcmeAccount struct { BaseModel Email string `gorm:"type:varchar(256);not null" json:"email"` URL string `gorm:"type:varchar(256);not null" json:"url"` - PrivateKey string `gorm:"type:longtext;not null" json:"_"` + PrivateKey string `gorm:"type:longtext;not null" json:"-"` } func (w WebsiteAcmeAccount) TableName() string { diff --git a/backend/app/model/website_ssl.go b/backend/app/model/website_ssl.go index 3afafcc06..e5b0fbdfa 100644 --- a/backend/app/model/website_ssl.go +++ b/backend/app/model/website_ssl.go @@ -4,18 +4,19 @@ import "time" type WebSiteSSL struct { BaseModel - PrimaryDomain string `gorm:"type:varchar(256);not null" json:"primaryDomain"` - PrivateKey string `gorm:"type:longtext;not null" json:"privateKey"` - Pem string `gorm:"type:longtext;not null" json:"pem"` - Domains string `gorm:"type:varchar(256);not null" json:"domains"` - CertURL string `gorm:"type:varchar(256);not null" json:"certURL"` - Type string `gorm:"type:varchar(64);not null" json:"type"` - Provider string `gorm:"type:varchar(64);not null" json:"provider"` - Organization string `gorm:"type:varchar(64);not null" json:"organization"` - DnsAccountID uint `gorm:"type:integer;not null" json:"dnsAccountId"` - AcmeAccountID uint `gorm:"type:integer;not null" json:"acmeAccountId"` - ExpireDate time.Time `json:"expireDate"` - StartDate time.Time `json:"startDate"` + PrimaryDomain string `gorm:"type:varchar(256);not null" json:"primaryDomain"` + PrivateKey string `gorm:"type:longtext;not null" json:"privateKey"` + Pem string `gorm:"type:longtext;not null" json:"pem"` + Domains string `gorm:"type:varchar(256);not null" json:"domains"` + CertURL string `gorm:"type:varchar(256);not null" json:"certURL"` + Type string `gorm:"type:varchar(64);not null" json:"type"` + Provider string `gorm:"type:varchar(64);not null" json:"provider"` + Organization string `gorm:"type:varchar(64);not null" json:"organization"` + DnsAccountID uint `gorm:"type:integer;not null" json:"dnsAccountId"` + AcmeAccountID uint `gorm:"type:integer;not null" json:"acmeAccountId"` + AcmeAccount WebsiteAcmeAccount `json:"acmeAccount"` + ExpireDate time.Time `json:"expireDate"` + StartDate time.Time `json:"startDate"` } func (w WebSiteSSL) TableName() string { diff --git a/backend/app/repo/website.go b/backend/app/repo/website.go index 28c8c7b7d..2cb5f94b7 100644 --- a/backend/app/repo/website.go +++ b/backend/app/repo/website.go @@ -8,28 +8,51 @@ import ( "gorm.io/gorm/clause" ) +type IWebsiteRepo interface { + WithAppInstallId(appInstallId uint) DBOption + WithDomain(domain string) DBOption + WithAlias(alias string) DBOption + WithWebsiteSSLID(sslId uint) DBOption + Page(page, size int, opts ...DBOption) (int64, []model.WebSite, error) + GetFirst(opts ...DBOption) (model.WebSite, error) + GetBy(opts ...DBOption) ([]model.WebSite, error) + Save(ctx context.Context, app *model.WebSite) error + DeleteBy(ctx context.Context, opts ...DBOption) error + Create(ctx context.Context, app *model.WebSite) error +} + +func NewIWebsiteRepo() IWebsiteRepo { + return &WebSiteRepo{} +} + type WebSiteRepo struct { } -func (w WebSiteRepo) WithAppInstallId(appInstallId uint) DBOption { +func (w *WebSiteRepo) WithAppInstallId(appInstallId uint) DBOption { return func(db *gorm.DB) *gorm.DB { return db.Where("app_install_id = ?", appInstallId) } } -func (w WebSiteRepo) WithDomain(domain string) DBOption { +func (w *WebSiteRepo) WithDomain(domain string) DBOption { return func(db *gorm.DB) *gorm.DB { return db.Where("primary_domain = ?", domain) } } -func (w WebSiteRepo) WithAlias(alias string) DBOption { +func (w *WebSiteRepo) WithAlias(alias string) DBOption { return func(db *gorm.DB) *gorm.DB { return db.Where("alias = ?", alias) } } -func (w WebSiteRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebSite, error) { +func (w *WebSiteRepo) WithWebsiteSSLID(sslId uint) DBOption { + return func(db *gorm.DB) *gorm.DB { + return db.Where("web_site_ssl_id = ?", sslId) + } +} + +func (w *WebSiteRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebSite, error) { var websites []model.WebSite db := getDb(opts...).Model(&model.WebSite{}) count := int64(0) @@ -38,7 +61,7 @@ func (w WebSiteRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebS return count, websites, err } -func (w WebSiteRepo) GetFirst(opts ...DBOption) (model.WebSite, error) { +func (w *WebSiteRepo) GetFirst(opts ...DBOption) (model.WebSite, error) { var website model.WebSite db := getDb(opts...).Model(&model.WebSite{}) if err := db.Preload("Domains").First(&website).Error; err != nil { @@ -47,7 +70,7 @@ func (w WebSiteRepo) GetFirst(opts ...DBOption) (model.WebSite, error) { return website, nil } -func (w WebSiteRepo) GetBy(opts ...DBOption) ([]model.WebSite, error) { +func (w *WebSiteRepo) GetBy(opts ...DBOption) ([]model.WebSite, error) { var websites []model.WebSite db := getDb(opts...).Model(&model.WebSite{}) if err := db.Find(&websites).Error; err != nil { @@ -56,14 +79,14 @@ func (w WebSiteRepo) GetBy(opts ...DBOption) ([]model.WebSite, error) { return websites, nil } -func (w WebSiteRepo) Create(ctx context.Context, app *model.WebSite) error { +func (w *WebSiteRepo) Create(ctx context.Context, app *model.WebSite) error { return getTx(ctx).Omit(clause.Associations).Create(app).Error } -func (w WebSiteRepo) Save(ctx context.Context, app *model.WebSite) error { +func (w *WebSiteRepo) Save(ctx context.Context, app *model.WebSite) error { return getTx(ctx).Omit(clause.Associations).Save(app).Error } -func (w WebSiteRepo) DeleteBy(ctx context.Context, opts ...DBOption) error { +func (w *WebSiteRepo) DeleteBy(ctx context.Context, opts ...DBOption) error { return getTx(ctx, opts...).Delete(&model.WebSite{}).Error } diff --git a/backend/app/repo/website_acme_account.go b/backend/app/repo/website_acme_account.go index c5ce6a7ae..27fba9672 100644 --- a/backend/app/repo/website_acme_account.go +++ b/backend/app/repo/website_acme_account.go @@ -2,10 +2,22 @@ package repo import "github.com/1Panel-dev/1Panel/backend/app/model" +type IAcmeAccountRepo interface { + Page(page, size int, opts ...DBOption) (int64, []model.WebsiteAcmeAccount, error) + GetFirst(opts ...DBOption) (model.WebsiteAcmeAccount, error) + Create(account model.WebsiteAcmeAccount) error + Save(account model.WebsiteAcmeAccount) error + DeleteBy(opts ...DBOption) error +} + +func NewIAcmeAccountRepo() IAcmeAccountRepo { + return &WebsiteAcmeAccountRepo{} +} + type WebsiteAcmeAccountRepo struct { } -func (w WebsiteAcmeAccountRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebsiteAcmeAccount, error) { +func (w *WebsiteAcmeAccountRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebsiteAcmeAccount, error) { var accounts []model.WebsiteAcmeAccount db := getDb(opts...).Model(&model.WebsiteAcmeAccount{}) count := int64(0) @@ -14,7 +26,7 @@ func (w WebsiteAcmeAccountRepo) Page(page, size int, opts ...DBOption) (int64, [ return count, accounts, err } -func (w WebsiteAcmeAccountRepo) GetFirst(opts ...DBOption) (model.WebsiteAcmeAccount, error) { +func (w *WebsiteAcmeAccountRepo) GetFirst(opts ...DBOption) (model.WebsiteAcmeAccount, error) { var account model.WebsiteAcmeAccount db := getDb(opts...).Model(&model.WebsiteAcmeAccount{}) if err := db.First(&account).Error; err != nil { @@ -23,14 +35,14 @@ func (w WebsiteAcmeAccountRepo) GetFirst(opts ...DBOption) (model.WebsiteAcmeAcc return account, nil } -func (w WebsiteAcmeAccountRepo) Create(account model.WebsiteAcmeAccount) error { +func (w *WebsiteAcmeAccountRepo) Create(account model.WebsiteAcmeAccount) error { return getDb().Create(&account).Error } -func (w WebsiteAcmeAccountRepo) Save(account model.WebsiteAcmeAccount) error { +func (w *WebsiteAcmeAccountRepo) Save(account model.WebsiteAcmeAccount) error { return getDb().Save(&account).Error } -func (w WebsiteAcmeAccountRepo) DeleteBy(opts ...DBOption) error { +func (w *WebsiteAcmeAccountRepo) DeleteBy(opts ...DBOption) error { return getDb(opts...).Debug().Delete(&model.WebsiteAcmeAccount{}).Error } diff --git a/backend/app/repo/website_ssl.go b/backend/app/repo/website_ssl.go index ad412c6a8..4d035df30 100644 --- a/backend/app/repo/website_ssl.go +++ b/backend/app/repo/website_ssl.go @@ -6,28 +6,56 @@ import ( "gorm.io/gorm" ) +func NewISSLRepo() ISSLRepo { + return &WebsiteSSLRepo{} +} + +type ISSLRepo interface { + WithByAlias(alias string) DBOption + WithByAcmeAccountId(acmeAccountId uint) DBOption + WithByDnsAccountId(dnsAccountId uint) DBOption + Page(page, size int, opts ...DBOption) (int64, []model.WebSiteSSL, error) + GetFirst(opts ...DBOption) (model.WebSiteSSL, error) + List(opts ...DBOption) ([]model.WebSiteSSL, error) + Create(ctx context.Context, ssl *model.WebSiteSSL) error + Save(ssl model.WebSiteSSL) error + DeleteBy(opts ...DBOption) error +} + type WebsiteSSLRepo struct { } -func (w WebsiteSSLRepo) ByAlias(alias string) DBOption { +func (w WebsiteSSLRepo) WithByAlias(alias string) DBOption { return func(db *gorm.DB) *gorm.DB { return db.Where("alias = ?", alias) } } +func (w WebsiteSSLRepo) WithByAcmeAccountId(acmeAccountId uint) DBOption { + return func(db *gorm.DB) *gorm.DB { + return db.Where("acme_account_id = ?", acmeAccountId) + } +} + +func (w WebsiteSSLRepo) WithByDnsAccountId(dnsAccountId uint) DBOption { + return func(db *gorm.DB) *gorm.DB { + return db.Where("dns_account_id = ?", dnsAccountId) + } +} + func (w WebsiteSSLRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebSiteSSL, error) { var sslList []model.WebSiteSSL db := getDb(opts...).Model(&model.WebSiteSSL{}) count := int64(0) db = db.Count(&count) - err := db.Debug().Limit(size).Offset(size * (page - 1)).Find(&sslList).Error + err := db.Limit(size).Offset(size * (page - 1)).Preload("AcmeAccount").Find(&sslList).Error return count, sslList, err } func (w WebsiteSSLRepo) GetFirst(opts ...DBOption) (model.WebSiteSSL, error) { var website model.WebSiteSSL db := getDb(opts...).Model(&model.WebSiteSSL{}) - if err := db.First(&website).Error; err != nil { + if err := db.Preload("AcmeAccount").First(&website).Error; err != nil { return website, err } return website, nil @@ -36,7 +64,7 @@ func (w WebsiteSSLRepo) GetFirst(opts ...DBOption) (model.WebSiteSSL, error) { 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 { + if err := db.Preload("AcmeAccount").Find(&websites).Error; err != nil { return websites, err } return websites, nil diff --git a/backend/app/service/entry.go b/backend/app/service/entry.go index 88acc1142..3d4c2ce36 100644 --- a/backend/app/service/entry.go +++ b/backend/app/service/entry.go @@ -66,12 +66,12 @@ var ( settingRepo = repo.RepoGroupApp.SettingRepo backupRepo = repo.RepoGroupApp.BackupRepo - websiteRepo = repo.RepoGroupApp.WebSiteRepo + websiteRepo = repo.NewIWebsiteRepo() websiteGroupRepo = repo.RepoGroupApp.WebSiteGroupRepo websiteDomainRepo = repo.RepoGroupApp.WebSiteDomainRepo websiteDnsRepo = repo.RepoGroupApp.WebsiteDnsAccountRepo - websiteSSLRepo = repo.RepoGroupApp.WebsiteSSLRepo - websiteAcmeRepo = repo.RepoGroupApp.WebsiteAcmeAccountRepo + websiteSSLRepo = repo.NewISSLRepo() + websiteAcmeRepo = repo.NewIAcmeAccountRepo() logRepo = repo.RepoGroupApp.LogRepo ) diff --git a/backend/app/service/website_acme_account.go b/backend/app/service/website_acme_account.go index 1fef6ea01..2b42e7966 100644 --- a/backend/app/service/website_acme_account.go +++ b/backend/app/service/website_acme_account.go @@ -3,6 +3,8 @@ package service import ( "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/model" + "github.com/1Panel-dev/1Panel/backend/buserr" + "github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/utils/ssl" ) @@ -37,5 +39,8 @@ func (w WebSiteAcmeAccountService) Create(create dto.WebsiteAcmeAccountCreate) ( } func (w WebSiteAcmeAccountService) Delete(id uint) error { + if ssls, _ := websiteSSLRepo.List(websiteSSLRepo.WithByAcmeAccountId(id)); len(ssls) > 0 { + return buserr.New(constant.ErrAccountCannotDelete) + } return websiteAcmeRepo.DeleteBy(commonRepo.WithByID(id)) } diff --git a/backend/app/service/website_dns_account.go b/backend/app/service/website_dns_account.go index dded95865..9eda02169 100644 --- a/backend/app/service/website_dns_account.go +++ b/backend/app/service/website_dns_account.go @@ -3,6 +3,8 @@ package service import ( "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/model" + "github.com/1Panel-dev/1Panel/backend/buserr" + "github.com/1Panel-dev/1Panel/backend/constant" "gopkg.in/square/go-jose.v2/json" ) @@ -24,7 +26,6 @@ func (w WebSiteDnsAccountService) Page(search dto.PageInfo) (int64, []dto.Websit } func (w WebSiteDnsAccountService) Create(create dto.WebsiteDnsAccountCreate) (dto.WebsiteDnsAccountCreate, error) { - authorization, err := json.Marshal(create.Authorization) if err != nil { return dto.WebsiteDnsAccountCreate{}, err @@ -42,7 +43,6 @@ func (w WebSiteDnsAccountService) Create(create dto.WebsiteDnsAccountCreate) (dt } func (w WebSiteDnsAccountService) Update(update dto.WebsiteDnsAccountUpdate) (dto.WebsiteDnsAccountUpdate, error) { - authorization, err := json.Marshal(update.Authorization) if err != nil { return dto.WebsiteDnsAccountUpdate{}, err @@ -63,5 +63,8 @@ func (w WebSiteDnsAccountService) Update(update dto.WebsiteDnsAccountUpdate) (dt } func (w WebSiteDnsAccountService) Delete(id uint) error { + if ssls, _ := websiteSSLRepo.List(websiteSSLRepo.WithByDnsAccountId(id)); len(ssls) > 0 { + return buserr.New(constant.ErrAccountCannotDelete) + } return websiteDnsRepo.DeleteBy(commonRepo.WithByID(id)) } diff --git a/backend/app/service/website_ssl.go b/backend/app/service/website_ssl.go index 6842382b9..b98ccc6d8 100644 --- a/backend/app/service/website_ssl.go +++ b/backend/app/service/website_ssl.go @@ -6,6 +6,7 @@ import ( "encoding/pem" "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/model" + "github.com/1Panel-dev/1Panel/backend/buserr" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/utils/ssl" "path" @@ -209,5 +210,8 @@ func (w WebSiteSSLService) GetWebsiteSSL(websiteId uint) (dto.WebsiteSSLDTO, err } func (w WebSiteSSLService) Delete(id uint) error { + if websites, _ := websiteRepo.GetBy(websiteRepo.WithWebsiteSSLID(id)); len(websites) > 0 { + return buserr.New(constant.ErrSSLCannotDelete) + } return websiteSSLRepo.DeleteBy(commonRepo.WithByID(id)) } diff --git a/backend/constant/errs.go b/backend/constant/errs.go index 7259dd979..a6d4230e3 100644 --- a/backend/constant/errs.go +++ b/backend/constant/errs.go @@ -60,3 +60,9 @@ var ( ErrDomainIsExist = "ErrDomainIsExist" ErrAliasIsExist = "ErrAliasIsExist" ) + +//ssl +var ( + ErrSSLCannotDelete = "ErrSSLCannotDelete" + ErrAccountCannotDelete = "ErrAccountCannotDelete" +) diff --git a/backend/i18n/lang/en.yaml b/backend/i18n/lang/en.yaml index a88ad690f..ec89164df 100644 --- a/backend/i18n/lang/en.yaml +++ b/backend/i18n/lang/en.yaml @@ -29,4 +29,8 @@ ErrFileToLarge: "file is too large" #website ErrDomainIsExist: "Domain is already exist" -ErrAliasIsExist: "Alias is already exist" \ No newline at end of file +ErrAliasIsExist: "Alias is already exist" + +#ssl +ErrSSLCannotDelete: "The certificate is being used by the website and cannot be removed" +ErrAccountCannotDelete: "The certificate associated with the account cannot be deleted" \ No newline at end of file diff --git a/backend/i18n/lang/zh.yaml b/backend/i18n/lang/zh.yaml index 4e9b36fc7..f7474d651 100644 --- a/backend/i18n/lang/zh.yaml +++ b/backend/i18n/lang/zh.yaml @@ -22,11 +22,14 @@ ErrAppLimit: "应用超出安装数量限制" ErrAppRequired: "请先安装 {{ .detail }} 应用" ErrNotInstall: "应用未安装" - #file ErrFileCanNotRead: "文件不可读" ErrFileToLarge: "文件超过10M,无法打开" #website ErrDomainIsExist: "域名已存在" -ErrAliasIsExist: "代号已存在" \ No newline at end of file +ErrAliasIsExist: "代号已存在" + +#ssl +ErrSSLCannotDelete: "证书正在被网站使用,无法删除" +ErrAccountCannotDelete: "账号关联证书,无法删除" \ No newline at end of file diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 94539095c..9eec75da5 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -867,4 +867,9 @@ export default { waiting: '驻留进程(Waiting)', status: '负载状态', }, + ssl: { + provider: '类型', + manualCreate: '手动创建', + acmeAccount: 'Acme 账号', + }, }; diff --git a/frontend/src/views/app-store/installed/index.vue b/frontend/src/views/app-store/installed/index.vue index 7cc0a248f..312099133 100644 --- a/frontend/src/views/app-store/installed/index.vue +++ b/frontend/src/views/app-store/installed/index.vue @@ -56,7 +56,7 @@ - {{ row.status }} + @@ -129,6 +129,7 @@ import Backups from './backups.vue'; import AppResources from './check/index.vue'; import { App } from '@/api/interface/app'; import { useDeleteData } from '@/hooks/use-delete-data'; +import Status from '@/components/status/index.vue'; let data = ref(); let loading = ref(false); diff --git a/frontend/src/views/website/ssl/create/index.vue b/frontend/src/views/website/ssl/create/index.vue index 1ee7004b2..595fa151b 100644 --- a/frontend/src/views/website/ssl/create/index.vue +++ b/frontend/src/views/website/ssl/create/index.vue @@ -119,8 +119,8 @@ let ssl = ref({ otherDomains: '', provider: 'dnsAccount', websiteId: 0, - acmeAccountId: 0, - dnsAccountId: 0, + acmeAccountId: undefined, + dnsAccountId: undefined, }); let dnsResolve = ref([]); let hasResolve = ref(false); diff --git a/frontend/src/views/website/ssl/dns-account/index.vue b/frontend/src/views/website/ssl/dns-account/index.vue index f52c46092..8074a1b4e 100644 --- a/frontend/src/views/website/ssl/dns-account/index.vue +++ b/frontend/src/views/website/ssl/dns-account/index.vue @@ -18,7 +18,7 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + +