diff --git a/route/v1/user.go b/route/v1/user.go index dabdddb..9314c06 100644 --- a/route/v1/user.go +++ b/route/v1/user.go @@ -317,7 +317,6 @@ func OnePanelUpdateWebsite(c *gin.Context) { } if search.Data.Items[0].Protocol != protocol && protocol == "http" { //TODO disable HTTPS - if sslId > 0 { var updateHttps, err = UpdateWebsiteHttps(false, acmeId, sslId, search.Data.Items[0].ID, headers) if err != nil { @@ -428,6 +427,7 @@ func OnePanelCreateWebsite(c *gin.Context) { } if protocol == "https" { //TODO Find SSL + var validSSL bool var searchSSL model2.SearchSSLRequest searchSSL.Page = 0 searchSSL.PageSize = 0 @@ -459,6 +459,18 @@ func OnePanelCreateWebsite(c *gin.Context) { }) return } + if sslId > 0 { + validSSL, err = checkGlobalSSLStatus(sslId, headers, domain, 10) + if err != nil { + c.JSON(common_err.SUCCESS, + model.Result{ + Success: common_err.COMMAND_ERROR_INVALID_OPERATION, + Message: fmt.Sprintf("Fail to upgrade %s from http to https", domain), + Data: false, + }) + return + } + } } else { sslId, err = IssueSelfSignedCert(domain, search.Data.Items[0].ID, headers, 3) if err != nil { @@ -470,13 +482,23 @@ func OnePanelCreateWebsite(c *gin.Context) { }) return } + validSSL = true } } + if sslId < 0 || !validSSL { + c.JSON(common_err.SUCCESS, + model.Result{ + Success: common_err.COMMAND_ERROR_INVALID_OPERATION, + Message: fmt.Sprintf("Fail to Create SSL or domain %s is invalid to create global SSL", domain), + Data: false, + }) + return + } // TODO Enable HTTPS var searchAcme model2.AcmeSearchRequest acmeId := 0 - searchAcme.Page = 0 - searchAcme.PageSize = 0 + searchAcme.Page = 1 + searchAcme.PageSize = 1000 if sslProvider == "http" { acme, err := service.MyService.OnePanel().AcmeAccountSearch(searchAcme, config.NextWebInfo.Server, headers) if err != nil { @@ -531,6 +553,27 @@ func OnePanelCreateWebsite(c *gin.Context) { Message: common_err.GetMsg(common_err.SUCCESS), }) } + +func checkGlobalSSLStatus(sslId int, headers map[string]string, domain string, retries int) (bool, error) { + if retries <= 0 { + return false, errors.New("timeout waiting for SSL certificate to become ready") + } + + sslDetail, err := service.MyService.OnePanel().GetSSLDetail(sslId, config.NextWebInfo.Server, headers) + if err != nil { + return false, err + } + if sslDetail.Data.Status == "ready" { + return true, nil + } + if sslDetail.Data.Status == "applyError" { + return false, nil + } + + time.Sleep(3 * time.Second) + + return checkGlobalSSLStatus(sslId, headers, domain, retries-1) +} func IssueSelfSignedCert(domain string, websiteId int, headers map[string]string, maxAttempts int) (int, error) { if maxAttempts <= 0 { return 0, errors.New("maximum attempts reached") @@ -593,8 +636,8 @@ func IssueSelfSignedCert(domain string, websiteId int, headers map[string]string } func OnePanelApplyWebsiteSSl(domain string, websiteId int, headers map[string]string) (int, error) { var searchAcme model2.AcmeSearchRequest - searchAcme.Page = 0 - searchAcme.PageSize = 0 + searchAcme.Page = 1 + searchAcme.PageSize = 10000 acme, err := service.MyService.OnePanel().AcmeAccountSearch(searchAcme, config.NextWebInfo.Server, headers) if err != nil { return 0, err diff --git a/service/1panel.go b/service/1panel.go index 2d39dd5..a8f5c71 100644 --- a/service/1panel.go +++ b/service/1panel.go @@ -29,6 +29,7 @@ type OnePanelService interface { SearchWebsiteSSl(m model2.SearchSSLRequest, baseUrl string, headers map[string]string) (model2.SearchSSLResponse, error) UpdateWebsiteProtocol(m model2.WebsiteHttpsConfigRequest, baseUrl string, headers map[string]string) (model2.GenericResponse, error) DeleteWebsiteSSL(m model2.DeleteSSLRequest, baseUrl string, headers map[string]string) (model2.GenericResponse, error) + GetSSLDetail(sslId int, baseUrl string, headers map[string]string) (model2.SSLDetail, error) } var ( @@ -38,7 +39,32 @@ var ( type onePanelService struct { } -// TODO A lot of redundant code need refactor +func (o *onePanelService) GetSSLDetail(sslId int, baseUrl string, headers map[string]string) (model2.SSLDetail, error) { + path := baseUrl + fmt.Sprintf("/api/v1/websites/ssl/%d", sslId) + + req, err := http.NewRequest("GET", path, nil) + if err != nil { + return model2.SSLDetail{}, fmt.Errorf("error creating request: %v", err) + } + // Add headers to the request + for key, value := range headers { + req.Header.Set(key, value) + } + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return model2.SSLDetail{}, fmt.Errorf("error making request: %v", err) + } + defer resp.Body.Close() + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return model2.SSLDetail{}, fmt.Errorf("HTTP error: %s", resp.Status) + } + var result model2.SSLDetail + if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { + return model2.SSLDetail{}, fmt.Errorf("error decoding response: %v", err) + } + return result, nil +} func (o *onePanelService) DeleteWebsiteSSL(m model2.DeleteSSLRequest, baseUrl string, headers map[string]string) (model2.GenericResponse, error) { path := baseUrl + "/api/v1/websites/ssl/del" reqBody, err := json.Marshal(m) diff --git a/service/model/dto_onepanel_ssl.go b/service/model/dto_onepanel_ssl.go index edaa920..c3fa0cb 100644 --- a/service/model/dto_onepanel_ssl.go +++ b/service/model/dto_onepanel_ssl.go @@ -282,3 +282,59 @@ type DNSAccount struct { Name string `json:"name"` Type string `json:"type"` } + +type SSLDetail struct { + Code int `json:"code"` + Message string `json:"message"` + Data struct { + ID int `json:"id"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + PrimaryDomain string `json:"primaryDomain"` + PrivateKey string `json:"privateKey"` + Pem string `json:"pem"` + Domains string `json:"domains"` + CertURL string `json:"certURL"` + Type string `json:"type"` + Provider string `json:"provider"` + Organization string `json:"organization"` + DNSAccountID int `json:"dnsAccountId"` + AcmeAccountID int `json:"acmeAccountId"` + CaID int `json:"caId"` + AutoRenew bool `json:"autoRenew"` + ExpireDate time.Time `json:"expireDate"` + StartDate time.Time `json:"startDate"` + Status string `json:"status"` + Message string `json:"message"` + KeyType string `json:"keyType"` + PushDir bool `json:"pushDir"` + Dir string `json:"dir"` + Description string `json:"description"` + SkipDNS bool `json:"skipDNS"` + Nameserver1 string `json:"nameserver1"` + Nameserver2 string `json:"nameserver2"` + DisableCNAME bool `json:"disableCNAME"` + ExecShell bool `json:"execShell"` + Shell string `json:"shell"` + AcmeAccount struct { + ID int `json:"id"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + Email string `json:"email"` + URL string `json:"url"` + Type string `json:"type"` + EabKid string `json:"eabKid"` + EabHmacKey string `json:"eabHmacKey"` + KeyType string `json:"keyType"` + } `json:"acmeAccount"` + DNSAccount struct { + ID int `json:"id"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + Name string `json:"name"` + Type string `json:"type"` + } `json:"dnsAccount"` + Websites interface{} `json:"websites"` + LogPath string `json:"logPath"` + } `json:"data"` +}