fixup mailbox info (#3189)
#### Does this PR need a docs update or release note? - [x] ⛔ No #### Type of change - [x] 🐛 Bugfix - [x] 🧹 Tech Debt/Cleanup #### Test Plan - [x] 💪 Manual - [x] 💚 E2E
This commit is contained in:
parent
41f742eba2
commit
b331f38654
@ -18,19 +18,19 @@ import (
|
|||||||
"github.com/alcionai/corso/src/pkg/services/m365/api"
|
"github.com/alcionai/corso/src/pkg/services/m365/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DiscoveryIntegrationSuite struct {
|
type DiscoveryIntgSuite struct {
|
||||||
tester.Suite
|
tester.Suite
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDiscoveryIntegrationSuite(t *testing.T) {
|
func TestDiscoveryIntgSuite(t *testing.T) {
|
||||||
suite.Run(t, &DiscoveryIntegrationSuite{
|
suite.Run(t, &DiscoveryIntgSuite{
|
||||||
Suite: tester.NewIntegrationSuite(
|
Suite: tester.NewIntegrationSuite(
|
||||||
t,
|
t,
|
||||||
[][]string{tester.M365AcctCredEnvs}),
|
[][]string{tester.M365AcctCredEnvs}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *DiscoveryIntegrationSuite) TestUsers() {
|
func (suite *DiscoveryIntgSuite) TestUsers() {
|
||||||
ctx, flush := tester.NewContext()
|
ctx, flush := tester.NewContext()
|
||||||
defer flush()
|
defer flush()
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ func (suite *DiscoveryIntegrationSuite) TestUsers() {
|
|||||||
assert.NotEmpty(t, users)
|
assert.NotEmpty(t, users)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *DiscoveryIntegrationSuite) TestUsers_InvalidCredentials() {
|
func (suite *DiscoveryIntgSuite) TestUsers_InvalidCredentials() {
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
acct func(t *testing.T) account.Account
|
acct func(t *testing.T) account.Account
|
||||||
@ -101,7 +101,7 @@ func (suite *DiscoveryIntegrationSuite) TestUsers_InvalidCredentials() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *DiscoveryIntegrationSuite) TestSites() {
|
func (suite *DiscoveryIntgSuite) TestSites() {
|
||||||
ctx, flush := tester.NewContext()
|
ctx, flush := tester.NewContext()
|
||||||
defer flush()
|
defer flush()
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ func (suite *DiscoveryIntegrationSuite) TestSites() {
|
|||||||
assert.NotEmpty(t, sites)
|
assert.NotEmpty(t, sites)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *DiscoveryIntegrationSuite) TestSites_InvalidCredentials() {
|
func (suite *DiscoveryIntgSuite) TestSites_InvalidCredentials() {
|
||||||
ctx, flush := tester.NewContext()
|
ctx, flush := tester.NewContext()
|
||||||
defer flush()
|
defer flush()
|
||||||
|
|
||||||
@ -171,10 +171,9 @@ func (suite *DiscoveryIntegrationSuite) TestSites_InvalidCredentials() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *DiscoveryIntegrationSuite) TestUserInfo() {
|
func (suite *DiscoveryIntgSuite) TestUserInfo() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
acct := tester.NewM365Account(t)
|
acct := tester.NewM365Account(t)
|
||||||
userID := tester.M365UserID(t)
|
|
||||||
|
|
||||||
creds, err := acct.M365Config()
|
creds, err := acct.M365Config()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -185,37 +184,34 @@ func (suite *DiscoveryIntegrationSuite) TestUserInfo() {
|
|||||||
uapi := cli.Users()
|
uapi := cli.Users()
|
||||||
|
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
user string
|
user string
|
||||||
expect *api.UserInfo
|
expect *api.UserInfo
|
||||||
|
expectErr require.ErrorAssertionFunc
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "standard test user",
|
name: "standard test user",
|
||||||
user: userID,
|
user: tester.M365UserID(t),
|
||||||
expect: &api.UserInfo{
|
expect: &api.UserInfo{
|
||||||
DiscoveredServices: map[path.ServiceType]struct{}{
|
DiscoveredServices: map[path.ServiceType]struct{}{
|
||||||
path.ExchangeService: {},
|
path.ExchangeService: {},
|
||||||
path.OneDriveService: {},
|
path.OneDriveService: {},
|
||||||
},
|
},
|
||||||
HasMailBox: true,
|
|
||||||
HasOneDrive: true,
|
|
||||||
Mailbox: api.MailboxInfo{
|
Mailbox: api.MailboxInfo{
|
||||||
Purpose: "user",
|
Purpose: "user",
|
||||||
ErrGetMailBoxSetting: nil,
|
ErrGetMailBoxSetting: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
expectErr: require.NoError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "user does not exist",
|
name: "user does not exist",
|
||||||
user: uuid.NewString(),
|
user: uuid.NewString(),
|
||||||
expect: &api.UserInfo{
|
expect: &api.UserInfo{
|
||||||
DiscoveredServices: map[path.ServiceType]struct{}{},
|
DiscoveredServices: map[path.ServiceType]struct{}{},
|
||||||
HasMailBox: false,
|
Mailbox: api.MailboxInfo{},
|
||||||
HasOneDrive: false,
|
|
||||||
Mailbox: api.MailboxInfo{
|
|
||||||
ErrGetMailBoxSetting: api.ErrMailBoxSettingsNotFound,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
expectErr: require.NoError,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range table {
|
for _, test := range table {
|
||||||
@ -226,15 +222,18 @@ func (suite *DiscoveryIntegrationSuite) TestUserInfo() {
|
|||||||
t := suite.T()
|
t := suite.T()
|
||||||
|
|
||||||
result, err := discovery.UserInfo(ctx, uapi, test.user)
|
result, err := discovery.UserInfo(ctx, uapi, test.user)
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
test.expectErr(t, err, clues.ToCore(err))
|
||||||
assert.Equal(t, test.expect.HasMailBox, result.HasMailBox)
|
|
||||||
assert.Equal(t, test.expect.HasOneDrive, result.HasOneDrive)
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
assert.Equal(t, test.expect.DiscoveredServices, result.DiscoveredServices)
|
assert.Equal(t, test.expect.DiscoveredServices, result.DiscoveredServices)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *DiscoveryIntegrationSuite) TestUserWithoutDrive() {
|
func (suite *DiscoveryIntgSuite) TestUserWithoutDrive() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
acct := tester.NewM365Account(t)
|
acct := tester.NewM365Account(t)
|
||||||
userID := tester.M365UserID(t)
|
userID := tester.M365UserID(t)
|
||||||
@ -249,10 +248,8 @@ func (suite *DiscoveryIntegrationSuite) TestUserWithoutDrive() {
|
|||||||
user: "a53c26f7-5100-4acb-a910-4d20960b2c19", // User: testevents@10rqc2.onmicrosoft.com
|
user: "a53c26f7-5100-4acb-a910-4d20960b2c19", // User: testevents@10rqc2.onmicrosoft.com
|
||||||
expect: &api.UserInfo{
|
expect: &api.UserInfo{
|
||||||
DiscoveredServices: map[path.ServiceType]struct{}{},
|
DiscoveredServices: map[path.ServiceType]struct{}{},
|
||||||
HasOneDrive: false,
|
|
||||||
HasMailBox: false,
|
|
||||||
Mailbox: api.MailboxInfo{
|
Mailbox: api.MailboxInfo{
|
||||||
ErrGetMailBoxSetting: api.ErrMailBoxSettingsNotFound,
|
ErrGetMailBoxSetting: []error{api.ErrMailBoxSettingsNotFound},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -264,11 +261,9 @@ func (suite *DiscoveryIntegrationSuite) TestUserWithoutDrive() {
|
|||||||
path.ExchangeService: {},
|
path.ExchangeService: {},
|
||||||
path.OneDriveService: {},
|
path.OneDriveService: {},
|
||||||
},
|
},
|
||||||
HasOneDrive: true,
|
|
||||||
HasMailBox: true,
|
|
||||||
Mailbox: api.MailboxInfo{
|
Mailbox: api.MailboxInfo{
|
||||||
Purpose: "user",
|
Purpose: "user",
|
||||||
ErrGetMailBoxSetting: nil,
|
ErrGetMailBoxSetting: []error{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -283,8 +278,6 @@ func (suite *DiscoveryIntegrationSuite) TestUserWithoutDrive() {
|
|||||||
result, err := discovery.GetUserInfo(ctx, acct, test.user, fault.New(true))
|
result, err := discovery.GetUserInfo(ctx, acct, test.user, fault.New(true))
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
assert.Equal(t, test.expect.DiscoveredServices, result.DiscoveredServices)
|
assert.Equal(t, test.expect.DiscoveredServices, result.DiscoveredServices)
|
||||||
assert.Equal(t, test.expect.HasOneDrive, result.HasOneDrive)
|
|
||||||
assert.Equal(t, test.expect.HasMailBox, result.HasMailBox)
|
|
||||||
assert.Equal(t, test.expect.Mailbox.ErrGetMailBoxSetting, result.Mailbox.ErrGetMailBoxSetting)
|
assert.Equal(t, test.expect.Mailbox.ErrGetMailBoxSetting, result.Mailbox.ErrGetMailBoxSetting)
|
||||||
assert.Equal(t, test.expect.Mailbox.Purpose, result.Mailbox.Purpose)
|
assert.Equal(t, test.expect.Mailbox.Purpose, result.Mailbox.Purpose)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -14,10 +14,10 @@ import (
|
|||||||
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||||
"github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors"
|
"github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/exp/slices"
|
|
||||||
|
|
||||||
"github.com/alcionai/corso/src/internal/common/ptr"
|
"github.com/alcionai/corso/src/internal/common/ptr"
|
||||||
"github.com/alcionai/corso/src/pkg/fault"
|
"github.com/alcionai/corso/src/pkg/fault"
|
||||||
|
"github.com/alcionai/corso/src/pkg/filters"
|
||||||
"github.com/alcionai/corso/src/pkg/logger"
|
"github.com/alcionai/corso/src/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -25,20 +25,22 @@ import (
|
|||||||
// Error Interpretation Helpers
|
// Error Interpretation Helpers
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type errorCode string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
errCodeActivityLimitReached = "activityLimitReached"
|
activityLimitReached errorCode = "activityLimitReached"
|
||||||
errCodeItemNotFound = "ErrorItemNotFound"
|
emailFolderNotFound errorCode = "ErrorSyncFolderNotFound"
|
||||||
errCodeItemNotFoundShort = "itemNotFound"
|
errorAccessDenied errorCode = "ErrorAccessDenied"
|
||||||
errCodeEmailFolderNotFound = "ErrorSyncFolderNotFound"
|
itemNotFound errorCode = "ErrorItemNotFound"
|
||||||
errCodeResyncRequired = "ResyncRequired" // alt: resyncRequired
|
itemNotFoundShort errorCode = "itemNotFound"
|
||||||
errCodeMalwareDetected = "malwareDetected"
|
mailboxNotEnabledForRESTAPI errorCode = "MailboxNotEnabledForRESTAPI"
|
||||||
errCodeSyncFolderNotFound = "ErrorSyncFolderNotFound"
|
malwareDetected errorCode = "malwareDetected"
|
||||||
errCodeSyncStateNotFound = "SyncStateNotFound"
|
requestResourceNotFound errorCode = "Request_ResourceNotFound"
|
||||||
errCodeSyncStateInvalid = "SyncStateInvalid"
|
resourceNotFound errorCode = "ResourceNotFound"
|
||||||
errCodeResourceNotFound = "ResourceNotFound"
|
resyncRequired errorCode = "ResyncRequired" // alt: resyncRequired
|
||||||
errCodeRequestResourceNotFound = "Request_ResourceNotFound"
|
syncFolderNotFound errorCode = "ErrorSyncFolderNotFound"
|
||||||
errCodeMailboxNotEnabledForRESTAPI = "MailboxNotEnabledForRESTAPI"
|
syncStateInvalid errorCode = "SyncStateInvalid"
|
||||||
errCodeErrorAccessDenied = "ErrorAccessDenied"
|
syncStateNotFound errorCode = "SyncStateNotFound"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -84,9 +86,9 @@ func IsErrDeletedInFlight(err error) bool {
|
|||||||
|
|
||||||
if hasErrorCode(
|
if hasErrorCode(
|
||||||
err,
|
err,
|
||||||
errCodeItemNotFound,
|
itemNotFound,
|
||||||
errCodeItemNotFoundShort,
|
itemNotFoundShort,
|
||||||
errCodeSyncFolderNotFound,
|
syncFolderNotFound,
|
||||||
) {
|
) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -95,20 +97,24 @@ func IsErrDeletedInFlight(err error) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func IsErrInvalidDelta(err error) bool {
|
func IsErrInvalidDelta(err error) bool {
|
||||||
return hasErrorCode(err, errCodeSyncStateNotFound, errCodeResyncRequired, errCodeSyncStateInvalid) ||
|
return hasErrorCode(err, syncStateNotFound, resyncRequired, syncStateInvalid) ||
|
||||||
errors.Is(err, ErrInvalidDelta)
|
errors.Is(err, ErrInvalidDelta)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsErrExchangeMailFolderNotFound(err error) bool {
|
func IsErrExchangeMailFolderNotFound(err error) bool {
|
||||||
return hasErrorCode(err, errCodeResourceNotFound, errCodeMailboxNotEnabledForRESTAPI)
|
return hasErrorCode(err, resourceNotFound, mailboxNotEnabledForRESTAPI)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsErrUserNotFound(err error) bool {
|
func IsErrUserNotFound(err error) bool {
|
||||||
return hasErrorCode(err, errCodeRequestResourceNotFound)
|
return hasErrorCode(err, requestResourceNotFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsErrResourceNotFound(err error) bool {
|
||||||
|
return hasErrorCode(err, resourceNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsErrAccessDenied(err error) bool {
|
func IsErrAccessDenied(err error) bool {
|
||||||
return hasErrorCode(err, errCodeErrorAccessDenied)
|
return hasErrorCode(err, errorAccessDenied) || clues.HasLabel(err, LabelStatus(http.StatusForbidden))
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsErrTimeout(err error) bool {
|
func IsErrTimeout(err error) bool {
|
||||||
@ -143,7 +149,7 @@ func LabelStatus(statusCode int) string {
|
|||||||
|
|
||||||
// IsMalware is true if the graphAPI returns a "malware detected" error code.
|
// IsMalware is true if the graphAPI returns a "malware detected" error code.
|
||||||
func IsMalware(err error) bool {
|
func IsMalware(err error) bool {
|
||||||
return hasErrorCode(err, errCodeMalwareDetected)
|
return hasErrorCode(err, malwareDetected)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsMalwareResp(ctx context.Context, resp *http.Response) bool {
|
func IsMalwareResp(ctx context.Context, resp *http.Response) bool {
|
||||||
@ -159,7 +165,7 @@ func IsMalwareResp(ctx context.Context, resp *http.Response) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(string(respDump), errCodeMalwareDetected) {
|
if strings.Contains(string(respDump), string(malwareDetected)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +176,7 @@ func IsMalwareResp(ctx context.Context, resp *http.Response) bool {
|
|||||||
// error parsers
|
// error parsers
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
func hasErrorCode(err error, codes ...string) bool {
|
func hasErrorCode(err error, codes ...errorCode) bool {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -180,16 +186,17 @@ func hasErrorCode(err error, codes ...string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if oDataError.GetError().GetCode() == nil {
|
code, ok := ptr.ValOK(oDataError.GetError().GetCode())
|
||||||
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
lcodes := []string{}
|
cs := make([]string, len(codes))
|
||||||
for _, c := range codes {
|
for i, c := range codes {
|
||||||
lcodes = append(lcodes, strings.ToLower(c))
|
cs[i] = string(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
return slices.Contains(lcodes, strings.ToLower(*oDataError.GetError().GetCode()))
|
return filters.Equal(cs).Compare(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap is a helper function that extracts ODataError metadata from
|
// Wrap is a helper function that extracts ODataError metadata from
|
||||||
|
|||||||
@ -90,12 +90,12 @@ func (suite *GraphErrorsUnitSuite) TestIsErrDeletedInFlight() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not-found oDataErr",
|
name: "not-found oDataErr",
|
||||||
err: odErr(errCodeItemNotFound),
|
err: odErr(string(itemNotFound)),
|
||||||
expect: assert.True,
|
expect: assert.True,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "sync-not-found oDataErr",
|
name: "sync-not-found oDataErr",
|
||||||
err: odErr(errCodeSyncFolderNotFound),
|
err: odErr(string(syncFolderNotFound)),
|
||||||
expect: assert.True,
|
expect: assert.True,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -134,12 +134,12 @@ func (suite *GraphErrorsUnitSuite) TestIsErrInvalidDelta() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "resync-required oDataErr",
|
name: "resync-required oDataErr",
|
||||||
err: odErr(errCodeResyncRequired),
|
err: odErr(string(resyncRequired)),
|
||||||
expect: assert.True,
|
expect: assert.True,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "sync state invalid oDataErr",
|
name: "sync state invalid oDataErr",
|
||||||
err: odErr(errCodeSyncStateInvalid),
|
err: odErr(string(syncStateInvalid)),
|
||||||
expect: assert.True,
|
expect: assert.True,
|
||||||
},
|
},
|
||||||
// next two tests are to make sure the checks are case insensitive
|
// next two tests are to make sure the checks are case insensitive
|
||||||
@ -184,7 +184,7 @@ func (suite *GraphErrorsUnitSuite) TestIsErrUserNotFound() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "request resource not found oDataErr",
|
name: "request resource not found oDataErr",
|
||||||
err: odErr(errCodeRequestResourceNotFound),
|
err: odErr(string(requestResourceNotFound)),
|
||||||
expect: assert.True,
|
expect: assert.True,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -286,8 +286,7 @@ func TestOneDriveDriveSuite(t *testing.T) {
|
|||||||
suite.Run(t, &OneDriveSuite{
|
suite.Run(t, &OneDriveSuite{
|
||||||
Suite: tester.NewIntegrationSuite(
|
Suite: tester.NewIntegrationSuite(
|
||||||
t,
|
t,
|
||||||
[][]string{tester.M365AcctCredEnvs},
|
[][]string{tester.M365AcctCredEnvs}),
|
||||||
),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package api
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/alcionai/clues"
|
"github.com/alcionai/clues"
|
||||||
abstractions "github.com/microsoft/kiota-abstractions-go"
|
abstractions "github.com/microsoft/kiota-abstractions-go"
|
||||||
@ -41,8 +42,6 @@ type Users struct {
|
|||||||
|
|
||||||
type UserInfo struct {
|
type UserInfo struct {
|
||||||
DiscoveredServices map[path.ServiceType]struct{}
|
DiscoveredServices map[path.ServiceType]struct{}
|
||||||
HasMailBox bool
|
|
||||||
HasOneDrive bool
|
|
||||||
Mailbox MailboxInfo
|
Mailbox MailboxInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +55,7 @@ type MailboxInfo struct {
|
|||||||
AutomaticRepliesSetting AutomaticRepliesSettings
|
AutomaticRepliesSetting AutomaticRepliesSettings
|
||||||
Language Language
|
Language Language
|
||||||
WorkingHours WorkingHours
|
WorkingHours WorkingHours
|
||||||
ErrGetMailBoxSetting error
|
ErrGetMailBoxSetting []error
|
||||||
}
|
}
|
||||||
|
|
||||||
type AutomaticRepliesSettings struct {
|
type AutomaticRepliesSettings struct {
|
||||||
@ -229,204 +228,212 @@ func (c Users) GetIDAndName(ctx context.Context, userID string) (string, string,
|
|||||||
func (c Users) GetInfo(ctx context.Context, userID string) (*UserInfo, error) {
|
func (c Users) GetInfo(ctx context.Context, userID string) (*UserInfo, error) {
|
||||||
// Assume all services are enabled
|
// Assume all services are enabled
|
||||||
// then filter down to only services the user has enabled
|
// then filter down to only services the user has enabled
|
||||||
var (
|
userInfo := newUserInfo()
|
||||||
err error
|
|
||||||
userInfo = newUserInfo()
|
|
||||||
|
|
||||||
requestParameters = &users.ItemMailFoldersRequestBuilderGetQueryParameters{
|
requestParameters := users.ItemMailFoldersRequestBuilderGetQueryParameters{
|
||||||
Select: []string{"id"},
|
Select: []string{"id"},
|
||||||
Top: ptr.To[int32](1), // if we get any folders, then we have access.
|
Top: ptr.To[int32](1), // if we get any folders, then we have access.
|
||||||
}
|
|
||||||
|
|
||||||
options = users.ItemMailFoldersRequestBuilderGetRequestConfiguration{
|
|
||||||
QueryParameters: requestParameters,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
userInfo.HasMailBox = true
|
|
||||||
|
|
||||||
err = c.GetExchange(ctx, userID, options)
|
|
||||||
if err != nil {
|
|
||||||
if !graph.IsErrExchangeMailFolderNotFound(err) {
|
|
||||||
logger.Ctx(ctx).Errorf("err getting user's mail folder: %s", err)
|
|
||||||
|
|
||||||
return nil, graph.Wrap(ctx, err, "getting user's mail folder")
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Ctx(ctx).Infof("resource owner does not have a mailbox enabled")
|
|
||||||
delete(userInfo.DiscoveredServices, path.ExchangeService)
|
|
||||||
|
|
||||||
userInfo.HasMailBox = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
userInfo.HasOneDrive = true
|
options := users.ItemMailFoldersRequestBuilderGetRequestConfiguration{
|
||||||
|
QueryParameters: &requestParameters,
|
||||||
|
}
|
||||||
|
|
||||||
err = c.GetOnedrive(ctx, userID)
|
if _, err := c.GetMailFolders(ctx, userID, options); err != nil {
|
||||||
if err != nil {
|
if graph.IsErrUserNotFound(err) {
|
||||||
err = graph.Stack(ctx, err)
|
logger.CtxErr(ctx, err).Error("user not found")
|
||||||
|
return nil, err
|
||||||
if !clues.HasLabel(err, graph.LabelsMysiteNotFound) {
|
|
||||||
logger.Ctx(ctx).Errorf("err getting user's onedrive's data: %s", err)
|
|
||||||
|
|
||||||
return nil, graph.Wrap(ctx, err, "getting user's onedrive's data")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Ctx(ctx).Infof("resource owner does not have a drive")
|
if !graph.IsErrExchangeMailFolderNotFound(err) ||
|
||||||
|
clues.HasLabel(err, graph.LabelStatus(http.StatusNotFound)) {
|
||||||
|
logger.CtxErr(ctx, err).Error("getting user's mail folder")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Ctx(ctx).Info("resource owner does not have a mailbox enabled")
|
||||||
|
delete(userInfo.DiscoveredServices, path.ExchangeService)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := c.GetDrives(ctx, userID); err != nil {
|
||||||
|
if !clues.HasLabel(err, graph.LabelsMysiteNotFound) {
|
||||||
|
logger.CtxErr(ctx, err).Error("getting user's drives")
|
||||||
|
|
||||||
|
return nil, graph.Wrap(ctx, err, "getting user's drives")
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Ctx(ctx).Info("resource owner does not have a drive")
|
||||||
|
|
||||||
delete(userInfo.DiscoveredServices, path.OneDriveService)
|
delete(userInfo.DiscoveredServices, path.OneDriveService)
|
||||||
userInfo.HasOneDrive = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.getAdditionalData(ctx, userID, &userInfo.Mailbox)
|
mbxInfo, err := c.getMailboxSettings(ctx, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userInfo.Mailbox = mbxInfo
|
||||||
|
|
||||||
return userInfo, nil
|
return userInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify mailbox enabled for user
|
// TODO: remove when exchange api goes into this package
|
||||||
func (c Users) GetExchange(
|
func (c Users) GetMailFolders(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
userID string,
|
userID string,
|
||||||
options users.ItemMailFoldersRequestBuilderGetRequestConfiguration,
|
options users.ItemMailFoldersRequestBuilderGetRequestConfiguration,
|
||||||
) error {
|
) (models.MailFolderCollectionResponseable, error) {
|
||||||
_, err := c.stable.Client().UsersById(userID).MailFolders().Get(ctx, &options)
|
mailFolders, err := c.stable.Client().UsersById(userID).MailFolders().Get(ctx, &options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, graph.Wrap(ctx, err, "getting MailFolders")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return mailFolders, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify onedrive enabled for user
|
// TODO: remove when drive api goes into this package
|
||||||
func (c Users) GetOnedrive(ctx context.Context, userID string) error {
|
func (c Users) GetDrives(ctx context.Context, userID string) (models.DriveCollectionResponseable, error) {
|
||||||
_, err := c.stable.Client().UsersById(userID).Drives().Get(ctx, nil)
|
drives, err := c.stable.Client().UsersById(userID).Drives().Get(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, graph.Wrap(ctx, err, "getting drives")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return drives, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Users) getAdditionalData(ctx context.Context, userID string, mailbox *MailboxInfo) error {
|
func (c Users) getMailboxSettings(
|
||||||
|
ctx context.Context,
|
||||||
|
userID string,
|
||||||
|
) (MailboxInfo, error) {
|
||||||
var (
|
var (
|
||||||
rawURL = fmt.Sprintf("https://graph.microsoft.com/v1.0/users/%s/mailboxSettings", userID)
|
rawURL = fmt.Sprintf("https://graph.microsoft.com/v1.0/users/%s/mailboxSettings", userID)
|
||||||
adapter = c.stable.Adapter()
|
adapter = c.stable.Adapter()
|
||||||
mailBoundErr clues.Err
|
mi = MailboxInfo{
|
||||||
|
ErrGetMailBoxSetting: []error{},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
settings, err := users.NewUserItemRequestBuilder(rawURL, adapter).Get(ctx, nil)
|
settings, err := users.NewUserItemRequestBuilder(rawURL, adapter).Get(ctx, nil)
|
||||||
if err != nil && !(graph.IsErrAccessDenied(err) || graph.IsErrExchangeMailFolderNotFound(err)) {
|
if err != nil && !(graph.IsErrAccessDenied(err) || graph.IsErrExchangeMailFolderNotFound(err)) {
|
||||||
logger.CtxErr(ctx, err).Error("getting mailbox settings")
|
logger.CtxErr(ctx, err).Error("getting mailbox settings")
|
||||||
|
return mi, graph.Wrap(ctx, err, "getting additional data")
|
||||||
return graph.Wrap(ctx, err, "getting additional data")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if graph.IsErrAccessDenied(err) {
|
if graph.IsErrAccessDenied(err) {
|
||||||
logger.Ctx(ctx).Info("err getting additional data: access denied")
|
logger.Ctx(ctx).Info("err getting additional data: access denied")
|
||||||
|
|
||||||
mailbox.ErrGetMailBoxSetting = clues.New("access denied")
|
mi.ErrGetMailBoxSetting = append(mi.ErrGetMailBoxSetting, clues.New("access denied"))
|
||||||
|
|
||||||
return nil
|
return mi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if graph.IsErrExchangeMailFolderNotFound(err) {
|
if graph.IsErrExchangeMailFolderNotFound(err) {
|
||||||
logger.Ctx(ctx).Info("err exchange mail folder not found")
|
logger.Ctx(ctx).Info("mailfolders not found")
|
||||||
|
|
||||||
mailbox.ErrGetMailBoxSetting = ErrMailBoxSettingsNotFound
|
mi.ErrGetMailBoxSetting = append(mi.ErrGetMailBoxSetting, ErrMailBoxSettingsNotFound)
|
||||||
|
|
||||||
return nil
|
return mi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
additionalData := settings.GetAdditionalData()
|
additionalData := settings.GetAdditionalData()
|
||||||
|
|
||||||
mailbox.ArchiveFolder = toString(ctx, additionalData["archiveFolder"], &mailBoundErr)
|
mi.ArchiveFolder, err = toString(ctx, "archiveFolder", additionalData)
|
||||||
mailbox.Timezone = toString(ctx, additionalData["timeZone"], &mailBoundErr)
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
mailbox.DateFormat = toString(ctx, additionalData["dateFormat"], &mailBoundErr)
|
|
||||||
mailbox.TimeFormat = toString(ctx, additionalData["timeFormat"], &mailBoundErr)
|
mi.Timezone, err = toString(ctx, "timeZone", additionalData)
|
||||||
mailbox.Purpose = toString(ctx, additionalData["userPurpose"], &mailBoundErr)
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
mailbox.DelegateMeetMsgDeliveryOpt = toString(
|
|
||||||
ctx,
|
mi.DateFormat, err = toString(ctx, "dateFormat", additionalData)
|
||||||
additionalData["delegateMeetingMessageDeliveryOptions"],
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
&mailBoundErr)
|
|
||||||
|
mi.TimeFormat, err = toString(ctx, "timeFormat", additionalData)
|
||||||
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
|
|
||||||
|
mi.Purpose, err = toString(ctx, "userPurpose", additionalData)
|
||||||
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
|
|
||||||
|
mi.DelegateMeetMsgDeliveryOpt, err = toString(ctx, "delegateMeetingMessageDeliveryOptions", additionalData)
|
||||||
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
|
|
||||||
// decode automatic replies settings
|
// decode automatic replies settings
|
||||||
replySetting := toMap(ctx, additionalData["automaticRepliesSetting"], &mailBoundErr)
|
replySetting, err := toT[map[string]any](ctx, "automaticRepliesSetting", additionalData)
|
||||||
mailbox.AutomaticRepliesSetting.Status = toString(
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
ctx,
|
|
||||||
replySetting["status"],
|
mi.AutomaticRepliesSetting.Status, err = toString(ctx, "status", replySetting)
|
||||||
&mailBoundErr)
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
mailbox.AutomaticRepliesSetting.ExternalAudience = toString(
|
|
||||||
ctx,
|
mi.AutomaticRepliesSetting.ExternalAudience, err = toString(ctx, "externalAudience", replySetting)
|
||||||
replySetting["externalAudience"],
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
&mailBoundErr)
|
|
||||||
mailbox.AutomaticRepliesSetting.ExternalReplyMessage = toString(
|
mi.AutomaticRepliesSetting.ExternalReplyMessage, err = toString(ctx, "externalReplyMessage", replySetting)
|
||||||
ctx,
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
replySetting["externalReplyMessage"],
|
|
||||||
&mailBoundErr)
|
mi.AutomaticRepliesSetting.InternalReplyMessage, err = toString(ctx, "internalReplyMessage", replySetting)
|
||||||
mailbox.AutomaticRepliesSetting.InternalReplyMessage = toString(
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
ctx,
|
|
||||||
replySetting["internalReplyMessage"],
|
|
||||||
&mailBoundErr)
|
|
||||||
|
|
||||||
// decode scheduledStartDateTime
|
// decode scheduledStartDateTime
|
||||||
startDateTime := toMap(ctx, replySetting["scheduledStartDateTime"], &mailBoundErr)
|
startDateTime, err := toT[map[string]any](ctx, "scheduledStartDateTime", replySetting)
|
||||||
mailbox.AutomaticRepliesSetting.ScheduledStartDateTime.DateTime = toString(
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
ctx,
|
|
||||||
startDateTime["dateTime"],
|
|
||||||
&mailBoundErr)
|
|
||||||
mailbox.AutomaticRepliesSetting.ScheduledStartDateTime.Timezone = toString(
|
|
||||||
ctx,
|
|
||||||
startDateTime["timeZone"],
|
|
||||||
&mailBoundErr)
|
|
||||||
|
|
||||||
endDateTime := toMap(ctx, replySetting["scheduledEndDateTime"], &mailBoundErr)
|
mi.AutomaticRepliesSetting.ScheduledStartDateTime.DateTime, err = toString(ctx, "dateTime", startDateTime)
|
||||||
mailbox.AutomaticRepliesSetting.ScheduledEndDateTime.DateTime = toString(
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
ctx,
|
|
||||||
endDateTime["dateTime"],
|
mi.AutomaticRepliesSetting.ScheduledStartDateTime.Timezone, err = toString(ctx, "timeZone", startDateTime)
|
||||||
&mailBoundErr)
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
mailbox.AutomaticRepliesSetting.ScheduledEndDateTime.Timezone = toString(
|
|
||||||
ctx,
|
endDateTime, err := toT[map[string]any](ctx, "scheduledEndDateTime", replySetting)
|
||||||
endDateTime["timeZone"],
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
&mailBoundErr)
|
|
||||||
|
mi.AutomaticRepliesSetting.ScheduledEndDateTime.DateTime, err = toString(ctx, "dateTime", endDateTime)
|
||||||
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
|
|
||||||
|
mi.AutomaticRepliesSetting.ScheduledEndDateTime.Timezone, err = toString(ctx, "timeZone", endDateTime)
|
||||||
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
|
|
||||||
// Language decode
|
// Language decode
|
||||||
language := toMap(ctx, additionalData["language"], &mailBoundErr)
|
language, err := toT[map[string]any](ctx, "language", additionalData)
|
||||||
mailbox.Language.DisplayName = toString(
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
ctx,
|
|
||||||
language["displayName"],
|
mi.Language.DisplayName, err = toString(ctx, "displayName", language)
|
||||||
&mailBoundErr)
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
mailbox.Language.Locale = toString(ctx, language["locale"], &mailBoundErr)
|
|
||||||
|
mi.Language.Locale, err = toString(ctx, "locale", language)
|
||||||
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
|
|
||||||
// working hours
|
// working hours
|
||||||
workingHours := toMap(ctx, additionalData["workingHours"], &mailBoundErr)
|
workingHours, err := toT[map[string]any](ctx, "workingHours", additionalData)
|
||||||
mailbox.WorkingHours.StartTime = toString(
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
ctx,
|
|
||||||
workingHours["startTime"],
|
|
||||||
&mailBoundErr)
|
|
||||||
mailbox.WorkingHours.EndTime = toString(
|
|
||||||
ctx,
|
|
||||||
workingHours["endTime"],
|
|
||||||
&mailBoundErr)
|
|
||||||
|
|
||||||
timeZone := toMap(ctx, workingHours["timeZone"], &mailBoundErr)
|
mi.WorkingHours.StartTime, err = toString(ctx, "startTime", workingHours)
|
||||||
mailbox.WorkingHours.TimeZone.Name = toString(
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
ctx,
|
|
||||||
timeZone["name"],
|
mi.WorkingHours.EndTime, err = toString(ctx, "endTime", workingHours)
|
||||||
&mailBoundErr)
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
|
|
||||||
|
timeZone, err := toT[map[string]any](ctx, "timeZone", workingHours)
|
||||||
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
|
|
||||||
|
mi.WorkingHours.TimeZone.Name, err = toString(ctx, "name", timeZone)
|
||||||
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
|
|
||||||
|
days, err := toT[[]any](ctx, "daysOfWeek", workingHours)
|
||||||
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
|
|
||||||
days := toArray(ctx, workingHours["daysOfWeek"], &mailBoundErr)
|
|
||||||
for _, day := range days {
|
for _, day := range days {
|
||||||
mailbox.WorkingHours.DaysOfWeek = append(mailbox.WorkingHours.DaysOfWeek,
|
s, err := anyToString(ctx, "dayOfTheWeek", day)
|
||||||
toString(ctx, day, &mailBoundErr))
|
mi.ErrGetMailBoxSetting = appendIfErr(mi.ErrGetMailBoxSetting, err)
|
||||||
|
mi.WorkingHours.DaysOfWeek = append(mi.WorkingHours.DaysOfWeek, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
if mailBoundErr.Core().Msg != "" {
|
return mi, nil
|
||||||
mailbox.ErrGetMailBoxSetting = &mailBoundErr
|
}
|
||||||
|
|
||||||
|
func appendIfErr(errs []error, err error) []error {
|
||||||
|
if err == nil {
|
||||||
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return append(errs, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@ -453,50 +460,52 @@ func validateUser(item any) (models.Userable, error) {
|
|||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func toString(ctx context.Context, data any, mailBoxErr *clues.Err) string {
|
func toString(ctx context.Context, key string, data map[string]any) (string, error) {
|
||||||
dataPointer, ok := data.(*string)
|
ctx = clues.Add(ctx, "setting_name", key)
|
||||||
if !ok {
|
|
||||||
logger.Ctx(ctx).Info("error getting data from mailboxSettings")
|
|
||||||
|
|
||||||
*mailBoxErr = *ErrMailBoxSettingsNotFound
|
if len(data) == 0 {
|
||||||
|
logger.Ctx(ctx).Info("not found: ", key)
|
||||||
return ""
|
return "", ErrMailBoxSettingsNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
value, ok := ptr.ValOK(dataPointer)
|
return anyToString(ctx, key, data[key])
|
||||||
if !ok {
|
|
||||||
logger.Ctx(ctx).Info("error getting value from pointer for mailboxSettings")
|
|
||||||
|
|
||||||
*mailBoxErr = *ErrMailBoxSettingsNotFound
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func toMap(ctx context.Context, data any, mailBoxErr *clues.Err) map[string]interface{} {
|
func anyToString(ctx context.Context, key string, val any) (string, error) {
|
||||||
value, ok := data.(map[string]interface{})
|
if val == nil {
|
||||||
if !ok {
|
logger.Ctx(ctx).Info("nil value: ", key)
|
||||||
logger.Ctx(ctx).Info("error getting mailboxSettings")
|
return "", ErrMailBoxSettingsNotFound
|
||||||
|
|
||||||
*mailBoxErr = *clues.New("mailbox settings not found")
|
|
||||||
|
|
||||||
return value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return value
|
sp, ok := val.(*string)
|
||||||
}
|
|
||||||
|
|
||||||
func toArray(ctx context.Context, data any, mailBoxErr *clues.Err) []interface{} {
|
|
||||||
value, ok := data.([]interface{})
|
|
||||||
if !ok {
|
if !ok {
|
||||||
logger.Ctx(ctx).Info("error getting mailboxSettings")
|
logger.Ctx(ctx).Info("value is not a *string: ", key)
|
||||||
|
return "", ErrMailBoxSettingsNotFound
|
||||||
*mailBoxErr = *clues.New("mailbox settings not found")
|
|
||||||
|
|
||||||
return value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return value
|
return ptr.Val(sp), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func toT[T any](ctx context.Context, key string, data map[string]any) (T, error) {
|
||||||
|
ctx = clues.Add(ctx, "setting_name", key)
|
||||||
|
|
||||||
|
if len(data) == 0 {
|
||||||
|
logger.Ctx(ctx).Info("not found: ", key)
|
||||||
|
return *new(T), ErrMailBoxSettingsNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
val := data[key]
|
||||||
|
|
||||||
|
if data == nil {
|
||||||
|
logger.Ctx(ctx).Info("nil value: ", key)
|
||||||
|
return *new(T), ErrMailBoxSettingsNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
value, ok := val.(T)
|
||||||
|
if !ok {
|
||||||
|
logger.Ctx(ctx).Info(fmt.Sprintf("unexpected type for %s: %T", key, val))
|
||||||
|
return *new(T), ErrMailBoxSettingsNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return value, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user