diff --git a/.vscode/launch.json b/.vscode/launch.json index b979b03..5338493 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,7 +6,7 @@ "type": "go", "debugAdapter": "dlv-dap", "request": "launch", - "port": 46535, + "port": 39117, "host": "127.0.0.1", "mode": "exec", "program": "${workspaceFolder}/dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user-service" diff --git a/route/v1.go b/route/v1.go index 8507ec1..941e290 100644 --- a/route/v1.go +++ b/route/v1.go @@ -55,6 +55,7 @@ func InitRouter() *gin.Engine { // r.POST("/v1/1panel/website/search", v1.ExternalAPIMiddleware, v1.OnePanelLogin) r.POST("/v1/1panel/website/create", v1.ExternalAPIMiddleware, v1.OnePanelCreateWebsite) r.POST("/v1/1panel/website/delete", v1.ExternalAPIMiddleware, v1.OnePanelDeleteWebsite) + r.POST("/v1/1panel/website/update-proxy", v1.ExternalAPIMiddleware, v1.OnePanelUpdateProxyWebsite) v1Group := r.Group("/v1") v1Group.Use(jwt.JWT( diff --git a/route/v1/user.go b/route/v1/user.go index ebdea06..bdd3e16 100644 --- a/route/v1/user.go +++ b/route/v1/user.go @@ -208,22 +208,85 @@ func OnePanelLogin(c *gin.Context) error { // Data: response, // }) // } -// - +func OnePanelUpdateProxyWebsite(c *gin.Context) { + json := make(map[string]string) + c.ShouldBind(&json) + domain := json["domain"] + port := json["port"] + hostname := json["hostname"] + protocol := json["protocol"] + var searchParam model2.SearchWebsiteRequest + searchParam.Name = domain + searchParam.Page = 1 + searchParam.PageSize = 1 + searchParam.OrderBy = "created_at" + searchParam.Order = "null" + searchParam.WebsiteGroupID = 0 + headers := make(map[string]string) + for key, value := range c.Request.Header { + headers[key] = value[0] + } + var search model2.SearchWebsiteResponse + search, err := service.MyService.OnePanel().SearchWebsite(searchParam, onePanelServer, headers) + if err != nil { + c.JSON(common_err.SERVICE_ERROR, + model.Result{ + Success: common_err.SERVICE_ERROR, + Message: common_err.GetMsg(common_err.SERVICE_ERROR), + }) + } + if search.Data.Total > 0 { + var proxy model2.ProxyWebsiteRequest + proxy.ID = search.Data.Items[0].ID + var proxyResult model2.ProxyWebsiteResponse + proxyResult, err := service.MyService.OnePanel().GetProxyWebsite(proxy, onePanelServer, headers) + if err != nil { + c.JSON(common_err.SERVICE_ERROR, + model.Result{ + Success: common_err.SERVICE_ERROR, + Message: common_err.GetMsg(common_err.SERVICE_ERROR), + }) + } + var updateProxy model2.ProxyDetail + updateProxy = proxyResult.Data[0] + updateProxy.Operate = "edit" + updateProxy.ProxyPass = protocol + "://" + hostname + ":" + port + updateProxyResult, err := service.MyService.OnePanel().UpdateProxyWebsite(updateProxy, onePanelServer, headers) + if err != nil { + c.JSON(common_err.SERVICE_ERROR, + model.Result{ + Success: common_err.SERVICE_ERROR, + Message: common_err.GetMsg(common_err.SERVICE_ERROR), + }) + } + c.JSON(common_err.SUCCESS, + model.Result{ + Success: common_err.SUCCESS, + Message: common_err.GetMsg(common_err.SUCCESS), + Data: updateProxyResult, + }) + return + } + c.JSON(common_err.SUCCESS, + model.Result{ + Success: common_err.SUCCESS, + Message: common_err.GetMsg(common_err.SUCCESS), + }) +} func OnePanelCreateWebsite(c *gin.Context) { json := make(map[string]string) c.ShouldBind(&json) domain := json["domain"] port := json["port"] protocol := json["protocol"] - host := json["host"] + hostname := json["hostname"] var website model2.CreateWebsiteRequest website.PrimaryDomain = domain website.Type = "proxy" website.Alias = domain website.AppType = "installed" website.WebSiteGroupID = 2 - website.Proxy = protocol + "://" + host + ":" + port + website.Proxy = protocol + "://" + hostname + ":" + port portInt, err := strconv.ParseInt(port, 10, 64) if err != nil { log.Printf("Error converting port to integer: %v", err) @@ -231,7 +294,7 @@ func OnePanelCreateWebsite(c *gin.Context) { } website.Port = portInt website.ProxyProtocol = protocol - website.ProxyAddress = host + ":" + port + website.ProxyAddress = hostname + ":" + port website.RuntimeType = "php" headers := make(map[string]string) for key, value := range c.Request.Header { @@ -268,8 +331,6 @@ func OnePanelCreateWebsite(c *gin.Context) { Data: response, }) return - } else { - } c.JSON(common_err.SUCCESS, model.Result{ @@ -435,10 +496,12 @@ func InitOIDC() { oidcInit = true failCount = 0 successCount++ + // TODO will enable in production // Exponential backoff with a cap - sleepTime = minSleep * time.Duration(successCount) + // sleepTime = minSleep * time.Duration(successCount) if sleepTime > maxSleep { - sleepTime = maxSleep + // TODO will enable in production + // sleepTime = maxSleep } } else { @@ -448,7 +511,8 @@ func InitOIDC() { // Exponential backoff with a cap sleepTime = minSleep * time.Duration(failCount) if failCount > maxRetryBackoff { - sleepTime = minSleep * time.Duration(maxRetryBackoff) + // TODO will enable in production + // sleepTime = minSleep * time.Duration(maxRetryBackoff) } log.Printf("OIDC initialization failed: %v. Retrying in %v", err, sleepTime) } diff --git a/service/1panel.go b/service/1panel.go index fbf4549..99e6158 100644 --- a/service/1panel.go +++ b/service/1panel.go @@ -20,7 +20,11 @@ type OnePanelService interface { CreateWebsite(m model2.CreateWebsiteRequest, baseUrl string, headers map[string]string) (model2.GenericResponse, error) DeleteWebsite(m model2.DeleteWebsiteRequest, baseUrl string, headers map[string]string) (model2.GenericResponse, error) GetProxyWebsite(m model2.ProxyWebsiteRequest, baseUrl string, headers map[string]string) (model2.ProxyWebsiteResponse, error) - UpdateProxyWebsite(m model2.UpdateProxyRequest, baseUrl string, headers map[string]string) (model2.GenericResponse, error) + UpdateProxyWebsite(m model2.ProxyDetail, baseUrl string, headers map[string]string) (model2.GenericResponse, error) + AcmeAccountSearch(m model2.AcmeSearchRequest, baseUrl string, headers map[string]string) (model2.AcmeSearchResponse, error) + ApplyWebsiteSSl(m model2.CreateSSLRequest, baseUrl string, headers map[string]string) (model2.CreateSSLResponse, error) + SearchWebsiteSSl(m model2.SearchSSLRequest, baseUrl string, headers map[string]string) (model2.SearchSSLResponse, error) + //UpdateWebsiteProtocol } var ( @@ -31,7 +35,94 @@ type onePanelService struct { } // TODO A lot of redundant code need refactor -func (o *onePanelService) UpdateProxyWebsite(m model2.UpdateProxyRequest, baseUrl string, headers map[string]string) (model2.GenericResponse, error) { +func (o *onePanelService) SearchWebsiteSSl(m model2.SearchSSLRequest, baseUrl string, headers map[string]string) (model2.SearchSSLResponse, error) { + path := baseUrl + "/api/v1/websites/ssl/search" + reqBody, err := json.Marshal(m) + if err != nil { + return model2.SearchSSLResponse{}, fmt.Errorf("error marshaling request body: %v", err) + } + req, err := http.NewRequest("POST", path, bytes.NewReader(reqBody)) + if err != nil { + return model2.SearchSSLResponse{}, 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.SearchSSLResponse{}, fmt.Errorf("error making request: %v", err) + } + defer resp.Body.Close() + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return model2.SearchSSLResponse{}, fmt.Errorf("HTTP error: %s", resp.Status) + } + var result model2.SearchSSLResponse + if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { + return model2.SearchSSLResponse{}, fmt.Errorf("error decoding response: %v", err) + } + return result, nil +} +func (o *onePanelService) ApplyWebsiteSSl(m model2.CreateSSLRequest, baseUrl string, headers map[string]string) (model2.CreateSSLResponse, error) { + path := baseUrl + "/api/v1/websites/ssl" + reqBody, err := json.Marshal(m) + if err != nil { + return model2.CreateSSLResponse{}, fmt.Errorf("error marshaling request body: %v", err) + } + req, err := http.NewRequest("POST", path, bytes.NewReader(reqBody)) + if err != nil { + return model2.CreateSSLResponse{}, 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.CreateSSLResponse{}, fmt.Errorf("error making request: %v", err) + } + defer resp.Body.Close() + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return model2.CreateSSLResponse{}, fmt.Errorf("HTTP error: %s", resp.Status) + } + var result model2.CreateSSLResponse + if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { + return model2.CreateSSLResponse{}, fmt.Errorf("error decoding response: %v", err) + } + return result, nil +} +func (o *onePanelService) AcmeAccountSearch(m model2.AcmeSearchRequest, baseUrl string, headers map[string]string) (model2.AcmeSearchResponse, error) { + path := baseUrl + "/api/v1/websites/acme/search" + reqBody, err := json.Marshal(m) + if err != nil { + return model2.AcmeSearchResponse{}, fmt.Errorf("error marshaling request body: %v", err) + } + req, err := http.NewRequest("POST", path, bytes.NewReader(reqBody)) + if err != nil { + return model2.AcmeSearchResponse{}, 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.AcmeSearchResponse{}, fmt.Errorf("error making request: %v", err) + } + defer resp.Body.Close() + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return model2.AcmeSearchResponse{}, fmt.Errorf("HTTP error: %s", resp.Status) + } + var result model2.AcmeSearchResponse + if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { + return model2.AcmeSearchResponse{}, fmt.Errorf("error decoding response: %v", err) + } + return result, nil +} +func (o *onePanelService) UpdateProxyWebsite(m model2.ProxyDetail, baseUrl string, headers map[string]string) (model2.GenericResponse, error) { path := baseUrl + "/api/v1/websites/proxies/update" reqBody, err := json.Marshal(m) if err != nil { diff --git a/service/model/dto_onepanel_ssl.go b/service/model/dto_onepanel_ssl.go index 2f3259c..92ab713 100644 --- a/service/model/dto_onepanel_ssl.go +++ b/service/model/dto_onepanel_ssl.go @@ -1,5 +1,7 @@ package model +import "time" + type CreateSSLRequest struct { ID int `json:"id"` PrimaryDomain string `json:"primaryDomain"` @@ -45,3 +47,81 @@ type CreateSSLResponse struct { } `json:"data"` } +type AcmeSearchRequest struct { + Page int `json:"page"` + PageSize int `json:"pageSize"` +} + +type SearchSSLRequest struct { + Page int `json:"page"` + PageSize int `json:"pageSize"` +} +type SearchSSLResponse struct { + Code int `json:"code"` + Message string `json:"message"` + Data struct { + Total int `json:"total"` + Items []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 AcmeAccount `json:"acmeAccount"` + DNSAccount DNSAccount `json:"dnsAccount"` + Websites []interface{} `json:"websites"` + LogPath string `json:"logPath"` + } `json:"items"` + } `json:"data"` +} +type AcmeSearchResponse struct { + Code int `json:"code"` + Message string `json:"message"` + Data struct { + Total int `json:"total"` + Items []AcmeAccount `json:"items"` + } `json:"data"` +} + +type 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"` +} +type DNSAccount struct { + ID int `json:"id"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + Name string `json:"name"` + Type string `json:"type"` +} diff --git a/service/model/dtop_onepanel_website.go b/service/model/dtop_onepanel_website.go index d01e541..4dd9b4c 100644 --- a/service/model/dtop_onepanel_website.go +++ b/service/model/dtop_onepanel_website.go @@ -90,28 +90,12 @@ type ProxyWebsiteRequest struct { } type ProxyWebsiteResponse struct { - Code int `json:"code"` - Message string `json:"message"` - Data []struct { - ID int `json:"id"` - Operate string `json:"operate"` - Enable bool `json:"enable"` - Cache bool `json:"cache"` - CacheTime int `json:"cacheTime"` - CacheUnit string `json:"cacheUnit"` - Name string `json:"name"` - Modifier string `json:"modifier"` - Match string `json:"match"` - ProxyPass string `json:"proxyPass"` - ProxyHost string `json:"proxyHost"` - Content string `json:"content"` - FilePath string `json:"filePath"` - Replaces interface{} `json:"replaces"` - Sni bool `json:"sni"` - } `json:"data"` + Code int `json:"code"` + Message string `json:"message"` + Data []ProxyDetail `json:"data"` } -type UpdateProxyRequest struct { +type ProxyDetail struct { ID int `json:"id"` Operate string `json:"operate"` Enable bool `json:"enable"` @@ -131,3 +115,81 @@ type UpdateProxyRequest struct { ProxyProtocol string `json:"proxyProtocol"` ProxyAddress string `json:"proxyAddress"` } +type WebsiteHttpsRequest struct { + AcmeAccountID int `json:"acmeAccountID"` + Enable bool `json:"enable"` + WebsiteID int `json:"websiteId"` + WebsiteSSLID int `json:"websiteSSLId"` + Type string `json:"type"` + ImportType string `json:"importType"` + PrivateKey string `json:"privateKey"` + Certificate string `json:"certificate"` + PrivateKeyPath string `json:"privateKeyPath"` + CertificatePath string `json:"certificatePath"` + HTTPConfig string `json:"httpConfig"` + Hsts bool `json:"hsts"` + Algorithm string `json:"algorithm"` + SSLProtocol []string `json:"SSLProtocol"` +} + +type WebsiteHttpsResponse struct { + Code int `json:"code"` + Message string `json:"message"` + Data struct { + Enable bool `json:"enable"` + HTTPConfig string `json:"httpConfig"` + SSL 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"` + } `json:"SSL"` + SSLProtocol []string `json:"SSLProtocol"` + Algorithm string `json:"algorithm"` + Hsts bool `json:"hsts"` + } `json:"data"` +} diff --git a/service/user.go b/service/user.go index 0d9f9cf..2fc9244 100644 --- a/service/user.go +++ b/service/user.go @@ -35,7 +35,6 @@ type UserService interface { DeleteAllUser() GetUserInfoByUserName(userName string) (m model.UserDBModel) GetAllUserName() (list []model.UserDBModel) - GetKeyPair() (*ecdsa.PrivateKey, *ecdsa.PublicKey) }