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"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
"github.com/alcionai/corso/internal/common"
|
"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/connector/mockconnector"
|
||||||
"github.com/alcionai/corso/internal/tester"
|
"github.com/alcionai/corso/internal/tester"
|
||||||
"github.com/alcionai/corso/pkg/account"
|
"github.com/alcionai/corso/pkg/account"
|
||||||
@ -430,61 +430,57 @@ func (suite *ExchangeServiceSuite) TestRestoreContact() {
|
|||||||
assert.NoError(t, err)
|
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.
|
// GraphConnector's Restore Workflow based on OptionIdentifier.
|
||||||
func (suite *ExchangeServiceSuite) TestEstablishFolder() {
|
func (suite *ExchangeServiceSuite) TestGetRestoreContainer() {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
option optionIdentifier
|
option string
|
||||||
checkError assert.ErrorAssertionFunc
|
checkError assert.ErrorAssertionFunc
|
||||||
|
cleanupFunc func(graph.Service, string, string) error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Establish User Restore Folder",
|
name: "Establish User Restore Folder",
|
||||||
option: users,
|
option: "users",
|
||||||
checkError: assert.Error,
|
checkError: assert.Error,
|
||||||
|
cleanupFunc: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Establish Event Restore Location",
|
name: "Establish Event Restore Location",
|
||||||
option: events,
|
option: "events",
|
||||||
checkError: assert.Error,
|
checkError: assert.NoError,
|
||||||
|
cleanupFunc: DeleteCalendar,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Establish Restore Folder for Unknown",
|
name: "Establish Restore Folder for Unknown",
|
||||||
option: unknown,
|
option: "unknown",
|
||||||
checkError: assert.Error,
|
checkError: assert.Error,
|
||||||
|
cleanupFunc: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Establish Restore folder for Mail",
|
name: "Establish Restore folder for Mail",
|
||||||
option: messages,
|
option: "mail",
|
||||||
checkError: assert.NoError,
|
checkError: assert.NoError,
|
||||||
|
cleanupFunc: DeleteMailFolder,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Establish Restore folder for Contacts",
|
name: "Establish Restore folder for Contacts",
|
||||||
option: contacts,
|
option: "contacts",
|
||||||
checkError: assert.NoError,
|
checkError: assert.NoError,
|
||||||
|
cleanupFunc: DeleteContactFolder,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
now := time.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)
|
containerID, err := GetRestoreContainer(suite.es, userID, test.option)
|
||||||
require.True(t, test.checkError(t, err))
|
require.True(t, test.checkError(t, err))
|
||||||
if folderID != "" {
|
|
||||||
switch test.option {
|
if test.cleanupFunc != nil {
|
||||||
case messages:
|
err = test.cleanupFunc(suite.es, userID, containerID)
|
||||||
err = DeleteMailFolder(suite.es, userID, folderID)
|
|
||||||
assert.NoError(t, err)
|
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()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,6 +90,21 @@ type MailFolder struct {
|
|||||||
DisplayName string
|
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.
|
// 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(gs graph.Service, user, folderName string) (models.ContactFolderable, error) {
|
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
|
transform = models.CreateCalendarCollectionResponseFromDiscriminatorValue
|
||||||
isCalendar = true
|
isCalendar = true
|
||||||
default:
|
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)
|
response, err := query(service, user)
|
||||||
@ -197,7 +212,7 @@ func GetContainerID(service graph.Service, containerName, user string, category
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
callbackFunc := iterateFindFolderID(
|
callbackFunc := iterateFindContainerID(
|
||||||
&targetID,
|
&targetID,
|
||||||
containerName,
|
containerName,
|
||||||
service.Adapter().GetBaseUrl(),
|
service.Adapter().GetBaseUrl(),
|
||||||
@ -281,30 +296,18 @@ func SetupExchangeCollectionVars(scope selectors.ExchangeScope) (
|
|||||||
return nil, nil, nil, errors.New("exchange scope option not supported")
|
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
|
// an unique folder for the restore process
|
||||||
// @param category: input from fullPath()[2]
|
// @param category: input from fullPath()[2]
|
||||||
// that defines the application the folder is created in.
|
// that defines the application the folder is created in.
|
||||||
func GetRestoreFolder(
|
func GetRestoreContainer(
|
||||||
service graph.Service,
|
service graph.Service,
|
||||||
user, category string,
|
user, category string,
|
||||||
) (string, error) {
|
) (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 {
|
folderID, err := GetContainerID(service, name, user, option)
|
||||||
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)
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return *folderID, nil
|
return *folderID, nil
|
||||||
}
|
}
|
||||||
@ -313,23 +316,30 @@ func establishFolder(
|
|||||||
return "", support.WrapAndAppend(user, err, err)
|
return "", support.WrapAndAppend(user, err, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch optID {
|
switch option {
|
||||||
case messages:
|
case messages:
|
||||||
fold, err := CreateMailFolder(service, user, folderName)
|
fold, err := CreateMailFolder(service, user, name)
|
||||||
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, name)
|
||||||
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 events:
|
||||||
|
calendar, err := CreateCalendar(service, user, name)
|
||||||
|
if err != nil {
|
||||||
|
return "", support.WrapAndAppend(user, err, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return *calendar.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", 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
|
// M365 folders objects that matches the folderName. Iterator callback function
|
||||||
// will work on folderCollection responses whose objects implement
|
// will work on folderCollection responses whose objects implement
|
||||||
// the displayable interface. If folder exists, the function updates the
|
// the displayable interface. If folder exists, the function updates the
|
||||||
// folderID memory address that was passed in.
|
// containerID memory address that was passed in.
|
||||||
func iterateFindFolderID(
|
// @param containerName is the string representation of the folder, directory or calendar holds
|
||||||
folderID **string,
|
// the underlying M365 objects
|
||||||
folderName, errorIdentifier string,
|
func iterateFindContainerID(
|
||||||
|
containerID **string,
|
||||||
|
containerName, errorIdentifier string,
|
||||||
isCalendar bool,
|
isCalendar bool,
|
||||||
errs error,
|
errs error,
|
||||||
) func(any) bool {
|
) func(any) bool {
|
||||||
@ -334,12 +336,12 @@ func iterateFindFolderID(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if folderName == *folder.GetDisplayName() {
|
if containerName == *folder.GetDisplayName() {
|
||||||
if folder.GetId() == nil {
|
if folder.GetId() == nil {
|
||||||
return true // invalid folder
|
return true // invalid folder
|
||||||
}
|
}
|
||||||
|
|
||||||
*folderID = folder.GetId()
|
*containerID = folder.GetId()
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -263,7 +263,7 @@ func (gc *GraphConnector) RestoreExchangeDataCollection(
|
|||||||
|
|
||||||
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.GetRestoreContainer(&gc.graphService, user, category)
|
||||||
|
|
||||||
if errs != nil {
|
if errs != nil {
|
||||||
return errs
|
return errs
|
||||||
|
|||||||
@ -321,3 +321,18 @@ func (suite *GraphConnectorIntegrationSuite) TestCreateAndDeleteContactFolder()
|
|||||||
assert.NoError(suite.T(), err)
|
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