GC: Restore Event to M365 user account feature (#711)
## Description logic and orchestration to take byte representation of M365 event, create a Corso calendar, and place the event and calendar into the M365 user's account. ## Type of change Please check the type of change your PR introduces: - [x] 🌻 Feature ## Issue(s) <!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. --> closes #599 closes #710 Requires PR #708 to ensure test folder is where events are created. ## Test Plan <!-- How will this be tested prior to merging.--> - [x] ⚡ Unit test
This commit is contained in:
parent
3d9aa326e8
commit
7a25a7b70e
@ -76,9 +76,10 @@ func (suite *EventSuite) TestEventInfo() {
|
|||||||
bytes := mockconnector.GetMockEventBytes("Test Mock")
|
bytes := mockconnector.GetMockEventBytes("Test Mock")
|
||||||
event, err := support.CreateEventFromBytes(bytes)
|
event, err := support.CreateEventFromBytes(bytes)
|
||||||
require.NoError(suite.T(), err)
|
require.NoError(suite.T(), err)
|
||||||
subject := " Test MockReview + Lunch"
|
subject := " Test Mock Review + Lunch"
|
||||||
organizer := "foobar3@8qzvrj.onmicrosoft.com"
|
organizer := "foobar3@8qzvrj.onmicrosoft.com"
|
||||||
eventTime := time.Date(2022, time.April, 28, 3, 41, 58, 0, time.UTC)
|
future := time.Now().AddDate(0, 0, 1)
|
||||||
|
eventTime := time.Date(2022, future.Month(), future.Day(), 6, 0, 0, 0, time.UTC)
|
||||||
i := &details.ExchangeInfo{
|
i := &details.ExchangeInfo{
|
||||||
ItemType: details.ExchangeEvent,
|
ItemType: details.ExchangeEvent,
|
||||||
Subject: subject,
|
Subject: subject,
|
||||||
|
|||||||
@ -410,7 +410,7 @@ func (suite *ExchangeServiceSuite) TestGetContainerID() {
|
|||||||
// the Corso Folder. The function handles test clean-up.
|
// the Corso Folder. The function handles test clean-up.
|
||||||
func (suite *ExchangeServiceSuite) TestRestoreContact() {
|
func (suite *ExchangeServiceSuite) TestRestoreContact() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
userID := tester.M365UserID(suite.T())
|
userID := tester.M365UserID(t)
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
folderName := "TestRestoreContact: " + common.FormatSimpleDateTime(now)
|
folderName := "TestRestoreContact: " + common.FormatSimpleDateTime(now)
|
||||||
@ -430,6 +430,28 @@ func (suite *ExchangeServiceSuite) TestRestoreContact() {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestRestoreEvent verifies that event object is able to created
|
||||||
|
// and sent into the test account of the Corso user in the newly created Corso Calendar
|
||||||
|
func (suite *ExchangeServiceSuite) TestRestoreEvent() {
|
||||||
|
t := suite.T()
|
||||||
|
userID := tester.M365UserID(t)
|
||||||
|
name := "TestRestoreEvent: " + common.FormatSimpleDateTime(time.Now())
|
||||||
|
calendar, err := CreateCalendar(suite.es, userID, name)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
calendarID := *calendar.GetId()
|
||||||
|
err = RestoreExchangeEvent(context.Background(),
|
||||||
|
mockconnector.GetMockEventBytes("Restore Event "),
|
||||||
|
suite.es,
|
||||||
|
control.Copy,
|
||||||
|
calendarID,
|
||||||
|
userID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
// Removes calendar containing events created during the test
|
||||||
|
err = DeleteCalendar(suite.es, userID, *calendar.GetId())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
// TestGetRestoreContainer 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) TestGetRestoreContainer() {
|
func (suite *ExchangeServiceSuite) TestGetRestoreContainer() {
|
||||||
|
|||||||
@ -369,6 +369,8 @@ func RestoreExchangeObject(
|
|||||||
return RestoreMailMessage(ctx, bits, service, control.Copy, destination, user)
|
return RestoreMailMessage(ctx, bits, service, control.Copy, destination, user)
|
||||||
case contacts:
|
case contacts:
|
||||||
return RestoreExchangeContact(ctx, bits, service, control.Copy, destination, user)
|
return RestoreExchangeContact(ctx, bits, service, control.Copy, destination, user)
|
||||||
|
case events:
|
||||||
|
return RestoreExchangeEvent(ctx, bits, service, control.Copy, destination, user)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("type: %s not supported for exchange restore", category)
|
return fmt.Errorf("type: %s not supported for exchange restore", category)
|
||||||
}
|
}
|
||||||
@ -404,6 +406,30 @@ func RestoreExchangeContact(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RestoreExchangeEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
bits []byte,
|
||||||
|
service graph.Service,
|
||||||
|
cp control.CollisionPolicy,
|
||||||
|
destination, user string,
|
||||||
|
) error {
|
||||||
|
event, err := support.CreateEventFromBytes(bits)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := service.Client().UsersById(user).CalendarsById(destination).Events().Post(event)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, support.ConnectorStackErrorTrace(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
if response == nil {
|
||||||
|
return errors.New("msgraph event post fail: REST response not received")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// RestoreMailMessage utility function to place an exchange.Mail
|
// RestoreMailMessage utility function to place an exchange.Mail
|
||||||
// message into the user's M365 Exchange account.
|
// message into the user's M365 Exchange account.
|
||||||
// @param bits - byte array representation of exchange.Message from Corso backstore
|
// @param bits - byte array representation of exchange.Message from Corso backstore
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package mockconnector
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@ -122,17 +123,32 @@ func GetMockContactBytes(middleName string) []byte {
|
|||||||
|
|
||||||
// GetMockEventBytes returns test byte array representative of full Eventable item.
|
// GetMockEventBytes returns test byte array representative of full Eventable item.
|
||||||
func GetMockEventBytes(subject string) []byte {
|
func GetMockEventBytes(subject string) []byte {
|
||||||
|
newTime := time.Now().AddDate(0, 0, 1)
|
||||||
|
conversion := common.FormatTime(newTime)
|
||||||
|
timeSlice := strings.Split(conversion, "T")
|
||||||
|
|
||||||
//nolint:lll
|
//nolint:lll
|
||||||
event := "{\"id\":\"AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAADSEBNbUIB9RL6ePDeF3FIYAAAAAG76AAA=\",\"calendar@odata.navigationLink\":\"https://graph.microsoft.com/v1.0/users('foobar@8qzvrj.onmicrosoft.com')/calendars('AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwAuAAAAAADCNgjhM9QmQYWNcI7hCpPrAQDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAAA=')\",\"calendar@odata.associationLink\":\"https://graph.microsoft.com/v1.0/users('foobar@8qzvrj.onmicrosoft.com')/calendars('AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwAuAAAAAADCNgjhM9QmQYWNcI7hCpPrAQDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAAA=')/$ref\"," +
|
event := "{\"id\":\"AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAADSEBNbUIB9RL6ePDeF3FIYAAAAAG76AAA=\",\"calendar@odata.navigationLink\":" +
|
||||||
"\"@odata.etag\":\"W/\\\"0hATW1CAfUS+njw3hdxSGAAAJIxNug==\\\"\",\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('foobar%408qzvrj.onmicrosoft.com')/events/$entity\",\"categories\":[],\"changeKey\":\"0hATW1CAfUS+njw3hdxSGAAAJIxNug==\",\"createdDateTime\":\"2022-03-28T03:42:03Z\",\"lastModifiedDateTime\":\"2022-05-26T19:25:58Z\",\"allowNewTimeProposals\":true,\"attendees\"" +
|
"\"https://graph.microsoft.com/v1.0/users('foobar@8qzvrj.onmicrosoft.com')/calendars('AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwAuAAAAAADCNgjhM9QmQYWNcI7hCpPrAQDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAAA=')\"," +
|
||||||
|
"\"calendar@odata.associationLink\":\"https://graph.microsoft.com/v1.0/users('foobar@8qzvrj.onmicrosoft.com')/calendars('AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwAuAAAAAADCNgjhM9QmQYWNcI7hCpPrAQDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAAA=')/$ref\"," +
|
||||||
|
"\"@odata.etag\":\"W/\\\"0hATW1CAfUS+njw3hdxSGAAAJIxNug==\\\"\",\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('foobar%408qzvrj.onmicrosoft.com')/events/$entity\",\"categories\":[],\"changeKey\":\"0hATW1CAfUS+njw3hdxSGAAAJIxNug==\"," +
|
||||||
|
"\"createdDateTime\":\"2022-03-28T03:42:03Z\",\"lastModifiedDateTime\":\"2022-05-26T19:25:58Z\",\"allowNewTimeProposals\":true,\"attendees\"" +
|
||||||
":[{\"emailAddress\":{\"address\":\"foobar@8qzvrj.onmicrosoft.com\",\"name\":\"Fuu Gu\"},\"type\":\"required\",\"status\"" +
|
":[{\"emailAddress\":{\"address\":\"foobar@8qzvrj.onmicrosoft.com\",\"name\":\"Fuu Gu\"},\"type\":\"required\",\"status\"" +
|
||||||
":{\"response\":\"none\",\"time\":\"0001-01-01T00:00:00Z\"}},{\"emailAddress\":{\"address\":\"foobar1@8qzvrj.onmicrosoft.com\",\"name\":\"Fuu Bar\"},\"type\":\"required\"" +
|
":{\"response\":\"none\",\"time\":\"0001-01-01T00:00:00Z\"}},{\"emailAddress\":{\"address\":\"foobar1@8qzvrj.onmicrosoft.com\",\"name\":\"Fuu Bar\"},\"type\":\"required\"" +
|
||||||
",\"status\":{\"response\":\"none\",\"time\":\"0001-01-01T00:00:00Z\"}},{\"emailAddress\":{\"address\":\"foobar2@8qzvrj.onmicrosoft.com\",\"name\":\"Ru Buu\"},\"type\":\"required\",\"status\":{\"response\":\"none\",\"time\":\"0001-01-01T00:00:00Z\"}}],\"body\":{\"content\":\"<html>\\r\\n<head>\\r\\n<meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html; charset=utf-8\\\">\\r\\n</head>\\r\\n<body>\\r\\n<p>This meeting is to review the latest Tailspin Toys project proposal.<br>\\r\\nBut why not eat some sushi while we’re at it? :)</p>\\r\\n</body>\\r\\n</html>\\r\\n\"" +
|
",\"status\":{\"response\":\"none\",\"time\":\"0001-01-01T00:00:00Z\"}},{\"emailAddress\":{\"address\":\"foobar2@8qzvrj.onmicrosoft.com\",\"name\":\"Ru Buu\"}," +
|
||||||
",\"contentType\":\"html\"},\"bodyPreview\":\"This meeting is to review the latest Tailspin Toys project proposal.\\r\\nBut why not eat some sushi while we’re at it? :)\",\"end\":{\"dateTime\":\"2022-04-28T04:41:58.0000000\",\"timeZone\":\"UTC\"},\"hasAttachments\":false,\"hideAttendees\":false,\"iCalUId\":\"040000008200E00074C5B7101A82E0080000000035723BC75542D801000000000000000010000000E1E7C8F785242E4894DA13AEFB947B85\",\"importance\":\"normal\",\"isAllDay\":false,\"isCancelled\":false,\"isDraft\":false,\"isOnlineMeeting\":false,\"isOrganizer\":false,\"isReminderOn\":true," +
|
"\"type\":\"required\",\"status\":{\"response\":\"none\",\"time\":\"0001-01-01T00:00:00Z\"}}],\"body\":{\"content\":\"<html>\\r\\n<head>\\r\\n<meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html; charset=utf-8\\\">\\r\\n</head>\\r\\n<body>\\r\\n" +
|
||||||
"\"location\":{\"displayName\":\"Umi Sake House (2230 1st Ave, Seattle, WA 98121 US)\",\"locationType\":\"default\",\"uniqueId\":\"Umi Sake House (2230 1st Ave, Seattle, WA 98121 US)\",\"uniqueIdType\":\"private\"},\"locations\":[{\"displayName\":\"Umi Sake House (2230 1st Ave, Seattle, WA 98121 US)\",\"locationType\":\"default\",\"uniqueId\":\"\",\"uniqueIdType\":\"unknown\"}],\"onlineMeetingProvider\":\"unknown\",\"organizer\"" +
|
"<p>This meeting is to review the latest Tailspin Toys project proposal.<br>\\r\\nBut why not eat some sushi while we’re at it? :)</p>\\r\\n</body>\\r\\n</html>\\r\\n\"" +
|
||||||
":{\"emailAddress\":{\"address\":\"foobar3@8qzvrj.onmicrosoft.com\",\"name\":\"Anu Pierson\"}},\"originalEndTimeZone\":\"UTC\",\"originalStartTimeZone\":\"UTC\",\"reminderMinutesBeforeStart\":15,\"responseRequested\":true,\"responseStatus\":{\"response\":\"notResponded\",\"time\":\"0001-01-01T00:00:00Z\"},\"sensitivity\":\"normal\",\"showAs\":\"tentative\",\"start\":{\"dateTime\":\"2022-04-28T03:41:58.0000000\",\"timeZone\":\"UTC\"}," +
|
",\"contentType\":\"html\"},\"bodyPreview\":\"This meeting is to review the latest Tailspin Toys project proposal.\\r\\nBut why not eat some sushi while we’re at it? :)\"," +
|
||||||
|
"\"end\":{\"dateTime\":\"" + timeSlice[0] + "T07:00:00.0000000\",\"timeZone\":\"UTC\"},\"hasAttachments\":false,\"hideAttendees\":false,\"iCalUId\":" +
|
||||||
|
"\"040000008200E00074C5B7101A82E0080000000035723BC75542D801000000000000000010000000E1E7C8F785242E4894DA13AEFB947B85\",\"importance\":\"normal\",\"isAllDay\":false,\"isCancelled\":false," +
|
||||||
|
"\"isDraft\":false,\"isOnlineMeeting\":false,\"isOrganizer\":false,\"isReminderOn\":true," +
|
||||||
|
"\"location\":{\"displayName\":\"Umi Sake House (2230 1st Ave, Seattle, WA 98121 US)\",\"locationType\":\"default\",\"uniqueId\":\"Umi Sake House (2230 1st Ave, Seattle, WA 98121 US)\"," +
|
||||||
|
"\"uniqueIdType\":\"private\"},\"locations\":[{\"displayName\":\"Umi Sake House (2230 1st Ave, Seattle, WA 98121 US)\",\"locationType\":\"default\",\"uniqueId\":\"\",\"uniqueIdType\":\"unknown\"}],\"onlineMeetingProvider\":\"unknown\",\"organizer\"" +
|
||||||
|
":{\"emailAddress\":{\"address\":\"foobar3@8qzvrj.onmicrosoft.com\",\"name\":\"Anu Pierson\"}},\"originalEndTimeZone\":\"UTC\",\"originalStartTimeZone\":\"UTC\"," +
|
||||||
|
"\"reminderMinutesBeforeStart\":15,\"responseRequested\":true,\"responseStatus\":{\"response\":\"notResponded\",\"time\":\"0001-01-01T00:00:00Z\"},\"sensitivity\":\"normal\",\"showAs\":\"tentative\"," +
|
||||||
|
"\"start\":{\"dateTime\":\"" + timeSlice[0] + "T06:00:00.0000000\",\"timeZone\":\"UTC\"}," +
|
||||||
"\"subject\":\" " + subject +
|
"\"subject\":\" " + subject +
|
||||||
"Review + Lunch\",\"type\":\"singleInstance\",\"webLink\":\"https://outlook.office365.com/owa/?itemid=AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAADSEBNbUIB9RL6ePDeF3FIYAAAAAG76AAA%3D&exvsurl=1&path=/calendar/item\"}"
|
" Review + Lunch\",\"type\":\"singleInstance\",\"webLink\":\"https://outlook.office365.com/owa/?itemid=AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAENAADSEBNbUIB9RL6ePDeF3FIYAAAAAG76AAA%3D&exvsurl=1&path=/calendar/item\"}"
|
||||||
|
|
||||||
return []byte(event)
|
return []byte(event)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user