refactor: re-impl sdk3rd
This commit is contained in:
@@ -1,78 +0,0 @@
|
||||
package unicloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (c *Client) ensureServerlessJwtTokenExists() error {
|
||||
c.serverlessJwtTokenMtx.Lock()
|
||||
defer c.serverlessJwtTokenMtx.Unlock()
|
||||
if c.serverlessJwtToken != "" && c.serverlessJwtTokenExp.After(time.Now()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
params := &loginParams{
|
||||
Password: c.password,
|
||||
}
|
||||
if regexp.MustCompile("^1\\d{10}$").MatchString(c.username) {
|
||||
params.Mobile = c.username
|
||||
} else if regexp.MustCompile("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$").MatchString(c.username) {
|
||||
params.Email = c.username
|
||||
} else {
|
||||
params.Username = c.username
|
||||
}
|
||||
|
||||
resp := &loginResponse{}
|
||||
if err := c.invokeServerlessWithResult(
|
||||
uniIdentityEndpoint, uniIdentityClientSecret, uniIdentityAppId, uniIdentitySpaceId,
|
||||
"uni-id-co", "login", "", params, nil,
|
||||
resp); err != nil {
|
||||
return err
|
||||
} else if resp.Data == nil || resp.Data.NewToken == nil || resp.Data.NewToken.Token == "" {
|
||||
return fmt.Errorf("unicloud api error: received empty token")
|
||||
}
|
||||
|
||||
c.serverlessJwtToken = resp.Data.NewToken.Token
|
||||
c.serverlessJwtTokenExp = time.UnixMilli(resp.Data.NewToken.TokenExpired)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) ensureApiUserTokenExists() error {
|
||||
if err := c.ensureServerlessJwtTokenExists(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.apiUserTokenMtx.Lock()
|
||||
defer c.apiUserTokenMtx.Unlock()
|
||||
if c.apiUserToken != "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
resp := &getUserTokenResponse{}
|
||||
if err := c.invokeServerlessWithResult(
|
||||
uniConsoleEndpoint, uniConsoleClientSecret, uniConsoleAppId, uniConsoleSpaceId,
|
||||
"uni-cloud-kernel", "", "user/getUserToken", nil, map[string]any{"isLogin": true},
|
||||
resp); err != nil {
|
||||
return err
|
||||
} else if resp.Data == nil || resp.Data.Data == nil || resp.Data.Data.Data == nil || resp.Data.Data.Data.Token == "" {
|
||||
return fmt.Errorf("unicloud api error: received empty user token")
|
||||
}
|
||||
|
||||
c.apiUserToken = resp.Data.Data.Data.Token
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) CreateDomainWithCert(req *CreateDomainWithCertRequest) (*CreateDomainWithCertResponse, error) {
|
||||
if err := c.ensureApiUserTokenExists(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := &CreateDomainWithCertResponse{}
|
||||
err := c.sendRequestWithResult(http.MethodPost, "/host/create-domain-with-cert", req, resp)
|
||||
return resp, err
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package unicloud
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type CreateDomainWithCertRequest struct {
|
||||
Provider string `json:"provider"`
|
||||
SpaceId string `json:"spaceId"`
|
||||
Domain string `json:"domain"`
|
||||
Cert string `json:"cert"`
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
type CreateDomainWithCertResponse struct {
|
||||
apiResponseBase
|
||||
}
|
||||
|
||||
func (c *Client) CreateDomainWithCert(req *CreateDomainWithCertRequest) (*CreateDomainWithCertResponse, error) {
|
||||
if err := c.ensureApiUserTokenExists(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := &CreateDomainWithCertResponse{}
|
||||
err := c.sendRequestWithResult(http.MethodPost, "/host/create-domain-with-cert", req, resp)
|
||||
return resp, err
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -43,14 +44,26 @@ const (
|
||||
uniConsoleSpaceId = "dc-6nfabcn6ada8d3dd"
|
||||
)
|
||||
|
||||
func NewClient(username, password string) *Client {
|
||||
func NewClient(username, password string) (*Client, error) {
|
||||
if username == "" {
|
||||
return nil, fmt.Errorf("sdkerr: unset username")
|
||||
}
|
||||
if password == "" {
|
||||
return nil, fmt.Errorf("sdkerr: unset password")
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
username: username,
|
||||
password: password,
|
||||
}
|
||||
client.serverlessClient = resty.New()
|
||||
client.serverlessClient = resty.New().
|
||||
SetHeader("Accept", "application/json").
|
||||
SetHeader("Content-Type", "application/json").
|
||||
SetHeader("User-Agent", "certimate")
|
||||
client.apiClient = resty.New().
|
||||
SetBaseURL("https://unicloud-api.dcloud.net.cn/unicloud/api").
|
||||
SetHeader("Accept", "application/json").
|
||||
SetHeader("Content-Type", "application/json").
|
||||
SetHeader("User-Agent", "certimate").
|
||||
SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
|
||||
if client.apiUserToken != "" {
|
||||
@@ -60,37 +73,14 @@ func NewClient(username, password string) *Client {
|
||||
return nil
|
||||
})
|
||||
|
||||
return client
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (c *Client) WithTimeout(timeout time.Duration) *Client {
|
||||
func (c *Client) SetTimeout(timeout time.Duration) *Client {
|
||||
c.serverlessClient.SetTimeout(timeout)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Client) generateSignature(params map[string]any, secret string) string {
|
||||
keys := make([]string, 0, len(params))
|
||||
for k := range params {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
canonicalStr := ""
|
||||
for i, k := range keys {
|
||||
if i > 0 {
|
||||
canonicalStr += "&"
|
||||
}
|
||||
canonicalStr += k + "=" + fmt.Sprintf("%v", params[k])
|
||||
}
|
||||
|
||||
mac := hmac.New(md5.New, []byte(secret))
|
||||
mac.Write([]byte(canonicalStr))
|
||||
sign := mac.Sum(nil)
|
||||
signHex := hex.EncodeToString(sign)
|
||||
|
||||
return signHex
|
||||
}
|
||||
|
||||
func (c *Client) buildServerlessClientInfo(appId string) (_clientInfo map[string]any, _err error) {
|
||||
return map[string]any{
|
||||
"PLATFORM": "web",
|
||||
@@ -171,7 +161,7 @@ func (c *Client) invokeServerless(endpoint, clientSecret, appId, spaceId, target
|
||||
clientInfo, _ := c.buildServerlessClientInfo(appId)
|
||||
clientInfoJsonb, _ := json.Marshal(clientInfo)
|
||||
|
||||
sign := c.generateSignature(payload, clientSecret)
|
||||
sign := generateSignature(payload, clientSecret)
|
||||
|
||||
req := c.serverlessClient.R().
|
||||
SetHeader("Content-Type", "application/json").
|
||||
@@ -191,7 +181,7 @@ func (c *Client) invokeServerless(endpoint, clientSecret, appId, spaceId, target
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *Client) invokeServerlessWithResult(endpoint, clientSecret, appId, spaceId, target, method, action string, params, data interface{}, result BaseResponse) error {
|
||||
func (c *Client) invokeServerlessWithResult(endpoint, clientSecret, appId, spaceId, target, method, action string, params, data interface{}, result apiResponse) error {
|
||||
resp, err := c.invokeServerless(endpoint, clientSecret, appId, spaceId, target, method, action, params, data)
|
||||
if err != nil {
|
||||
if resp != nil {
|
||||
@@ -239,7 +229,7 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error {
|
||||
func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result apiResponse) error {
|
||||
resp, err := c.sendRequest(method, path, params)
|
||||
if err != nil {
|
||||
if resp != nil {
|
||||
@@ -256,3 +246,113 @@ func (c *Client) sendRequestWithResult(method string, path string, params interf
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) ensureServerlessJwtTokenExists() error {
|
||||
c.serverlessJwtTokenMtx.Lock()
|
||||
defer c.serverlessJwtTokenMtx.Unlock()
|
||||
if c.serverlessJwtToken != "" && c.serverlessJwtTokenExp.After(time.Now()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
params := map[string]string{
|
||||
"password": "password",
|
||||
}
|
||||
if regexp.MustCompile("^1\\d{10}$").MatchString(c.username) {
|
||||
params["mobile"] = c.username
|
||||
} else if regexp.MustCompile("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$").MatchString(c.username) {
|
||||
params["email"] = c.username
|
||||
} else {
|
||||
params["username"] = c.username
|
||||
}
|
||||
|
||||
type loginResponse struct {
|
||||
apiResponseBase
|
||||
Data *struct {
|
||||
Code int32 `json:"errCode"`
|
||||
UID string `json:"uid"`
|
||||
NewToken *struct {
|
||||
Token string `json:"token"`
|
||||
TokenExpired int64 `json:"tokenExpired"`
|
||||
} `json:"newToken,omitempty"`
|
||||
} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
resp := &loginResponse{}
|
||||
if err := c.invokeServerlessWithResult(
|
||||
uniIdentityEndpoint, uniIdentityClientSecret, uniIdentityAppId, uniIdentitySpaceId,
|
||||
"uni-id-co", "login", "", params, nil,
|
||||
resp); err != nil {
|
||||
return err
|
||||
} else if resp.Data == nil || resp.Data.NewToken == nil || resp.Data.NewToken.Token == "" {
|
||||
return fmt.Errorf("unicloud api error: received empty token")
|
||||
}
|
||||
|
||||
c.serverlessJwtToken = resp.Data.NewToken.Token
|
||||
c.serverlessJwtTokenExp = time.UnixMilli(resp.Data.NewToken.TokenExpired)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) ensureApiUserTokenExists() error {
|
||||
if err := c.ensureServerlessJwtTokenExists(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.apiUserTokenMtx.Lock()
|
||||
defer c.apiUserTokenMtx.Unlock()
|
||||
if c.apiUserToken != "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
type getUserTokenResponse struct {
|
||||
apiResponseBase
|
||||
Data *struct {
|
||||
Code int32 `json:"code"`
|
||||
Data *struct {
|
||||
Result int32 `json:"ret"`
|
||||
Description string `json:"desc"`
|
||||
Data *struct {
|
||||
Email string `json:"email"`
|
||||
Token string `json:"token"`
|
||||
} `json:"data,omitempty"`
|
||||
} `json:"data,omitempty"`
|
||||
} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
resp := &getUserTokenResponse{}
|
||||
if err := c.invokeServerlessWithResult(
|
||||
uniConsoleEndpoint, uniConsoleClientSecret, uniConsoleAppId, uniConsoleSpaceId,
|
||||
"uni-cloud-kernel", "", "user/getUserToken", nil, map[string]any{"isLogin": true},
|
||||
resp); err != nil {
|
||||
return err
|
||||
} else if resp.Data == nil || resp.Data.Data == nil || resp.Data.Data.Data == nil || resp.Data.Data.Data.Token == "" {
|
||||
return fmt.Errorf("unicloud api error: received empty user token")
|
||||
}
|
||||
|
||||
c.apiUserToken = resp.Data.Data.Data.Token
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateSignature(params map[string]any, secret string) string {
|
||||
keys := make([]string, 0, len(params))
|
||||
for k := range params {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
canonicalStr := ""
|
||||
for i, k := range keys {
|
||||
if i > 0 {
|
||||
canonicalStr += "&"
|
||||
}
|
||||
canonicalStr += k + "=" + fmt.Sprintf("%v", params[k])
|
||||
}
|
||||
|
||||
mac := hmac.New(md5.New, []byte(secret))
|
||||
mac.Write([]byte(canonicalStr))
|
||||
sign := mac.Sum(nil)
|
||||
signHex := hex.EncodeToString(sign)
|
||||
|
||||
return signHex
|
||||
}
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
package unicloud
|
||||
|
||||
type BaseResponse interface {
|
||||
GetSuccess() bool
|
||||
GetErrorCode() string
|
||||
GetErrorMessage() string
|
||||
|
||||
GetReturnCode() int32
|
||||
GetReturnDesc() string
|
||||
}
|
||||
|
||||
type baseResponse struct {
|
||||
Success *bool `json:"success,omitempty"`
|
||||
Header *map[string]string `json:"header,omitempty"`
|
||||
Error *struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"message"`
|
||||
} `json:"error,omitempty"`
|
||||
|
||||
ReturnCode *int32 `json:"ret,omitempty"`
|
||||
ReturnDesc *string `json:"desc,omitempty"`
|
||||
}
|
||||
|
||||
func (r *baseResponse) GetReturnCode() int32 {
|
||||
if r.ReturnCode != nil {
|
||||
return *r.ReturnCode
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (r *baseResponse) GetReturnDesc() string {
|
||||
if r.ReturnDesc != nil {
|
||||
return *r.ReturnDesc
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *baseResponse) GetSuccess() bool {
|
||||
if r.Success != nil {
|
||||
return *r.Success
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *baseResponse) GetErrorCode() string {
|
||||
if r.Error != nil {
|
||||
return r.Error.Code
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *baseResponse) GetErrorMessage() string {
|
||||
if r.Error != nil {
|
||||
return r.Error.Message
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type loginParams struct {
|
||||
Email string `json:"email,omitempty"`
|
||||
Mobile string `json:"mobile,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type loginResponse struct {
|
||||
baseResponse
|
||||
Data *struct {
|
||||
Code int32 `json:"errCode"`
|
||||
UID string `json:"uid"`
|
||||
NewToken *struct {
|
||||
Token string `json:"token"`
|
||||
TokenExpired int64 `json:"tokenExpired"`
|
||||
} `json:"newToken,omitempty"`
|
||||
} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
type getUserTokenResponse struct {
|
||||
baseResponse
|
||||
Data *struct {
|
||||
Code int32 `json:"code"`
|
||||
Data *struct {
|
||||
Result int32 `json:"ret"`
|
||||
Description string `json:"desc"`
|
||||
Data *struct {
|
||||
Email string `json:"email"`
|
||||
Token string `json:"token"`
|
||||
} `json:"data,omitempty"`
|
||||
} `json:"data,omitempty"`
|
||||
} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
type CreateDomainWithCertRequest struct {
|
||||
Provider string `json:"provider"`
|
||||
SpaceId string `json:"spaceId"`
|
||||
Domain string `json:"domain"`
|
||||
Cert string `json:"cert"`
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
type CreateDomainWithCertResponse struct {
|
||||
baseResponse
|
||||
}
|
||||
64
internal/pkg/sdk3rd/dcloud/unicloud/types.go
Normal file
64
internal/pkg/sdk3rd/dcloud/unicloud/types.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package unicloud
|
||||
|
||||
type apiResponse interface {
|
||||
GetSuccess() bool
|
||||
GetErrorCode() string
|
||||
GetErrorMessage() string
|
||||
|
||||
GetReturnCode() int32
|
||||
GetReturnDesc() string
|
||||
}
|
||||
|
||||
type apiResponseBase struct {
|
||||
Success *bool `json:"success,omitempty"`
|
||||
Header *map[string]string `json:"header,omitempty"`
|
||||
Error *struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"message"`
|
||||
} `json:"error,omitempty"`
|
||||
|
||||
ReturnCode *int32 `json:"ret,omitempty"`
|
||||
ReturnDesc *string `json:"desc,omitempty"`
|
||||
}
|
||||
|
||||
func (r *apiResponseBase) GetReturnCode() int32 {
|
||||
if r.ReturnCode == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return *r.ReturnCode
|
||||
}
|
||||
|
||||
func (r *apiResponseBase) GetReturnDesc() string {
|
||||
if r.ReturnDesc == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return *r.ReturnDesc
|
||||
}
|
||||
|
||||
func (r *apiResponseBase) GetSuccess() bool {
|
||||
if r.Success == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return *r.Success
|
||||
}
|
||||
|
||||
func (r *apiResponseBase) GetErrorCode() string {
|
||||
if r.Error == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return r.Error.Code
|
||||
}
|
||||
|
||||
func (r *apiResponseBase) GetErrorMessage() string {
|
||||
if r.Error == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return r.Error.Message
|
||||
}
|
||||
|
||||
var _ apiResponse = (*apiResponseBase)(nil)
|
||||
Reference in New Issue
Block a user