add insufficient auth to graph, errs (#4776)
#### Does this PR need a docs update or release note? - [x] ⛔ No #### Type of change - [x] 🌻 Feature #### Test Plan - [x] ⚡ Unit test
This commit is contained in:
parent
79a37bfb91
commit
37dcb952fb
@ -13,12 +13,13 @@ import (
|
||||
type errEnum string
|
||||
|
||||
const (
|
||||
ApplicationThrottled errEnum = "application-throttled"
|
||||
BackupNotFound errEnum = "backup-not-found"
|
||||
RepoAlreadyExists errEnum = "repository-already-exists"
|
||||
ResourceNotAccessible errEnum = "resource-not-accesible"
|
||||
ResourceOwnerNotFound errEnum = "resource-owner-not-found"
|
||||
ServiceNotEnabled errEnum = "service-not-enabled"
|
||||
ApplicationThrottled errEnum = "application-throttled"
|
||||
BackupNotFound errEnum = "backup-not-found"
|
||||
InsufficientAuthorization errEnum = "insufficient-authorization"
|
||||
RepoAlreadyExists errEnum = "repository-already-exists"
|
||||
ResourceNotAccessible errEnum = "resource-not-accesible"
|
||||
ResourceOwnerNotFound errEnum = "resource-owner-not-found"
|
||||
ServiceNotEnabled errEnum = "service-not-enabled"
|
||||
)
|
||||
|
||||
// map of enums to errors. We might want to re-use an enum for multiple
|
||||
@ -41,9 +42,10 @@ type ErrCheck func(error) bool
|
||||
// checks. This allows us to apply those comparison checks instead of relying
|
||||
// only on sentinels.
|
||||
var externalToInternalCheck = map[errEnum][]ErrCheck{
|
||||
ApplicationThrottled: {graph.IsErrApplicationThrottled},
|
||||
ResourceNotAccessible: {graph.IsErrResourceLocked},
|
||||
ResourceOwnerNotFound: {graph.IsErrItemNotFound},
|
||||
ApplicationThrottled: {graph.IsErrApplicationThrottled},
|
||||
ResourceNotAccessible: {graph.IsErrResourceLocked},
|
||||
ResourceOwnerNotFound: {graph.IsErrItemNotFound},
|
||||
InsufficientAuthorization: {graph.IsErrInsufficientAuthorization},
|
||||
}
|
||||
|
||||
// Internal returns the internal errors and error checking functions which
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"github.com/alcionai/corso/src/internal/tester"
|
||||
"github.com/alcionai/corso/src/pkg/repository"
|
||||
"github.com/alcionai/corso/src/pkg/services/m365/api/graph"
|
||||
graphTD "github.com/alcionai/corso/src/pkg/services/m365/api/graph/testdata"
|
||||
)
|
||||
|
||||
type ErrUnitSuite struct {
|
||||
@ -103,6 +104,12 @@ func (suite *ErrUnitSuite) TestInternal_checks() {
|
||||
expectHasChecks: assert.NotEmpty,
|
||||
expect: assert.True,
|
||||
},
|
||||
{
|
||||
get: InsufficientAuthorization,
|
||||
err: graphTD.ODataErr(string(graph.AuthorizationRequestDenied)),
|
||||
expectHasChecks: assert.NotEmpty,
|
||||
expect: assert.True,
|
||||
},
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.Run(string(test.get), func() {
|
||||
@ -155,6 +162,10 @@ func (suite *ErrUnitSuite) TestIs() {
|
||||
target: ResourceNotAccessible,
|
||||
err: graph.ErrResourceLocked,
|
||||
},
|
||||
{
|
||||
target: InsufficientAuthorization,
|
||||
err: graphTD.ODataErr(string(graph.AuthorizationRequestDenied)),
|
||||
},
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.Run(string(test.target), func() {
|
||||
|
||||
@ -30,9 +30,12 @@ type errorCode string
|
||||
|
||||
const (
|
||||
applicationThrottled errorCode = "ApplicationThrottled"
|
||||
// this auth error is a catch-all used by graph in a variety of cases:
|
||||
// this authN error is a catch-all used by graph in a variety of cases:
|
||||
// users without licenses, bad jwts, missing account permissions, etc.
|
||||
AuthenticationError errorCode = "AuthenticationError"
|
||||
// on the other hand, authZ errors apply specifically to authenticated,
|
||||
// but unauthorized, user requests
|
||||
AuthorizationRequestDenied errorCode = "Authorization_RequestDenied"
|
||||
// cannotOpenFileAttachment happen when an attachment is
|
||||
// inaccessible. The error message is usually "OLE conversion
|
||||
// failed for an attachment."
|
||||
@ -137,6 +140,10 @@ func IsErrAuthenticationError(err error) bool {
|
||||
return hasErrorCode(err, AuthenticationError)
|
||||
}
|
||||
|
||||
func IsErrInsufficientAuthorization(err error) bool {
|
||||
return hasErrorCode(err, AuthorizationRequestDenied)
|
||||
}
|
||||
|
||||
func IsErrDeletedInFlight(err error) bool {
|
||||
if errors.Is(err, ErrDeletedInFlight) {
|
||||
return true
|
||||
|
||||
@ -124,6 +124,40 @@ func (suite *GraphErrorsUnitSuite) TestIsErrAuthenticationError() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *GraphErrorsUnitSuite) TestIsErrInsufficientAuthorization() {
|
||||
table := []struct {
|
||||
name string
|
||||
err error
|
||||
expect assert.BoolAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "nil",
|
||||
err: nil,
|
||||
expect: assert.False,
|
||||
},
|
||||
{
|
||||
name: "non-matching",
|
||||
err: assert.AnError,
|
||||
expect: assert.False,
|
||||
},
|
||||
{
|
||||
name: "non-matching oDataErr",
|
||||
err: graphTD.ODataErr("fnords"),
|
||||
expect: assert.False,
|
||||
},
|
||||
{
|
||||
name: "AuthorizationRequestDenied oDataErr",
|
||||
err: graphTD.ODataErr(string(AuthorizationRequestDenied)),
|
||||
expect: assert.True,
|
||||
},
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.Run(test.name, func() {
|
||||
test.expect(suite.T(), IsErrInsufficientAuthorization(test.err))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *GraphErrorsUnitSuite) TestIsErrDeletedInFlight() {
|
||||
table := []struct {
|
||||
name string
|
||||
|
||||
@ -22,9 +22,7 @@ const (
|
||||
func shouldLogRespBody(resp *http.Response) bool {
|
||||
return logger.DebugAPIFV ||
|
||||
os.Getenv(logGraphRequestsEnvKey) != "" ||
|
||||
resp.StatusCode == http.StatusBadRequest ||
|
||||
resp.StatusCode == http.StatusForbidden ||
|
||||
resp.StatusCode == http.StatusConflict
|
||||
resp.StatusCode > 399
|
||||
}
|
||||
|
||||
func logResp(ctx context.Context, resp *http.Response) {
|
||||
@ -47,6 +45,7 @@ func logResp(ctx context.Context, resp *http.Response) {
|
||||
// Log api calls according to api debugging configurations.
|
||||
switch respClass {
|
||||
case 2:
|
||||
// only log 2xx's if we want the full response body.
|
||||
if logBody {
|
||||
// only dump the body if it's under a size limit. We don't want to copy gigs into memory for a log.
|
||||
dump := getRespDump(ctx, resp, os.Getenv(log2xxGraphResponseEnvKey) != "" && resp.ContentLength < logMBLimit)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user