transition api methods to interfaces (#2010)
## Description replaces the new api client methods with interfaces, to prepare for testing funcions with mocks instead of integration. ## Does this PR need a docs update or release note? - [x] ⛔ No ## Type of change - [x] 🤖 Test ## Issue(s) * #1967 ## Test Plan - [x] ⚡ Unit test - [x] 💚 E2E
This commit is contained in:
parent
2e92d10777
commit
70d5a5ab56
@ -87,6 +87,18 @@ func newService(creds account.M365Config) (*graph.Service, error) {
|
||||
return graph.NewService(adapter), nil
|
||||
}
|
||||
|
||||
func (c Client) Contacts() Contacts {
|
||||
return Contacts{c}
|
||||
}
|
||||
|
||||
func (c Client) Events() Events {
|
||||
return Events{c}
|
||||
}
|
||||
|
||||
func (c Client) Mail() Mail {
|
||||
return Mail{c}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// helper funcs
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@ -174,11 +174,11 @@ func (suite *ExchangeServiceSuite) TestGraphQueryFunctions() {
|
||||
}{
|
||||
{
|
||||
name: "GraphQuery: Get All ContactFolders",
|
||||
function: c.GetAllContactFolderNamesForUser,
|
||||
function: c.Contacts().GetAllContactFolderNamesForUser,
|
||||
},
|
||||
{
|
||||
name: "GraphQuery: Get All Calendars for User",
|
||||
function: c.GetAllCalendarNamesForUser,
|
||||
function: c.Events().GetAllCalendarNamesForUser,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -13,9 +13,21 @@ import (
|
||||
"github.com/alcionai/corso/src/internal/connector/support"
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// controller
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
type Contacts struct {
|
||||
Client
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// methods
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// CreateContactFolder makes a contact folder with the displayName of folderName.
|
||||
// If successful, returns the created folder object.
|
||||
func (c Client) CreateContactFolder(
|
||||
func (c Contacts) CreateContactFolder(
|
||||
ctx context.Context,
|
||||
user, folderName string,
|
||||
) (models.ContactFolderable, error) {
|
||||
@ -28,7 +40,7 @@ func (c Client) CreateContactFolder(
|
||||
|
||||
// DeleteContactFolder deletes the ContactFolder associated with the M365 ID if permissions are valid.
|
||||
// Errors returned if the function call was not successful.
|
||||
func (c Client) DeleteContactFolder(
|
||||
func (c Contacts) DeleteContactFolder(
|
||||
ctx context.Context,
|
||||
user, folderID string,
|
||||
) error {
|
||||
@ -36,7 +48,7 @@ func (c Client) DeleteContactFolder(
|
||||
}
|
||||
|
||||
// RetrieveContactDataForUser is a GraphRetrievalFun that returns all associated fields.
|
||||
func (c Client) RetrieveContactDataForUser(
|
||||
func (c Contacts) RetrieveContactDataForUser(
|
||||
ctx context.Context,
|
||||
user, m365ID string,
|
||||
) (serialization.Parsable, error) {
|
||||
@ -46,7 +58,7 @@ func (c Client) RetrieveContactDataForUser(
|
||||
// GetAllContactFolderNamesForUser is a GraphQuery function for getting
|
||||
// ContactFolderId and display names for contacts. All other information is omitted.
|
||||
// Does not return the default Contact Folder
|
||||
func (c Client) GetAllContactFolderNamesForUser(
|
||||
func (c Contacts) GetAllContactFolderNamesForUser(
|
||||
ctx context.Context,
|
||||
user string,
|
||||
) (serialization.Parsable, error) {
|
||||
@ -58,16 +70,13 @@ func (c Client) GetAllContactFolderNamesForUser(
|
||||
return c.stable.Client().UsersById(user).ContactFolders().Get(ctx, options)
|
||||
}
|
||||
|
||||
func (c Client) GetContactFolderByID(
|
||||
func (c Contacts) GetContainerByID(
|
||||
ctx context.Context,
|
||||
userID, dirID string,
|
||||
optionalFields ...string,
|
||||
) (models.ContactFolderable, error) {
|
||||
fields := append([]string{"displayName", "parentFolderId"}, optionalFields...)
|
||||
|
||||
ofcf, err := optionsForContactFolderByID(fields)
|
||||
) (graph.Container, error) {
|
||||
ofcf, err := optionsForContactFolderByID([]string{"displayName", "parentFolderId"})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "options for contact folder: %v", fields)
|
||||
return nil, errors.Wrap(err, "options for contact folder")
|
||||
}
|
||||
|
||||
return c.stable.Client().
|
||||
@ -76,13 +85,13 @@ func (c Client) GetContactFolderByID(
|
||||
Get(ctx, ofcf)
|
||||
}
|
||||
|
||||
// EnumerateContactsFolders iterates through all of the users current
|
||||
// EnumerateContainers iterates through all of the users current
|
||||
// contacts folders, converting each to a graph.CacheFolder, and calling
|
||||
// fn(cf) on each one. If fn(cf) errors, the error is aggregated
|
||||
// into a multierror that gets returned to the caller.
|
||||
// Folder hierarchy is represented in its current state, and does
|
||||
// not contain historical data.
|
||||
func (c Client) EnumerateContactsFolders(
|
||||
func (c Contacts) EnumerateContainers(
|
||||
ctx context.Context,
|
||||
userID, baseDirID string,
|
||||
fn func(graph.CacheFolder) error,
|
||||
@ -138,9 +147,7 @@ func (c Client) EnumerateContactsFolders(
|
||||
return errs.ErrorOrNil()
|
||||
}
|
||||
|
||||
// FetchContactIDsFromDirectory function that returns a list of all the m365IDs of the contacts
|
||||
// of the targeted directory
|
||||
func (c Client) FetchContactIDsFromDirectory(
|
||||
func (c Contacts) GetAddedAndRemovedItemIDs(
|
||||
ctx context.Context,
|
||||
user, directoryID, oldDelta string,
|
||||
) ([]string, []string, DeltaUpdate, error) {
|
||||
|
||||
@ -14,9 +14,21 @@ import (
|
||||
"github.com/alcionai/corso/src/pkg/path"
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// controller
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
type Events struct {
|
||||
Client
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// methods
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// CreateCalendar makes an event Calendar with the name in the user's M365 exchange account
|
||||
// Reference: https://docs.microsoft.com/en-us/graph/api/user-post-calendars?view=graph-rest-1.0&tabs=go
|
||||
func (c Client) CreateCalendar(
|
||||
func (c Events) CreateCalendar(
|
||||
ctx context.Context,
|
||||
user, calendarName string,
|
||||
) (models.Calendarable, error) {
|
||||
@ -28,7 +40,7 @@ func (c Client) CreateCalendar(
|
||||
|
||||
// DeleteCalendar removes calendar from user's M365 account
|
||||
// Reference: https://docs.microsoft.com/en-us/graph/api/calendar-delete?view=graph-rest-1.0&tabs=go
|
||||
func (c Client) DeleteCalendar(
|
||||
func (c Events) DeleteCalendar(
|
||||
ctx context.Context,
|
||||
user, calendarID string,
|
||||
) error {
|
||||
@ -36,7 +48,7 @@ func (c Client) DeleteCalendar(
|
||||
}
|
||||
|
||||
// RetrieveEventDataForUser is a GraphRetrievalFunc that returns event data.
|
||||
func (c Client) RetrieveEventDataForUser(
|
||||
func (c Events) RetrieveEventDataForUser(
|
||||
ctx context.Context,
|
||||
user, m365ID string,
|
||||
) (serialization.Parsable, error) {
|
||||
@ -55,15 +67,15 @@ func (c Client) GetAllCalendarNamesForUser(
|
||||
return c.stable.Client().UsersById(user).Calendars().Get(ctx, options)
|
||||
}
|
||||
|
||||
// EnumerateCalendars iterates through all of the users current
|
||||
// contacts folders, converting each to a graph.CacheFolder, and
|
||||
// EnumerateContainers iterates through all of the users current
|
||||
// calendars, converting each to a graph.CacheFolder, and
|
||||
// calling fn(cf) on each one. If fn(cf) errors, the error is
|
||||
// aggregated into a multierror that gets returned to the caller.
|
||||
// Folder hierarchy is represented in its current state, and does
|
||||
// not contain historical data.
|
||||
func (c Client) EnumerateCalendars(
|
||||
func (c Events) EnumerateContainers(
|
||||
ctx context.Context,
|
||||
userID string,
|
||||
userID, baseDirID string,
|
||||
fn func(graph.CacheFolder) error,
|
||||
) error {
|
||||
service, err := c.service()
|
||||
@ -112,8 +124,7 @@ func (c Client) EnumerateCalendars(
|
||||
return errs.ErrorOrNil()
|
||||
}
|
||||
|
||||
// FetchEventIDsFromCalendar returns a list of all M365IDs of events of the targeted Calendar.
|
||||
func (c Client) FetchEventIDsFromCalendar(
|
||||
func (c Events) GetAddedAndRemovedItemIDs(
|
||||
ctx context.Context,
|
||||
user, calendarID, oldDelta string,
|
||||
) ([]string, []string, DeltaUpdate, error) {
|
||||
|
||||
@ -13,9 +13,21 @@ import (
|
||||
"github.com/alcionai/corso/src/internal/connector/support"
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// controller
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
type Mail struct {
|
||||
Client
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// methods
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// CreateMailFolder makes a mail folder iff a folder of the same name does not exist
|
||||
// Reference: https://docs.microsoft.com/en-us/graph/api/user-post-mailfolders?view=graph-rest-1.0&tabs=http
|
||||
func (c Client) CreateMailFolder(
|
||||
func (c Mail) CreateMailFolder(
|
||||
ctx context.Context,
|
||||
user, folder string,
|
||||
) (models.MailFolderable, error) {
|
||||
@ -27,7 +39,7 @@ func (c Client) CreateMailFolder(
|
||||
return c.stable.Client().UsersById(user).MailFolders().Post(ctx, requestBody, nil)
|
||||
}
|
||||
|
||||
func (c Client) CreateMailFolderWithParent(
|
||||
func (c Mail) CreateMailFolderWithParent(
|
||||
ctx context.Context,
|
||||
user, folder, parentID string,
|
||||
) (models.MailFolderable, error) {
|
||||
@ -51,30 +63,47 @@ func (c Client) CreateMailFolderWithParent(
|
||||
|
||||
// DeleteMailFolder removes a mail folder with the corresponding M365 ID from the user's M365 Exchange account
|
||||
// Reference: https://docs.microsoft.com/en-us/graph/api/mailfolder-delete?view=graph-rest-1.0&tabs=http
|
||||
func (c Client) DeleteMailFolder(
|
||||
func (c Mail) DeleteMailFolder(
|
||||
ctx context.Context,
|
||||
user, folderID string,
|
||||
) error {
|
||||
return c.stable.Client().UsersById(user).MailFoldersById(folderID).Delete(ctx, nil)
|
||||
}
|
||||
|
||||
func (c Mail) GetContainerByID(
|
||||
ctx context.Context,
|
||||
userID, dirID string,
|
||||
) (graph.Container, error) {
|
||||
service, err := c.service()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ofmf, err := optionsForMailFoldersItem([]string{"displayName", "parentFolderId"})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "options for mail folder")
|
||||
}
|
||||
|
||||
return service.Client().UsersById(userID).MailFoldersById(dirID).Get(ctx, ofmf)
|
||||
}
|
||||
|
||||
// RetrieveMessageDataForUser is a GraphRetrievalFunc that returns message data.
|
||||
func (c Client) RetrieveMessageDataForUser(
|
||||
func (c Mail) RetrieveMessageDataForUser(
|
||||
ctx context.Context,
|
||||
user, m365ID string,
|
||||
) (serialization.Parsable, error) {
|
||||
return c.stable.Client().UsersById(user).MessagesById(m365ID).Get(ctx, nil)
|
||||
}
|
||||
|
||||
// EnumeratetMailFolders iterates through all of the users current
|
||||
// EnumerateContainers iterates through all of the users current
|
||||
// mail folders, converting each to a graph.CacheFolder, and calling
|
||||
// fn(cf) on each one. If fn(cf) errors, the error is aggregated
|
||||
// into a multierror that gets returned to the caller.
|
||||
// Folder hierarchy is represented in its current state, and does
|
||||
// not contain historical data.
|
||||
func (c Client) EnumerateMailFolders(
|
||||
func (c Mail) EnumerateContainers(
|
||||
ctx context.Context,
|
||||
userID string,
|
||||
userID, baseDirID string,
|
||||
fn func(graph.CacheFolder) error,
|
||||
) error {
|
||||
service, err := c.service()
|
||||
@ -116,22 +145,7 @@ func (c Client) EnumerateMailFolders(
|
||||
return errs.ErrorOrNil()
|
||||
}
|
||||
|
||||
func (c Client) GetMailFolderByID(
|
||||
ctx context.Context,
|
||||
userID, dirID string,
|
||||
optionalFields ...string,
|
||||
) (models.MailFolderable, error) {
|
||||
ofmf, err := optionsForMailFoldersItem(optionalFields)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "options for mail folder: %v", optionalFields)
|
||||
}
|
||||
|
||||
return c.stable.Client().UsersById(userID).MailFoldersById(dirID).Get(ctx, ofmf)
|
||||
}
|
||||
|
||||
// FetchMessageIDsFromDirectory function that returns a list of all the m365IDs of the exchange.Mail
|
||||
// of the targeted directory
|
||||
func (c Client) FetchMessageIDsFromDirectory(
|
||||
func (c Mail) GetAddedAndRemovedItemIDs(
|
||||
ctx context.Context,
|
||||
user, directoryID, oldDelta string,
|
||||
) ([]string, []string, DeltaUpdate, error) {
|
||||
|
||||
@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/connector/exchange/api"
|
||||
"github.com/alcionai/corso/src/internal/connector/graph"
|
||||
"github.com/alcionai/corso/src/internal/connector/support"
|
||||
"github.com/alcionai/corso/src/pkg/path"
|
||||
@ -15,7 +14,8 @@ var _ graph.ContainerResolver = &contactFolderCache{}
|
||||
|
||||
type contactFolderCache struct {
|
||||
*containerResolver
|
||||
ac api.Client
|
||||
enumer containersEnumerator
|
||||
getter containerGetter
|
||||
userID string
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ func (cfc *contactFolderCache) populateContactRoot(
|
||||
directoryID string,
|
||||
baseContainerPath []string,
|
||||
) error {
|
||||
f, err := cfc.ac.GetContactFolderByID(ctx, cfc.userID, directoryID)
|
||||
f, err := cfc.getter.GetContainerByID(ctx, cfc.userID, directoryID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(
|
||||
err,
|
||||
@ -53,7 +53,7 @@ func (cfc *contactFolderCache) Populate(
|
||||
return err
|
||||
}
|
||||
|
||||
err := cfc.ac.EnumerateContactsFolders(ctx, cfc.userID, baseID, cfc.addFolder)
|
||||
err := cfc.enumer.EnumerateContainers(ctx, cfc.userID, baseID, cfc.addFolder)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -10,6 +10,29 @@ import (
|
||||
"github.com/alcionai/corso/src/pkg/path"
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// common interfaces
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
type containerGetter interface {
|
||||
GetContainerByID(
|
||||
ctx context.Context,
|
||||
userID, dirID string,
|
||||
) (graph.Container, error)
|
||||
}
|
||||
|
||||
type containersEnumerator interface {
|
||||
EnumerateContainers(
|
||||
ctx context.Context,
|
||||
userID, baseDirID string,
|
||||
fn func(graph.CacheFolder) error,
|
||||
) error
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// controller
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Exchange has a limit of 300 for folder depth. OneDrive has a limit on path
|
||||
// length of 400 characters (including separators) which would be roughly 200
|
||||
// folders if each folder is only a single character.
|
||||
|
||||
@ -8,6 +8,7 @@ import (
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/connector/exchange/api"
|
||||
"github.com/alcionai/corso/src/internal/connector/graph"
|
||||
"github.com/alcionai/corso/src/internal/connector/support"
|
||||
"github.com/alcionai/corso/src/internal/data"
|
||||
@ -205,12 +206,25 @@ func DataCollections(
|
||||
return collections, errs
|
||||
}
|
||||
|
||||
func getterByType(ac api.Client, category path.CategoryType) (addedAndRemovedItemIDsGetter, error) {
|
||||
switch category {
|
||||
case path.EmailCategory:
|
||||
return ac.Mail(), nil
|
||||
case path.EventsCategory:
|
||||
return ac.Events(), nil
|
||||
case path.ContactsCategory:
|
||||
return ac.Contacts(), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("category %s not supported by getFetchIDFunc", category)
|
||||
}
|
||||
}
|
||||
|
||||
// createCollections - utility function that retrieves M365
|
||||
// IDs through Microsoft Graph API. The selectors.ExchangeScope
|
||||
// determines the type of collections that are retrieved.
|
||||
func createCollections(
|
||||
ctx context.Context,
|
||||
acct account.M365Config,
|
||||
creds account.M365Config,
|
||||
user string,
|
||||
scope selectors.ExchangeScope,
|
||||
dps DeltaPaths,
|
||||
@ -220,15 +234,22 @@ func createCollections(
|
||||
var (
|
||||
errs *multierror.Error
|
||||
allCollections = make([]data.Collection, 0)
|
||||
ac = api.Client{Credentials: creds}
|
||||
category = scope.Category().PathType()
|
||||
)
|
||||
|
||||
getter, err := getterByType(ac, category)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create collection of ExchangeDataCollection
|
||||
collections := make(map[string]data.Collection)
|
||||
|
||||
qp := graph.QueryParams{
|
||||
Category: scope.Category().PathType(),
|
||||
Category: category,
|
||||
ResourceOwner: user,
|
||||
Credentials: acct,
|
||||
Credentials: creds,
|
||||
}
|
||||
|
||||
foldersComplete, closer := observe.MessageWithCompletion(fmt.Sprintf("∙ %s - %s:", qp.Category, user))
|
||||
@ -243,6 +264,7 @@ func createCollections(
|
||||
err = filterContainersAndFillCollections(
|
||||
ctx,
|
||||
qp,
|
||||
getter,
|
||||
collections,
|
||||
su,
|
||||
resolver,
|
||||
|
||||
@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/connector/exchange/api"
|
||||
"github.com/alcionai/corso/src/internal/connector/graph"
|
||||
"github.com/alcionai/corso/src/pkg/path"
|
||||
)
|
||||
@ -14,7 +13,7 @@ var _ graph.ContainerResolver = &eventCalendarCache{}
|
||||
|
||||
type eventCalendarCache struct {
|
||||
*containerResolver
|
||||
ac api.Client
|
||||
enumer containersEnumerator
|
||||
userID string
|
||||
}
|
||||
|
||||
@ -30,7 +29,7 @@ func (ecc *eventCalendarCache) Populate(
|
||||
ecc.containerResolver = newContainerResolver()
|
||||
}
|
||||
|
||||
err := ecc.ac.EnumerateCalendars(ctx, ecc.userID, ecc.addFolder)
|
||||
err := ecc.enumer.EnumerateContainers(ctx, ecc.userID, "", ecc.addFolder)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -142,11 +142,11 @@ func (col *Collection) Items() <-chan data.Stream {
|
||||
func GetQueryAndSerializeFunc(ac api.Client, category path.CategoryType) (api.GraphRetrievalFunc, GraphSerializeFunc) {
|
||||
switch category {
|
||||
case path.ContactsCategory:
|
||||
return ac.RetrieveContactDataForUser, serializeAndStreamContact
|
||||
return ac.Contacts().RetrieveContactDataForUser, serializeAndStreamContact
|
||||
case path.EventsCategory:
|
||||
return ac.RetrieveEventDataForUser, serializeAndStreamEvent
|
||||
return ac.Events().RetrieveEventDataForUser, serializeAndStreamEvent
|
||||
case path.EmailCategory:
|
||||
return ac.RetrieveMessageDataForUser, serializeAndStreamMessage
|
||||
return ac.Mail().RetrieveMessageDataForUser, serializeAndStreamMessage
|
||||
// Unsupported options returns nil, nil
|
||||
default:
|
||||
return nil, nil
|
||||
|
||||
@ -50,14 +50,15 @@ func (suite *CacheResolverSuite) TestPopulate() {
|
||||
eventFunc := func(t *testing.T) graph.ContainerResolver {
|
||||
return &eventCalendarCache{
|
||||
userID: tester.M365UserID(t),
|
||||
ac: ac,
|
||||
enumer: ac.Events(),
|
||||
}
|
||||
}
|
||||
|
||||
contactFunc := func(t *testing.T) graph.ContainerResolver {
|
||||
return &contactFolderCache{
|
||||
userID: tester.M365UserID(t),
|
||||
ac: ac,
|
||||
enumer: ac.Contacts(),
|
||||
getter: ac.Contacts(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/connector/exchange/api"
|
||||
"github.com/alcionai/corso/src/internal/connector/graph"
|
||||
"github.com/alcionai/corso/src/internal/connector/support"
|
||||
"github.com/alcionai/corso/src/pkg/path"
|
||||
@ -18,7 +17,8 @@ var _ graph.ContainerResolver = &mailFolderCache{}
|
||||
// nameLookup map: Key: DisplayName Value: ID
|
||||
type mailFolderCache struct {
|
||||
*containerResolver
|
||||
ac api.Client
|
||||
enumer containersEnumerator
|
||||
getter containerGetter
|
||||
userID string
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ func (mc *mailFolderCache) populateMailRoot(
|
||||
for _, fldr := range []string{rootFolderAlias, DefaultMailFolder} {
|
||||
var directory string
|
||||
|
||||
f, err := mc.ac.GetMailFolderByID(ctx, mc.userID, fldr, "displayName", "parentFolderId")
|
||||
f, err := mc.getter.GetContainerByID(ctx, mc.userID, fldr)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching root folder"+support.ConnectorStackErrorTrace(err))
|
||||
}
|
||||
@ -65,7 +65,7 @@ func (mc *mailFolderCache) Populate(
|
||||
return err
|
||||
}
|
||||
|
||||
err := mc.ac.EnumerateMailFolders(ctx, mc.userID, mc.addFolder)
|
||||
err := mc.enumer.EnumerateContainers(ctx, mc.userID, "", mc.addFolder)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -84,9 +84,12 @@ func (suite *MailFolderCacheIntegrationSuite) TestDeltaFetch() {
|
||||
ac, err := api.NewClient(suite.credentials)
|
||||
require.NoError(t, err)
|
||||
|
||||
acm := ac.Mail()
|
||||
|
||||
mfc := mailFolderCache{
|
||||
userID: userID,
|
||||
ac: ac,
|
||||
enumer: acm,
|
||||
getter: acm,
|
||||
}
|
||||
|
||||
require.NoError(t, mfc.Populate(ctx, test.root, test.path...))
|
||||
|
||||
@ -69,14 +69,14 @@ func (suite *ExchangeRestoreSuite) TestRestoreContact() {
|
||||
folderName = "TestRestoreContact: " + common.FormatSimpleDateTime(now)
|
||||
)
|
||||
|
||||
aFolder, err := suite.ac.CreateContactFolder(ctx, userID, folderName)
|
||||
aFolder, err := suite.ac.Contacts().CreateContactFolder(ctx, userID, folderName)
|
||||
require.NoError(t, err)
|
||||
|
||||
folderID := *aFolder.GetId()
|
||||
|
||||
defer func() {
|
||||
// Remove the folder containing contact prior to exiting test
|
||||
err = suite.ac.DeleteContactFolder(ctx, userID, folderID)
|
||||
err = suite.ac.Contacts().DeleteContactFolder(ctx, userID, folderID)
|
||||
assert.NoError(t, err)
|
||||
}()
|
||||
|
||||
@ -103,14 +103,14 @@ func (suite *ExchangeRestoreSuite) TestRestoreEvent() {
|
||||
name = "TestRestoreEvent: " + common.FormatSimpleDateTime(time.Now())
|
||||
)
|
||||
|
||||
calendar, err := suite.ac.CreateCalendar(ctx, userID, name)
|
||||
calendar, err := suite.ac.Events().CreateCalendar(ctx, userID, name)
|
||||
require.NoError(t, err)
|
||||
|
||||
calendarID := *calendar.GetId()
|
||||
|
||||
defer func() {
|
||||
// Removes calendar containing events created during the test
|
||||
err = suite.ac.DeleteCalendar(ctx, userID, calendarID)
|
||||
err = suite.ac.Events().DeleteCalendar(ctx, userID, calendarID)
|
||||
assert.NoError(t, err)
|
||||
}()
|
||||
|
||||
@ -146,10 +146,10 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() {
|
||||
name: "Test Mail",
|
||||
bytes: mockconnector.GetMockMessageBytes("Restore Exchange Object"),
|
||||
category: path.EmailCategory,
|
||||
cleanupFunc: suite.ac.DeleteMailFolder,
|
||||
cleanupFunc: suite.ac.Mail().DeleteMailFolder,
|
||||
destination: func(t *testing.T, ctx context.Context) string {
|
||||
folderName := "TestRestoreMailObject: " + common.FormatSimpleDateTime(now)
|
||||
folder, err := suite.ac.CreateMailFolder(ctx, userID, folderName)
|
||||
folder, err := suite.ac.Mail().CreateMailFolder(ctx, userID, folderName)
|
||||
require.NoError(t, err)
|
||||
|
||||
return *folder.GetId()
|
||||
@ -159,10 +159,10 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() {
|
||||
name: "Test Mail: One Direct Attachment",
|
||||
bytes: mockconnector.GetMockMessageWithDirectAttachment("Restore 1 Attachment"),
|
||||
category: path.EmailCategory,
|
||||
cleanupFunc: suite.ac.DeleteMailFolder,
|
||||
cleanupFunc: suite.ac.Mail().DeleteMailFolder,
|
||||
destination: func(t *testing.T, ctx context.Context) string {
|
||||
folderName := "TestRestoreMailwithAttachment: " + common.FormatSimpleDateTime(now)
|
||||
folder, err := suite.ac.CreateMailFolder(ctx, userID, folderName)
|
||||
folder, err := suite.ac.Mail().CreateMailFolder(ctx, userID, folderName)
|
||||
require.NoError(t, err)
|
||||
|
||||
return *folder.GetId()
|
||||
@ -172,10 +172,10 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() {
|
||||
name: "Test Mail: One Large Attachment",
|
||||
bytes: mockconnector.GetMockMessageWithLargeAttachment("Restore Large Attachment"),
|
||||
category: path.EmailCategory,
|
||||
cleanupFunc: suite.ac.DeleteMailFolder,
|
||||
cleanupFunc: suite.ac.Mail().DeleteMailFolder,
|
||||
destination: func(t *testing.T, ctx context.Context) string {
|
||||
folderName := "TestRestoreMailwithLargeAttachment: " + common.FormatSimpleDateTime(now)
|
||||
folder, err := suite.ac.CreateMailFolder(ctx, userID, folderName)
|
||||
folder, err := suite.ac.Mail().CreateMailFolder(ctx, userID, folderName)
|
||||
require.NoError(t, err)
|
||||
|
||||
return *folder.GetId()
|
||||
@ -185,10 +185,10 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() {
|
||||
name: "Test Mail: Two Attachments",
|
||||
bytes: mockconnector.GetMockMessageWithTwoAttachments("Restore 2 Attachments"),
|
||||
category: path.EmailCategory,
|
||||
cleanupFunc: suite.ac.DeleteMailFolder,
|
||||
cleanupFunc: suite.ac.Mail().DeleteMailFolder,
|
||||
destination: func(t *testing.T, ctx context.Context) string {
|
||||
folderName := "TestRestoreMailwithAttachments: " + common.FormatSimpleDateTime(now)
|
||||
folder, err := suite.ac.CreateMailFolder(ctx, userID, folderName)
|
||||
folder, err := suite.ac.Mail().CreateMailFolder(ctx, userID, folderName)
|
||||
require.NoError(t, err)
|
||||
|
||||
return *folder.GetId()
|
||||
@ -198,10 +198,10 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() {
|
||||
name: "Test Mail: Reference(OneDrive) Attachment",
|
||||
bytes: mockconnector.GetMessageWithOneDriveAttachment("Restore Reference(OneDrive) Attachment"),
|
||||
category: path.EmailCategory,
|
||||
cleanupFunc: suite.ac.DeleteMailFolder,
|
||||
cleanupFunc: suite.ac.Mail().DeleteMailFolder,
|
||||
destination: func(t *testing.T, ctx context.Context) string {
|
||||
folderName := "TestRestoreMailwithReferenceAttachment: " + common.FormatSimpleDateTime(now)
|
||||
folder, err := suite.ac.CreateMailFolder(ctx, userID, folderName)
|
||||
folder, err := suite.ac.Mail().CreateMailFolder(ctx, userID, folderName)
|
||||
require.NoError(t, err)
|
||||
|
||||
return *folder.GetId()
|
||||
@ -212,10 +212,10 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() {
|
||||
name: "Test Contact",
|
||||
bytes: mockconnector.GetMockContactBytes("Test_Omega"),
|
||||
category: path.ContactsCategory,
|
||||
cleanupFunc: suite.ac.DeleteContactFolder,
|
||||
cleanupFunc: suite.ac.Contacts().DeleteContactFolder,
|
||||
destination: func(t *testing.T, ctx context.Context) string {
|
||||
folderName := "TestRestoreContactObject: " + common.FormatSimpleDateTime(now)
|
||||
folder, err := suite.ac.CreateContactFolder(ctx, userID, folderName)
|
||||
folder, err := suite.ac.Contacts().CreateContactFolder(ctx, userID, folderName)
|
||||
require.NoError(t, err)
|
||||
|
||||
return *folder.GetId()
|
||||
@ -225,10 +225,10 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() {
|
||||
name: "Test Events",
|
||||
bytes: mockconnector.GetDefaultMockEventBytes("Restored Event Object"),
|
||||
category: path.EventsCategory,
|
||||
cleanupFunc: suite.ac.DeleteCalendar,
|
||||
cleanupFunc: suite.ac.Events().DeleteCalendar,
|
||||
destination: func(t *testing.T, ctx context.Context) string {
|
||||
calendarName := "TestRestoreEventObject: " + common.FormatSimpleDateTime(now)
|
||||
calendar, err := suite.ac.CreateCalendar(ctx, userID, calendarName)
|
||||
calendar, err := suite.ac.Events().CreateCalendar(ctx, userID, calendarName)
|
||||
require.NoError(t, err)
|
||||
|
||||
return *calendar.GetId()
|
||||
@ -238,10 +238,10 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() {
|
||||
name: "Test Event with Attachment",
|
||||
bytes: mockconnector.GetMockEventWithAttachment("Restored Event Attachment"),
|
||||
category: path.EventsCategory,
|
||||
cleanupFunc: suite.ac.DeleteCalendar,
|
||||
cleanupFunc: suite.ac.Events().DeleteCalendar,
|
||||
destination: func(t *testing.T, ctx context.Context) string {
|
||||
calendarName := "TestRestoreEventObject_" + common.FormatSimpleDateTime(now)
|
||||
calendar, err := suite.ac.CreateCalendar(ctx, userID, calendarName)
|
||||
calendar, err := suite.ac.Events().CreateCalendar(ctx, userID, calendarName)
|
||||
require.NoError(t, err)
|
||||
|
||||
return *calendar.GetId()
|
||||
|
||||
@ -48,23 +48,27 @@ func PopulateExchangeContainerResolver(
|
||||
|
||||
switch qp.Category {
|
||||
case path.EmailCategory:
|
||||
acm := ac.Mail()
|
||||
res = &mailFolderCache{
|
||||
userID: qp.ResourceOwner,
|
||||
ac: ac,
|
||||
getter: acm,
|
||||
enumer: acm,
|
||||
}
|
||||
cacheRoot = rootFolderAlias
|
||||
|
||||
case path.ContactsCategory:
|
||||
acc := ac.Contacts()
|
||||
res = &contactFolderCache{
|
||||
userID: qp.ResourceOwner,
|
||||
ac: ac,
|
||||
getter: acc,
|
||||
enumer: acc,
|
||||
}
|
||||
cacheRoot = DefaultContactFolder
|
||||
|
||||
case path.EventsCategory:
|
||||
res = &eventCalendarCache{
|
||||
userID: qp.ResourceOwner,
|
||||
ac: ac,
|
||||
enumer: ac.Events(),
|
||||
}
|
||||
cacheRoot = DefaultCalendar
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@ package exchange
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
@ -16,6 +15,13 @@ import (
|
||||
"github.com/alcionai/corso/src/pkg/selectors"
|
||||
)
|
||||
|
||||
type addedAndRemovedItemIDsGetter interface {
|
||||
GetAddedAndRemovedItemIDs(
|
||||
ctx context.Context,
|
||||
user, containerID, oldDeltaToken string,
|
||||
) ([]string, []string, api.DeltaUpdate, error)
|
||||
}
|
||||
|
||||
// filterContainersAndFillCollections is a utility function
|
||||
// that places the M365 object ids belonging to specific directories
|
||||
// into a Collection. Messages outside of those directories are omitted.
|
||||
@ -24,6 +30,7 @@ import (
|
||||
func filterContainersAndFillCollections(
|
||||
ctx context.Context,
|
||||
qp graph.QueryParams,
|
||||
getter addedAndRemovedItemIDsGetter,
|
||||
collections map[string]data.Collection,
|
||||
statusUpdater support.StatusUpdater,
|
||||
resolver graph.ContainerResolver,
|
||||
@ -41,17 +48,14 @@ func filterContainersAndFillCollections(
|
||||
tombstones = makeTombstones(dps)
|
||||
)
|
||||
|
||||
// TODO(rkeepers): pass in the api client instead of generating it here.
|
||||
// TODO(rkeepers): this should be passed in from the caller, probably
|
||||
// as an interface that satisfies the NewCollection requirements.
|
||||
// But this will work for the short term.
|
||||
ac, err := api.NewClient(qp.Credentials)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
getJobs, err := getFetchIDFunc(ac, qp.Category)
|
||||
if err != nil {
|
||||
return support.WrapAndAppend(qp.ResourceOwner, err, errs)
|
||||
}
|
||||
|
||||
for _, c := range resolver.Items() {
|
||||
if ctrlOpts.FailFast && errs != nil {
|
||||
return errs
|
||||
@ -89,7 +93,7 @@ func filterContainersAndFillCollections(
|
||||
}
|
||||
}
|
||||
|
||||
added, removed, newDelta, err := getJobs(ctx, qp.ResourceOwner, cID, prevDelta)
|
||||
added, removed, newDelta, err := getter.GetAddedAndRemovedItemIDs(ctx, qp.ResourceOwner, cID, prevDelta)
|
||||
if err != nil {
|
||||
if graph.IsErrDeletedInFlight(err) == nil {
|
||||
errs = support.WrapAndAppend(qp.ResourceOwner, err, errs)
|
||||
@ -217,24 +221,3 @@ func pathFromPrevString(ps string) (path.Path, error) {
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// FetchIDFunc collection of helper functions which return a list of all item
|
||||
// IDs in the given container and a delta token for future requests if the
|
||||
// container supports fetching delta records.
|
||||
type FetchIDFunc func(
|
||||
ctx context.Context,
|
||||
user, containerID, oldDeltaToken string,
|
||||
) ([]string, []string, api.DeltaUpdate, error)
|
||||
|
||||
func getFetchIDFunc(ac api.Client, category path.CategoryType) (FetchIDFunc, error) {
|
||||
switch category {
|
||||
case path.EmailCategory:
|
||||
return ac.FetchMessageIDsFromDirectory, nil
|
||||
case path.EventsCategory:
|
||||
return ac.FetchEventIDsFromCalendar, nil
|
||||
case path.ContactsCategory:
|
||||
return ac.FetchContactIDsFromDirectory, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("category %s not supported by getFetchIDFunc", category)
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,9 +455,11 @@ func CreateContainerDestinaion(
|
||||
switch category {
|
||||
case path.EmailCategory:
|
||||
if directoryCache == nil {
|
||||
acm := ac.Mail()
|
||||
mfc := &mailFolderCache{
|
||||
userID: user,
|
||||
ac: ac,
|
||||
enumer: acm,
|
||||
getter: acm,
|
||||
}
|
||||
|
||||
caches[category] = mfc
|
||||
@ -475,9 +477,11 @@ func CreateContainerDestinaion(
|
||||
|
||||
case path.ContactsCategory:
|
||||
if directoryCache == nil {
|
||||
acc := ac.Contacts()
|
||||
cfc := &contactFolderCache{
|
||||
userID: user,
|
||||
ac: ac,
|
||||
enumer: acc,
|
||||
getter: acc,
|
||||
}
|
||||
caches[category] = cfc
|
||||
newCache = true
|
||||
@ -496,7 +500,7 @@ func CreateContainerDestinaion(
|
||||
if directoryCache == nil {
|
||||
ecc := &eventCalendarCache{
|
||||
userID: user,
|
||||
ac: ac,
|
||||
enumer: ac.Events(),
|
||||
}
|
||||
caches[category] = ecc
|
||||
newCache = true
|
||||
@ -543,7 +547,7 @@ func establishMailRestoreLocation(
|
||||
continue
|
||||
}
|
||||
|
||||
temp, err := ac.CreateMailFolderWithParent(ctx, user, folder, folderID)
|
||||
temp, err := ac.Mail().CreateMailFolderWithParent(ctx, user, folder, folderID)
|
||||
if err != nil {
|
||||
// Should only error if cache malfunctions or incorrect parameters
|
||||
return "", errors.Wrap(err, support.ConnectorStackErrorTrace(err))
|
||||
@ -590,7 +594,7 @@ func establishContactsRestoreLocation(
|
||||
return cached, nil
|
||||
}
|
||||
|
||||
temp, err := ac.CreateContactFolder(ctx, user, folders[0])
|
||||
temp, err := ac.Contacts().CreateContactFolder(ctx, user, folders[0])
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, support.ConnectorStackErrorTrace(err))
|
||||
}
|
||||
@ -623,7 +627,7 @@ func establishEventsRestoreLocation(
|
||||
return cached, nil
|
||||
}
|
||||
|
||||
temp, err := ac.CreateCalendar(ctx, user, folders[0])
|
||||
temp, err := ac.Events().CreateCalendar(ctx, user, folders[0])
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, support.ConnectorStackErrorTrace(err))
|
||||
}
|
||||
|
||||
@ -942,7 +942,7 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_exchangeIncrementals() {
|
||||
|
||||
switch category {
|
||||
case path.EmailCategory:
|
||||
ids, _, _, err := ac.FetchMessageIDsFromDirectory(ctx, suite.user, containerID, "")
|
||||
ids, _, _, err := ac.Mail().GetAddedAndRemovedItemIDs(ctx, suite.user, containerID, "")
|
||||
require.NoError(t, err, "getting message ids")
|
||||
require.NotEmpty(t, ids, "message ids in folder")
|
||||
|
||||
@ -950,7 +950,7 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_exchangeIncrementals() {
|
||||
require.NoError(t, err, "deleting email item: %s", support.ConnectorStackErrorTrace(err))
|
||||
|
||||
case path.ContactsCategory:
|
||||
ids, _, _, err := ac.FetchContactIDsFromDirectory(ctx, suite.user, containerID, "")
|
||||
ids, _, _, err := ac.Contacts().GetAddedAndRemovedItemIDs(ctx, suite.user, containerID, "")
|
||||
require.NoError(t, err, "getting contact ids")
|
||||
require.NotEmpty(t, ids, "contact ids in folder")
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user