lookup contact folder as fallback (#1174)
## Description In the event that a user only has a primary contact folder, and no subfolders, the contact folder legacy iter needs to fall back to checking for the contacts default folder in an isolated query, because that folder isn't provided as part of the contacts folders get request. ## Type of change - [x] 🐛 Bugfix ## Issue(s) * #1113 ## Test Plan - [x] 💪 Manual - [x] 💚 E2E
This commit is contained in:
parent
0963bbe364
commit
48cb751ee0
@ -291,6 +291,10 @@ func (suite *ExchangeServiceSuite) TestGraphQueryFunctions() {
|
||||
name: "GraphQuery: Get All ContactFolders",
|
||||
function: GetAllContactFolderNamesForUser,
|
||||
},
|
||||
{
|
||||
name: "GraphQuery: Get Default ContactFolder",
|
||||
function: GetDefaultContactFolderForUser,
|
||||
},
|
||||
{
|
||||
name: "GraphQuery: Get All Events for User",
|
||||
function: GetAllEventsForUser,
|
||||
|
||||
@ -123,6 +123,12 @@ func (suite *ExchangeIteratorSuite) TestIterativeFunctions() {
|
||||
iterativeFunction: IterateFilterContainersForCollections,
|
||||
scope: contactScope[0],
|
||||
transformer: models.CreateContactFolderCollectionResponseFromDiscriminatorValue,
|
||||
}, {
|
||||
name: "Default Contacts Folder",
|
||||
queryFunction: GetDefaultContactFolderForUser,
|
||||
iterativeFunction: IterateSelectAllContactsForCollections,
|
||||
scope: contactScope[0],
|
||||
transformer: models.CreateContactFolderCollectionResponseFromDiscriminatorValue,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
|
||||
@ -6,8 +6,9 @@ import (
|
||||
msuser "github.com/microsoftgraph/msgraph-sdk-go/users"
|
||||
mscalendars "github.com/microsoftgraph/msgraph-sdk-go/users/item/calendars"
|
||||
mscontactfolder "github.com/microsoftgraph/msgraph-sdk-go/users/item/contactfolders"
|
||||
mscontactbyid "github.com/microsoftgraph/msgraph-sdk-go/users/item/contactfolders/item"
|
||||
mscontactfolderitem "github.com/microsoftgraph/msgraph-sdk-go/users/item/contactfolders/item/contacts"
|
||||
mscontactfolderitem "github.com/microsoftgraph/msgraph-sdk-go/users/item/contactfolders/item"
|
||||
mscontactfolderchild "github.com/microsoftgraph/msgraph-sdk-go/users/item/contactfolders/item/childfolders"
|
||||
mscontactfolderitemcontact "github.com/microsoftgraph/msgraph-sdk-go/users/item/contactfolders/item/contacts"
|
||||
mscontacts "github.com/microsoftgraph/msgraph-sdk-go/users/item/contacts"
|
||||
msevents "github.com/microsoftgraph/msgraph-sdk-go/users/item/events"
|
||||
msfolder "github.com/microsoftgraph/msgraph-sdk-go/users/item/mailfolders"
|
||||
@ -236,7 +237,7 @@ func optionsForContactFolders(moreOps []string) (
|
||||
}
|
||||
|
||||
func optionsForContactFolderByID(moreOps []string) (
|
||||
*mscontactbyid.ContactFolderItemRequestBuilderGetRequestConfiguration,
|
||||
*mscontactfolderitem.ContactFolderItemRequestBuilderGetRequestConfiguration,
|
||||
error,
|
||||
) {
|
||||
selecting, err := buildOptions(moreOps, folders)
|
||||
@ -244,10 +245,10 @@ func optionsForContactFolderByID(moreOps []string) (
|
||||
return nil, err
|
||||
}
|
||||
|
||||
requestParameters := &mscontactbyid.ContactFolderItemRequestBuilderGetQueryParameters{
|
||||
requestParameters := &mscontactfolderitem.ContactFolderItemRequestBuilderGetQueryParameters{
|
||||
Select: selecting,
|
||||
}
|
||||
options := &mscontactbyid.ContactFolderItemRequestBuilderGetRequestConfiguration{
|
||||
options := &mscontactfolderitem.ContactFolderItemRequestBuilderGetRequestConfiguration{
|
||||
QueryParameters: requestParameters,
|
||||
}
|
||||
|
||||
@ -298,16 +299,16 @@ func optionsForMailFoldersItem(
|
||||
// TODO: Remove after Issue #828; requires updating msgraph to v0.34
|
||||
func optionsForContactFoldersItem(
|
||||
moreOps []string,
|
||||
) (*mscontactfolderitem.ContactsRequestBuilderGetRequestConfiguration, error) {
|
||||
) (*mscontactfolderitemcontact.ContactsRequestBuilderGetRequestConfiguration, error) {
|
||||
selecting, err := buildOptions(moreOps, contacts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
requestParameters := &mscontactfolderitem.ContactsRequestBuilderGetQueryParameters{
|
||||
requestParameters := &mscontactfolderitemcontact.ContactsRequestBuilderGetQueryParameters{
|
||||
Select: selecting,
|
||||
}
|
||||
options := &mscontactfolderitem.ContactsRequestBuilderGetRequestConfiguration{
|
||||
options := &mscontactfolderitemcontact.ContactsRequestBuilderGetRequestConfiguration{
|
||||
QueryParameters: requestParameters,
|
||||
}
|
||||
|
||||
@ -332,6 +333,25 @@ func optionsForEvents(moreOps []string) (*msevents.EventsRequestBuilderGetReques
|
||||
return options, nil
|
||||
}
|
||||
|
||||
// optionsForContactChildFolders builds a contacts child folders request.
|
||||
func optionsForContactChildFolders(
|
||||
moreOps []string,
|
||||
) (*mscontactfolderchild.ChildFoldersRequestBuilderGetRequestConfiguration, error) {
|
||||
selecting, err := buildOptions(moreOps, contacts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
requestParameters := &mscontactfolderchild.ChildFoldersRequestBuilderGetQueryParameters{
|
||||
Select: selecting,
|
||||
}
|
||||
options := &mscontactfolderchild.ChildFoldersRequestBuilderGetRequestConfiguration{
|
||||
QueryParameters: requestParameters,
|
||||
}
|
||||
|
||||
return options, nil
|
||||
}
|
||||
|
||||
// optionsForContacts transforms options into select query for MailContacts
|
||||
// @return is the first call in Contacts().GetWithRequestConfigurationAndResponseHandler(options, handler)
|
||||
func optionsForContacts(moreOps []string) (*mscontacts.ContactsRequestBuilderGetRequestConfiguration, error) {
|
||||
|
||||
@ -346,10 +346,12 @@ func GetContainerID(
|
||||
}
|
||||
|
||||
// SetupExchangeCollectionVars is a helper function returns a sets
|
||||
// Exchange.Type specific functions based on scope
|
||||
// Exchange.Type specific functions based on scope.
|
||||
// The []GraphQuery slice provides fallback queries in the event that
|
||||
// initial queries provide zero results.
|
||||
func SetupExchangeCollectionVars(scope selectors.ExchangeScope) (
|
||||
absser.ParsableFactory,
|
||||
GraphQuery,
|
||||
[]GraphQuery,
|
||||
GraphIterateFunc,
|
||||
error,
|
||||
) {
|
||||
@ -359,14 +361,14 @@ func SetupExchangeCollectionVars(scope selectors.ExchangeScope) (
|
||||
|
||||
if scope.IncludesCategory(selectors.ExchangeContact) {
|
||||
return models.CreateContactFolderCollectionResponseFromDiscriminatorValue,
|
||||
GetAllContactFolderNamesForUser,
|
||||
[]GraphQuery{GetAllContactFolderNamesForUser, GetDefaultContactFolderForUser},
|
||||
IterateSelectAllContactsForCollections,
|
||||
nil
|
||||
}
|
||||
|
||||
if scope.IncludesCategory(selectors.ExchangeEvent) {
|
||||
return models.CreateCalendarCollectionResponseFromDiscriminatorValue,
|
||||
GetAllCalendarNamesForUser,
|
||||
[]GraphQuery{GetAllCalendarNamesForUser},
|
||||
IterateSelectAllEventsFromCalendars,
|
||||
nil
|
||||
}
|
||||
|
||||
@ -51,9 +51,25 @@ func GetAllCalendarNamesForUser(ctx context.Context, gs graph.Service, user stri
|
||||
return gs.Client().UsersById(user).Calendars().Get(ctx, options)
|
||||
}
|
||||
|
||||
// GetDefaultContactFolderForUser is a GraphQuery function for getting the ContactFolderId
|
||||
// and display names for the default "Contacts" folder.
|
||||
// Only returns the default Contact Folder
|
||||
func GetDefaultContactFolderForUser(ctx context.Context, gs graph.Service, user string) (absser.Parsable, error) {
|
||||
options, err := optionsForContactChildFolders([]string{"displayName", "parentFolderId"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return gs.Client().
|
||||
UsersById(user).
|
||||
ContactFoldersById(rootFolderAlias).
|
||||
ChildFolders().
|
||||
Get(ctx, options)
|
||||
}
|
||||
|
||||
// GetAllContactFolderNamesForUser is a GraphQuery function for getting ContactFolderId
|
||||
// and display names for contacts. All other information is omitted.
|
||||
// Does not return the primary Contact Folder
|
||||
// Does not return the default Contact Folder
|
||||
func GetAllContactFolderNamesForUser(ctx context.Context, gs graph.Service, user string) (absser.Parsable, error) {
|
||||
options, err := optionsForContactFolders([]string{"displayName", "parentFolderId"})
|
||||
if err != nil {
|
||||
|
||||
@ -334,40 +334,46 @@ func (gc *GraphConnector) legacyFetchItems(
|
||||
resolver graph.ContainerResolver,
|
||||
) (map[string]*exchange.Collection, error) {
|
||||
var (
|
||||
errs error
|
||||
errs error
|
||||
errUpdater = func(id string, err error) {
|
||||
errs = support.WrapAndAppend(id, err, errs)
|
||||
}
|
||||
collections = map[string]*exchange.Collection{}
|
||||
)
|
||||
|
||||
transformer, query, gIter, err := exchange.SetupExchangeCollectionVars(scope)
|
||||
transformer, queries, gIter, err := exchange.SetupExchangeCollectionVars(scope)
|
||||
if err != nil {
|
||||
return nil, support.WrapAndAppend(gc.Service().Adapter().GetBaseUrl(), err, nil)
|
||||
}
|
||||
|
||||
response, err := query(ctx, &gc.graphService, qp.User)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(
|
||||
err,
|
||||
"user %s M365 query: %s",
|
||||
qp.User, support.ConnectorStackErrorTrace(err))
|
||||
}
|
||||
// queries is assumed to provide fallbacks in case of empty results. Any
|
||||
// non-zero collection production will break out of the loop.
|
||||
for _, query := range queries {
|
||||
response, err := query(ctx, &gc.graphService, qp.User)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(
|
||||
err,
|
||||
"user %s M365 query: %s",
|
||||
qp.User, support.ConnectorStackErrorTrace(err))
|
||||
}
|
||||
|
||||
pageIterator, err := msgraphgocore.NewPageIterator(response, &gc.graphService.adapter, transformer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pageIterator, err := msgraphgocore.NewPageIterator(response, &gc.graphService.adapter, transformer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
errUpdater := func(id string, err error) {
|
||||
errs = support.WrapAndAppend(id, err, errs)
|
||||
}
|
||||
// callbackFunc iterates through all M365 object target and fills exchange.Collection.jobs[]
|
||||
// with corresponding item M365IDs. New collections are created for each directory.
|
||||
// Each directory used the M365 Identifier. The use of ID stops collisions betweens users
|
||||
callbackFunc := gIter(ctx, qp, errUpdater, collections, gc.UpdateStatus, resolver)
|
||||
|
||||
// callbackFunc iterates through all M365 object target and fills exchange.Collection.jobs[]
|
||||
// with corresponding item M365IDs. New collections are created for each directory.
|
||||
// Each directory used the M365 Identifier. The use of ID stops collisions betweens users
|
||||
callbackFunc := gIter(ctx, qp, errUpdater, collections, gc.UpdateStatus, resolver)
|
||||
iterateError := pageIterator.Iterate(ctx, callbackFunc)
|
||||
if err := pageIterator.Iterate(ctx, callbackFunc); err != nil {
|
||||
return nil, support.WrapAndAppend(gc.graphService.adapter.GetBaseUrl(), err, errs)
|
||||
}
|
||||
|
||||
if iterateError != nil {
|
||||
errs = support.WrapAndAppend(gc.graphService.adapter.GetBaseUrl(), iterateError, errs)
|
||||
if len(collections) > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return collections, errs
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user