GC: Restore: Create / Delete Calendar Feature (#708)
Feature creation: Create/Delete Calendar for aM365 user added to main branch
This commit is contained in:
parent
5c59522fc2
commit
8ead744e9f
@ -5,12 +5,12 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/alcionai/corso/internal/common"
|
||||
"github.com/alcionai/corso/internal/connector/graph"
|
||||
"github.com/alcionai/corso/internal/connector/mockconnector"
|
||||
"github.com/alcionai/corso/internal/tester"
|
||||
"github.com/alcionai/corso/pkg/account"
|
||||
@ -430,61 +430,57 @@ func (suite *ExchangeServiceSuite) TestRestoreContact() {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
// TestEstablishFolder checks the ability to Create a "container" for the
|
||||
// TestGetRestoreContainer checks the ability to Create a "container" for the
|
||||
// GraphConnector's Restore Workflow based on OptionIdentifier.
|
||||
func (suite *ExchangeServiceSuite) TestEstablishFolder() {
|
||||
func (suite *ExchangeServiceSuite) TestGetRestoreContainer() {
|
||||
tests := []struct {
|
||||
name string
|
||||
option optionIdentifier
|
||||
checkError assert.ErrorAssertionFunc
|
||||
name string
|
||||
option string
|
||||
checkError assert.ErrorAssertionFunc
|
||||
cleanupFunc func(graph.Service, string, string) error
|
||||
}{
|
||||
{
|
||||
name: "Establish User Restore Folder",
|
||||
option: users,
|
||||
checkError: assert.Error,
|
||||
name: "Establish User Restore Folder",
|
||||
option: "users",
|
||||
checkError: assert.Error,
|
||||
cleanupFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "Establish Event Restore Location",
|
||||
option: events,
|
||||
checkError: assert.Error,
|
||||
name: "Establish Event Restore Location",
|
||||
option: "events",
|
||||
checkError: assert.NoError,
|
||||
cleanupFunc: DeleteCalendar,
|
||||
},
|
||||
{
|
||||
name: "Establish Restore Folder for Unknown",
|
||||
option: unknown,
|
||||
checkError: assert.Error,
|
||||
name: "Establish Restore Folder for Unknown",
|
||||
option: "unknown",
|
||||
checkError: assert.Error,
|
||||
cleanupFunc: nil,
|
||||
},
|
||||
{
|
||||
name: "Establish Restore folder for Mail",
|
||||
option: messages,
|
||||
checkError: assert.NoError,
|
||||
name: "Establish Restore folder for Mail",
|
||||
option: "mail",
|
||||
checkError: assert.NoError,
|
||||
cleanupFunc: DeleteMailFolder,
|
||||
},
|
||||
{
|
||||
name: "Establish Restore folder for Contacts",
|
||||
option: contacts,
|
||||
checkError: assert.NoError,
|
||||
name: "Establish Restore folder for Contacts",
|
||||
option: "contacts",
|
||||
checkError: assert.NoError,
|
||||
cleanupFunc: DeleteContactFolder,
|
||||
},
|
||||
}
|
||||
now := time.Now()
|
||||
folderName := "CorsoEstablishFolder" + common.FormatSimpleDateTime(now)
|
||||
|
||||
userID := tester.M365UserID(suite.T())
|
||||
|
||||
for _, test := range tests {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
folderID, err := establishFolder(suite.es, folderName, userID, test.option)
|
||||
containerID, err := GetRestoreContainer(suite.es, userID, test.option)
|
||||
require.True(t, test.checkError(t, err))
|
||||
if folderID != "" {
|
||||
switch test.option {
|
||||
case messages:
|
||||
err = DeleteMailFolder(suite.es, userID, folderID)
|
||||
assert.NoError(t, err)
|
||||
case contacts:
|
||||
err = DeleteContactFolder(suite.es, userID, folderID)
|
||||
assert.NoError(t, err)
|
||||
default:
|
||||
assert.NoError(t,
|
||||
errors.New("unsupported type received folderID: "+test.option.String()),
|
||||
)
|
||||
}
|
||||
|
||||
if test.cleanupFunc != nil {
|
||||
err = test.cleanupFunc(suite.es, userID, containerID)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -90,6 +90,21 @@ type MailFolder struct {
|
||||
DisplayName string
|
||||
}
|
||||
|
||||
// CreateCalendar makes an event Calendar with the name in the user's M365 exchange account
|
||||
// Reference: https://docs.microsoft.com/en-us/graph/api/user-post-calendars?view=graph-rest-1.0&tabs=go
|
||||
func CreateCalendar(gs graph.Service, user, calendarName string) (models.Calendarable, error) {
|
||||
requestbody := models.NewCalendar()
|
||||
requestbody.SetName(&calendarName)
|
||||
|
||||
return gs.Client().UsersById(user).Calendars().Post(requestbody)
|
||||
}
|
||||
|
||||
// DeleteCalendar removes calendar from user's M365 account
|
||||
// Reference: https://docs.microsoft.com/en-us/graph/api/calendar-delete?view=graph-rest-1.0&tabs=go
|
||||
func DeleteCalendar(gs graph.Service, user, calendarID string) error {
|
||||
return gs.Client().UsersById(user).CalendarsById(calendarID).Delete()
|
||||
}
|
||||
|
||||
// CreateContactFolder makes a contact folder with the displayName of folderName.
|
||||
// If successful, returns the created folder object.
|
||||
func CreateContactFolder(gs graph.Service, user, folderName string) (models.ContactFolderable, error) {
|
||||
@ -176,7 +191,7 @@ func GetContainerID(service graph.Service, containerName, user string, category
|
||||
transform = models.CreateCalendarCollectionResponseFromDiscriminatorValue
|
||||
isCalendar = true
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported category %s for GetFolderID()", category)
|
||||
return nil, fmt.Errorf("unsupported category %s for GetContainerID()", category)
|
||||
}
|
||||
|
||||
response, err := query(service, user)
|
||||
@ -197,7 +212,7 @@ func GetContainerID(service graph.Service, containerName, user string, category
|
||||
return nil, err
|
||||
}
|
||||
|
||||
callbackFunc := iterateFindFolderID(
|
||||
callbackFunc := iterateFindContainerID(
|
||||
&targetID,
|
||||
containerName,
|
||||
service.Adapter().GetBaseUrl(),
|
||||
@ -281,30 +296,18 @@ func SetupExchangeCollectionVars(scope selectors.ExchangeScope) (
|
||||
return nil, nil, nil, errors.New("exchange scope option not supported")
|
||||
}
|
||||
|
||||
// GetRestoreFolder utility function to create
|
||||
// GetRestoreContainer utility function to create
|
||||
// an unique folder for the restore process
|
||||
// @param category: input from fullPath()[2]
|
||||
// that defines the application the folder is created in.
|
||||
func GetRestoreFolder(
|
||||
func GetRestoreContainer(
|
||||
service graph.Service,
|
||||
user, category string,
|
||||
) (string, error) {
|
||||
newFolder := fmt.Sprintf("Corso_Restore_%s", common.FormatNow(common.SimpleDateTimeFormat))
|
||||
name := fmt.Sprintf("Corso_Restore_%s", common.FormatNow(common.SimpleDateTimeFormat))
|
||||
option := categoryToOptionIdentifier(category)
|
||||
|
||||
switch category {
|
||||
case mailCategory, contactsCategory:
|
||||
return establishFolder(service, newFolder, user, categoryToOptionIdentifier(category))
|
||||
default:
|
||||
return "", fmt.Errorf("%s category not supported", category)
|
||||
}
|
||||
}
|
||||
|
||||
func establishFolder(
|
||||
service graph.Service,
|
||||
folderName, user string,
|
||||
optID optionIdentifier,
|
||||
) (string, error) {
|
||||
folderID, err := GetContainerID(service, folderName, user, optID)
|
||||
folderID, err := GetContainerID(service, name, user, option)
|
||||
if err == nil {
|
||||
return *folderID, nil
|
||||
}
|
||||
@ -313,23 +316,30 @@ func establishFolder(
|
||||
return "", support.WrapAndAppend(user, err, err)
|
||||
}
|
||||
|
||||
switch optID {
|
||||
switch option {
|
||||
case messages:
|
||||
fold, err := CreateMailFolder(service, user, folderName)
|
||||
fold, err := CreateMailFolder(service, user, name)
|
||||
if err != nil {
|
||||
return "", support.WrapAndAppend(user, err, err)
|
||||
}
|
||||
|
||||
return *fold.GetId(), nil
|
||||
case contacts:
|
||||
fold, err := CreateContactFolder(service, user, folderName)
|
||||
fold, err := CreateContactFolder(service, user, name)
|
||||
if err != nil {
|
||||
return "", support.WrapAndAppend(user, err, err)
|
||||
}
|
||||
|
||||
return *fold.GetId(), nil
|
||||
case events:
|
||||
calendar, err := CreateCalendar(service, user, name)
|
||||
if err != nil {
|
||||
return "", support.WrapAndAppend(user, err, err)
|
||||
}
|
||||
|
||||
return *calendar.GetId(), nil
|
||||
default:
|
||||
return "", fmt.Errorf("category: %s not supported for folder creation", optID)
|
||||
return "", fmt.Errorf("category: %s not supported for folder creation", option)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -299,14 +299,16 @@ func IterateFilterFolderDirectoriesForCollections(
|
||||
}
|
||||
}
|
||||
|
||||
// iterateFindFolderID is a utility function that supports finding
|
||||
// iterateFindContainerID is a utility function that supports finding
|
||||
// M365 folders objects that matches the folderName. Iterator callback function
|
||||
// will work on folderCollection responses whose objects implement
|
||||
// the displayable interface. If folder exists, the function updates the
|
||||
// folderID memory address that was passed in.
|
||||
func iterateFindFolderID(
|
||||
folderID **string,
|
||||
folderName, errorIdentifier string,
|
||||
// containerID memory address that was passed in.
|
||||
// @param containerName is the string representation of the folder, directory or calendar holds
|
||||
// the underlying M365 objects
|
||||
func iterateFindContainerID(
|
||||
containerID **string,
|
||||
containerName, errorIdentifier string,
|
||||
isCalendar bool,
|
||||
errs error,
|
||||
) func(any) bool {
|
||||
@ -334,12 +336,12 @@ func iterateFindFolderID(
|
||||
return true
|
||||
}
|
||||
|
||||
if folderName == *folder.GetDisplayName() {
|
||||
if containerName == *folder.GetDisplayName() {
|
||||
if folder.GetId() == nil {
|
||||
return true // invalid folder
|
||||
}
|
||||
|
||||
*folderID = folder.GetId()
|
||||
*containerID = folder.GetId()
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@ -263,7 +263,7 @@ func (gc *GraphConnector) RestoreExchangeDataCollection(
|
||||
|
||||
if _, ok := pathCounter[directory]; !ok {
|
||||
pathCounter[directory] = true
|
||||
folderID, errs = exchange.GetRestoreFolder(&gc.graphService, user, category)
|
||||
folderID, errs = exchange.GetRestoreContainer(&gc.graphService, user, category)
|
||||
|
||||
if errs != nil {
|
||||
return errs
|
||||
|
||||
@ -321,3 +321,18 @@ func (suite *GraphConnectorIntegrationSuite) TestCreateAndDeleteContactFolder()
|
||||
assert.NoError(suite.T(), err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestCreateAndDeleteCalendar verifies GraphConnector has the ability to create and remove
|
||||
// exchange.Event.Calendars within the tenant
|
||||
func (suite *GraphConnectorIntegrationSuite) TestCreateAndDeleteCalendar() {
|
||||
now := time.Now()
|
||||
service := suite.connector.Service()
|
||||
calendarName := "TestCalendar: " + common.FormatSimpleDateTime(now)
|
||||
calendar, err := exchange.CreateCalendar(service, suite.user, calendarName)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
if calendar != nil {
|
||||
err = exchange.DeleteCalendar(service, suite.user, *calendar.GetId())
|
||||
assert.NoError(suite.T(), err)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user