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