GC: Add WSL Linting Formatting src/internal/connector (#694)
Lint remaining of `internal/connector` package for wsl
This commit is contained in:
parent
6f04321a60
commit
67bc038c55
@ -80,13 +80,5 @@ issues:
|
|||||||
- revive
|
- revive
|
||||||
text: "import-shadowing:.*'suite' shadows"
|
text: "import-shadowing:.*'suite' shadows"
|
||||||
# Temporarily skip linting wsl on `connector` package until fixes are merged.
|
# Temporarily skip linting wsl on `connector` package until fixes are merged.
|
||||||
- path: internal/connector/graph_connector_test.go
|
|
||||||
linters: wsl
|
|
||||||
- path: internal/connector/graph_connector.go
|
|
||||||
linters: wsl
|
|
||||||
- path: internal/connector/exchange/exchange_service_test.go
|
|
||||||
linters: wsl
|
|
||||||
- path: internal/connector/exchange/service_functions.go
|
|
||||||
linters: wsl
|
|
||||||
- path: internal/connector/onedrive
|
- path: internal/connector/onedrive
|
||||||
linters: wsl
|
linters: wsl
|
||||||
|
|||||||
@ -33,6 +33,7 @@ func TestExchangeServiceSuite(t *testing.T) {
|
|||||||
); err != nil {
|
); err != nil {
|
||||||
t.Skip(err)
|
t.Skip(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Run(t, new(ExchangeServiceSuite))
|
suite.Run(t, new(ExchangeServiceSuite))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +48,7 @@ func (suite *ExchangeServiceSuite) SetupSuite() {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service, err := createService(m365, false)
|
service, err := createService(m365, false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
suite.es = service
|
suite.es = service
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,6 +209,7 @@ func (suite *ExchangeServiceSuite) TestSetupExchangeCollection() {
|
|||||||
sel.Include(sel.Users([]string{userID}))
|
sel.Include(sel.Users([]string{userID}))
|
||||||
eb, err := sel.ToExchangeBackup()
|
eb, err := sel.ToExchangeBackup()
|
||||||
require.NoError(suite.T(), err)
|
require.NoError(suite.T(), err)
|
||||||
|
|
||||||
scopes := eb.Scopes()
|
scopes := eb.Scopes()
|
||||||
|
|
||||||
for _, test := range scopes {
|
for _, test := range scopes {
|
||||||
@ -253,6 +256,7 @@ func (suite *ExchangeServiceSuite) TestGraphQueryFunctions() {
|
|||||||
function: GetAllEventsForUser,
|
function: GetAllEventsForUser,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
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(suite.es, userID)
|
response, err := test.function(suite.es, userID)
|
||||||
@ -341,6 +345,7 @@ func (suite *ExchangeServiceSuite) TestGetFolderID() {
|
|||||||
checkError: assert.NoError,
|
checkError: assert.NoError,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
_, err := GetFolderID(
|
_, err := GetFolderID(
|
||||||
@ -356,17 +361,24 @@ func (suite *ExchangeServiceSuite) TestGetFolderID() {
|
|||||||
// TestIterativeFunctions verifies that GraphQuery to Iterate
|
// TestIterativeFunctions verifies that GraphQuery to Iterate
|
||||||
// functions are valid for current versioning of msgraph-go-sdk
|
// functions are valid for current versioning of msgraph-go-sdk
|
||||||
func (suite *ExchangeServiceSuite) TestIterativeFunctions() {
|
func (suite *ExchangeServiceSuite) TestIterativeFunctions() {
|
||||||
userID := tester.M365UserID(suite.T())
|
var (
|
||||||
sel := selectors.NewExchangeBackup()
|
mailScope, contactScope selectors.ExchangeScope
|
||||||
|
userID = tester.M365UserID(suite.T())
|
||||||
|
sel = selectors.NewExchangeBackup()
|
||||||
|
)
|
||||||
|
|
||||||
sel.Include(sel.Users([]string{userID}))
|
sel.Include(sel.Users([]string{userID}))
|
||||||
|
|
||||||
eb, err := sel.ToExchangeBackup()
|
eb, err := sel.ToExchangeBackup()
|
||||||
require.NoError(suite.T(), err)
|
require.NoError(suite.T(), err)
|
||||||
|
|
||||||
scopes := eb.Scopes()
|
scopes := eb.Scopes()
|
||||||
var mailScope, contactScope selectors.ExchangeScope
|
|
||||||
for _, scope := range scopes {
|
for _, scope := range scopes {
|
||||||
if scope.IncludesCategory(selectors.ExchangeContactFolder) {
|
if scope.IncludesCategory(selectors.ExchangeContactFolder) {
|
||||||
contactScope = scope
|
contactScope = scope
|
||||||
}
|
}
|
||||||
|
|
||||||
if scope.IncludesCategory(selectors.ExchangeMail) {
|
if scope.IncludesCategory(selectors.ExchangeMail) {
|
||||||
mailScope = scope
|
mailScope = scope
|
||||||
}
|
}
|
||||||
@ -437,6 +449,7 @@ func (suite *ExchangeServiceSuite) TestRestoreContact() {
|
|||||||
folderName := "TestRestoreContact: " + common.FormatSimpleDateTime(now)
|
folderName := "TestRestoreContact: " + common.FormatSimpleDateTime(now)
|
||||||
aFolder, err := CreateContactFolder(suite.es, userID, folderName)
|
aFolder, err := CreateContactFolder(suite.es, userID, folderName)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
folderID := *aFolder.GetId()
|
folderID := *aFolder.GetId()
|
||||||
err = RestoreExchangeContact(context.Background(),
|
err = RestoreExchangeContact(context.Background(),
|
||||||
mockconnector.GetMockContactBytes("Corso TestContact"),
|
mockconnector.GetMockContactBytes("Corso TestContact"),
|
||||||
@ -487,6 +500,7 @@ func (suite *ExchangeServiceSuite) TestEstablishFolder() {
|
|||||||
now := time.Now()
|
now := time.Now()
|
||||||
folderName := "CorsoEstablishFolder" + common.FormatSimpleDateTime(now)
|
folderName := "CorsoEstablishFolder" + common.FormatSimpleDateTime(now)
|
||||||
userID := tester.M365UserID(suite.T())
|
userID := tester.M365UserID(suite.T())
|
||||||
|
|
||||||
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) {
|
||||||
folderID, err := establishFolder(suite.es, folderName, userID, test.option)
|
folderID, err := establishFolder(suite.es, folderName, userID, test.option)
|
||||||
|
|||||||
@ -56,12 +56,14 @@ func createService(credentials account.M365Config, shouldFailFast bool) (*exchan
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
service := exchangeService{
|
service := exchangeService{
|
||||||
adapter: *adapter,
|
adapter: *adapter,
|
||||||
client: *msgraphsdk.NewGraphServiceClient(adapter),
|
client: *msgraphsdk.NewGraphServiceClient(adapter),
|
||||||
failFast: shouldFailFast,
|
failFast: shouldFailFast,
|
||||||
credentials: credentials,
|
credentials: credentials,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &service, err
|
return &service, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,6 +72,7 @@ func createService(credentials account.M365Config, shouldFailFast bool) (*exchan
|
|||||||
func CreateMailFolder(gs graph.Service, user, folder string) (models.MailFolderable, error) {
|
func CreateMailFolder(gs graph.Service, user, folder string) (models.MailFolderable, error) {
|
||||||
requestBody := models.NewMailFolder()
|
requestBody := models.NewMailFolder()
|
||||||
requestBody.SetDisplayName(&folder)
|
requestBody.SetDisplayName(&folder)
|
||||||
|
|
||||||
isHidden := false
|
isHidden := false
|
||||||
requestBody.SetIsHidden(&isHidden)
|
requestBody.SetIsHidden(&isHidden)
|
||||||
|
|
||||||
@ -110,6 +113,7 @@ func GetAllMailFolders(gs graph.Service, user, nameContains string) ([]MailFolde
|
|||||||
mfs = []MailFolder{}
|
mfs = []MailFolder{}
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
resp, err := GetAllFolderNamesForUser(gs, user)
|
resp, err := GetAllFolderNamesForUser(gs, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -143,6 +147,7 @@ func GetAllMailFolders(gs graph.Service, user, nameContains string) ([]MailFolde
|
|||||||
if err := iter.Iterate(cb); err != nil {
|
if err := iter.Iterate(cb); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return mfs, err
|
return mfs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,6 +162,7 @@ func GetFolderID(service graph.Service, folderName, user string, category option
|
|||||||
query GraphQuery
|
query GraphQuery
|
||||||
transform absser.ParsableFactory
|
transform absser.ParsableFactory
|
||||||
)
|
)
|
||||||
|
|
||||||
switch category {
|
switch category {
|
||||||
case messages:
|
case messages:
|
||||||
query = GetAllFolderNamesForUser
|
query = GetAllFolderNamesForUser
|
||||||
@ -176,6 +182,7 @@ func GetFolderID(service graph.Service, folderName, user string, category option
|
|||||||
user, support.ConnectorStackErrorTrace(err),
|
user, support.ConnectorStackErrorTrace(err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pageIterator, err := msgraphgocore.NewPageIterator(
|
pageIterator, err := msgraphgocore.NewPageIterator(
|
||||||
response,
|
response,
|
||||||
service.Adapter(),
|
service.Adapter(),
|
||||||
@ -184,6 +191,7 @@ func GetFolderID(service graph.Service, folderName, user string, category option
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
callbackFunc := iterateFindFolderID(category,
|
callbackFunc := iterateFindFolderID(category,
|
||||||
&folderID,
|
&folderID,
|
||||||
folderName,
|
folderName,
|
||||||
@ -211,12 +219,16 @@ func parseCalendarIDFromEvent(reference string) (string, error) {
|
|||||||
if len(stringArray) < 2 {
|
if len(stringArray) < 2 {
|
||||||
return "", errors.New("calendarID not found")
|
return "", errors.New("calendarID not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
temp := stringArray[1]
|
temp := stringArray[1]
|
||||||
stringArray = strings.Split(temp, "')/$ref")
|
stringArray = strings.Split(temp, "')/$ref")
|
||||||
|
|
||||||
if len(stringArray) < 2 {
|
if len(stringArray) < 2 {
|
||||||
return "", errors.New("calendarID not found")
|
return "", errors.New("calendarID not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
calendarID := stringArray[0]
|
calendarID := stringArray[0]
|
||||||
|
|
||||||
if len(calendarID) == 0 {
|
if len(calendarID) == 0 {
|
||||||
return "", errors.New("calendarID empty")
|
return "", errors.New("calendarID empty")
|
||||||
}
|
}
|
||||||
@ -245,6 +257,7 @@ func SetupExchangeCollectionVars(scope selectors.ExchangeScope) (
|
|||||||
IterateAndFilterMessagesForCollections,
|
IterateAndFilterMessagesForCollections,
|
||||||
nil
|
nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if scope.IncludesCategory(selectors.ExchangeEvent) {
|
if scope.IncludesCategory(selectors.ExchangeEvent) {
|
||||||
return models.CreateEventCollectionResponseFromDiscriminatorValue,
|
return models.CreateEventCollectionResponseFromDiscriminatorValue,
|
||||||
GetAllEventsForUser,
|
GetAllEventsForUser,
|
||||||
@ -271,6 +284,7 @@ func GetRestoreFolder(
|
|||||||
user, category string,
|
user, category string,
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
newFolder := fmt.Sprintf("Corso_Restore_%s", common.FormatNow(common.SimpleDateTimeFormat))
|
newFolder := fmt.Sprintf("Corso_Restore_%s", common.FormatNow(common.SimpleDateTimeFormat))
|
||||||
|
|
||||||
switch category {
|
switch category {
|
||||||
case mailCategory, contactsCategory:
|
case mailCategory, contactsCategory:
|
||||||
return establishFolder(service, newFolder, user, categoryToOptionIdentifier(category))
|
return establishFolder(service, newFolder, user, categoryToOptionIdentifier(category))
|
||||||
@ -292,18 +306,21 @@ func establishFolder(
|
|||||||
if !errors.Is(err, ErrFolderNotFound) {
|
if !errors.Is(err, ErrFolderNotFound) {
|
||||||
return "", support.WrapAndAppend(user, err, err)
|
return "", support.WrapAndAppend(user, err, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch optID {
|
switch optID {
|
||||||
case messages:
|
case messages:
|
||||||
fold, err := CreateMailFolder(service, user, folderName)
|
fold, err := CreateMailFolder(service, user, folderName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", support.WrapAndAppend(user, err, err)
|
return "", support.WrapAndAppend(user, err, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return *fold.GetId(), nil
|
return *fold.GetId(), nil
|
||||||
case contacts:
|
case contacts:
|
||||||
fold, err := CreateContactFolder(service, user, folderName)
|
fold, err := CreateContactFolder(service, user, folderName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", support.WrapAndAppend(user, err, err)
|
return "", support.WrapAndAppend(user, err, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return *fold.GetId(), nil
|
return *fold.GetId(), nil
|
||||||
default:
|
default:
|
||||||
return "", fmt.Errorf("category: %s not supported for folder creation", optID)
|
return "", fmt.Errorf("category: %s not supported for folder creation", optID)
|
||||||
@ -319,12 +336,14 @@ func RestoreExchangeObject(
|
|||||||
destination, user string,
|
destination, user string,
|
||||||
) error {
|
) error {
|
||||||
var setting optionIdentifier
|
var setting optionIdentifier
|
||||||
|
|
||||||
switch category {
|
switch category {
|
||||||
case mailCategory, contactsCategory:
|
case mailCategory, contactsCategory:
|
||||||
setting = categoryToOptionIdentifier(category)
|
setting = categoryToOptionIdentifier(category)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("type: %s not supported for exchange restore", category)
|
return fmt.Errorf("type: %s not supported for exchange restore", category)
|
||||||
}
|
}
|
||||||
|
|
||||||
if policy != control.Copy {
|
if policy != control.Copy {
|
||||||
return fmt.Errorf("restore policy: %s not supported", policy)
|
return fmt.Errorf("restore policy: %s not supported", policy)
|
||||||
}
|
}
|
||||||
@ -361,9 +380,11 @@ func RestoreExchangeContact(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, support.ConnectorStackErrorTrace(err))
|
return errors.Wrap(err, support.ConnectorStackErrorTrace(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if response == nil {
|
if response == nil {
|
||||||
return errors.New("msgraph contact post fail: REST response not received")
|
return errors.New("msgraph contact post fail: REST response not received")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,6 +416,7 @@ func RestoreMailMessage(
|
|||||||
sv.SetValue(&enableValue)
|
sv.SetValue(&enableValue)
|
||||||
svlep := []models.SingleValueLegacyExtendedPropertyable{sv}
|
svlep := []models.SingleValueLegacyExtendedPropertyable{sv}
|
||||||
clone.SetSingleValueExtendedProperties(svlep)
|
clone.SetSingleValueExtendedProperties(svlep)
|
||||||
|
|
||||||
draft := false
|
draft := false
|
||||||
clone.SetIsDraft(&draft)
|
clone.SetIsDraft(&draft)
|
||||||
|
|
||||||
@ -418,8 +440,10 @@ func SendMailToBackStore(service graph.Service, user, destination string, messag
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return support.WrapAndAppend(": "+support.ConnectorStackErrorTrace(err), err, nil)
|
return support.WrapAndAppend(": "+support.ConnectorStackErrorTrace(err), err, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sentMessage == nil {
|
if sentMessage == nil {
|
||||||
return errors.New("message not Sent: blocked by server")
|
return errors.New("message not Sent: blocked by server")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
absser "github.com/microsoft/kiota-abstractions-go/serialization"
|
|
||||||
msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
|
msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
|
||||||
msgraphgocore "github.com/microsoftgraph/msgraph-sdk-go-core"
|
msgraphgocore "github.com/microsoftgraph/msgraph-sdk-go-core"
|
||||||
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||||
@ -67,6 +66,7 @@ func NewGraphConnector(acct account.Account) (*GraphConnector, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "retrieving m356 account configuration")
|
return nil, errors.Wrap(err, "retrieving m356 account configuration")
|
||||||
}
|
}
|
||||||
|
|
||||||
gc := GraphConnector{
|
gc := GraphConnector{
|
||||||
tenant: m365.TenantID,
|
tenant: m365.TenantID,
|
||||||
Users: make(map[string]string, 0),
|
Users: make(map[string]string, 0),
|
||||||
@ -74,15 +74,19 @@ func NewGraphConnector(acct account.Account) (*GraphConnector, error) {
|
|||||||
statusCh: make(chan *support.ConnectorOperationStatus),
|
statusCh: make(chan *support.ConnectorOperationStatus),
|
||||||
credentials: m365,
|
credentials: m365,
|
||||||
}
|
}
|
||||||
|
|
||||||
aService, err := gc.createService(false)
|
aService, err := gc.createService(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
gc.graphService = *aService
|
gc.graphService = *aService
|
||||||
|
|
||||||
err = gc.setTenantUsers()
|
err = gc.setTenantUsers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &gc, nil
|
return &gc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,11 +100,13 @@ func (gc *GraphConnector) createService(shouldFailFast bool) (*graphService, err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
connector := graphService{
|
connector := graphService{
|
||||||
adapter: *adapter,
|
adapter: *adapter,
|
||||||
client: *msgraphsdk.NewGraphServiceClient(adapter),
|
client: *msgraphsdk.NewGraphServiceClient(adapter),
|
||||||
failFast: shouldFailFast,
|
failFast: shouldFailFast,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &connector, err
|
return &connector, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,10 +127,12 @@ func (gc *GraphConnector) setTenantUsers() error {
|
|||||||
support.ConnectorStackErrorTrace(err),
|
support.ConnectorStackErrorTrace(err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if response == nil {
|
if response == nil {
|
||||||
err = support.WrapAndAppend("general access", errors.New("connector failed: No access"), err)
|
err = support.WrapAndAppend("general access", errors.New("connector failed: No access"), err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
userIterator, err := msgraphgocore.NewPageIterator(
|
userIterator, err := msgraphgocore.NewPageIterator(
|
||||||
response,
|
response,
|
||||||
&gc.graphService.adapter,
|
&gc.graphService.adapter,
|
||||||
@ -133,31 +141,35 @@ func (gc *GraphConnector) setTenantUsers() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, support.ConnectorStackErrorTrace(err))
|
return errors.Wrap(err, support.ConnectorStackErrorTrace(err))
|
||||||
}
|
}
|
||||||
var iterateError error
|
|
||||||
callbackFunc := func(userItem interface{}) bool {
|
callbackFunc := func(userItem interface{}) bool {
|
||||||
user, ok := userItem.(models.Userable)
|
user, ok := userItem.(models.Userable)
|
||||||
if !ok {
|
if !ok {
|
||||||
err = support.WrapAndAppend(gc.graphService.adapter.GetBaseUrl(), errors.New("user iteration failure"), err)
|
err = support.WrapAndAppend(gc.graphService.adapter.GetBaseUrl(), errors.New("user iteration failure"), err)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.GetUserPrincipalName() == nil {
|
if user.GetUserPrincipalName() == nil {
|
||||||
err = support.WrapAndAppend(
|
err = support.WrapAndAppend(
|
||||||
gc.graphService.adapter.GetBaseUrl(),
|
gc.graphService.adapter.GetBaseUrl(),
|
||||||
fmt.Errorf("no email address for User: %s", *user.GetId()),
|
fmt.Errorf("no email address for User: %s", *user.GetId()),
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// *user.GetId() is populated for every M365 entityable object by M365 backstore
|
// *user.GetId() is populated for every M365 entityable object by M365 backstore
|
||||||
gc.Users[*user.GetUserPrincipalName()] = *user.GetId()
|
gc.Users[*user.GetUserPrincipalName()] = *user.GetId()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
iterateError = userIterator.Iterate(callbackFunc)
|
iterateError := userIterator.Iterate(callbackFunc)
|
||||||
if iterateError != nil {
|
if iterateError != nil {
|
||||||
err = support.WrapAndAppend(gc.graphService.adapter.GetBaseUrl(), iterateError, err)
|
err = support.WrapAndAppend(gc.graphService.adapter.GetBaseUrl(), iterateError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +187,7 @@ func (gc *GraphConnector) GetUsersIds() []string {
|
|||||||
// Returns list of keys iff true; otherwise returns a list of values
|
// Returns list of keys iff true; otherwise returns a list of values
|
||||||
func buildFromMap(isKey bool, mapping map[string]string) []string {
|
func buildFromMap(isKey bool, mapping map[string]string) []string {
|
||||||
returnString := make([]string, 0)
|
returnString := make([]string, 0)
|
||||||
|
|
||||||
if isKey {
|
if isKey {
|
||||||
for k := range mapping {
|
for k := range mapping {
|
||||||
returnString = append(returnString, k)
|
returnString = append(returnString, k)
|
||||||
@ -184,6 +197,7 @@ func buildFromMap(isKey bool, mapping map[string]string) []string {
|
|||||||
returnString = append(returnString, v)
|
returnString = append(returnString, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnString
|
return returnString
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,9 +213,13 @@ func (gc *GraphConnector) ExchangeDataCollection(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "exchangeDataCollection: unable to parse selector")
|
return nil, errors.Wrap(err, "exchangeDataCollection: unable to parse selector")
|
||||||
}
|
}
|
||||||
scopes := eb.DiscreteScopes(gc.GetUsers())
|
|
||||||
collections := []data.Collection{}
|
var (
|
||||||
var errs error
|
scopes = eb.DiscreteScopes(gc.GetUsers())
|
||||||
|
collections = []data.Collection{}
|
||||||
|
errs error
|
||||||
|
)
|
||||||
|
|
||||||
for _, scope := range scopes {
|
for _, scope := range scopes {
|
||||||
// Creates a map of collections based on scope
|
// Creates a map of collections based on scope
|
||||||
dcs, err := gc.createCollections(ctx, scope)
|
dcs, err := gc.createCollections(ctx, scope)
|
||||||
@ -209,6 +227,7 @@ func (gc *GraphConnector) ExchangeDataCollection(
|
|||||||
user := scope.Get(selectors.ExchangeUser)
|
user := scope.Get(selectors.ExchangeUser)
|
||||||
return nil, support.WrapAndAppend(user[0], err, errs)
|
return nil, support.WrapAndAppend(user[0], err, errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, collection := range dcs {
|
for _, collection := range dcs {
|
||||||
collections = append(collections, collection)
|
collections = append(collections, collection)
|
||||||
}
|
}
|
||||||
@ -229,22 +248,28 @@ func (gc *GraphConnector) RestoreExchangeDataCollection(
|
|||||||
attempts, successes int
|
attempts, successes int
|
||||||
errs error
|
errs error
|
||||||
folderID string
|
folderID string
|
||||||
|
// TODO policy to be updated from external source after completion of refactoring
|
||||||
|
policy = control.Copy
|
||||||
)
|
)
|
||||||
policy := control.Copy // TODO policy to be updated from external source after completion of refactoring
|
|
||||||
|
|
||||||
for _, dc := range dcs {
|
for _, dc := range dcs {
|
||||||
directory := strings.Join(dc.FullPath(), "")
|
var (
|
||||||
user := dc.FullPath()[1]
|
directory = strings.Join(dc.FullPath(), "")
|
||||||
items := dc.Items()
|
user = dc.FullPath()[1]
|
||||||
category := dc.FullPath()[2]
|
items = dc.Items()
|
||||||
|
category = dc.FullPath()[2]
|
||||||
|
exit bool
|
||||||
|
)
|
||||||
|
|
||||||
if _, ok := pathCounter[directory]; !ok {
|
if _, ok := pathCounter[directory]; !ok {
|
||||||
pathCounter[directory] = true
|
pathCounter[directory] = true
|
||||||
folderID, errs = exchange.GetRestoreFolder(&gc.graphService, user, category)
|
folderID, errs = exchange.GetRestoreFolder(&gc.graphService, user, category)
|
||||||
|
|
||||||
if errs != nil {
|
if errs != nil {
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var exit bool
|
|
||||||
for !exit {
|
for !exit {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
@ -257,11 +282,13 @@ func (gc *GraphConnector) RestoreExchangeDataCollection(
|
|||||||
attempts++
|
attempts++
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
|
|
||||||
_, err := buf.ReadFrom(itemData.ToReader())
|
_, err := buf.ReadFrom(itemData.ToReader())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = support.WrapAndAppend(itemData.UUID(), err, errs)
|
errs = support.WrapAndAppend(itemData.UUID(), err, errs)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
err = exchange.RestoreExchangeObject(ctx, buf.Bytes(), category, policy, &gc.graphService, folderID, user)
|
err = exchange.RestoreExchangeObject(ctx, buf.Bytes(), category, policy, &gc.graphService, folderID, user)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -272,12 +299,15 @@ func (gc *GraphConnector) RestoreExchangeDataCollection(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gc.incrementAwaitingMessages()
|
gc.incrementAwaitingMessages()
|
||||||
|
|
||||||
status := support.CreateStatus(ctx, support.Restore, attempts, successes, len(pathCounter), errs)
|
status := support.CreateStatus(ctx, support.Restore, attempts, successes, len(pathCounter), errs)
|
||||||
// set the channel asynchronously so that this func doesn't block.
|
// set the channel asynchronously so that this func doesn't block.
|
||||||
go func(cos *support.ConnectorOperationStatus) {
|
go func(cos *support.ConnectorOperationStatus) {
|
||||||
gc.statusCh <- cos
|
gc.statusCh <- cos
|
||||||
}(status)
|
}(status)
|
||||||
|
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,20 +320,20 @@ func (gc *GraphConnector) createCollections(
|
|||||||
scope selectors.ExchangeScope,
|
scope selectors.ExchangeScope,
|
||||||
) ([]*exchange.Collection, error) {
|
) ([]*exchange.Collection, error) {
|
||||||
var (
|
var (
|
||||||
transformer absser.ParsableFactory
|
errs error
|
||||||
query exchange.GraphQuery
|
transformer, query, gIter, err = exchange.SetupExchangeCollectionVars(scope)
|
||||||
gIter exchange.GraphIterateFunc
|
|
||||||
errs error
|
|
||||||
)
|
)
|
||||||
transformer, query, gIter, err := exchange.SetupExchangeCollectionVars(scope)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, support.WrapAndAppend(gc.Service().Adapter().GetBaseUrl(), err, nil)
|
return nil, support.WrapAndAppend(gc.Service().Adapter().GetBaseUrl(), err, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
users := scope.Get(selectors.ExchangeUser)
|
users := scope.Get(selectors.ExchangeUser)
|
||||||
allCollections := make([]*exchange.Collection, 0)
|
allCollections := make([]*exchange.Collection, 0)
|
||||||
// Create collection of ExchangeDataCollection
|
// Create collection of ExchangeDataCollection
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
collections := make(map[string]*exchange.Collection)
|
collections := make(map[string]*exchange.Collection)
|
||||||
|
|
||||||
response, err := query(&gc.graphService, user)
|
response, err := query(&gc.graphService, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(
|
return nil, errors.Wrapf(
|
||||||
@ -322,17 +352,22 @@ func (gc *GraphConnector) createCollections(
|
|||||||
// Each directory used the M365 Identifier. The use of ID stops collisions betweens users
|
// Each directory used the M365 Identifier. The use of ID stops collisions betweens users
|
||||||
callbackFunc := gIter(user, scope, errs, gc.failFast, gc.credentials, collections, gc.statusCh)
|
callbackFunc := gIter(user, scope, errs, gc.failFast, gc.credentials, collections, gc.statusCh)
|
||||||
iterateError := pageIterator.Iterate(callbackFunc)
|
iterateError := pageIterator.Iterate(callbackFunc)
|
||||||
|
|
||||||
if iterateError != nil {
|
if iterateError != nil {
|
||||||
errs = support.WrapAndAppend(gc.graphService.adapter.GetBaseUrl(), iterateError, errs)
|
errs = support.WrapAndAppend(gc.graphService.adapter.GetBaseUrl(), iterateError, errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if errs != nil {
|
if errs != nil {
|
||||||
return nil, errs // return error if snapshot is incomplete
|
return nil, errs // return error if snapshot is incomplete
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, collection := range collections {
|
for _, collection := range collections {
|
||||||
gc.incrementAwaitingMessages()
|
gc.incrementAwaitingMessages()
|
||||||
|
|
||||||
allCollections = append(allCollections, collection)
|
allCollections = append(allCollections, collection)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return allCollections, errs
|
return allCollections, errs
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,6 +377,7 @@ func (gc *GraphConnector) AwaitStatus() *support.ConnectorOperationStatus {
|
|||||||
atomic.AddInt32(&gc.awaitingMessages, -1)
|
atomic.AddInt32(&gc.awaitingMessages, -1)
|
||||||
gc.status = <-gc.statusCh
|
gc.status = <-gc.statusCh
|
||||||
}
|
}
|
||||||
|
|
||||||
return gc.status
|
return gc.status
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,6 +391,7 @@ func (gc *GraphConnector) PrintableStatus() string {
|
|||||||
if gc.status == nil {
|
if gc.status == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return gc.status.String()
|
return gc.status.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,7 @@ func loadConnector(t *testing.T) *GraphConnector {
|
|||||||
a := tester.NewM365Account(t)
|
a := tester.NewM365Account(t)
|
||||||
connector, err := NewGraphConnector(a)
|
connector, err := NewGraphConnector(a)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return connector
|
return connector
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,6 +42,7 @@ func TestGraphConnectorIntegrationSuite(t *testing.T) {
|
|||||||
); err != nil {
|
); err != nil {
|
||||||
t.Skip(err)
|
t.Skip(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Run(t, new(GraphConnectorIntegrationSuite))
|
suite.Run(t, new(GraphConnectorIntegrationSuite))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,8 +68,10 @@ func (suite *GraphConnectorIntegrationSuite) TestSetTenantUsers() {
|
|||||||
statusCh: make(chan *support.ConnectorOperationStatus),
|
statusCh: make(chan *support.ConnectorOperationStatus),
|
||||||
credentials: suite.connector.credentials,
|
credentials: suite.connector.credentials,
|
||||||
}
|
}
|
||||||
|
|
||||||
service, err := newConnector.createService(false)
|
service, err := newConnector.createService(false)
|
||||||
require.NoError(suite.T(), err)
|
require.NoError(suite.T(), err)
|
||||||
|
|
||||||
newConnector.graphService = *service
|
newConnector.graphService = *service
|
||||||
|
|
||||||
suite.Equal(len(newConnector.Users), 0)
|
suite.Equal(len(newConnector.Users), 0)
|
||||||
@ -92,6 +96,7 @@ func (suite *GraphConnectorIntegrationSuite) TestExchangeDataCollection() {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, connector.awaitingMessages > 0)
|
assert.True(t, connector.awaitingMessages > 0)
|
||||||
assert.Nil(t, connector.status)
|
assert.Nil(t, connector.status)
|
||||||
|
|
||||||
streams := make(map[string]<-chan data.Stream)
|
streams := make(map[string]<-chan data.Stream)
|
||||||
// Verify Items() call returns an iterable channel(e.g. a channel that has been closed)
|
// Verify Items() call returns an iterable channel(e.g. a channel that has been closed)
|
||||||
for _, collection := range collectionList {
|
for _, collection := range collectionList {
|
||||||
@ -115,6 +120,7 @@ func (suite *GraphConnectorIntegrationSuite) TestExchangeDataCollection() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
exchangeData := collectionList[0]
|
exchangeData := collectionList[0]
|
||||||
suite.Greater(len(exchangeData.FullPath()), 2)
|
suite.Greater(len(exchangeData.FullPath()), 2)
|
||||||
}
|
}
|
||||||
@ -129,11 +135,13 @@ func (suite *GraphConnectorIntegrationSuite) TestMailSerializationRegression() {
|
|||||||
sel.Include(sel.MailFolders([]string{suite.user}, selectors.Any()))
|
sel.Include(sel.MailFolders([]string{suite.user}, selectors.Any()))
|
||||||
eb, err := sel.ToExchangeBackup()
|
eb, err := sel.ToExchangeBackup()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
scopes := eb.Scopes()
|
scopes := eb.Scopes()
|
||||||
suite.Len(scopes, 1)
|
suite.Len(scopes, 1)
|
||||||
mailScope := scopes[0]
|
mailScope := scopes[0]
|
||||||
collection, err := connector.createCollections(context.Background(), mailScope)
|
collection, err := connector.createCollections(context.Background(), mailScope)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
for _, edc := range collection {
|
for _, edc := range collection {
|
||||||
testName := strings.Join(edc.FullPath(), " ")
|
testName := strings.Join(edc.FullPath(), " ")
|
||||||
suite.T().Run(testName, func(t *testing.T) {
|
suite.T().Run(testName, func(t *testing.T) {
|
||||||
@ -150,6 +158,7 @@ func (suite *GraphConnectorIntegrationSuite) TestMailSerializationRegression() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
status := connector.AwaitStatus()
|
status := connector.AwaitStatus()
|
||||||
suite.NotNil(status)
|
suite.NotNil(status)
|
||||||
suite.Equal(status.ObjectCount, status.Successful)
|
suite.Equal(status.ObjectCount, status.Successful)
|
||||||
@ -164,13 +173,17 @@ func (suite *GraphConnectorIntegrationSuite) TestContactSerializationRegression(
|
|||||||
sel.Include(sel.ContactFolders([]string{suite.user}, selectors.Any()))
|
sel.Include(sel.ContactFolders([]string{suite.user}, selectors.Any()))
|
||||||
eb, err := sel.ToExchangeBackup()
|
eb, err := sel.ToExchangeBackup()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
scopes := eb.Scopes()
|
scopes := eb.Scopes()
|
||||||
connector := loadConnector(t)
|
connector := loadConnector(t)
|
||||||
|
|
||||||
suite.Len(scopes, 1)
|
suite.Len(scopes, 1)
|
||||||
contactsOnly := scopes[0]
|
contactsOnly := scopes[0]
|
||||||
collections, err := connector.createCollections(context.Background(), contactsOnly)
|
collections, err := connector.createCollections(context.Background(), contactsOnly)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
number := 0
|
number := 0
|
||||||
|
|
||||||
for _, edc := range collections {
|
for _, edc := range collections {
|
||||||
testName := fmt.Sprintf("%s_ContactFolder_%d", edc.FullPath()[1], number)
|
testName := fmt.Sprintf("%s_ContactFolder_%d", edc.FullPath()[1], number)
|
||||||
suite.T().Run(testName, func(t *testing.T) {
|
suite.T().Run(testName, func(t *testing.T) {
|
||||||
@ -188,6 +201,7 @@ func (suite *GraphConnectorIntegrationSuite) TestContactSerializationRegression(
|
|||||||
number++
|
number++
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
status := connector.AwaitStatus()
|
status := connector.AwaitStatus()
|
||||||
suite.NotNil(status)
|
suite.NotNil(status)
|
||||||
suite.Equal(status.ObjectCount, status.Successful)
|
suite.Equal(status.ObjectCount, status.Successful)
|
||||||
@ -204,9 +218,11 @@ func (suite *GraphConnectorIntegrationSuite) TestEventsSerializationRegression()
|
|||||||
suite.Equal(len(scopes), 1)
|
suite.Equal(len(scopes), 1)
|
||||||
collections, err := connector.createCollections(context.Background(), scopes[0])
|
collections, err := connector.createCollections(context.Background(), scopes[0])
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
for _, edc := range collections {
|
for _, edc := range collections {
|
||||||
streamChannel := edc.Items()
|
streamChannel := edc.Items()
|
||||||
number := 0
|
number := 0
|
||||||
|
|
||||||
for stream := range streamChannel {
|
for stream := range streamChannel {
|
||||||
testName := fmt.Sprintf("%s_Event_%d", edc.FullPath()[2], number)
|
testName := fmt.Sprintf("%s_Event_%d", edc.FullPath()[2], number)
|
||||||
suite.T().Run(testName, func(t *testing.T) {
|
suite.T().Run(testName, func(t *testing.T) {
|
||||||
@ -220,6 +236,7 @@ func (suite *GraphConnectorIntegrationSuite) TestEventsSerializationRegression()
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
status := connector.AwaitStatus()
|
status := connector.AwaitStatus()
|
||||||
suite.NotNil(status)
|
suite.NotNil(status)
|
||||||
suite.Equal(status.ObjectCount, status.Successful)
|
suite.Equal(status.ObjectCount, status.Successful)
|
||||||
@ -234,6 +251,7 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreMessages() {
|
|||||||
category := "mail"
|
category := "mail"
|
||||||
connector := loadConnector(t)
|
connector := loadConnector(t)
|
||||||
collection := make([]data.Collection, 0)
|
collection := make([]data.Collection, 0)
|
||||||
|
|
||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 3; i++ {
|
||||||
mdc := mockconnector.NewMockExchangeCollection(
|
mdc := mockconnector.NewMockExchangeCollection(
|
||||||
[]string{"tenant", suite.user, category, "Inbox"},
|
[]string{"tenant", suite.user, category, "Inbox"},
|
||||||
@ -243,6 +261,7 @@ func (suite *GraphConnectorIntegrationSuite) TestRestoreMessages() {
|
|||||||
|
|
||||||
err := connector.RestoreExchangeDataCollection(context.Background(), collection)
|
err := connector.RestoreExchangeDataCollection(context.Background(), collection)
|
||||||
assert.NoError(suite.T(), err)
|
assert.NoError(suite.T(), err)
|
||||||
|
|
||||||
status := connector.AwaitStatus()
|
status := connector.AwaitStatus()
|
||||||
assert.NotNil(t, status)
|
assert.NotNil(t, status)
|
||||||
assert.Equal(t, status.ObjectCount, status.Successful)
|
assert.Equal(t, status.ObjectCount, status.Successful)
|
||||||
@ -261,6 +280,7 @@ func (suite *GraphConnectorIntegrationSuite) TestAccessOfInboxAllUsers() {
|
|||||||
sel := selectors.NewExchangeBackup()
|
sel := selectors.NewExchangeBackup()
|
||||||
sel.Include(sel.MailFolders(selectors.Any(), []string{"Inbox"}))
|
sel.Include(sel.MailFolders(selectors.Any(), []string{"Inbox"}))
|
||||||
scopes := sel.DiscreteScopes(connector.GetUsers())
|
scopes := sel.DiscreteScopes(connector.GetUsers())
|
||||||
|
|
||||||
for _, scope := range scopes {
|
for _, scope := range scopes {
|
||||||
users := scope.Get(selectors.ExchangeUser)
|
users := scope.Get(selectors.ExchangeUser)
|
||||||
standard := (len(users) / 4) * 3
|
standard := (len(users) / 4) * 3
|
||||||
@ -281,6 +301,7 @@ func (suite *GraphConnectorIntegrationSuite) TestCreateAndDeleteMailFolder() {
|
|||||||
folderName := "TestFolder: " + common.FormatSimpleDateTime(now)
|
folderName := "TestFolder: " + common.FormatSimpleDateTime(now)
|
||||||
aFolder, err := exchange.CreateMailFolder(&suite.connector.graphService, suite.user, folderName)
|
aFolder, err := exchange.CreateMailFolder(&suite.connector.graphService, suite.user, folderName)
|
||||||
assert.NoError(suite.T(), err, support.ConnectorStackErrorTrace(err))
|
assert.NoError(suite.T(), err, support.ConnectorStackErrorTrace(err))
|
||||||
|
|
||||||
if aFolder != nil {
|
if aFolder != nil {
|
||||||
err = exchange.DeleteMailFolder(suite.connector.Service(), suite.user, *aFolder.GetId())
|
err = exchange.DeleteMailFolder(suite.connector.Service(), suite.user, *aFolder.GetId())
|
||||||
assert.NoError(suite.T(), err)
|
assert.NoError(suite.T(), err)
|
||||||
@ -294,6 +315,7 @@ func (suite *GraphConnectorIntegrationSuite) TestCreateAndDeleteContactFolder()
|
|||||||
folderName := "TestContactFolder: " + common.FormatSimpleDateTime(now)
|
folderName := "TestContactFolder: " + common.FormatSimpleDateTime(now)
|
||||||
aFolder, err := exchange.CreateContactFolder(suite.connector.Service(), suite.user, folderName)
|
aFolder, err := exchange.CreateContactFolder(suite.connector.Service(), suite.user, folderName)
|
||||||
assert.NoError(suite.T(), err)
|
assert.NoError(suite.T(), err)
|
||||||
|
|
||||||
if aFolder != nil {
|
if aFolder != nil {
|
||||||
err = exchange.DeleteContactFolder(suite.connector.Service(), suite.user, *aFolder.GetId())
|
err = exchange.DeleteContactFolder(suite.connector.Service(), suite.user, *aFolder.GetId())
|
||||||
assert.NoError(suite.T(), err)
|
assert.NoError(suite.T(), err)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user