Skip to content

Commit c477d20

Browse files
feat: support batch SSL configuration for websites (#11339)
Refs #8250
1 parent 2fdb170 commit c477d20

File tree

23 files changed

+642
-283
lines changed

23 files changed

+642
-283
lines changed

agent/app/api/v2/website.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,3 +1243,23 @@ func (b *BaseApi) UpdateStreamConfig(c *gin.Context) {
12431243
}
12441244
helper.Success(c)
12451245
}
1246+
1247+
// @Tags Website
1248+
// @Summary Batch set HTTPS for websites
1249+
// @Accept json
1250+
// @Param request body request.BatchWebsiteHttps true "request"
1251+
// @Success 200
1252+
// @Security ApiKeyAuth
1253+
// @Security Timestamp
1254+
// @Router /websites/batch/https [post]
1255+
func (b *BaseApi) BatchSetHttps(c *gin.Context) {
1256+
var req request.BatchWebsiteHttps
1257+
if err := helper.CheckBindAndValidate(&req, c); err != nil {
1258+
return
1259+
}
1260+
if err := websiteService.BatchSetHttps(c, req); err != nil {
1261+
helper.InternalServer(c, err)
1262+
return
1263+
}
1264+
helper.Success(c)
1265+
}

agent/app/dto/request/website.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,25 @@ type BatchWebsiteGroup struct {
129129
GroupID uint `json:"groupID" validate:"required"`
130130
}
131131

132+
type BatchWebsiteHttps struct {
133+
IDs []uint `json:"ids" validate:"required"`
134+
TaskID string `json:"taskID" validate:"required"`
135+
WebsiteSSLID uint `json:"websiteSSLId"`
136+
Type string `json:"type" validate:"oneof=existed auto manual"`
137+
PrivateKey string `json:"privateKey"`
138+
Certificate string `json:"certificate"`
139+
PrivateKeyPath string `json:"privateKeyPath"`
140+
CertificatePath string `json:"certificatePath"`
141+
ImportType string `json:"importType"`
142+
HttpConfig string `json:"httpConfig" validate:"oneof=HTTPSOnly HTTPAlso HTTPToHTTPS"`
143+
SSLProtocol []string `json:"SSLProtocol"`
144+
Algorithm string `json:"algorithm"`
145+
Hsts bool `json:"hsts"`
146+
HstsIncludeSubDomains bool `json:"hstsIncludeSubDomains"`
147+
HttpsPorts []int `json:"httpsPorts"`
148+
Http3 bool `json:"http3"`
149+
}
150+
132151
type WebsiteRedirectUpdate struct {
133152
WebsiteID uint `json:"websiteId" validate:"required"`
134153
Key string `json:"key" validate:"required"`

agent/app/service/website.go

Lines changed: 5 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"os"
1313
"path"
1414
"reflect"
15-
"sort"
1615
"strconv"
1716
"strings"
1817
"syscall"
@@ -58,9 +57,7 @@ type IWebsiteService interface {
5857
UpdateWebsite(req request.WebsiteUpdate) error
5958
DeleteWebsite(req request.WebsiteDelete) error
6059
GetWebsite(id uint) (response.WebsiteDTO, error)
61-
BatchOpWebsite(req request.BatchWebsiteOp) error
6260

63-
BatchSetGroup(req request.BatchWebsiteGroup) error
6461
ChangePHPVersion(req request.WebsitePHPVersionReq) error
6562
OperateCrossSiteAccess(req request.CrossSiteAccessOp) error
6663
ExecComposer(req request.ExecComposerReq) error
@@ -130,6 +127,10 @@ type IWebsiteService interface {
130127
UpdateAuthBasic(req request.NginxAuthUpdate) (err error)
131128
GetPathAuthBasics(req request.NginxAuthReq) (res []response.NginxPathAuthRes, err error)
132129
UpdatePathAuthBasic(req request.NginxPathAuthUpdate) error
130+
131+
BatchOpWebsite(req request.BatchWebsiteOp) error
132+
BatchSetGroup(req request.BatchWebsiteGroup) error
133+
BatchSetHttps(ctx context.Context, req request.BatchWebsiteHttps) error
133134
}
134135

135136
func NewIWebsiteService() IWebsiteService {
@@ -540,63 +541,6 @@ func (w WebsiteService) OpWebsite(req request.WebsiteOp) error {
540541
return websiteRepo.Save(context.Background(), &website)
541542
}
542543

543-
func (w WebsiteService) BatchSetGroup(req request.BatchWebsiteGroup) error {
544-
websites, _ := websiteRepo.List(repo.WithByIDs(req.IDs))
545-
for _, web := range websites {
546-
web.WebsiteGroupID = req.GroupID
547-
if err := websiteRepo.Save(context.Background(), &web); err != nil {
548-
return err
549-
}
550-
}
551-
return nil
552-
}
553-
554-
func (w WebsiteService) BatchOpWebsite(req request.BatchWebsiteOp) error {
555-
websites, _ := websiteRepo.List(repo.WithByIDs(req.IDs))
556-
opTask, err := task.NewTaskWithOps(i18n.GetMsgByKey("Status"), task.TaskBatch, task.TaskScopeWebsite, req.TaskID, 0)
557-
if err != nil {
558-
return err
559-
}
560-
sort.SliceStable(websites, func(i, j int) bool {
561-
if websites[i].Type == constant.Subsite && websites[j].Type != constant.Subsite {
562-
return true
563-
}
564-
if websites[i].Type != constant.Subsite && websites[j].Type == constant.Subsite {
565-
return false
566-
}
567-
return false
568-
})
569-
opWebsiteTask := func(t *task.Task) error {
570-
for _, web := range websites {
571-
msg := fmt.Sprintf("%s %s", i18n.GetMsgByKey(req.Operate), web.PrimaryDomain)
572-
switch req.Operate {
573-
case constant.StopWeb, constant.StartWeb:
574-
if err := opWebsite(&web, req.Operate); err != nil {
575-
t.LogFailedWithErr(msg, err)
576-
continue
577-
}
578-
_ = websiteRepo.Save(context.Background(), &web)
579-
case "delete":
580-
if err := w.DeleteWebsite(request.WebsiteDelete{
581-
ID: web.ID,
582-
}); err != nil {
583-
t.LogFailedWithErr(msg, err)
584-
continue
585-
}
586-
}
587-
588-
t.LogSuccess(msg)
589-
}
590-
return nil
591-
}
592-
opTask.AddSubTask("", opWebsiteTask, nil)
593-
594-
go func() {
595-
_ = opTask.Execute()
596-
}()
597-
return nil
598-
}
599-
600544
func (w WebsiteService) GetWebsiteOptions(req request.WebsiteOptionReq) ([]response.WebsiteOption, error) {
601545
var options []repo.DBOption
602546
if len(req.Types) > 0 {
@@ -2403,7 +2347,7 @@ func (w WebsiteService) ExecComposer(req request.ExecComposerReq) error {
24032347
}
24042348

24052349
func (w WebsiteService) UpdateStream(req request.StreamUpdate) error {
2406-
if req.StreamConfig.StreamPorts == ""{
2350+
if req.StreamConfig.StreamPorts == "" {
24072351
return buserr.New("ErrTypePortRange")
24082352
}
24092353
website, err := websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))

agent/app/service/website_op.go

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package service
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
7+
"github.com/1Panel-dev/1Panel/agent/app/repo"
8+
"github.com/1Panel-dev/1Panel/agent/app/task"
9+
"github.com/1Panel-dev/1Panel/agent/constant"
10+
"github.com/1Panel-dev/1Panel/agent/i18n"
11+
"sort"
12+
)
13+
14+
func (w WebsiteService) BatchOpWebsite(req request.BatchWebsiteOp) error {
15+
websites, _ := websiteRepo.List(repo.WithByIDs(req.IDs))
16+
opTask, err := task.NewTaskWithOps(i18n.GetMsgByKey("Status"), task.TaskBatch, task.TaskScopeWebsite, req.TaskID, 0)
17+
if err != nil {
18+
return err
19+
}
20+
sort.SliceStable(websites, func(i, j int) bool {
21+
if websites[i].Type == constant.Subsite && websites[j].Type != constant.Subsite {
22+
return true
23+
}
24+
if websites[i].Type != constant.Subsite && websites[j].Type == constant.Subsite {
25+
return false
26+
}
27+
return false
28+
})
29+
opWebsiteTask := func(t *task.Task) error {
30+
for _, web := range websites {
31+
msg := fmt.Sprintf("%s %s", i18n.GetMsgByKey(req.Operate), web.PrimaryDomain)
32+
switch req.Operate {
33+
case constant.StopWeb, constant.StartWeb:
34+
if err := opWebsite(&web, req.Operate); err != nil {
35+
t.LogFailedWithErr(msg, err)
36+
continue
37+
}
38+
_ = websiteRepo.Save(context.Background(), &web)
39+
case "delete":
40+
if err := w.DeleteWebsite(request.WebsiteDelete{
41+
ID: web.ID,
42+
}); err != nil {
43+
t.LogFailedWithErr(msg, err)
44+
continue
45+
}
46+
}
47+
48+
t.LogSuccess(msg)
49+
}
50+
return nil
51+
}
52+
opTask.AddSubTask("", opWebsiteTask, nil)
53+
54+
go func() {
55+
_ = opTask.Execute()
56+
}()
57+
return nil
58+
}
59+
60+
func (w WebsiteService) BatchSetGroup(req request.BatchWebsiteGroup) error {
61+
websites, _ := websiteRepo.List(repo.WithByIDs(req.IDs))
62+
for _, web := range websites {
63+
web.WebsiteGroupID = req.GroupID
64+
if err := websiteRepo.Save(context.Background(), &web); err != nil {
65+
return err
66+
}
67+
}
68+
return nil
69+
}
70+
71+
func (w WebsiteService) BatchSetHttps(ctx context.Context, req request.BatchWebsiteHttps) error {
72+
websites, _ := websiteRepo.List(repo.WithByIDs(req.IDs))
73+
opTask, err := task.NewTaskWithOps(i18n.GetMsgByKey("SSL"), task.TaskBatch, task.TaskScopeWebsite, req.TaskID, 0)
74+
if err != nil {
75+
return err
76+
}
77+
websiteHttpsOp := request.WebsiteHTTPSOp{
78+
Enable: true,
79+
WebsiteSSLID: req.WebsiteSSLID,
80+
Type: req.Type,
81+
PrivateKey: req.PrivateKey,
82+
Certificate: req.Certificate,
83+
PrivateKeyPath: req.PrivateKeyPath,
84+
CertificatePath: req.CertificatePath,
85+
ImportType: req.ImportType,
86+
HttpConfig: req.HttpConfig,
87+
SSLProtocol: req.SSLProtocol,
88+
Algorithm: req.Algorithm,
89+
Hsts: req.Hsts,
90+
HstsIncludeSubDomains: req.HstsIncludeSubDomains,
91+
HttpsPorts: req.HttpsPorts,
92+
Http3: req.Http3,
93+
}
94+
opWebsiteTask := func(t *task.Task) error {
95+
for _, web := range websites {
96+
if web.Type == constant.Stream {
97+
continue
98+
}
99+
websiteHttpsOp.WebsiteID = web.ID
100+
msg := fmt.Sprintf("%s [%s] %s", i18n.GetMsgByKey("Set"), web.PrimaryDomain, i18n.GetMsgByKey("SSL"))
101+
if _, err := w.OpWebsiteHTTPS(ctx, websiteHttpsOp); err != nil {
102+
t.LogFailedWithErr(msg, err)
103+
continue
104+
}
105+
t.LogSuccess(msg)
106+
}
107+
return nil
108+
}
109+
110+
opTask.AddSubTask("", opWebsiteTask, nil)
111+
go func() {
112+
_ = opTask.Execute()
113+
}()
114+
return nil
115+
}

agent/constant/website.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const (
3131

3232
StartWeb = "start"
3333
StopWeb = "stop"
34+
SetHttps = "setHttps"
3435

3536
HTTPSOnly = "HTTPSOnly"
3637
HTTPAlso = "HTTPAlso"

agent/i18n/lang/en.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ unpause: 'Resume'
154154
remove: 'Delete'
155155
delete: 'Delete'
156156
ErrDefaultWebsite: 'Default website has been set, please cancel it before setting!'
157+
SSL: 'Certificate'
158+
Set: 'Settings'
157159

158160
#ssl
159161
ErrSSLCannotDelete: 'The {{ .name }} certificate is being used by a website and cannot be deleted'

agent/i18n/lang/es-ES.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ unpause: 'Reanudar'
153153
remove: 'Eliminar'
154154
delete: 'Eliminar'
155155
ErrDefaultWebsite: 'El sitio web predeterminado ya está configurado, ¡cancélelo antes de configurar!'
156+
SSL: 'Certificado'
157+
Set: 'Configuración'
156158

157159
#ssl
158160
ErrSSLCannotDelete: 'El certificado {{ .name }} está siendo utilizado por un sitio web y no puede eliminarse'

agent/i18n/lang/ja.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ unpause: '再開'
153153
remove: '削除'
154154
delete: '削除'
155155
ErrDefaultWebsite: 'デフォルト Web サイトが既に設定されています。設定する前にキャンセルしてください!'
156+
SSL: '証明書'
157+
Set: '設定'
156158

157159
#ssl
158160
ErrSSLCannotDelete: '{{ .name }} 証明書は Web サイトで使用されているため、削除できません'

agent/i18n/lang/ko.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ unpause: '재개'
154154
remove: '삭제'
155155
delete: '삭제'
156156
ErrDefaultWebsite: '기본 웹사이트가 이미 설정되었습니다. 설정하기 전에 취소하세요!'
157+
SSL: '인증서'
158+
Set: '설정'
157159

158160
#SSL인증
159161
ErrSSLCannotDelete: '{{ .name }} 인증서는 웹사이트에서 사용 중이므로 삭제할 수 없습니다.'

agent/i18n/lang/ms.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ unpause: 'Sambung Semula'
157157
remove: 'Padam'
158158
delete: 'Padam'
159159
ErrDefaultWebsite: 'Laman web lalai telah ditetapkan, sila batalkan sebelum menetapkan!'
160+
SSL: 'Sijil'
161+
Set: 'Tetapan'
160162

161163
#ssl
162164
ErrSSLCannotDelete: 'Sijil {{ .name }} sedang digunakan oleh tapak web dan tidak boleh dipadamkan'

0 commit comments

Comments
 (0)