From d7abed1406acb9be91364b3c356eb967a3d52c41 Mon Sep 17 00:00:00 2001 From: Danny Date: Mon, 22 Aug 2022 17:07:57 -0400 Subject: [PATCH] GC: `setTenants` not checking *users.GetMail() (#629) User query updated from `*user.GetMail()` -> `*user.GetPrincipalName()`. Guard checks added and added GetUsers as one of the GraphQueryFunctions --- .../exchange/exchange_service_test.go | 4 ++ .../connector/exchange/service_query.go | 44 +++++++++++++++---- src/internal/connector/graph_connector.go | 24 +++++----- 3 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/internal/connector/exchange/exchange_service_test.go b/src/internal/connector/exchange/exchange_service_test.go index 8f9fac5b9..c45c9ac7b 100644 --- a/src/internal/connector/exchange/exchange_service_test.go +++ b/src/internal/connector/exchange/exchange_service_test.go @@ -234,6 +234,10 @@ func (suite *ExchangeServiceSuite) TestGraphQueryFunctions() { name: "GraphQuery: Get All Folders", function: GetAllFolderNamesForUser, }, + { + name: "GraphQuery: Get All Users", + function: GetAllUsersForTenant, + }, } for _, test := range tests { suite.T().Run(test.name, func(t *testing.T) { diff --git a/src/internal/connector/exchange/service_query.go b/src/internal/connector/exchange/service_query.go index 428fb9449..173049692 100644 --- a/src/internal/connector/exchange/service_query.go +++ b/src/internal/connector/exchange/service_query.go @@ -6,6 +6,7 @@ import ( absser "github.com/microsoft/kiota-abstractions-go/serialization" msgraphgocore "github.com/microsoftgraph/msgraph-sdk-go-core" "github.com/microsoftgraph/msgraph-sdk-go/models" + msuser "github.com/microsoftgraph/msgraph-sdk-go/users" 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" @@ -43,14 +44,16 @@ var ( } fieldsForUsers = map[string]int{ - "birthday": 1, - "businessPhones": 2, - "city": 3, - "companyName": 4, - "department": 5, - "displayName": 6, - "employeeId": 7, - "id": 8, + "birthday": 1, + "businessPhones": 2, + "city": 3, + "companyName": 4, + "department": 5, + "displayName": 6, + "employeeId": 7, + "id": 8, + "mail": 9, + "userPrincipalName": 10, } fieldsForMessages = map[string]int{ @@ -132,6 +135,17 @@ func GetAllFolderNamesForUser(gs graph.Service, user string) (absser.Parsable, e return gs.Client().UsersById(user).MailFolders().GetWithRequestConfigurationAndResponseHandler(options, nil) } +// GetAllUsersForTenant is a GraphQuery for retrieving all the UserCollectionResponse with +// that contains the UserID and email for each user. All other information is omitted +func GetAllUsersForTenant(gs graph.Service, user string) (absser.Parsable, error) { + selecting := []string{"userPrincipalName"} + options, err := optionsForUsers(selecting) + if err != nil { + return nil, err + } + return gs.Client().Users().GetWithRequestConfigurationAndResponseHandler(options, nil) +} + // GetAllEvents for User. Default returns EventResponseCollection for future events. // of the time that the call was made. There a func GetAllEventsForUser(gs graph.Service, user string) (absser.Parsable, error) { @@ -544,6 +558,20 @@ func optionsForContacts(moreOps []string) (*mscontacts.ContactsRequestBuilderGet return options, nil } +func optionsForUsers(moreOps []string) (*msuser.UsersRequestBuilderGetRequestConfiguration, error) { + selecting, err := buildOptions(moreOps, users) + if err != nil { + return nil, err + } + requestParams := &msuser.UsersRequestBuilderGetQueryParameters{ + Select: selecting, + } + options := &msuser.UsersRequestBuilderGetRequestConfiguration{ + QueryParameters: requestParams, + } + return options, nil +} + // buildOptions - Utility Method for verifying if select options are valid for the m365 object type // @return is a pair. The first is a string literal of allowable options based on the object type, // the second is an error. An error is returned if an unsupported option or optionIdentifier was used diff --git a/src/internal/connector/graph_connector.go b/src/internal/connector/graph_connector.go index 3c240e022..92eb0f141 100644 --- a/src/internal/connector/graph_connector.go +++ b/src/internal/connector/graph_connector.go @@ -5,6 +5,7 @@ package connector import ( "bytes" "context" + "fmt" "strings" "sync/atomic" @@ -12,7 +13,6 @@ import ( msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go" msgraphgocore "github.com/microsoftgraph/msgraph-sdk-go-core" "github.com/microsoftgraph/msgraph-sdk-go/models" - msuser "github.com/microsoftgraph/msgraph-sdk-go/users" "github.com/pkg/errors" "github.com/alcionai/corso/internal/connector/exchange" @@ -116,14 +116,7 @@ func (gs *graphService) EnableFailFast() { // workspace. The users field is updated during this method // iff the return value is true func (gc *GraphConnector) setTenantUsers() error { - selecting := []string{"id, mail"} - requestParams := &msuser.UsersRequestBuilderGetQueryParameters{ - Select: selecting, - } - options := &msuser.UsersRequestBuilderGetRequestConfiguration{ - QueryParameters: requestParams, - } - response, err := gc.Client().Users().GetWithRequestConfigurationAndResponseHandler(options, nil) + response, err := exchange.GetAllUsersForTenant(gc.graphService, "") if err != nil { return errors.Wrapf( err, @@ -151,9 +144,20 @@ func (gc *GraphConnector) setTenantUsers() error { err = support.WrapAndAppend(gc.graphService.adapter.GetBaseUrl(), errors.New("user iteration failure"), err) return true } - gc.Users[*user.GetMail()] = *user.GetId() + if user.GetUserPrincipalName() == nil { + err = support.WrapAndAppend( + gc.graphService.adapter.GetBaseUrl(), + fmt.Errorf("no email address for User: %s", *user.GetId()), + err, + ) + return true + } + + // *user.GetId() is populated for every M365 entityable object by M365 backstore + gc.Users[*user.GetUserPrincipalName()] = *user.GetId() return true } + iterateError = userIterator.Iterate(callbackFunc) if iterateError != nil { err = support.WrapAndAppend(gc.graphService.adapter.GetBaseUrl(), iterateError, err)