From 6457e498822ceb9d418639c696c95eff479da00b Mon Sep 17 00:00:00 2001 From: Danny Date: Mon, 2 Jan 2023 16:39:36 -0500 Subject: [PATCH] GC: Restore: SharePoint: ListItem modification on upload (#2011) ## Description Functions for encapsulation of ListItem object for restore workflow. ListItems bytes cannot be uploaded with previous M365 IDs from the original ListItems. Upload functions remove `ETags`, `M365IDs`, and other fields that are not permitted upon ListItem creation. ## Does this PR need a docs update or release note? - [x] :no_entry: No ## Type of change - [x] :sunflower: Feature ## Issue(s) Related: - #1935 ## Test Plan - [x] :zap: Unit test --- .../connector/support/m365Transform.go | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/internal/connector/support/m365Transform.go b/src/internal/connector/support/m365Transform.go index 9d8d8c35c..14fa0cb5d 100644 --- a/src/internal/connector/support/m365Transform.go +++ b/src/internal/connector/support/m365Transform.go @@ -120,6 +120,63 @@ func insertStringToBody(body getContenter, newContent string) string { return newContent + content } +// CloneListItem creates a new `SharePoint.ListItem` and stores the original item's +// M365 data into it set fields. +// - https://learn.microsoft.com/en-us/graph/api/resources/listitem?view=graph-rest-1.0 +func CloneListItem(orig models.ListItemable) models.ListItemable { + newItem := models.NewListItem() + newFieldData := retrieveFieldData(orig.GetFields()) + + newItem.SetAdditionalData(orig.GetAdditionalData()) + newItem.SetAnalytics(orig.GetAnalytics()) + newItem.SetContentType(orig.GetContentType()) + newItem.SetCreatedBy(orig.GetCreatedBy()) + newItem.SetCreatedByUser(orig.GetCreatedByUser()) + newItem.SetCreatedDateTime(orig.GetCreatedDateTime()) + newItem.SetDescription(orig.GetDescription()) + // ETag cannot be carried forward + newItem.SetFields(newFieldData) + newItem.SetLastModifiedBy(orig.GetLastModifiedBy()) + newItem.SetLastModifiedByUser(orig.GetLastModifiedByUser()) + newItem.SetLastModifiedDateTime(orig.GetLastModifiedDateTime()) + newItem.SetOdataType(orig.GetOdataType()) + // parentReference and SharePointIDs cause error on upload. + // POST Command will link items to the created list. + newItem.SetVersions(orig.GetVersions()) + + return newItem +} + +// retrieveFieldData utility function to clone raw listItem data from the embedded +// additionalData map +// Further details on FieldValueSets: +// - https://learn.microsoft.com/en-us/graph/api/resources/fieldvalueset?view=graph-rest-1.0 +func retrieveFieldData(orig models.FieldValueSetable) models.FieldValueSetable { + fields := models.NewFieldValueSet() + additionalData := make(map[string]any) + fieldData := orig.GetAdditionalData() + + // M365 Book keeping values removed during new Item Creation + // Removed Values: + // -- Prefixes -> @odata.context : absolute path to previous list + // . -> @odata.etag : Embedded link to Prior M365 ID + // -- String Match: Read-Only Fields + // -> id : previous un + for key, value := range fieldData { + if strings.HasPrefix(key, "_") || strings.HasPrefix(key, "@") || + key == "Edit" || key == "Created" || key == "Modified" || + strings.Contains(key, "LookupId") || strings.Contains(key, "ChildCount") || strings.Contains(key, "LinkTitle") { + continue + } + + additionalData[key] = value + } + + fields.SetAdditionalData(additionalData) + + return fields +} + // ToListable utility function to encapsulate stored data for restoration. // New Listable omits trackable fields such as `id` or `ETag` and other read-only // objects that are prevented upon upload. Additionally, read-Only columns are