Skip to content

Commit 59c216c

Browse files
feat: 手动创建证书增加更新功能 (#3087)
Refs #2329
1 parent 73b2804 commit 59c216c

File tree

8 files changed

+62
-33
lines changed

8 files changed

+62
-33
lines changed

backend/app/dto/request/website_ssl.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,12 @@ type WebsiteBatchDelReq struct {
6363
}
6464

6565
type WebsiteSSLUpdate struct {
66-
ID uint `json:"id" validate:"required"`
67-
AutoRenew bool `json:"autoRenew"`
66+
ID uint `json:"id" validate:"required"`
67+
AutoRenew bool `json:"autoRenew"`
68+
Description string `json:"description"`
69+
PrivateKey string `json:"privateKey"`
70+
Certificate string `json:"certificate"`
71+
Type string `json:"type" validate:"required,oneof=autoRenew description certificate privateKey"`
6872
}
6973

7074
type WebsiteSSLUpload struct {
@@ -73,6 +77,7 @@ type WebsiteSSLUpload struct {
7377
PrivateKeyPath string `json:"privateKeyPath"`
7478
CertificatePath string `json:"certificatePath"`
7579
Type string `json:"type" validate:"required,oneof=paste local"`
80+
SSLID uint `json:"sslID"`
7681
}
7782

7883
type WebsiteCASearch struct {

backend/app/model/website_ssl.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type WebsiteSSL struct {
2828
KeyType string `gorm:"not null;default:2048" json:"keyType"`
2929
PushDir bool `gorm:"not null;default:0" json:"pushDir"`
3030
Dir string `json:"dir"`
31+
Description string `json:"description"`
3132

3233
AcmeAccount WebsiteAcmeAccount `json:"acmeAccount" gorm:"-:migration"`
3334
DnsAccount WebsiteDnsAccount `json:"dnsAccount" gorm:"-:migration"`

backend/app/service/website_ssl.go

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -345,10 +345,16 @@ func (w WebsiteSSLService) Update(update request.WebsiteSSLUpdate) error {
345345
}
346346

347347
func (w WebsiteSSLService) Upload(req request.WebsiteSSLUpload) error {
348-
newSSL := &model.WebsiteSSL{
348+
websiteSSL := &model.WebsiteSSL{
349349
Provider: constant.Manual,
350350
}
351-
351+
var err error
352+
if req.SSLID > 0 {
353+
websiteSSL, err = websiteSSLRepo.GetFirst(commonRepo.WithByID(req.SSLID))
354+
if err != nil {
355+
return err
356+
}
357+
}
352358
if req.Type == "local" {
353359
fileOp := files.NewFileOp()
354360
if !fileOp.Stat(req.PrivateKeyPath) {
@@ -360,48 +366,48 @@ func (w WebsiteSSLService) Upload(req request.WebsiteSSLUpload) error {
360366
if content, err := fileOp.GetContent(req.PrivateKeyPath); err != nil {
361367
return err
362368
} else {
363-
newSSL.PrivateKey = string(content)
369+
websiteSSL.PrivateKey = string(content)
364370
}
365371
if content, err := fileOp.GetContent(req.CertificatePath); err != nil {
366372
return err
367373
} else {
368-
newSSL.Pem = string(content)
374+
websiteSSL.Pem = string(content)
369375
}
370376
} else {
371-
newSSL.PrivateKey = req.PrivateKey
372-
newSSL.Pem = req.Certificate
377+
websiteSSL.PrivateKey = req.PrivateKey
378+
websiteSSL.Pem = req.Certificate
373379
}
374380

375-
privateKeyCertBlock, _ := pem.Decode([]byte(newSSL.PrivateKey))
381+
privateKeyCertBlock, _ := pem.Decode([]byte(websiteSSL.PrivateKey))
376382
if privateKeyCertBlock == nil {
377383
return buserr.New("ErrSSLKeyFormat")
378384
}
379385

380-
certBlock, _ := pem.Decode([]byte(newSSL.Pem))
386+
certBlock, _ := pem.Decode([]byte(websiteSSL.Pem))
381387
if certBlock == nil {
382388
return buserr.New("ErrSSLCertificateFormat")
383389
}
384390
cert, err := x509.ParseCertificate(certBlock.Bytes)
385391
if err != nil {
386392
return err
387393
}
388-
newSSL.ExpireDate = cert.NotAfter
389-
newSSL.StartDate = cert.NotBefore
390-
newSSL.Type = cert.Issuer.CommonName
394+
websiteSSL.ExpireDate = cert.NotAfter
395+
websiteSSL.StartDate = cert.NotBefore
396+
websiteSSL.Type = cert.Issuer.CommonName
391397
if len(cert.Issuer.Organization) > 0 {
392-
newSSL.Organization = cert.Issuer.Organization[0]
398+
websiteSSL.Organization = cert.Issuer.Organization[0]
393399
} else {
394-
newSSL.Organization = cert.Issuer.CommonName
400+
websiteSSL.Organization = cert.Issuer.CommonName
395401
}
396402

397403
var domains []string
398404
if len(cert.DNSNames) > 0 {
399-
newSSL.PrimaryDomain = cert.DNSNames[0]
405+
websiteSSL.PrimaryDomain = cert.DNSNames[0]
400406
domains = cert.DNSNames[1:]
401407
}
402408
if len(cert.IPAddresses) > 0 {
403-
if newSSL.PrimaryDomain == "" {
404-
newSSL.PrimaryDomain = cert.IPAddresses[0].String()
409+
if websiteSSL.PrimaryDomain == "" {
410+
websiteSSL.PrimaryDomain = cert.IPAddresses[0].String()
405411
for _, ip := range cert.IPAddresses[1:] {
406412
domains = append(domains, ip.String())
407413
}
@@ -411,9 +417,12 @@ func (w WebsiteSSLService) Upload(req request.WebsiteSSLUpload) error {
411417
}
412418
}
413419
}
414-
newSSL.Domains = strings.Join(domains, ",")
420+
websiteSSL.Domains = strings.Join(domains, ",")
415421

416-
return websiteSSLRepo.Create(context.Background(), newSSL)
422+
if websiteSSL.ID > 0 {
423+
return websiteSSLRepo.Save(websiteSSL)
424+
}
425+
return websiteSSLRepo.Create(context.Background(), websiteSSL)
417426
}
418427

419428
func (w WebsiteSSLService) SyncForRestart() error {

backend/init/migration/migrations/v_1_9.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ var AddWebsiteCA = &gormigrate.Migration{
2727
}
2828

2929
var UpdateWebsiteSSL = &gormigrate.Migration{
30-
ID: "20231127-update-website-ssl",
30+
ID: "20231128-update-website-ssl",
3131
Migrate: func(tx *gorm.DB) error {
3232
if err := tx.AutoMigrate(&model.WebsiteSSL{}); err != nil {
3333
return err

frontend/src/api/interface/website.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,7 @@ export namespace Website {
451451
privateKeyPath: string;
452452
certificatePath: string;
453453
type: string;
454+
sslID: number;
454455
}
455456

456457
export interface SSLObtain {

frontend/src/views/website/ssl/detail/index.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
</el-descriptions>
5454
</div>
5555
<div v-else-if="curr === 'ssl'">
56-
<el-input v-model="ssl.pem" :autosize="{ minRows: 10, maxRows: 15 }" type="textarea" id="textArea" />
56+
<el-input v-model="ssl.pem" :autosize="{ minRows: 15, maxRows: 30 }" type="textarea" id="textArea" />
5757
<div>
5858
<br />
5959
<el-button type="primary" @click="copyText(ssl.pem)">{{ $t('file.copy') }}</el-button>
@@ -62,7 +62,7 @@
6262
<div v-else>
6363
<el-input
6464
v-model="ssl.privateKey"
65-
:autosize="{ minRows: 10, maxRows: 15 }"
65+
:autosize="{ minRows: 15, maxRows: 30 }"
6666
type="textarea"
6767
id="textArea"
6868
/>

frontend/src/views/website/ssl/index.vue

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,13 @@
8383
placement="bottom"
8484
:width="400"
8585
trigger="hover"
86-
:content="row.message"
8786
>
8887
<template #reference>
8988
<Status :key="row.status" :status="row.status"></Status>
9089
</template>
90+
<div class="max-h-96 overflow-auto">
91+
<span>{{ row.message }}</span>
92+
</div>
9193
</el-popover>
9294
<div v-else>
9395
<Status :key="row.status" :status="row.status"></Status>
@@ -214,6 +216,18 @@ const buttons = [
214216
applySSL(row);
215217
}
216218
},
219+
show: function (row: Website.SSLDTO) {
220+
return row.provider != 'manual';
221+
},
222+
},
223+
{
224+
label: i18n.global.t('commons.operate.update'),
225+
click: function (row: Website.SSLDTO) {
226+
sslUploadRef.value.acceptParams(row.id);
227+
},
228+
show: function (row: Website.SSLDTO) {
229+
return row.provider == 'manual';
230+
},
217231
},
218232
{
219233
label: i18n.global.t('commons.button.delete'),

frontend/src/views/website/ssl/upload/index.vue

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,15 @@ const rules = ref({
7070
certificatePath: [Rules.requiredInput],
7171
type: [Rules.requiredSelect],
7272
});
73-
const ssl = ref({
73+
const initData = () => ({
7474
privateKey: '',
7575
certificate: '',
7676
privateKeyPath: '',
7777
certificatePath: '',
7878
type: 'paste',
79+
sslID: 0,
7980
});
81+
const ssl = ref(initData());
8082
8183
const em = defineEmits(['close']);
8284
const handleClose = () => {
@@ -86,17 +88,14 @@ const handleClose = () => {
8688
};
8789
const resetForm = () => {
8890
sslForm.value?.resetFields();
89-
ssl.value = {
90-
privateKey: '',
91-
certificate: '',
92-
privateKeyPath: '',
93-
certificatePath: '',
94-
type: 'paste',
95-
};
91+
ssl.value = initData();
9692
};
9793
98-
const acceptParams = () => {
94+
const acceptParams = (id: number) => {
9995
resetForm();
96+
if (id && id > 0) {
97+
ssl.value.sslID = id;
98+
}
10099
open.value = true;
101100
};
102101

0 commit comments

Comments
 (0)