fix mailbox user not found handling
This commit is contained in:
parent
8bdf86bbad
commit
a915cd1dc1
@ -23,7 +23,8 @@ func IsServiceEnabled(
|
||||
) (bool, error) {
|
||||
_, err := gmi.GetMailInbox(ctx, resource)
|
||||
if err != nil {
|
||||
if err := api.EvaluateMailboxError(err); err != nil {
|
||||
ignorable := api.IsMailboxErrorIgnorable(err)
|
||||
if !ignorable {
|
||||
logger.CtxErr(ctx, err).Error("getting user's mail folder")
|
||||
return false, clues.Stack(err)
|
||||
}
|
||||
@ -54,10 +55,10 @@ func GetMailboxInfo(
|
||||
// First check whether the user is able to access their inbox.
|
||||
inbox, err := gmb.GetMailInbox(ctx, userID)
|
||||
if err != nil {
|
||||
if err := api.EvaluateMailboxError(clues.Stack(err)); err != nil {
|
||||
ignorable := api.IsMailboxErrorIgnorable(clues.Stack(err))
|
||||
if !ignorable {
|
||||
logger.CtxErr(ctx, err).Error("getting user's mail folder")
|
||||
|
||||
return mi, err
|
||||
return mi, clues.Stack(err)
|
||||
}
|
||||
|
||||
logger.Ctx(ctx).Info("resource owner does not have a mailbox enabled")
|
||||
|
||||
@ -127,6 +127,8 @@ var (
|
||||
// error categorization
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
var ErrUserNotFound = clues.New("user not found")
|
||||
|
||||
func stackWithCoreErr(ctx context.Context, err error, traceDepth int) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
@ -141,7 +143,10 @@ func stackWithCoreErr(ctx context.Context, err error, traceDepth int) error {
|
||||
case isErrApplicationThrottled(ode, err):
|
||||
err = clues.Stack(core.ErrApplicationThrottled, err)
|
||||
case isErrUserNotFound(ode, err):
|
||||
err = clues.Stack(core.ErrNotFound, err)
|
||||
// stack both userNotFound and notFound to ensure some graph api
|
||||
// internals can distinguish between the two cases (where possible).
|
||||
// layers above the api should still handle only the core notFound.
|
||||
err = clues.Stack(ErrUserNotFound, core.ErrNotFound, err)
|
||||
case isErrResourceLocked(ode, err):
|
||||
err = clues.Stack(core.ErrResourceNotAccessible, err)
|
||||
case isErrInsufficientAuthorization(ode, err):
|
||||
|
||||
@ -1111,7 +1111,6 @@ func (suite *GraphErrorsUnitSuite) TestToErrByRespCode() {
|
||||
for _, test := range table {
|
||||
suite.Run(test.name, func() {
|
||||
t := suite.T()
|
||||
|
||||
err := toErrByRespCode(parseODataErr(test.err), test.err)
|
||||
|
||||
if test.expectNoStack {
|
||||
@ -1122,3 +1121,96 @@ func (suite *GraphErrorsUnitSuite) TestToErrByRespCode() {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *GraphErrorsUnitSuite) TestIsErrItemAlreadyExists() {
|
||||
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.ODataErrWithMsg("InvalidRequest", "item already exists"),
|
||||
expect: assert.False,
|
||||
},
|
||||
{
|
||||
name: "matching oDataErr code",
|
||||
err: graphTD.ODataInner(string(nameAlreadyExists)),
|
||||
expect: assert.True,
|
||||
},
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.Run(test.name, func() {
|
||||
ode := parseODataErr(test.err)
|
||||
test.expect(suite.T(), isErrItemAlreadyExists(ode, test.err))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *GraphErrorsUnitSuite) TestStackWithCoreErr() {
|
||||
table := []struct {
|
||||
name string
|
||||
err error
|
||||
expect []error
|
||||
}{
|
||||
{
|
||||
name: "bad jwt",
|
||||
err: graphTD.ODataErr(string(invalidAuthenticationToken)),
|
||||
expect: []error{core.ErrAuthTokenExpired},
|
||||
},
|
||||
{
|
||||
name: "throttled",
|
||||
err: graphTD.ODataErr(string(ApplicationThrottled)),
|
||||
expect: []error{core.ErrApplicationThrottled},
|
||||
},
|
||||
{
|
||||
name: "user not found",
|
||||
err: graphTD.ODataErrWithMsg(string(ResourceNotFound), "User not found"),
|
||||
expect: []error{ErrUserNotFound, core.ErrNotFound},
|
||||
},
|
||||
{
|
||||
name: "resource locked",
|
||||
err: graphTD.ODataErr(string(NotAllowed)),
|
||||
expect: []error{core.ErrResourceNotAccessible},
|
||||
},
|
||||
{
|
||||
name: "insufficient auth",
|
||||
err: graphTD.ODataErr(string(AuthorizationRequestDenied)),
|
||||
expect: []error{core.ErrInsufficientAuthorization},
|
||||
},
|
||||
{
|
||||
name: "already exists",
|
||||
err: graphTD.ODataInner(string(nameAlreadyExists)),
|
||||
expect: []error{core.ErrAlreadyExists},
|
||||
},
|
||||
{
|
||||
name: "not found",
|
||||
err: graphTD.ODataErr(string(ItemNotFound)),
|
||||
expect: []error{core.ErrNotFound},
|
||||
},
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.Run(test.name, func() {
|
||||
t := suite.T()
|
||||
|
||||
ctx, flush := tester.NewContext(t)
|
||||
defer flush()
|
||||
|
||||
result := stackWithCoreErr(ctx, test.err, 1)
|
||||
|
||||
for _, ex := range test.expect {
|
||||
assert.ErrorIs(t, result, ex, clues.ToCore(result))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,26 +185,18 @@ func appendIfErr(errs []error, err error) []error {
|
||||
return append(errs, err)
|
||||
}
|
||||
|
||||
// EvaluateMailboxError checks whether the provided error can be interpreted
|
||||
// IsMailboxErrorIgnorable checks whether the provided error can be interpreted
|
||||
// as "user does not have a mailbox", or whether it is some other error. If
|
||||
// the former (no mailbox), returns nil, otherwise returns an error.
|
||||
func EvaluateMailboxError(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsMailboxErrorIgnorable(err error) bool {
|
||||
// must occur before MailFolderNotFound, due to overlapping cases.
|
||||
if errors.Is(err, core.ErrResourceNotAccessible) {
|
||||
return err
|
||||
if errors.Is(err, core.ErrResourceNotAccessible) || errors.Is(err, graph.ErrUserNotFound) {
|
||||
return false
|
||||
}
|
||||
|
||||
if errors.Is(err, core.ErrNotFound) ||
|
||||
return err != nil && (errors.Is(err, core.ErrNotFound) ||
|
||||
graph.IsErrExchangeMailFolderNotFound(err) ||
|
||||
graph.IsErrAuthenticationError(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
graph.IsErrAuthenticationError(err))
|
||||
}
|
||||
|
||||
// IsAnyErrMailboxNotFound inspects the secondary errors inside MailboxInfo and
|
||||
|
||||
@ -70,54 +70,47 @@ func (suite *UsersUnitSuite) TestEvaluateMailboxError() {
|
||||
table := []struct {
|
||||
name string
|
||||
err error
|
||||
expect func(t *testing.T, err error)
|
||||
expect assert.BoolAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "nil",
|
||||
err: nil,
|
||||
expect: func(t *testing.T, err error) {
|
||||
assert.NoError(t, err, clues.ToCore(err))
|
||||
},
|
||||
name: "nil",
|
||||
err: nil,
|
||||
expect: assert.False,
|
||||
},
|
||||
{
|
||||
name: "mail inbox err - user not found",
|
||||
err: core.ErrNotFound,
|
||||
expect: func(t *testing.T, err error) {
|
||||
assert.NoError(t, err, clues.ToCore(err))
|
||||
},
|
||||
name: "user not found - corso sentinel",
|
||||
err: graph.ErrUserNotFound,
|
||||
expect: assert.False,
|
||||
},
|
||||
{
|
||||
name: "mail inbox err - resourceLocked",
|
||||
err: core.ErrResourceNotAccessible,
|
||||
expect: func(t *testing.T, err error) {
|
||||
assert.ErrorIs(t, err, core.ErrResourceNotAccessible, clues.ToCore(err))
|
||||
},
|
||||
name: "not found - corso sentinel",
|
||||
err: core.ErrNotFound,
|
||||
expect: assert.True,
|
||||
},
|
||||
{
|
||||
name: "mail inbox err - user not found",
|
||||
err: graphTD.ODataErr(string(graph.MailboxNotEnabledForRESTAPI)),
|
||||
expect: func(t *testing.T, err error) {
|
||||
assert.NoError(t, err, clues.ToCore(err))
|
||||
},
|
||||
name: "mailbox not enabled - graph api error",
|
||||
err: graphTD.ODataErr(string(graph.MailboxNotEnabledForRESTAPI)),
|
||||
expect: assert.True,
|
||||
},
|
||||
{
|
||||
name: "mail inbox err - authenticationError",
|
||||
err: graphTD.ODataErr(string(graph.AuthenticationError)),
|
||||
expect: func(t *testing.T, err error) {
|
||||
assert.NoError(t, err, clues.ToCore(err))
|
||||
},
|
||||
name: "resourceLocked",
|
||||
err: core.ErrResourceNotAccessible,
|
||||
expect: assert.False,
|
||||
},
|
||||
{
|
||||
name: "mail inbox err - other error",
|
||||
err: graphTD.ODataErrWithMsg("somecode", "somemessage"),
|
||||
expect: func(t *testing.T, err error) {
|
||||
assert.Error(t, err, clues.ToCore(err))
|
||||
},
|
||||
name: "authenticationError",
|
||||
err: graphTD.ODataErr(string(graph.AuthenticationError)),
|
||||
expect: assert.True,
|
||||
},
|
||||
{
|
||||
name: "other error",
|
||||
err: graphTD.ODataErrWithMsg("somecode", "somemessage"),
|
||||
expect: assert.False,
|
||||
},
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.Run(test.name, func() {
|
||||
test.expect(suite.T(), EvaluateMailboxError(test.err))
|
||||
test.expect(suite.T(), IsMailboxErrorIgnorable(test.err))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user