methodize all api funcs to the Client
In order to use the api layer as an interface, we need the functions therein to be methods, so that callers can leverage local interfaces. This change introduces the api.Client, and begins to spread it throughout the exchange package, largely in place of graph servicers.
This commit is contained in:
parent
94134bf013
commit
5ebbdd1b4e
@ -77,12 +77,12 @@ func handleGetCommand(cmd *cobra.Command, args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
gc, err := getGC(ctx)
|
gc, creds, err := getGC(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = runDisplayM365JSON(ctx, gc.Service)
|
err = runDisplayM365JSON(ctx, gc.Service, creds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Only(ctx, errors.Wrapf(err, "unable to create mock from M365: %s", m365ID))
|
return Only(ctx, errors.Wrapf(err, "unable to create mock from M365: %s", m365ID))
|
||||||
}
|
}
|
||||||
@ -93,6 +93,7 @@ func handleGetCommand(cmd *cobra.Command, args []string) error {
|
|||||||
func runDisplayM365JSON(
|
func runDisplayM365JSON(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
gs graph.Servicer,
|
||||||
|
creds account.M365Config,
|
||||||
) error {
|
) error {
|
||||||
var (
|
var (
|
||||||
get api.GraphRetrievalFunc
|
get api.GraphRetrievalFunc
|
||||||
@ -100,9 +101,11 @@ func runDisplayM365JSON(
|
|||||||
cat = graph.StringToPathCategory(category)
|
cat = graph.StringToPathCategory(category)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ac := api.Client{Credentials: creds}
|
||||||
|
|
||||||
switch cat {
|
switch cat {
|
||||||
case path.EmailCategory, path.EventsCategory, path.ContactsCategory:
|
case path.EmailCategory, path.EventsCategory, path.ContactsCategory:
|
||||||
get, serializeFunc = exchange.GetQueryAndSerializeFunc(cat)
|
get, serializeFunc = exchange.GetQueryAndSerializeFunc(ac, cat)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unable to process category: %s", cat)
|
return fmt.Errorf("unable to process category: %s", cat)
|
||||||
}
|
}
|
||||||
@ -111,7 +114,7 @@ func runDisplayM365JSON(
|
|||||||
|
|
||||||
sw := kw.NewJsonSerializationWriter()
|
sw := kw.NewJsonSerializationWriter()
|
||||||
|
|
||||||
response, err := get(ctx, gs, user, m365ID)
|
response, err := get(ctx, user, m365ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, support.ConnectorStackErrorTrace(err))
|
return errors.Wrap(err, support.ConnectorStackErrorTrace(err))
|
||||||
}
|
}
|
||||||
@ -159,7 +162,7 @@ func runDisplayM365JSON(
|
|||||||
// Helpers
|
// Helpers
|
||||||
//-------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
func getGC(ctx context.Context) (*connector.GraphConnector, error) {
|
func getGC(ctx context.Context) (*connector.GraphConnector, account.M365Config, error) {
|
||||||
// get account info
|
// get account info
|
||||||
m365Cfg := account.M365Config{
|
m365Cfg := account.M365Config{
|
||||||
M365: credentials.GetM365(),
|
M365: credentials.GetM365(),
|
||||||
@ -168,13 +171,13 @@ func getGC(ctx context.Context) (*connector.GraphConnector, error) {
|
|||||||
|
|
||||||
acct, err := account.NewAccount(account.ProviderM365, m365Cfg)
|
acct, err := account.NewAccount(account.ProviderM365, m365Cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, Only(ctx, errors.Wrap(err, "finding m365 account details"))
|
return nil, m365Cfg, Only(ctx, errors.Wrap(err, "finding m365 account details"))
|
||||||
}
|
}
|
||||||
|
|
||||||
gc, err := connector.NewGraphConnector(ctx, acct, connector.Users)
|
gc, err := connector.NewGraphConnector(ctx, acct, connector.Users)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, Only(ctx, errors.Wrap(err, "connecting to graph API"))
|
return nil, m365Cfg, Only(ctx, errors.Wrap(err, "connecting to graph API"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return gc, nil
|
return gc, m365Cfg, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,8 +4,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/microsoft/kiota-abstractions-go/serialization"
|
"github.com/microsoft/kiota-abstractions-go/serialization"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/alcionai/corso/src/internal/connector/graph"
|
"github.com/alcionai/corso/src/internal/connector/graph"
|
||||||
|
"github.com/alcionai/corso/src/pkg/account"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@ -26,14 +28,13 @@ type DeltaUpdate struct {
|
|||||||
// into M365 backstore. Responses -> returned items will only contain the information
|
// into M365 backstore. Responses -> returned items will only contain the information
|
||||||
// that is included in the options
|
// that is included in the options
|
||||||
// TODO: use selector or path for granularity into specific folders or specific date ranges
|
// TODO: use selector or path for granularity into specific folders or specific date ranges
|
||||||
type GraphQuery func(ctx context.Context, gs graph.Servicer, userID string) (serialization.Parsable, error)
|
type GraphQuery func(ctx context.Context, userID string) (serialization.Parsable, error)
|
||||||
|
|
||||||
// GraphRetrievalFunctions are functions from the Microsoft Graph API that retrieve
|
// GraphRetrievalFunctions are functions from the Microsoft Graph API that retrieve
|
||||||
// the default associated data of a M365 object. This varies by object. Additional
|
// the default associated data of a M365 object. This varies by object. Additional
|
||||||
// Queries must be run to obtain the omitted fields.
|
// Queries must be run to obtain the omitted fields.
|
||||||
type GraphRetrievalFunc func(
|
type GraphRetrievalFunc func(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
|
||||||
user, m365ID string,
|
user, m365ID string,
|
||||||
) (serialization.Parsable, error)
|
) (serialization.Parsable, error)
|
||||||
|
|
||||||
@ -41,10 +42,25 @@ type GraphRetrievalFunc func(
|
|||||||
// interfaces
|
// interfaces
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
// API is a struct used to fulfill the interface for exchange
|
// Client is used to fulfill the interface for exchange
|
||||||
// queries that are traditionally backed by GraphAPI. A
|
// queries that are traditionally backed by GraphAPI. A
|
||||||
// struct is used in this case, instead of deferring to
|
// struct is used in this case, instead of deferring to
|
||||||
// pure function wrappers, so that the boundary separates the
|
// pure function wrappers, so that the boundary separates the
|
||||||
// granular implementation of the graphAPI and kiota away
|
// granular implementation of the graphAPI and kiota away
|
||||||
// from the exchange package's broader intents.
|
// from the exchange package's broader intents.
|
||||||
// type API struct{}
|
type Client struct {
|
||||||
|
Credentials account.M365Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Client) service() (*graph.Service, error) {
|
||||||
|
adapter, err := graph.CreateAdapter(
|
||||||
|
c.Credentials.AzureTenantID,
|
||||||
|
c.Credentials.AzureClientID,
|
||||||
|
c.Credentials.AzureClientSecret,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "generating graph api service client")
|
||||||
|
}
|
||||||
|
|
||||||
|
return graph.NewService(adapter), nil
|
||||||
|
}
|
||||||
|
|||||||
@ -164,6 +164,8 @@ func (suite *ExchangeServiceSuite) TestGraphQueryFunctions() {
|
|||||||
ctx, flush := tester.NewContext()
|
ctx, flush := tester.NewContext()
|
||||||
defer flush()
|
defer flush()
|
||||||
|
|
||||||
|
c := Client{suite.credentials}
|
||||||
|
|
||||||
userID := tester.M365UserID(suite.T())
|
userID := tester.M365UserID(suite.T())
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@ -171,17 +173,17 @@ func (suite *ExchangeServiceSuite) TestGraphQueryFunctions() {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "GraphQuery: Get All ContactFolders",
|
name: "GraphQuery: Get All ContactFolders",
|
||||||
function: GetAllContactFolderNamesForUser,
|
function: c.GetAllContactFolderNamesForUser,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "GraphQuery: Get All Calendars for User",
|
name: "GraphQuery: Get All Calendars for User",
|
||||||
function: GetAllCalendarNamesForUser,
|
function: c.GetAllCalendarNamesForUser,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
suite.T().Run(test.name, func(t *testing.T) {
|
suite.T().Run(test.name, func(t *testing.T) {
|
||||||
response, err := test.function(ctx, suite.gs, userID)
|
response, err := test.function(ctx, userID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, response)
|
assert.NotNil(t, response)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -15,55 +15,79 @@ import (
|
|||||||
|
|
||||||
// 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 CreateContactFolder(
|
func (c Client) CreateContactFolder(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
|
||||||
user, folderName string,
|
user, folderName string,
|
||||||
) (models.ContactFolderable, error) {
|
) (models.ContactFolderable, error) {
|
||||||
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
requestBody := models.NewContactFolder()
|
requestBody := models.NewContactFolder()
|
||||||
temp := folderName
|
temp := folderName
|
||||||
requestBody.SetDisplayName(&temp)
|
requestBody.SetDisplayName(&temp)
|
||||||
|
|
||||||
return gs.Client().UsersById(user).ContactFolders().Post(ctx, requestBody, nil)
|
return service.Client().UsersById(user).ContactFolders().Post(ctx, requestBody, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 DeleteContactFolder(ctx context.Context, gs graph.Servicer, user, folderID string) error {
|
func (c Client) DeleteContactFolder(
|
||||||
return gs.Client().UsersById(user).ContactFoldersById(folderID).Delete(ctx, nil)
|
ctx context.Context,
|
||||||
|
user, folderID string,
|
||||||
|
) error {
|
||||||
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return service.Client().UsersById(user).ContactFoldersById(folderID).Delete(ctx, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RetrieveContactDataForUser is a GraphRetrievalFun that returns all associated fields.
|
// RetrieveContactDataForUser is a GraphRetrievalFun that returns all associated fields.
|
||||||
func RetrieveContactDataForUser(
|
func (c Client) RetrieveContactDataForUser(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
|
||||||
user, m365ID string,
|
user, m365ID string,
|
||||||
) (serialization.Parsable, error) {
|
) (serialization.Parsable, error) {
|
||||||
return gs.Client().UsersById(user).ContactsById(m365ID).Get(ctx, nil)
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return service.Client().UsersById(user).ContactsById(m365ID).Get(ctx, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 GetAllContactFolderNamesForUser(
|
func (c Client) GetAllContactFolderNamesForUser(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
|
||||||
user string,
|
user string,
|
||||||
) (serialization.Parsable, error) {
|
) (serialization.Parsable, error) {
|
||||||
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
options, err := optionsForContactFolders([]string{"displayName", "parentFolderId"})
|
options, err := optionsForContactFolders([]string{"displayName", "parentFolderId"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return gs.Client().UsersById(user).ContactFolders().Get(ctx, options)
|
return service.Client().UsersById(user).ContactFolders().Get(ctx, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetContactFolderByID(
|
func (c Client) GetContactFolderByID(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
|
||||||
userID, dirID string,
|
userID, dirID string,
|
||||||
optionalFields ...string,
|
optionalFields ...string,
|
||||||
) (models.ContactFolderable, error) {
|
) (models.ContactFolderable, error) {
|
||||||
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
fields := append([]string{"displayName", "parentFolderId"}, optionalFields...)
|
fields := append([]string{"displayName", "parentFolderId"}, optionalFields...)
|
||||||
|
|
||||||
ofcf, err := optionsForContactFolderByID(fields)
|
ofcf, err := optionsForContactFolderByID(fields)
|
||||||
@ -71,7 +95,7 @@ func GetContactFolderByID(
|
|||||||
return nil, errors.Wrapf(err, "options for contact folder: %v", fields)
|
return nil, errors.Wrapf(err, "options for contact folder: %v", fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
return gs.Client().
|
return service.Client().
|
||||||
UsersById(userID).
|
UsersById(userID).
|
||||||
ContactFoldersById(dirID).
|
ContactFoldersById(dirID).
|
||||||
Get(ctx, ofcf)
|
Get(ctx, ofcf)
|
||||||
@ -79,38 +103,47 @@ func GetContactFolderByID(
|
|||||||
|
|
||||||
// TODO: we want this to be the full handler, not only the builder.
|
// TODO: we want this to be the full handler, not only the builder.
|
||||||
// but this halfway point minimizes changes for now.
|
// but this halfway point minimizes changes for now.
|
||||||
func GetContactChildFoldersBuilder(
|
func (c Client) GetContactChildFoldersBuilder(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
|
||||||
userID, baseDirID string,
|
userID, baseDirID string,
|
||||||
optionalFields ...string,
|
optionalFields ...string,
|
||||||
) (
|
) (
|
||||||
*users.ItemContactFoldersItemChildFoldersRequestBuilder,
|
*users.ItemContactFoldersItemChildFoldersRequestBuilder,
|
||||||
*users.ItemContactFoldersItemChildFoldersRequestBuilderGetRequestConfiguration,
|
*users.ItemContactFoldersItemChildFoldersRequestBuilderGetRequestConfiguration,
|
||||||
|
*graph.Service,
|
||||||
error,
|
error,
|
||||||
) {
|
) {
|
||||||
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
fields := append([]string{"displayName", "parentFolderId"}, optionalFields...)
|
fields := append([]string{"displayName", "parentFolderId"}, optionalFields...)
|
||||||
|
|
||||||
ofcf, err := optionsForContactChildFolders(fields)
|
ofcf, err := optionsForContactChildFolders(fields)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrapf(err, "options for contact child folders: %v", fields)
|
return nil, nil, nil, errors.Wrapf(err, "options for contact child folders: %v", fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := gs.Client().
|
builder := service.Client().
|
||||||
UsersById(userID).
|
UsersById(userID).
|
||||||
ContactFoldersById(baseDirID).
|
ContactFoldersById(baseDirID).
|
||||||
ChildFolders()
|
ChildFolders()
|
||||||
|
|
||||||
return builder, ofcf, nil
|
return builder, ofcf, service, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchContactIDsFromDirectory function that returns a list of all the m365IDs of the contacts
|
// FetchContactIDsFromDirectory function that returns a list of all the m365IDs of the contacts
|
||||||
// of the targeted directory
|
// of the targeted directory
|
||||||
func FetchContactIDsFromDirectory(
|
func (c Client) FetchContactIDsFromDirectory(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
|
||||||
user, directoryID, oldDelta string,
|
user, directoryID, oldDelta string,
|
||||||
) ([]string, []string, DeltaUpdate, error) {
|
) ([]string, []string, DeltaUpdate, error) {
|
||||||
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, DeltaUpdate{}, err
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errs *multierror.Error
|
errs *multierror.Error
|
||||||
ids []string
|
ids []string
|
||||||
@ -167,14 +200,14 @@ func FetchContactIDsFromDirectory(
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
builder = users.NewItemContactFoldersItemContactsDeltaRequestBuilder(*nextLink, gs.Adapter())
|
builder = users.NewItemContactFoldersItemContactsDeltaRequestBuilder(*nextLink, service.Adapter())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(oldDelta) > 0 {
|
if len(oldDelta) > 0 {
|
||||||
err := getIDs(users.NewItemContactFoldersItemContactsDeltaRequestBuilder(oldDelta, gs.Adapter()))
|
err := getIDs(users.NewItemContactFoldersItemContactsDeltaRequestBuilder(oldDelta, service.Adapter()))
|
||||||
// note: happy path, not the error condition
|
// note: happy path, not the error condition
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return ids, removedIDs, DeltaUpdate{deltaURL, false}, errs.ErrorOrNil()
|
return ids, removedIDs, DeltaUpdate{deltaURL, false}, errs.ErrorOrNil()
|
||||||
@ -189,7 +222,7 @@ func FetchContactIDsFromDirectory(
|
|||||||
errs = nil
|
errs = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := gs.Client().
|
builder := service.Client().
|
||||||
UsersById(user).
|
UsersById(user).
|
||||||
ContactFoldersById(directoryID).
|
ContactFoldersById(directoryID).
|
||||||
Contacts().
|
Contacts().
|
||||||
|
|||||||
@ -15,68 +15,103 @@ import (
|
|||||||
|
|
||||||
// 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 CreateCalendar(ctx context.Context, gs graph.Servicer, user, calendarName string) (models.Calendarable, error) {
|
func (c Client) CreateCalendar(
|
||||||
|
ctx context.Context,
|
||||||
|
user, calendarName string,
|
||||||
|
) (models.Calendarable, error) {
|
||||||
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
requestbody := models.NewCalendar()
|
requestbody := models.NewCalendar()
|
||||||
requestbody.SetName(&calendarName)
|
requestbody.SetName(&calendarName)
|
||||||
|
|
||||||
return gs.Client().UsersById(user).Calendars().Post(ctx, requestbody, nil)
|
return service.Client().UsersById(user).Calendars().Post(ctx, requestbody, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 DeleteCalendar(ctx context.Context, gs graph.Servicer, user, calendarID string) error {
|
func (c Client) DeleteCalendar(
|
||||||
return gs.Client().UsersById(user).CalendarsById(calendarID).Delete(ctx, nil)
|
ctx context.Context,
|
||||||
|
user, calendarID string,
|
||||||
|
) error {
|
||||||
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return service.Client().UsersById(user).CalendarsById(calendarID).Delete(ctx, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RetrieveEventDataForUser is a GraphRetrievalFunc that returns event data.
|
// RetrieveEventDataForUser is a GraphRetrievalFunc that returns event data.
|
||||||
// Calendarable and attachment fields are omitted due to size
|
// Calendarable and attachment fields are omitted due to size
|
||||||
func RetrieveEventDataForUser(
|
func (c Client) RetrieveEventDataForUser(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
|
||||||
user, m365ID string,
|
user, m365ID string,
|
||||||
) (serialization.Parsable, error) {
|
) (serialization.Parsable, error) {
|
||||||
return gs.Client().UsersById(user).EventsById(m365ID).Get(ctx, nil)
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return service.Client().UsersById(user).EventsById(m365ID).Get(ctx, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAllCalendarNamesForUser(ctx context.Context, gs graph.Servicer, user string) (serialization.Parsable, error) {
|
func (c Client) GetAllCalendarNamesForUser(
|
||||||
|
ctx context.Context,
|
||||||
|
user string,
|
||||||
|
) (serialization.Parsable, error) {
|
||||||
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
options, err := optionsForCalendars([]string{"name", "owner"})
|
options, err := optionsForCalendars([]string{"name", "owner"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return gs.Client().UsersById(user).Calendars().Get(ctx, options)
|
return service.Client().UsersById(user).Calendars().Get(ctx, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: we want this to be the full handler, not only the builder.
|
// TODO: we want this to be the full handler, not only the builder.
|
||||||
// but this halfway point minimizes changes for now.
|
// but this halfway point minimizes changes for now.
|
||||||
func GetCalendarsBuilder(
|
func (c Client) GetCalendarsBuilder(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
|
||||||
userID string,
|
userID string,
|
||||||
optionalFields ...string,
|
optionalFields ...string,
|
||||||
) (
|
) (
|
||||||
*users.ItemCalendarsRequestBuilder,
|
*users.ItemCalendarsRequestBuilder,
|
||||||
*users.ItemCalendarsRequestBuilderGetRequestConfiguration,
|
*users.ItemCalendarsRequestBuilderGetRequestConfiguration,
|
||||||
|
*graph.Service,
|
||||||
error,
|
error,
|
||||||
) {
|
) {
|
||||||
ofcf, err := optionsForCalendars(optionalFields)
|
service, err := c.service()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrapf(err, "options for event calendars: %v", optionalFields)
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := gs.Client().
|
ofcf, err := optionsForCalendars(optionalFields)
|
||||||
UsersById(userID).
|
if err != nil {
|
||||||
Calendars()
|
return nil, nil, nil, errors.Wrapf(err, "options for event calendars: %v", optionalFields)
|
||||||
|
}
|
||||||
|
|
||||||
return builder, ofcf, nil
|
builder := service.Client().UsersById(userID).Calendars()
|
||||||
|
|
||||||
|
return builder, ofcf, service, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchEventIDsFromCalendar returns a list of all M365IDs of events of the targeted Calendar.
|
// FetchEventIDsFromCalendar returns a list of all M365IDs of events of the targeted Calendar.
|
||||||
func FetchEventIDsFromCalendar(
|
func (c Client) FetchEventIDsFromCalendar(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
|
||||||
user, calendarID, oldDelta string,
|
user, calendarID, oldDelta string,
|
||||||
) ([]string, []string, DeltaUpdate, error) {
|
) ([]string, []string, DeltaUpdate, error) {
|
||||||
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, DeltaUpdate{}, err
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errs *multierror.Error
|
errs *multierror.Error
|
||||||
ids []string
|
ids []string
|
||||||
@ -87,10 +122,7 @@ func FetchEventIDsFromCalendar(
|
|||||||
return nil, nil, DeltaUpdate{}, err
|
return nil, nil, DeltaUpdate{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := gs.Client().
|
builder := service.Client().UsersById(user).CalendarsById(calendarID).Events()
|
||||||
UsersById(user).
|
|
||||||
CalendarsById(calendarID).
|
|
||||||
Events()
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
resp, err := builder.Get(ctx, options)
|
resp, err := builder.Get(ctx, options)
|
||||||
@ -121,7 +153,7 @@ func FetchEventIDsFromCalendar(
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
builder = users.NewItemCalendarsItemEventsRequestBuilder(*nextLink, gs.Adapter())
|
builder = users.NewItemCalendarsItemEventsRequestBuilder(*nextLink, service.Adapter())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Events don't have a delta endpoint so just return an empty string.
|
// Events don't have a delta endpoint so just return an empty string.
|
||||||
|
|||||||
@ -15,26 +15,39 @@ import (
|
|||||||
|
|
||||||
// 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 CreateMailFolder(ctx context.Context, gs graph.Servicer, user, folder string) (models.MailFolderable, error) {
|
func (c Client) CreateMailFolder(
|
||||||
|
ctx context.Context,
|
||||||
|
user, folder string,
|
||||||
|
) (models.MailFolderable, error) {
|
||||||
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
isHidden := false
|
isHidden := false
|
||||||
requestBody := models.NewMailFolder()
|
requestBody := models.NewMailFolder()
|
||||||
requestBody.SetDisplayName(&folder)
|
requestBody.SetDisplayName(&folder)
|
||||||
requestBody.SetIsHidden(&isHidden)
|
requestBody.SetIsHidden(&isHidden)
|
||||||
|
|
||||||
return gs.Client().UsersById(user).MailFolders().Post(ctx, requestBody, nil)
|
return service.Client().UsersById(user).MailFolders().Post(ctx, requestBody, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateMailFolderWithParent(
|
func (c Client) CreateMailFolderWithParent(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
|
||||||
user, folder, parentID string,
|
user, folder, parentID string,
|
||||||
) (models.MailFolderable, error) {
|
) (models.MailFolderable, error) {
|
||||||
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
isHidden := false
|
isHidden := false
|
||||||
requestBody := models.NewMailFolder()
|
requestBody := models.NewMailFolder()
|
||||||
requestBody.SetDisplayName(&folder)
|
requestBody.SetDisplayName(&folder)
|
||||||
requestBody.SetIsHidden(&isHidden)
|
requestBody.SetIsHidden(&isHidden)
|
||||||
|
|
||||||
return gs.Client().
|
return service.
|
||||||
|
Client().
|
||||||
UsersById(user).
|
UsersById(user).
|
||||||
MailFoldersById(parentID).
|
MailFoldersById(parentID).
|
||||||
ChildFolders().
|
ChildFolders().
|
||||||
@ -43,18 +56,30 @@ func 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 DeleteMailFolder(ctx context.Context, gs graph.Servicer, user, folderID string) error {
|
func (c Client) DeleteMailFolder(
|
||||||
return gs.Client().UsersById(user).MailFoldersById(folderID).Delete(ctx, nil)
|
ctx context.Context,
|
||||||
|
user, folderID string,
|
||||||
|
) error {
|
||||||
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return service.Client().UsersById(user).MailFoldersById(folderID).Delete(ctx, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RetrieveMessageDataForUser is a GraphRetrievalFunc that returns message data.
|
// RetrieveMessageDataForUser is a GraphRetrievalFunc that returns message data.
|
||||||
// Attachment field is omitted due to size.
|
// Attachment field is omitted due to size.
|
||||||
func RetrieveMessageDataForUser(
|
func (c Client) RetrieveMessageDataForUser(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
|
||||||
user, m365ID string,
|
user, m365ID string,
|
||||||
) (serialization.Parsable, error) {
|
) (serialization.Parsable, error) {
|
||||||
return gs.Client().UsersById(user).MessagesById(m365ID).Get(ctx, nil)
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return service.Client().UsersById(user).MessagesById(m365ID).Get(ctx, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMailFoldersBuilder retrieves all of the users current mail folders.
|
// GetMailFoldersBuilder retrieves all of the users current mail folders.
|
||||||
@ -62,41 +87,56 @@ func RetrieveMessageDataForUser(
|
|||||||
// not contain historical data.
|
// not contain historical data.
|
||||||
// TODO: we want this to be the full handler, not only the builder.
|
// TODO: we want this to be the full handler, not only the builder.
|
||||||
// but this halfway point minimizes changes for now.
|
// but this halfway point minimizes changes for now.
|
||||||
func GetAllMailFoldersBuilder(
|
func (c Client) GetAllMailFoldersBuilder(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
|
||||||
userID string,
|
userID string,
|
||||||
) *users.ItemMailFoldersDeltaRequestBuilder {
|
) (
|
||||||
return gs.Client().
|
*users.ItemMailFoldersDeltaRequestBuilder,
|
||||||
|
*graph.Service,
|
||||||
|
error,
|
||||||
|
) {
|
||||||
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
builder := service.Client().
|
||||||
UsersById(userID).
|
UsersById(userID).
|
||||||
MailFolders().
|
MailFolders().
|
||||||
Delta()
|
Delta()
|
||||||
|
|
||||||
|
return builder, service, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMailFolderByID(
|
func (c Client) GetMailFolderByID(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
|
||||||
userID, dirID string,
|
userID, dirID string,
|
||||||
optionalFields ...string,
|
optionalFields ...string,
|
||||||
) (models.MailFolderable, error) {
|
) (models.MailFolderable, error) {
|
||||||
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
ofmf, err := optionsForMailFoldersItem(optionalFields)
|
ofmf, err := optionsForMailFoldersItem(optionalFields)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "options for mail folder: %v", optionalFields)
|
return nil, errors.Wrapf(err, "options for mail folder: %v", optionalFields)
|
||||||
}
|
}
|
||||||
|
|
||||||
return gs.Client().
|
return service.Client().UsersById(userID).MailFoldersById(dirID).Get(ctx, ofmf)
|
||||||
UsersById(userID).
|
|
||||||
MailFoldersById(dirID).
|
|
||||||
Get(ctx, ofmf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchMessageIDsFromDirectory function that returns a list of all the m365IDs of the exchange.Mail
|
// FetchMessageIDsFromDirectory function that returns a list of all the m365IDs of the exchange.Mail
|
||||||
// of the targeted directory
|
// of the targeted directory
|
||||||
func FetchMessageIDsFromDirectory(
|
func (c Client) FetchMessageIDsFromDirectory(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
|
||||||
user, directoryID, oldDelta string,
|
user, directoryID, oldDelta string,
|
||||||
) ([]string, []string, DeltaUpdate, error) {
|
) ([]string, []string, DeltaUpdate, error) {
|
||||||
|
service, err := c.service()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, DeltaUpdate{}, err
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errs *multierror.Error
|
errs *multierror.Error
|
||||||
ids []string
|
ids []string
|
||||||
@ -153,14 +193,14 @@ func FetchMessageIDsFromDirectory(
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
builder = users.NewItemMailFoldersItemMessagesDeltaRequestBuilder(*nextLink, gs.Adapter())
|
builder = users.NewItemMailFoldersItemMessagesDeltaRequestBuilder(*nextLink, service.Adapter())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(oldDelta) > 0 {
|
if len(oldDelta) > 0 {
|
||||||
err := getIDs(users.NewItemMailFoldersItemMessagesDeltaRequestBuilder(oldDelta, gs.Adapter()))
|
err := getIDs(users.NewItemMailFoldersItemMessagesDeltaRequestBuilder(oldDelta, service.Adapter()))
|
||||||
// note: happy path, not the error condition
|
// note: happy path, not the error condition
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return ids, removedIDs, DeltaUpdate{deltaURL, false}, errs.ErrorOrNil()
|
return ids, removedIDs, DeltaUpdate{deltaURL, false}, errs.ErrorOrNil()
|
||||||
@ -175,11 +215,7 @@ func FetchMessageIDsFromDirectory(
|
|||||||
errs = nil
|
errs = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := gs.Client().
|
builder := service.Client().UsersById(user).MailFoldersById(directoryID).Messages().Delta()
|
||||||
UsersById(user).
|
|
||||||
MailFoldersById(directoryID).
|
|
||||||
Messages().
|
|
||||||
Delta()
|
|
||||||
|
|
||||||
if err := getIDs(builder); err != nil {
|
if err := getIDs(builder); err != nil {
|
||||||
return nil, nil, DeltaUpdate{}, err
|
return nil, nil, DeltaUpdate{}, err
|
||||||
|
|||||||
@ -16,7 +16,8 @@ var _ graph.ContainerResolver = &contactFolderCache{}
|
|||||||
|
|
||||||
type contactFolderCache struct {
|
type contactFolderCache struct {
|
||||||
*containerResolver
|
*containerResolver
|
||||||
gs graph.Servicer
|
ac api.Client
|
||||||
|
// gs graph.Servicer
|
||||||
userID string
|
userID string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ func (cfc *contactFolderCache) populateContactRoot(
|
|||||||
directoryID string,
|
directoryID string,
|
||||||
baseContainerPath []string,
|
baseContainerPath []string,
|
||||||
) error {
|
) error {
|
||||||
f, err := api.GetContactFolderByID(ctx, cfc.gs, cfc.userID, directoryID)
|
f, err := cfc.ac.GetContactFolderByID(ctx, cfc.userID, directoryID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(
|
return errors.Wrapf(
|
||||||
err,
|
err,
|
||||||
@ -56,9 +57,8 @@ func (cfc *contactFolderCache) Populate(
|
|||||||
|
|
||||||
var errs error
|
var errs error
|
||||||
|
|
||||||
builder, options, err := api.GetContactChildFoldersBuilder(
|
builder, options, servicer, err := cfc.ac.GetContactChildFoldersBuilder(
|
||||||
ctx,
|
ctx,
|
||||||
cfc.gs,
|
|
||||||
cfc.userID,
|
cfc.userID,
|
||||||
baseID)
|
baseID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -97,7 +97,7 @@ func (cfc *contactFolderCache) Populate(
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
builder = msuser.NewItemContactFoldersItemChildFoldersRequestBuilder(*resp.GetOdataNextLink(), cfc.gs.Adapter())
|
builder = msuser.NewItemContactFoldersItemChildFoldersRequestBuilder(*resp.GetOdataNextLink(), servicer.Adapter())
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cfc.populatePaths(ctx); err != nil {
|
if err := cfc.populatePaths(ctx); err != nil {
|
||||||
|
|||||||
@ -494,9 +494,6 @@ func (suite *FolderCacheIntegrationSuite) TestCreateContainerDestination() {
|
|||||||
m365, err := a.M365Config()
|
m365, err := a.M365Config()
|
||||||
require.NoError(suite.T(), err)
|
require.NoError(suite.T(), err)
|
||||||
|
|
||||||
connector, err := createService(m365)
|
|
||||||
require.NoError(suite.T(), err)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
user = tester.M365UserID(suite.T())
|
user = tester.M365UserID(suite.T())
|
||||||
directoryCaches = make(map[path.CategoryType]graph.ContainerResolver)
|
directoryCaches = make(map[path.CategoryType]graph.ContainerResolver)
|
||||||
@ -596,11 +593,10 @@ func (suite *FolderCacheIntegrationSuite) TestCreateContainerDestination() {
|
|||||||
suite.T().Run(test.name, func(t *testing.T) {
|
suite.T().Run(test.name, func(t *testing.T) {
|
||||||
folderID, err := CreateContainerDestinaion(
|
folderID, err := CreateContainerDestinaion(
|
||||||
ctx,
|
ctx,
|
||||||
connector,
|
m365,
|
||||||
test.pathFunc1(t),
|
test.pathFunc1(t),
|
||||||
folderName,
|
folderName,
|
||||||
directoryCaches,
|
directoryCaches)
|
||||||
)
|
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resolver := directoryCaches[test.category]
|
resolver := directoryCaches[test.category]
|
||||||
@ -609,11 +605,10 @@ func (suite *FolderCacheIntegrationSuite) TestCreateContainerDestination() {
|
|||||||
|
|
||||||
secondID, err := CreateContainerDestinaion(
|
secondID, err := CreateContainerDestinaion(
|
||||||
ctx,
|
ctx,
|
||||||
connector,
|
m365,
|
||||||
test.pathFunc2(t),
|
test.pathFunc2(t),
|
||||||
folderName,
|
folderName,
|
||||||
directoryCaches,
|
directoryCaches)
|
||||||
)
|
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, err = resolver.IDToPath(ctx, secondID)
|
_, err = resolver.IDToPath(ctx, secondID)
|
||||||
|
|||||||
@ -16,7 +16,8 @@ var _ graph.ContainerResolver = &eventCalendarCache{}
|
|||||||
|
|
||||||
type eventCalendarCache struct {
|
type eventCalendarCache struct {
|
||||||
*containerResolver
|
*containerResolver
|
||||||
gs graph.Servicer
|
// gs graph.Servicer
|
||||||
|
ac api.Client
|
||||||
userID string
|
userID string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ func (ecc *eventCalendarCache) Populate(
|
|||||||
ecc.containerResolver = newContainerResolver()
|
ecc.containerResolver = newContainerResolver()
|
||||||
}
|
}
|
||||||
|
|
||||||
builder, options, err := api.GetCalendarsBuilder(ctx, ecc.gs, ecc.userID, "name")
|
builder, options, servicer, err := ecc.ac.GetCalendarsBuilder(ctx, ecc.userID, "name")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -67,7 +68,7 @@ func (ecc *eventCalendarCache) Populate(
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
builder = msuser.NewItemCalendarsRequestBuilder(*resp.GetOdataNextLink(), ecc.gs.Adapter())
|
builder = msuser.NewItemCalendarsRequestBuilder(*resp.GetOdataNextLink(), servicer.Adapter())
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, container := range directories {
|
for _, container := range directories {
|
||||||
|
|||||||
@ -59,6 +59,7 @@ type Collection struct {
|
|||||||
|
|
||||||
// service - client/adapter pair used to access M365 back store
|
// service - client/adapter pair used to access M365 back store
|
||||||
service graph.Servicer
|
service graph.Servicer
|
||||||
|
ac api.Client
|
||||||
|
|
||||||
category path.CategoryType
|
category path.CategoryType
|
||||||
statusUpdater support.StatusUpdater
|
statusUpdater support.StatusUpdater
|
||||||
@ -88,12 +89,14 @@ func NewCollection(
|
|||||||
user string,
|
user string,
|
||||||
curr, prev path.Path,
|
curr, prev path.Path,
|
||||||
category path.CategoryType,
|
category path.CategoryType,
|
||||||
|
ac api.Client,
|
||||||
service graph.Servicer,
|
service graph.Servicer,
|
||||||
statusUpdater support.StatusUpdater,
|
statusUpdater support.StatusUpdater,
|
||||||
ctrlOpts control.Options,
|
ctrlOpts control.Options,
|
||||||
doNotMergeItems bool,
|
doNotMergeItems bool,
|
||||||
) Collection {
|
) Collection {
|
||||||
collection := Collection{
|
collection := Collection{
|
||||||
|
ac: ac,
|
||||||
category: category,
|
category: category,
|
||||||
ctrl: ctrlOpts,
|
ctrl: ctrlOpts,
|
||||||
data: make(chan data.Stream, collectionChannelBufferSize),
|
data: make(chan data.Stream, collectionChannelBufferSize),
|
||||||
@ -136,14 +139,14 @@ func (col *Collection) Items() <-chan data.Stream {
|
|||||||
|
|
||||||
// GetQueryAndSerializeFunc helper function that returns the two functions functions
|
// GetQueryAndSerializeFunc helper function that returns the two functions functions
|
||||||
// required to convert M365 identifier into a byte array filled with the serialized data
|
// required to convert M365 identifier into a byte array filled with the serialized data
|
||||||
func GetQueryAndSerializeFunc(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 api.RetrieveContactDataForUser, serializeAndStreamContact
|
return ac.RetrieveContactDataForUser, serializeAndStreamContact
|
||||||
case path.EventsCategory:
|
case path.EventsCategory:
|
||||||
return api.RetrieveEventDataForUser, serializeAndStreamEvent
|
return ac.RetrieveEventDataForUser, serializeAndStreamEvent
|
||||||
case path.EmailCategory:
|
case path.EmailCategory:
|
||||||
return api.RetrieveMessageDataForUser, serializeAndStreamMessage
|
return ac.RetrieveMessageDataForUser, serializeAndStreamMessage
|
||||||
// Unsupported options returns nil, nil
|
// Unsupported options returns nil, nil
|
||||||
default:
|
default:
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -204,7 +207,7 @@ func (col *Collection) streamItems(ctx context.Context) {
|
|||||||
// get QueryBasedonIdentifier
|
// get QueryBasedonIdentifier
|
||||||
// verify that it is the correct type in called function
|
// verify that it is the correct type in called function
|
||||||
// serializationFunction
|
// serializationFunction
|
||||||
query, serializeFunc := GetQueryAndSerializeFunc(col.category)
|
query, serializeFunc := GetQueryAndSerializeFunc(col.ac, col.category)
|
||||||
if query == nil {
|
if query == nil {
|
||||||
errs = fmt.Errorf("unrecognized collection type: %s", col.category)
|
errs = fmt.Errorf("unrecognized collection type: %s", col.category)
|
||||||
return
|
return
|
||||||
@ -263,7 +266,7 @@ func (col *Collection) streamItems(ctx context.Context) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
for i := 1; i <= numberOfRetries; i++ {
|
for i := 1; i <= numberOfRetries; i++ {
|
||||||
response, err = query(ctx, col.service, user, id)
|
response, err = query(ctx, user, id)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
"github.com/alcionai/corso/src/internal/connector/exchange/api"
|
||||||
"github.com/alcionai/corso/src/internal/data"
|
"github.com/alcionai/corso/src/internal/data"
|
||||||
"github.com/alcionai/corso/src/pkg/control"
|
"github.com/alcionai/corso/src/pkg/control"
|
||||||
"github.com/alcionai/corso/src/pkg/path"
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
@ -136,7 +137,7 @@ func (suite *ExchangeDataCollectionSuite) TestNewCollection_state() {
|
|||||||
c := NewCollection(
|
c := NewCollection(
|
||||||
"u",
|
"u",
|
||||||
test.curr, test.prev,
|
test.curr, test.prev,
|
||||||
0, nil, nil, control.Options{},
|
0, api.Client{}, nil, nil, control.Options{},
|
||||||
false)
|
false)
|
||||||
assert.Equal(t, test.expect, c.State())
|
assert.Equal(t, test.expect, c.State())
|
||||||
})
|
})
|
||||||
|
|||||||
@ -7,13 +7,15 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
"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/tester"
|
"github.com/alcionai/corso/src/internal/tester"
|
||||||
|
"github.com/alcionai/corso/src/pkg/account"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CacheResolverSuite struct {
|
type CacheResolverSuite struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
gs graph.Servicer
|
credentials account.M365Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCacheResolverIntegrationSuite(t *testing.T) {
|
func TestCacheResolverIntegrationSuite(t *testing.T) {
|
||||||
@ -35,10 +37,7 @@ func (suite *CacheResolverSuite) SetupSuite() {
|
|||||||
m365, err := a.M365Config()
|
m365, err := a.M365Config()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
service, err := createService(m365)
|
suite.credentials = m365
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
suite.gs = service
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *CacheResolverSuite) TestPopulate() {
|
func (suite *CacheResolverSuite) TestPopulate() {
|
||||||
@ -48,14 +47,14 @@ 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),
|
||||||
gs: suite.gs,
|
ac: api.Client{Credentials: suite.credentials},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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),
|
||||||
gs: suite.gs,
|
ac: api.Client{Credentials: suite.credentials},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/alcionai/corso/src/internal/connector/mockconnector"
|
"github.com/alcionai/corso/src/internal/connector/mockconnector"
|
||||||
"github.com/alcionai/corso/src/internal/connector/support"
|
"github.com/alcionai/corso/src/internal/connector/support"
|
||||||
"github.com/alcionai/corso/src/internal/tester"
|
"github.com/alcionai/corso/src/internal/tester"
|
||||||
|
"github.com/alcionai/corso/src/pkg/account"
|
||||||
"github.com/alcionai/corso/src/pkg/selectors"
|
"github.com/alcionai/corso/src/pkg/selectors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -84,7 +85,7 @@ func (suite *ExchangeIteratorSuite) TestCollectionFunctions() {
|
|||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
queryFunc api.GraphQuery
|
queryFunc func(account.M365Config) api.GraphQuery
|
||||||
scope selectors.ExchangeScope
|
scope selectors.ExchangeScope
|
||||||
iterativeFunction func(
|
iterativeFunction func(
|
||||||
container map[string]graph.Container,
|
container map[string]graph.Container,
|
||||||
@ -94,13 +95,17 @@ func (suite *ExchangeIteratorSuite) TestCollectionFunctions() {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Contacts Iterative Check",
|
name: "Contacts Iterative Check",
|
||||||
queryFunc: api.GetAllContactFolderNamesForUser,
|
queryFunc: func(amc account.M365Config) api.GraphQuery {
|
||||||
|
return api.Client{Credentials: amc}.GetAllContactFolderNamesForUser
|
||||||
|
},
|
||||||
transformer: models.CreateContactFolderCollectionResponseFromDiscriminatorValue,
|
transformer: models.CreateContactFolderCollectionResponseFromDiscriminatorValue,
|
||||||
iterativeFunction: IterativeCollectContactContainers,
|
iterativeFunction: IterativeCollectContactContainers,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Events Iterative Check",
|
name: "Events Iterative Check",
|
||||||
queryFunc: api.GetAllCalendarNamesForUser,
|
queryFunc: func(amc account.M365Config) api.GraphQuery {
|
||||||
|
return api.Client{Credentials: amc}.GetAllCalendarNamesForUser
|
||||||
|
},
|
||||||
transformer: models.CreateCalendarCollectionResponseFromDiscriminatorValue,
|
transformer: models.CreateCalendarCollectionResponseFromDiscriminatorValue,
|
||||||
iterativeFunction: IterativeCollectCalendarContainers,
|
iterativeFunction: IterativeCollectCalendarContainers,
|
||||||
},
|
},
|
||||||
@ -114,7 +119,7 @@ func (suite *ExchangeIteratorSuite) TestCollectionFunctions() {
|
|||||||
service, err := createService(m365)
|
service, err := createService(m365)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
response, err := test.queryFunc(ctx, service, userID)
|
response, err := test.queryFunc(m365)(ctx, userID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Iterator Creation
|
// Iterator Creation
|
||||||
|
|||||||
@ -20,7 +20,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
|
||||||
gs graph.Servicer
|
// gs graph.Servicer
|
||||||
|
ac api.Client
|
||||||
userID string
|
userID string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +36,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 := api.GetMailFolderByID(ctx, mc.gs, mc.userID, fldr, "displayName", "parentFolderId")
|
f, err := mc.ac.GetMailFolderByID(ctx, mc.userID, fldr, "displayName", "parentFolderId")
|
||||||
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))
|
||||||
}
|
}
|
||||||
@ -67,7 +68,10 @@ func (mc *mailFolderCache) Populate(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
query := api.GetAllMailFoldersBuilder(ctx, mc.gs, mc.userID)
|
query, servicer, err := mc.ac.GetAllMailFoldersBuilder(ctx, mc.userID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
var errs *multierror.Error
|
var errs *multierror.Error
|
||||||
|
|
||||||
@ -94,7 +98,7 @@ func (mc *mailFolderCache) Populate(
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
query = msfolderdelta.NewItemMailFoldersDeltaRequestBuilder(*link, mc.gs.Adapter())
|
query = msfolderdelta.NewItemMailFoldersDeltaRequestBuilder(*link, servicer.Adapter())
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := mc.populatePaths(ctx); err != nil {
|
if err := mc.populatePaths(ctx); err != nil {
|
||||||
|
|||||||
@ -8,8 +8,9 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
"github.com/alcionai/corso/src/internal/connector/graph"
|
"github.com/alcionai/corso/src/internal/connector/exchange/api"
|
||||||
"github.com/alcionai/corso/src/internal/tester"
|
"github.com/alcionai/corso/src/internal/tester"
|
||||||
|
"github.com/alcionai/corso/src/pkg/account"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -26,7 +27,7 @@ const (
|
|||||||
|
|
||||||
type MailFolderCacheIntegrationSuite struct {
|
type MailFolderCacheIntegrationSuite struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
gs graph.Servicer
|
credentials account.M365Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMailFolderCacheIntegrationSuite(t *testing.T) {
|
func TestMailFolderCacheIntegrationSuite(t *testing.T) {
|
||||||
@ -48,10 +49,7 @@ func (suite *MailFolderCacheIntegrationSuite) SetupSuite() {
|
|||||||
m365, err := a.M365Config()
|
m365, err := a.M365Config()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
service, err := createService(m365)
|
suite.credentials = m365
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
suite.gs = service
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *MailFolderCacheIntegrationSuite) TestDeltaFetch() {
|
func (suite *MailFolderCacheIntegrationSuite) TestDeltaFetch() {
|
||||||
@ -85,7 +83,7 @@ func (suite *MailFolderCacheIntegrationSuite) TestDeltaFetch() {
|
|||||||
suite.T().Run(test.name, func(t *testing.T) {
|
suite.T().Run(test.name, func(t *testing.T) {
|
||||||
mfc := mailFolderCache{
|
mfc := mailFolderCache{
|
||||||
userID: userID,
|
userID: userID,
|
||||||
gs: suite.gs,
|
ac: api.Client{Credentials: suite.credentials},
|
||||||
}
|
}
|
||||||
|
|
||||||
require.NoError(t, mfc.Populate(ctx, test.root, test.path...))
|
require.NoError(t, mfc.Populate(ctx, test.root, test.path...))
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/alcionai/corso/src/internal/connector/mockconnector"
|
"github.com/alcionai/corso/src/internal/connector/mockconnector"
|
||||||
"github.com/alcionai/corso/src/internal/connector/support"
|
"github.com/alcionai/corso/src/internal/connector/support"
|
||||||
"github.com/alcionai/corso/src/internal/tester"
|
"github.com/alcionai/corso/src/internal/tester"
|
||||||
|
"github.com/alcionai/corso/src/pkg/account"
|
||||||
"github.com/alcionai/corso/src/pkg/control"
|
"github.com/alcionai/corso/src/pkg/control"
|
||||||
"github.com/alcionai/corso/src/pkg/path"
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
)
|
)
|
||||||
@ -22,6 +23,8 @@ import (
|
|||||||
type ExchangeRestoreSuite struct {
|
type ExchangeRestoreSuite struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
gs graph.Servicer
|
gs graph.Servicer
|
||||||
|
credentials account.M365Config
|
||||||
|
ac api.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExchangeRestoreSuite(t *testing.T) {
|
func TestExchangeRestoreSuite(t *testing.T) {
|
||||||
@ -41,13 +44,16 @@ func (suite *ExchangeRestoreSuite) SetupSuite() {
|
|||||||
m365, err := a.M365Config()
|
m365, err := a.M365Config()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
adpt, err := graph.CreateAdapter(
|
suite.credentials = m365
|
||||||
m365.AzureTenantID,
|
suite.ac = api.Client{Credentials: m365}
|
||||||
m365.AzureClientID,
|
|
||||||
m365.AzureClientSecret)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
suite.gs = graph.NewService(adpt)
|
// adpt, err := graph.CreateAdapter(
|
||||||
|
// m365.AzureTenantID,
|
||||||
|
// m365.AzureClientID,
|
||||||
|
// m365.AzureClientSecret)
|
||||||
|
// require.NoError(t, err)
|
||||||
|
|
||||||
|
// suite.gs = graph.NewService(adpt)
|
||||||
|
|
||||||
require.NoError(suite.T(), err)
|
require.NoError(suite.T(), err)
|
||||||
}
|
}
|
||||||
@ -65,14 +71,14 @@ func (suite *ExchangeRestoreSuite) TestRestoreContact() {
|
|||||||
folderName = "TestRestoreContact: " + common.FormatSimpleDateTime(now)
|
folderName = "TestRestoreContact: " + common.FormatSimpleDateTime(now)
|
||||||
)
|
)
|
||||||
|
|
||||||
aFolder, err := api.CreateContactFolder(ctx, suite.gs, userID, folderName)
|
aFolder, err := suite.ac.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 = api.DeleteContactFolder(ctx, suite.gs, userID, folderID)
|
err = suite.ac.DeleteContactFolder(ctx, userID, folderID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -98,14 +104,14 @@ func (suite *ExchangeRestoreSuite) TestRestoreEvent() {
|
|||||||
name = "TestRestoreEvent: " + common.FormatSimpleDateTime(time.Now())
|
name = "TestRestoreEvent: " + common.FormatSimpleDateTime(time.Now())
|
||||||
)
|
)
|
||||||
|
|
||||||
calendar, err := api.CreateCalendar(ctx, suite.gs, userID, name)
|
calendar, err := suite.ac.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 = api.DeleteCalendar(ctx, suite.gs, userID, calendarID)
|
err = suite.ac.DeleteCalendar(ctx, userID, calendarID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -134,17 +140,17 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() {
|
|||||||
name string
|
name string
|
||||||
bytes []byte
|
bytes []byte
|
||||||
category path.CategoryType
|
category path.CategoryType
|
||||||
cleanupFunc func(context.Context, graph.Servicer, string, string) error
|
cleanupFunc func(context.Context, string, string) error
|
||||||
destination func(*testing.T, context.Context) string
|
destination func(*testing.T, context.Context) string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
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: api.DeleteMailFolder,
|
cleanupFunc: suite.ac.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 := api.CreateMailFolder(ctx, suite.gs, userID, folderName)
|
folder, err := suite.ac.CreateMailFolder(ctx, userID, folderName)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return *folder.GetId()
|
return *folder.GetId()
|
||||||
@ -154,10 +160,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: api.DeleteMailFolder,
|
cleanupFunc: suite.ac.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 := api.CreateMailFolder(ctx, suite.gs, userID, folderName)
|
folder, err := suite.ac.CreateMailFolder(ctx, userID, folderName)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return *folder.GetId()
|
return *folder.GetId()
|
||||||
@ -167,10 +173,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: api.DeleteMailFolder,
|
cleanupFunc: suite.ac.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 := api.CreateMailFolder(ctx, suite.gs, userID, folderName)
|
folder, err := suite.ac.CreateMailFolder(ctx, userID, folderName)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return *folder.GetId()
|
return *folder.GetId()
|
||||||
@ -180,10 +186,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: api.DeleteMailFolder,
|
cleanupFunc: suite.ac.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 := api.CreateMailFolder(ctx, suite.gs, userID, folderName)
|
folder, err := suite.ac.CreateMailFolder(ctx, userID, folderName)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return *folder.GetId()
|
return *folder.GetId()
|
||||||
@ -193,10 +199,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: api.DeleteMailFolder,
|
cleanupFunc: suite.ac.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 := api.CreateMailFolder(ctx, suite.gs, userID, folderName)
|
folder, err := suite.ac.CreateMailFolder(ctx, userID, folderName)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return *folder.GetId()
|
return *folder.GetId()
|
||||||
@ -207,10 +213,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: api.DeleteContactFolder,
|
cleanupFunc: suite.ac.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 := api.CreateContactFolder(ctx, suite.gs, userID, folderName)
|
folder, err := suite.ac.CreateContactFolder(ctx, userID, folderName)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return *folder.GetId()
|
return *folder.GetId()
|
||||||
@ -220,10 +226,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: api.DeleteCalendar,
|
cleanupFunc: suite.ac.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 := api.CreateCalendar(ctx, suite.gs, userID, calendarName)
|
calendar, err := suite.ac.CreateCalendar(ctx, userID, calendarName)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return *calendar.GetId()
|
return *calendar.GetId()
|
||||||
@ -233,10 +239,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: api.DeleteCalendar,
|
cleanupFunc: suite.ac.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 := api.CreateCalendar(ctx, suite.gs, userID, calendarName)
|
calendar, err := suite.ac.CreateCalendar(ctx, userID, calendarName)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return *calendar.GetId()
|
return *calendar.GetId()
|
||||||
@ -262,7 +268,7 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() {
|
|||||||
assert.NoError(t, err, support.ConnectorStackErrorTrace(err))
|
assert.NoError(t, err, support.ConnectorStackErrorTrace(err))
|
||||||
assert.NotNil(t, info, "item info is populated")
|
assert.NotNil(t, info, "item info is populated")
|
||||||
|
|
||||||
cleanupError := test.cleanupFunc(ctx, service, userID, destination)
|
cleanupError := test.cleanupFunc(ctx, userID, destination)
|
||||||
assert.NoError(t, cleanupError)
|
assert.NoError(t, cleanupError)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ 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/account"
|
"github.com/alcionai/corso/src/pkg/account"
|
||||||
"github.com/alcionai/corso/src/pkg/path"
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
@ -38,32 +39,27 @@ func PopulateExchangeContainerResolver(
|
|||||||
var (
|
var (
|
||||||
res graph.ContainerResolver
|
res graph.ContainerResolver
|
||||||
cacheRoot string
|
cacheRoot string
|
||||||
service, err = createService(qp.Credentials)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch qp.Category {
|
switch qp.Category {
|
||||||
case path.EmailCategory:
|
case path.EmailCategory:
|
||||||
res = &mailFolderCache{
|
res = &mailFolderCache{
|
||||||
userID: qp.ResourceOwner,
|
userID: qp.ResourceOwner,
|
||||||
gs: service,
|
ac: api.Client{Credentials: qp.Credentials},
|
||||||
}
|
}
|
||||||
cacheRoot = rootFolderAlias
|
cacheRoot = rootFolderAlias
|
||||||
|
|
||||||
case path.ContactsCategory:
|
case path.ContactsCategory:
|
||||||
res = &contactFolderCache{
|
res = &contactFolderCache{
|
||||||
userID: qp.ResourceOwner,
|
userID: qp.ResourceOwner,
|
||||||
gs: service,
|
ac: api.Client{Credentials: qp.Credentials},
|
||||||
}
|
}
|
||||||
cacheRoot = DefaultContactFolder
|
cacheRoot = DefaultContactFolder
|
||||||
|
|
||||||
case path.EventsCategory:
|
case path.EventsCategory:
|
||||||
res = &eventCalendarCache{
|
res = &eventCalendarCache{
|
||||||
userID: qp.ResourceOwner,
|
userID: qp.ResourceOwner,
|
||||||
gs: service,
|
ac: api.Client{Credentials: qp.Credentials},
|
||||||
}
|
}
|
||||||
cacheRoot = DefaultCalendar
|
cacheRoot = DefaultCalendar
|
||||||
|
|
||||||
|
|||||||
@ -35,6 +35,7 @@ func filterContainersAndFillCollections(
|
|||||||
) error {
|
) error {
|
||||||
var (
|
var (
|
||||||
errs error
|
errs error
|
||||||
|
ac = api.Client{Credentials: qp.Credentials}
|
||||||
// folder ID -> delta url or folder path lookups
|
// folder ID -> delta url or folder path lookups
|
||||||
deltaURLs = map[string]string{}
|
deltaURLs = map[string]string{}
|
||||||
currPaths = map[string]string{}
|
currPaths = map[string]string{}
|
||||||
@ -43,7 +44,7 @@ func filterContainersAndFillCollections(
|
|||||||
tombstones = makeTombstones(dps)
|
tombstones = makeTombstones(dps)
|
||||||
)
|
)
|
||||||
|
|
||||||
getJobs, err := getFetchIDFunc(qp.Category)
|
getJobs, err := getFetchIDFunc(ac, qp.Category)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return support.WrapAndAppend(qp.ResourceOwner, err, errs)
|
return support.WrapAndAppend(qp.ResourceOwner, err, errs)
|
||||||
}
|
}
|
||||||
@ -85,7 +86,7 @@ func filterContainersAndFillCollections(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
added, removed, newDelta, err := getJobs(ctx, service, qp.ResourceOwner, cID, prevDelta)
|
added, removed, newDelta, err := getJobs(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)
|
||||||
@ -110,11 +111,11 @@ func filterContainersAndFillCollections(
|
|||||||
currPath,
|
currPath,
|
||||||
prevPath,
|
prevPath,
|
||||||
scope.Category().PathType(),
|
scope.Category().PathType(),
|
||||||
|
ac,
|
||||||
service,
|
service,
|
||||||
statusUpdater,
|
statusUpdater,
|
||||||
ctrlOpts,
|
ctrlOpts,
|
||||||
newDelta.Reset,
|
newDelta.Reset)
|
||||||
)
|
|
||||||
|
|
||||||
collections[cID] = &edc
|
collections[cID] = &edc
|
||||||
edc.added = append(edc.added, added...)
|
edc.added = append(edc.added, added...)
|
||||||
@ -160,11 +161,11 @@ func filterContainersAndFillCollections(
|
|||||||
nil, // marks the collection as deleted
|
nil, // marks the collection as deleted
|
||||||
prevPath,
|
prevPath,
|
||||||
scope.Category().PathType(),
|
scope.Category().PathType(),
|
||||||
|
ac,
|
||||||
service,
|
service,
|
||||||
statusUpdater,
|
statusUpdater,
|
||||||
ctrlOpts,
|
ctrlOpts,
|
||||||
false,
|
false)
|
||||||
)
|
|
||||||
collections[id] = &edc
|
collections[id] = &edc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,18 +268,17 @@ func IterativeCollectCalendarContainers(
|
|||||||
// container supports fetching delta records.
|
// container supports fetching delta records.
|
||||||
type FetchIDFunc func(
|
type FetchIDFunc func(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
|
||||||
user, containerID, oldDeltaToken string,
|
user, containerID, oldDeltaToken string,
|
||||||
) ([]string, []string, api.DeltaUpdate, error)
|
) ([]string, []string, api.DeltaUpdate, error)
|
||||||
|
|
||||||
func getFetchIDFunc(category path.CategoryType) (FetchIDFunc, error) {
|
func getFetchIDFunc(ac api.Client, category path.CategoryType) (FetchIDFunc, error) {
|
||||||
switch category {
|
switch category {
|
||||||
case path.EmailCategory:
|
case path.EmailCategory:
|
||||||
return api.FetchMessageIDsFromDirectory, nil
|
return ac.FetchMessageIDsFromDirectory, nil
|
||||||
case path.EventsCategory:
|
case path.EventsCategory:
|
||||||
return api.FetchEventIDsFromCalendar, nil
|
return ac.FetchEventIDsFromCalendar, nil
|
||||||
case path.ContactsCategory:
|
case path.ContactsCategory:
|
||||||
return api.FetchContactIDsFromDirectory, nil
|
return ac.FetchContactIDsFromDirectory, nil
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("category %s not supported by getFetchIDFunc", category)
|
return nil, fmt.Errorf("category %s not supported by getFetchIDFunc", category)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/alcionai/corso/src/internal/data"
|
"github.com/alcionai/corso/src/internal/data"
|
||||||
D "github.com/alcionai/corso/src/internal/diagnostics"
|
D "github.com/alcionai/corso/src/internal/diagnostics"
|
||||||
"github.com/alcionai/corso/src/internal/observe"
|
"github.com/alcionai/corso/src/internal/observe"
|
||||||
|
"github.com/alcionai/corso/src/pkg/account"
|
||||||
"github.com/alcionai/corso/src/pkg/backup/details"
|
"github.com/alcionai/corso/src/pkg/backup/details"
|
||||||
"github.com/alcionai/corso/src/pkg/control"
|
"github.com/alcionai/corso/src/pkg/control"
|
||||||
"github.com/alcionai/corso/src/pkg/logger"
|
"github.com/alcionai/corso/src/pkg/logger"
|
||||||
@ -284,6 +285,7 @@ func SendMailToBackStore(
|
|||||||
// @param dest: container destination to M365
|
// @param dest: container destination to M365
|
||||||
func RestoreExchangeDataCollections(
|
func RestoreExchangeDataCollections(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
|
creds account.M365Config,
|
||||||
gs graph.Servicer,
|
gs graph.Servicer,
|
||||||
dest control.RestoreDestination,
|
dest control.RestoreDestination,
|
||||||
dcs []data.Collection,
|
dcs []data.Collection,
|
||||||
@ -313,7 +315,7 @@ func RestoreExchangeDataCollections(
|
|||||||
|
|
||||||
containerID, err := CreateContainerDestinaion(
|
containerID, err := CreateContainerDestinaion(
|
||||||
ctx,
|
ctx,
|
||||||
gs,
|
creds,
|
||||||
dc.FullPath(),
|
dc.FullPath(),
|
||||||
dest.ContainerName,
|
dest.ContainerName,
|
||||||
userCaches)
|
userCaches)
|
||||||
@ -431,12 +433,13 @@ func restoreCollection(
|
|||||||
// @ returns the container ID of the new destination container.
|
// @ returns the container ID of the new destination container.
|
||||||
func CreateContainerDestinaion(
|
func CreateContainerDestinaion(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gs graph.Servicer,
|
creds account.M365Config,
|
||||||
directory path.Path,
|
directory path.Path,
|
||||||
destination string,
|
destination string,
|
||||||
caches map[path.CategoryType]graph.ContainerResolver,
|
caches map[path.CategoryType]graph.ContainerResolver,
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
var (
|
var (
|
||||||
|
ac = api.Client{Credentials: creds}
|
||||||
newCache = false
|
newCache = false
|
||||||
user = directory.ResourceOwner()
|
user = directory.ResourceOwner()
|
||||||
category = directory.Category()
|
category = directory.Category()
|
||||||
@ -449,7 +452,7 @@ func CreateContainerDestinaion(
|
|||||||
if directoryCache == nil {
|
if directoryCache == nil {
|
||||||
mfc := &mailFolderCache{
|
mfc := &mailFolderCache{
|
||||||
userID: user,
|
userID: user,
|
||||||
gs: gs,
|
ac: ac,
|
||||||
}
|
}
|
||||||
|
|
||||||
caches[category] = mfc
|
caches[category] = mfc
|
||||||
@ -459,16 +462,17 @@ func CreateContainerDestinaion(
|
|||||||
|
|
||||||
return establishMailRestoreLocation(
|
return establishMailRestoreLocation(
|
||||||
ctx,
|
ctx,
|
||||||
|
ac,
|
||||||
newPathFolders,
|
newPathFolders,
|
||||||
directoryCache,
|
directoryCache,
|
||||||
user,
|
user,
|
||||||
gs,
|
|
||||||
newCache)
|
newCache)
|
||||||
|
|
||||||
case path.ContactsCategory:
|
case path.ContactsCategory:
|
||||||
if directoryCache == nil {
|
if directoryCache == nil {
|
||||||
cfc := &contactFolderCache{
|
cfc := &contactFolderCache{
|
||||||
userID: user,
|
userID: user,
|
||||||
gs: gs,
|
ac: ac,
|
||||||
}
|
}
|
||||||
caches[category] = cfc
|
caches[category] = cfc
|
||||||
newCache = true
|
newCache = true
|
||||||
@ -477,16 +481,17 @@ func CreateContainerDestinaion(
|
|||||||
|
|
||||||
return establishContactsRestoreLocation(
|
return establishContactsRestoreLocation(
|
||||||
ctx,
|
ctx,
|
||||||
|
ac,
|
||||||
newPathFolders,
|
newPathFolders,
|
||||||
directoryCache,
|
directoryCache,
|
||||||
user,
|
user,
|
||||||
gs,
|
|
||||||
newCache)
|
newCache)
|
||||||
|
|
||||||
case path.EventsCategory:
|
case path.EventsCategory:
|
||||||
if directoryCache == nil {
|
if directoryCache == nil {
|
||||||
ecc := &eventCalendarCache{
|
ecc := &eventCalendarCache{
|
||||||
userID: user,
|
userID: user,
|
||||||
gs: gs,
|
ac: ac,
|
||||||
}
|
}
|
||||||
caches[category] = ecc
|
caches[category] = ecc
|
||||||
newCache = true
|
newCache = true
|
||||||
@ -495,10 +500,10 @@ func CreateContainerDestinaion(
|
|||||||
|
|
||||||
return establishEventsRestoreLocation(
|
return establishEventsRestoreLocation(
|
||||||
ctx,
|
ctx,
|
||||||
|
ac,
|
||||||
newPathFolders,
|
newPathFolders,
|
||||||
directoryCache,
|
directoryCache,
|
||||||
user,
|
user,
|
||||||
gs,
|
|
||||||
newCache,
|
newCache,
|
||||||
)
|
)
|
||||||
default:
|
default:
|
||||||
@ -513,10 +518,10 @@ func CreateContainerDestinaion(
|
|||||||
// @param isNewCache identifies if the cache is created and not populated
|
// @param isNewCache identifies if the cache is created and not populated
|
||||||
func establishMailRestoreLocation(
|
func establishMailRestoreLocation(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
|
ac api.Client,
|
||||||
folders []string,
|
folders []string,
|
||||||
mfc graph.ContainerResolver,
|
mfc graph.ContainerResolver,
|
||||||
user string,
|
user string,
|
||||||
service graph.Servicer,
|
|
||||||
isNewCache bool,
|
isNewCache bool,
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
// Process starts with the root folder in order to recreate
|
// Process starts with the root folder in order to recreate
|
||||||
@ -533,12 +538,7 @@ func establishMailRestoreLocation(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
temp, err := api.CreateMailFolderWithParent(
|
temp, err := ac.CreateMailFolderWithParent(ctx, user, folder, folderID)
|
||||||
ctx,
|
|
||||||
service,
|
|
||||||
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))
|
||||||
@ -574,10 +574,10 @@ func establishMailRestoreLocation(
|
|||||||
// @param isNewCache bool representation of whether Populate function needs to be run
|
// @param isNewCache bool representation of whether Populate function needs to be run
|
||||||
func establishContactsRestoreLocation(
|
func establishContactsRestoreLocation(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
|
ac api.Client,
|
||||||
folders []string,
|
folders []string,
|
||||||
cfc graph.ContainerResolver,
|
cfc graph.ContainerResolver,
|
||||||
user string,
|
user string,
|
||||||
gs graph.Servicer,
|
|
||||||
isNewCache bool,
|
isNewCache bool,
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
cached, ok := cfc.PathInCache(folders[0])
|
cached, ok := cfc.PathInCache(folders[0])
|
||||||
@ -585,7 +585,7 @@ func establishContactsRestoreLocation(
|
|||||||
return cached, nil
|
return cached, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
temp, err := api.CreateContactFolder(ctx, gs, user, folders[0])
|
temp, err := ac.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))
|
||||||
}
|
}
|
||||||
@ -607,10 +607,10 @@ func establishContactsRestoreLocation(
|
|||||||
|
|
||||||
func establishEventsRestoreLocation(
|
func establishEventsRestoreLocation(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
|
ac api.Client,
|
||||||
folders []string,
|
folders []string,
|
||||||
ecc graph.ContainerResolver, // eventCalendarCache
|
ecc graph.ContainerResolver, // eventCalendarCache
|
||||||
user string,
|
user string,
|
||||||
gs graph.Servicer,
|
|
||||||
isNewCache bool,
|
isNewCache bool,
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
cached, ok := ecc.PathInCache(folders[0])
|
cached, ok := ecc.PathInCache(folders[0])
|
||||||
@ -618,7 +618,7 @@ func establishEventsRestoreLocation(
|
|||||||
return cached, nil
|
return cached, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
temp, err := api.CreateCalendar(ctx, gs, user, folders[0])
|
temp, err := ac.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))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -252,6 +252,7 @@ func (gc *GraphConnector) UnionSiteIDsAndWebURLs(ctx context.Context, ids, urls
|
|||||||
// SideEffect: gc.status is updated at the completion of operation
|
// SideEffect: gc.status is updated at the completion of operation
|
||||||
func (gc *GraphConnector) RestoreDataCollections(
|
func (gc *GraphConnector) RestoreDataCollections(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
|
acct account.Account,
|
||||||
selector selectors.Selector,
|
selector selectors.Selector,
|
||||||
dest control.RestoreDestination,
|
dest control.RestoreDestination,
|
||||||
dcs []data.Collection,
|
dcs []data.Collection,
|
||||||
@ -265,9 +266,14 @@ func (gc *GraphConnector) RestoreDataCollections(
|
|||||||
deets = &details.Builder{}
|
deets = &details.Builder{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
creds, err := acct.M365Config()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "malformed azure credentials")
|
||||||
|
}
|
||||||
|
|
||||||
switch selector.Service {
|
switch selector.Service {
|
||||||
case selectors.ServiceExchange:
|
case selectors.ServiceExchange:
|
||||||
status, err = exchange.RestoreExchangeDataCollections(ctx, gc.Service, dest, dcs, deets)
|
status, err = exchange.RestoreExchangeDataCollections(ctx, creds, gc.Service, dest, dcs, deets)
|
||||||
case selectors.ServiceOneDrive:
|
case selectors.ServiceOneDrive:
|
||||||
status, err = onedrive.RestoreCollections(ctx, gc.Service, dest, dcs, deets)
|
status, err = onedrive.RestoreCollections(ctx, gc.Service, dest, dcs, deets)
|
||||||
case selectors.ServiceSharePoint:
|
case selectors.ServiceSharePoint:
|
||||||
|
|||||||
@ -168,18 +168,20 @@ func (suite *DisconnectedGraphConnectorSuite) TestGraphConnector_ErrorChecking()
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *DisconnectedGraphConnectorSuite) TestRestoreFailsBadService() {
|
func (suite *DisconnectedGraphConnectorSuite) TestRestoreFailsBadService() {
|
||||||
t := suite.T()
|
|
||||||
|
|
||||||
ctx, flush := tester.NewContext()
|
ctx, flush := tester.NewContext()
|
||||||
defer flush()
|
defer flush()
|
||||||
|
|
||||||
gc := GraphConnector{wg: &sync.WaitGroup{}}
|
var (
|
||||||
sel := selectors.Selector{
|
t = suite.T()
|
||||||
|
acct = tester.NewM365Account(t)
|
||||||
|
dest = tester.DefaultTestRestoreDestination()
|
||||||
|
gc = GraphConnector{wg: &sync.WaitGroup{}}
|
||||||
|
sel = selectors.Selector{
|
||||||
Service: selectors.ServiceUnknown,
|
Service: selectors.ServiceUnknown,
|
||||||
}
|
}
|
||||||
dest := tester.DefaultTestRestoreDestination()
|
)
|
||||||
|
|
||||||
deets, err := gc.RestoreDataCollections(ctx, sel, dest, nil)
|
deets, err := gc.RestoreDataCollections(ctx, acct, sel, dest, nil)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.NotNil(t, deets)
|
assert.NotNil(t, deets)
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import (
|
|||||||
"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"
|
||||||
"github.com/alcionai/corso/src/internal/tester"
|
"github.com/alcionai/corso/src/internal/tester"
|
||||||
|
"github.com/alcionai/corso/src/pkg/account"
|
||||||
"github.com/alcionai/corso/src/pkg/control"
|
"github.com/alcionai/corso/src/pkg/control"
|
||||||
"github.com/alcionai/corso/src/pkg/path"
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
"github.com/alcionai/corso/src/pkg/selectors"
|
"github.com/alcionai/corso/src/pkg/selectors"
|
||||||
@ -135,6 +136,8 @@ type GraphConnectorIntegrationSuite struct {
|
|||||||
suite.Suite
|
suite.Suite
|
||||||
connector *GraphConnector
|
connector *GraphConnector
|
||||||
user string
|
user string
|
||||||
|
acct account.Account
|
||||||
|
credentials account.M365Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGraphConnectorIntegrationSuite(t *testing.T) {
|
func TestGraphConnectorIntegrationSuite(t *testing.T) {
|
||||||
@ -155,6 +158,7 @@ func (suite *GraphConnectorIntegrationSuite) SetupSuite() {
|
|||||||
|
|
||||||
suite.connector = loadConnector(ctx, suite.T(), Users)
|
suite.connector = loadConnector(ctx, suite.T(), Users)
|
||||||
suite.user = tester.M365UserID(suite.T())
|
suite.user = tester.M365UserID(suite.T())
|
||||||
|
suite.acct = tester.NewM365Account(suite.T())
|
||||||
|
|
||||||
tester.LogTimeOfTest(suite.T())
|
tester.LogTimeOfTest(suite.T())
|
||||||
}
|
}
|
||||||
@ -265,7 +269,12 @@ func (suite *GraphConnectorIntegrationSuite) TestEmptyCollections() {
|
|||||||
ctx, flush := tester.NewContext()
|
ctx, flush := tester.NewContext()
|
||||||
defer flush()
|
defer flush()
|
||||||
|
|
||||||
deets, err := suite.connector.RestoreDataCollections(ctx, test.sel, dest, test.col)
|
deets, err := suite.connector.RestoreDataCollections(
|
||||||
|
ctx,
|
||||||
|
suite.acct,
|
||||||
|
test.sel,
|
||||||
|
dest,
|
||||||
|
test.col)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, deets)
|
assert.NotNil(t, deets)
|
||||||
|
|
||||||
@ -308,6 +317,7 @@ func mustGetDefaultDriveID(
|
|||||||
|
|
||||||
func runRestoreBackupTest(
|
func runRestoreBackupTest(
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
|
acct account.Account,
|
||||||
test restoreBackupInfo,
|
test restoreBackupInfo,
|
||||||
tenant string,
|
tenant string,
|
||||||
users []string,
|
users []string,
|
||||||
@ -349,7 +359,12 @@ func runRestoreBackupTest(
|
|||||||
|
|
||||||
restoreGC := loadConnector(ctx, t, test.resource)
|
restoreGC := loadConnector(ctx, t, test.resource)
|
||||||
restoreSel := getSelectorWith(test.service)
|
restoreSel := getSelectorWith(test.service)
|
||||||
deets, err := restoreGC.RestoreDataCollections(ctx, restoreSel, dest, collections)
|
deets, err := restoreGC.RestoreDataCollections(
|
||||||
|
ctx,
|
||||||
|
acct,
|
||||||
|
restoreSel,
|
||||||
|
dest,
|
||||||
|
collections)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, deets)
|
assert.NotNil(t, deets)
|
||||||
|
|
||||||
@ -724,7 +739,7 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreAndBackup() {
|
|||||||
|
|
||||||
for _, test := range table {
|
for _, test := range table {
|
||||||
suite.T().Run(test.name, func(t *testing.T) {
|
suite.T().Run(test.name, func(t *testing.T) {
|
||||||
runRestoreBackupTest(t, test, suite.connector.tenant, []string{suite.user})
|
runRestoreBackupTest(t, suite.acct, test, suite.connector.tenant, []string{suite.user})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -833,7 +848,7 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiFolderBackupDifferentNames
|
|||||||
)
|
)
|
||||||
|
|
||||||
restoreGC := loadConnector(ctx, t, test.resource)
|
restoreGC := loadConnector(ctx, t, test.resource)
|
||||||
deets, err := restoreGC.RestoreDataCollections(ctx, restoreSel, dest, collections)
|
deets, err := restoreGC.RestoreDataCollections(ctx, suite.acct, restoreSel, dest, collections)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, deets)
|
require.NotNil(t, deets)
|
||||||
|
|
||||||
@ -977,7 +992,7 @@ func (suite *GraphConnectorIntegrationSuite) TestMultiuserRestoreAndBackup() {
|
|||||||
|
|
||||||
for _, test := range table {
|
for _, test := range table {
|
||||||
suite.T().Run(test.name, func(t *testing.T) {
|
suite.T().Run(test.name, func(t *testing.T) {
|
||||||
runRestoreBackupTest(t, test, suite.connector.tenant, users)
|
runRestoreBackupTest(t, suite.acct, test, suite.connector.tenant, users)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -294,6 +294,7 @@ func generateContainerOfItems(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gc *connector.GraphConnector,
|
gc *connector.GraphConnector,
|
||||||
service path.ServiceType,
|
service path.ServiceType,
|
||||||
|
acct account.Account,
|
||||||
cat path.CategoryType,
|
cat path.CategoryType,
|
||||||
sel selectors.Selector,
|
sel selectors.Selector,
|
||||||
tenantID, userID, destFldr string,
|
tenantID, userID, destFldr string,
|
||||||
@ -330,7 +331,7 @@ func generateContainerOfItems(
|
|||||||
dest,
|
dest,
|
||||||
collections)
|
collections)
|
||||||
|
|
||||||
deets, err := gc.RestoreDataCollections(ctx, sel, dest, dataColls)
|
deets, err := gc.RestoreDataCollections(ctx, acct, sel, dest, dataColls)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return deets
|
return deets
|
||||||
@ -709,6 +710,7 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run_exchangeIncrementals() {
|
|||||||
ctx,
|
ctx,
|
||||||
gc,
|
gc,
|
||||||
path.ExchangeService,
|
path.ExchangeService,
|
||||||
|
acct,
|
||||||
category,
|
category,
|
||||||
selectors.NewExchangeRestore(users).Selector,
|
selectors.NewExchangeRestore(users).Selector,
|
||||||
m365.AzureTenantID, suite.user, destName,
|
m365.AzureTenantID, suite.user, destName,
|
||||||
|
|||||||
@ -188,7 +188,12 @@ func (op *RestoreOperation) Run(ctx context.Context) (restoreDetails *details.De
|
|||||||
defer closer()
|
defer closer()
|
||||||
defer close(restoreComplete)
|
defer close(restoreComplete)
|
||||||
|
|
||||||
restoreDetails, err = gc.RestoreDataCollections(ctx, op.Selectors, op.Destination, dcs)
|
restoreDetails, err = gc.RestoreDataCollections(
|
||||||
|
ctx,
|
||||||
|
op.account,
|
||||||
|
op.Selectors,
|
||||||
|
op.Destination,
|
||||||
|
dcs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Wrap(err, "restoring service data")
|
err = errors.Wrap(err, "restoring service data")
|
||||||
opStats.writeErr = err
|
opStats.writeErr = err
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user