Skip to content

Commit

Permalink
Merge branch 'release/0.7.16'
Browse files Browse the repository at this point in the history
  • Loading branch information
gildas committed Oct 1, 2022
2 parents 5867569 + 5ad1b9a commit 26848f9
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 8 deletions.
94 changes: 94 additions & 0 deletions client_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package gcloudcx_test

import (
"context"
"encoding/json"
"fmt"
"reflect"
"strings"
"testing"
"time"

"github.com/gildas/go-core"
"github.com/gildas/go-errors"
"github.com/gildas/go-gcloudcx"
"github.com/gildas/go-logger"
"github.com/google/uuid"
Expand Down Expand Up @@ -35,6 +39,7 @@ func (suite *ClientSuite) SetupSuite() {
Path: fmt.Sprintf("./log/test-%s.log", strings.ToLower(suite.Name)),
Unbuffered: true,
FilterLevel: logger.TRACE,
SourceInfo: true,
},
).Child("test", "test")
suite.Logger.Infof("Suite Start: %s %s", suite.Name, strings.Repeat("=", 80-14-len(suite.Name)))
Expand Down Expand Up @@ -79,3 +84,92 @@ func (suite *ClientSuite) TestCanInitializeWithoutOptions() {
client := gcloudcx.NewClient(nil)
suite.Require().NotNil(client, "GCloudCX Client is nil")
}

func (suite *ClientSuite) TestClientNotFoundErrorShouldBeBadRequest() {
payload := `{"error":"invalid_client","description":"client not found","error_description":"client not found"}`
var apiError gcloudcx.APIError

err := json.Unmarshal([]byte(payload), &apiError)
suite.Require().NoError(err, "Unmarshalling should have succeeded")
suite.Logger.Errorf("Expected Error", apiError)
suite.Assert().ErrorIs(apiError, gcloudcx.BadCredentialsError)
suite.Assert().NotErrorIs(apiError, errors.RuntimeError)
suite.Assert().Equal(gcloudcx.BadCredentialsError.Status, apiError.Status)
}

func (suite *ClientSuite) TestAuthFailedErrorShouldBeBadRequest() {
payload := `{"error":"invalid_client","description":"authentication failed","error_description":"authentication failed"}`
var apiError gcloudcx.APIError

err := json.Unmarshal([]byte(payload), &apiError)
suite.Require().NoError(err, "Unmarshalling should have succeeded")
suite.Logger.Errorf("Expected Error", apiError)
suite.Assert().ErrorIs(apiError, gcloudcx.BadCredentialsError)
suite.Assert().NotErrorIs(apiError, errors.RuntimeError)
suite.Assert().Equal(gcloudcx.BadCredentialsError.Status, apiError.Status)
}

func (suite *ClientSuite) TestCanLoginWithClientCredentials() {
clientID := uuid.New()

if value := core.GetEnvAsString("PURECLOUD_CLIENTID", ""); len(value) > 0 {
clientID = uuid.MustParse(value)
}

client := gcloudcx.NewClient(&gcloudcx.ClientOptions{
Region: core.GetEnvAsString("PURECLOUD_REGION", "mypurecloud.com"),
Logger: suite.Logger,
}).SetAuthorizationGrant(&gcloudcx.ClientCredentialsGrant{
ClientID: clientID,
Secret: core.GetEnvAsString("PURECLOUD_CLIENTSECRET", "s3cr3t"),
})
err := client.Login(context.Background())
suite.Require().NoError(err, "Login should have succeeded")
suite.Require().NotEmpty(client.Grant.AccessToken(), "Access Token should not be empty")
}

func (suite *ClientSuite) TestShouldFailLoginWithInvalidClientCredentialsSecret() {
clientID := uuid.New()

if value := core.GetEnvAsString("PURECLOUD_CLIENTID", ""); len(value) > 0 {
clientID = uuid.MustParse(value)
}

client := gcloudcx.NewClient(&gcloudcx.ClientOptions{
Region: core.GetEnvAsString("PURECLOUD_REGION", "mypurecloud.com"),
Logger: suite.Logger,
}).SetAuthorizationGrant(&gcloudcx.ClientCredentialsGrant{
ClientID: clientID,
Secret: "s3cr3t",
})
err := client.Login(context.Background())
suite.Require().Error(err, "Login should have failed")
suite.Logger.Errorf("Expected Error", err)
suite.Assert().NotErrorIs(err, errors.RuntimeError)
suite.Assert().ErrorIs(err, gcloudcx.BadCredentialsError)

var apiError gcloudcx.APIError
suite.Require().ErrorAs(err, &apiError, "Error should be an APIError")
suite.Require().NotEmpty(apiError.MessageParams, "Error should have some parameters")
suite.Assert().Equal("authentication failed", apiError.MessageParams["description"])
}

func (suite *ClientSuite) TestShouldFailLoginWithInvalidClientCredentialsClientID() {
client := gcloudcx.NewClient(&gcloudcx.ClientOptions{
Region: core.GetEnvAsString("PURECLOUD_REGION", "mypurecloud.com"),
Logger: suite.Logger,
}).SetAuthorizationGrant(&gcloudcx.ClientCredentialsGrant{
ClientID: uuid.New(), // The chances of this being a valid Client ID are very low
Secret: core.GetEnvAsString("PURECLOUD_CLIENTSECRET", "s3cr3t"),
})
err := client.Login(context.Background())
suite.Require().Error(err, "Login should have failed")
suite.Logger.Errorf("Expected Error", err)
suite.Assert().NotErrorIs(err, errors.RuntimeError)
suite.Assert().ErrorIs(err, gcloudcx.BadCredentialsError)

var apiError gcloudcx.APIError
suite.Require().ErrorAs(err, &apiError, "Error should be an APIError")
suite.Require().NotEmpty(apiError.MessageParams, "Error should have some parameters")
suite.Assert().Equal("client not found", apiError.MessageParams["description"])
}
29 changes: 25 additions & 4 deletions error.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ var (
// AuthenticationRequiredError means the request should authenticate first
AuthenticationRequiredError = APIError{Status: 401, Code: "authentication.required", Message: "No authentication bearer token specified in authorization header."}
// BadCredentialsError means the credentials are invalid
BadCredentialsError = APIError{Status: 401, Code: "bad.credentials", Message: "Invalid login credentials."}
BadCredentialsError = APIError{Status: 401, Code: "bad.credentials", Message: "Invalid login credentials (%s)."}
// CredentialsExpiredError means the credentials are expired
CredentialsExpiredError = APIError{Status: 401, Code: "credentials.expired", Message: "The supplied credentials are expired and cannot be used."}

Expand Down Expand Up @@ -138,6 +138,16 @@ func (e APIError) As(target interface{}) bool {
return false
}

// With creates a new Error from a given sentinel telling "what" is wrong and eventually their value.
//
// With also records the stack trace at the point it was called.
func (e APIError) With(what string, values ...interface{}) error {
final := e
final.MessageWithParams = fmt.Sprintf(final.Message, what)
final.Stack.Initialize()
return final
}

// WithStack creates a new error from a given Error and records its stack.
func (e APIError) WithStack() error {
final := e
Expand All @@ -154,9 +164,20 @@ func (e *APIError) UnmarshalJSON(payload []byte) (err error) {
}{}
err = json.Unmarshal(payload, &oauthError)
if err == nil && len(oauthError.Error) > 0 && len(oauthError.Description) > 0 {
*e = APIError{
Code: BadCredentialsError.Code,
Message: fmt.Sprintf("%s: %s", oauthError.Description, oauthError.Error),
switch oauthError.Error {
case "invalid_client":
*e = BadCredentialsError
e.Message = fmt.Sprintf(e.Message, oauthError.Description)
e.MessageParams = map[string]string{
"reason": oauthError.Error,
"description": oauthError.Description,
}
default:
*e = APIError{
Status: BadCredentialsError.Status,
Code: BadCredentialsError.Code,
Message: fmt.Sprintf("%s: %s", oauthError.Description, oauthError.Error),
}
}
return nil
}
Expand Down
6 changes: 3 additions & 3 deletions request.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func (client *Client) SendRequest(context context.Context, path URI, options *re
correlationID := ""
if res != nil {
correlationID = res.Headers.Get("Inin-Correlation-Id")
log = log.Record("correlationId", correlationID)
log = log.Record("gcloudcx-correlationId", correlationID)
}
if err != nil {
urlError := &url.Error{}
Expand Down Expand Up @@ -119,9 +119,9 @@ func (client *Client) SendRequest(context context.Context, path URI, options *re
apiError.Status = errors.HTTPUnauthorized.Code
apiError.Code = errors.HTTPUnauthorized.ID
}
return errors.WithStack(apiError)
return apiError.WithStack()
}
return err
return errors.WithStack(err)
}
log.Debugf("Successfuly sent request in %s", duration)
return nil
Expand Down
2 changes: 1 addition & 1 deletion version.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package gcloudcx
var commit string

// VERSION is the version of this application
var VERSION = "0.7.15" + commit
var VERSION = "0.7.16" + commit

// APP is the name of the application
const APP string = "GCloudCX Client"

0 comments on commit 26848f9

Please sign in to comment.