skips lists with certain templates from being backed-up (#4931)

skips documentLibrary templated lists from:
- restoration
- details

but the lists with 'documentLibrary' are backed-up.
this is in addition to 'webTemplateExtensionsList' templated lists which were previously skipped from restore.

the `skipping` of lists with template 'documentLibrary' is temporary and to be enabled with correct handling.

**update:27/12/2023**
skips `documentLibrary`, `sharingLinks`, `webTemplateExtensionsList` templated lists from being backed-up altogether


site contents of `https://10rqc2.sharepoint.com/sites/CorsoCI`:
![Screenshot from 2023-12-23 20-20-45](https://github.com/alcionai/corso/assets/48874082/c31bf233-57c9-497d-bb59-2dab0ffc5dab)

backup details
```
./corso backup details sharepoint --backup 5e0a13b0-bff0-471b-8860-2aec869717b2
Logging to file: /home/hitesh/.cache/corso/logs/2023-12-23T14-52-37Z.log
Connecting to M365                               done 
Connecting to repository                     30s done 
  ID            List                                                     Items  Created               Modified            
  c7ffe2f0a275  Test List                                                0      2023-05-12T12:28:51Z  2023-05-12T12:28:51Z
  5345df87b565  Meh                                                      0      2023-05-12T12:59:50Z  2023-05-12T12:59:50Z
  cd2854591ab4  corso-restore-list_135b9067-0e19-4a5c-9475-ced51730c211  0      2023-12-11T10:25:27Z  2023-12-23T13:19:24Z
  0f56b7f450fa  corsorestorelist_newlist                                 0      2023-12-11T10:31:54Z  2023-12-11T10:31:54Z
  3a7be2fb9d50  new list                                                 0      2023-11-29T18:29:07Z  2023-11-29T18:29:07Z
  edab0c775e5e  New List Name                                            0      2023-05-12T12:39:06Z  2023-12-23T13:25:39Z
  4d7ad9b1df98  MockListing                                              0      2023-05-12T12:15:14Z  2023-12-14T06:22:36Z
  d2bdca596f75  integration-test-list                                    6      2023-11-30T06:57:01Z  2023-12-14T06:09:45Z
  c9eccc9771a3  Sharing Links                                            74     2023-06-26T07:21:31Z  2023-12-14T06:06:31Z
  5e79dcd93c92  New List Name 2                                          0      2023-05-12T12:40:15Z  2023-05-12T12:40:15Z
  6a6acbaa0d10  corsorestorelist_7f99d792-cae0-4a87-9e68-fd930f5b123e    0      2023-12-11T10:28:25Z  2023-12-23T13:19:57Z
```

restore details
```
./corso restore sharepoint --backup 5e0a13b0-bff0-471b-8860-2aec869717b2
Logging to file: /home/hitesh/.cache/corso/logs/2023-12-23T14-53-37Z.log
Connecting to M365                               done 
Connecting to repository                     26s done 
Restoring to folder Corso_Restore_23-Dec-2023_14-54-05
  
Restoring ∙ https://10rqc2.sharepoint.com/sites/CorsoCI              
Discovered 11 items in backup 5e0a13b0-bff0-471b-8860-2aec869717b2 to restore   
Enumerating items in repository             1m2s done 
Restoring data                               50s done 
Restore Complete
Restored 11 items
  ID            List                                                                                        Items  Created               Modified            
  edab0c775e5e  Corso_Restore_23-Dec-2023_14-54-05_New List Name                                            0      2023-12-23T14:54:23Z  2023-12-23T14:54:23Z
  cd2854591ab4  Corso_Restore_23-Dec-2023_14-54-05_corso-restore-list_135b9067-0e19-4a5c-9475-ced51730c211  0      2023-12-23T14:54:25Z  2023-12-23T14:54:25Z
  5345df87b565  Corso_Restore_23-Dec-2023_14-54-05_Meh                                                      0      2023-12-23T14:54:26Z  2023-12-23T14:54:26Z
  4d7ad9b1df98  Corso_Restore_23-Dec-2023_14-54-05_MockListing                                              0      2023-12-23T14:54:28Z  2023-12-23T14:54:28Z
  d2bdca596f75  Corso_Restore_23-Dec-2023_14-54-05_integration-test-list                                    6      2023-12-23T14:54:29Z  2023-12-23T14:54:31Z
  c7ffe2f0a275  Corso_Restore_23-Dec-2023_14-54-05_Test List                                                0      2023-12-23T14:54:34Z  2023-12-23T14:54:34Z
  c9eccc9771a3  Corso_Restore_23-Dec-2023_14-54-05_Sharing Links                                            74     2023-12-23T14:54:36Z  2023-12-23T14:54:36Z
  5e79dcd93c92  Corso_Restore_23-Dec-2023_14-54-05_New List Name 2                                          0      2023-12-23T14:55:09Z  2023-12-23T14:55:09Z
  6a6acbaa0d10  Corso_Restore_23-Dec-2023_14-54-05_corsorestorelist_7f99d792-cae0-4a87-9e68-fd930f5b123e    0      2023-12-23T14:55:10Z  2023-12-23T14:55:10Z
  0f56b7f450fa  Corso_Restore_23-Dec-2023_14-54-05_corsorestorelist_newlist                                 0      2023-12-23T14:55:11Z  2023-12-23T14:55:11Z
```


#### Does this PR need a docs update or release note?
- [x]  No

#### Type of change

<!--- Please check the type of change your PR introduces: --->
- [x] 🐛 Bugfix

#### Issue(s)
#4754 

#### Test Plan

<!-- How will this be tested prior to merging.-->
- [x] 💪 Manual
- [x]  Unit test
- [x] 💚 E2E
This commit is contained in:
Hitesh Pattanayak 2023-12-28 22:29:23 +05:30 committed by GitHub
parent 2be9b3f301
commit 823fcdc559
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 120 additions and 30 deletions

View File

@ -210,13 +210,17 @@ func RestoreListCollection(
siteID,
restoreContainerName,
errs)
if err != nil &&
errors.Is(err, api.ErrSkippableListTemplate) {
if errors.Is(err, api.ErrSkippableListTemplate) {
// should never be encountered as lists with skippable template are not backed up
// this is an additional check
logger.Ctx(ctx).Info("failed to create listItem due to skippable template")
continue
}
if err != nil {
el.AddRecoverable(ctx, err)
logger.CtxErr(ctx, err).Info("failed to create listItem")
el.AddRecoverable(ctx, clues.WrapWC(ctx, err, "failed to create listItem"))
continue
}
@ -224,7 +228,9 @@ func RestoreListCollection(
itemPath, err := dc.FullPath().AppendItem(itemData.ID())
if err != nil {
logger.CtxErr(ctx, err).Info("failed to append item id to full path")
el.AddRecoverable(ctx, clues.WrapWC(ctx, err, "appending item to full path"))
continue
}

View File

@ -96,16 +96,58 @@ func (suite *SharePointRestoreSuite) TestListCollection_Restore_invalidListTempl
ctx, flush := tester.NewContext(t)
defer flush()
_, lrh, destName, mockData := setupDependencies(
suite,
suite.ac,
suite.siteID,
suite.creds,
api.WebTemplateExtensionsListTemplateName)
tests := []struct {
name string
getParams func() (listsRestoreHandler, string, *dataMock.Item)
expect assert.ErrorAssertionFunc
}{
{
name: "list with template documentLibrary",
getParams: func() (listsRestoreHandler, string, *dataMock.Item) {
_, lrh, destName, mockData := setupDependencies(
suite,
suite.ac,
suite.siteID,
suite.creds,
api.DocumentLibraryListTemplateName)
_, err := restoreListItem(ctx, lrh, mockData, suite.siteID, destName, fault.New(true))
require.Error(t, err)
assert.Contains(t, err.Error(), api.ErrSkippableListTemplate.Error())
return lrh, destName, mockData
},
expect: assert.Error,
},
{
name: "list with template webTemplateExtensionsList",
getParams: func() (listsRestoreHandler, string, *dataMock.Item) {
_, lrh, destName, mockData := setupDependencies(
suite,
suite.ac,
suite.siteID,
suite.creds,
api.WebTemplateExtensionsListTemplateName)
return lrh, destName, mockData
},
expect: assert.Error,
},
}
for _, test := range tests {
suite.Run(test.name, func() {
t := suite.T()
lrh, destName, mockData := test.getParams()
_, err := restoreListItem(
ctx,
lrh,
mockData,
suite.siteID,
destName,
fault.New(false))
require.Error(t, err)
assert.Contains(t, err.Error(), api.ErrSkippableListTemplate.Error())
})
}
}
func deleteList(

View File

@ -49,6 +49,10 @@ const (
DescoratorFieldNamePrefix = "@"
WebTemplateExtensionsListTemplateName = "webTemplateExtensionsList"
// This issue https://github.com/alcionai/corso/issues/4932
// tracks to backup/restore supportability of `documentLibrary` templated lists
DocumentLibraryListTemplateName = "documentLibrary"
SharingLinksListTemplateName = "sharingLinks"
)
var addressFieldNames = []string{
@ -85,6 +89,8 @@ var readOnlyFieldNames = keys.Set{
var SkipListTemplates = keys.Set{
WebTemplateExtensionsListTemplateName: {},
DocumentLibraryListTemplateName: {},
SharingLinksListTemplateName: {},
}
// ---------------------------------------------------------------------------
@ -260,8 +266,7 @@ func (c Lists) PostList(
// this ensure all columns, contentTypes are set to the newList
newList := ToListable(oldList, newListName)
if newList != nil &&
newList.GetList() != nil &&
if newList.GetList() != nil &&
SkipListTemplates.HasKey(ptr.Val(newList.GetList().GetTemplate())) {
return nil, clues.StackWC(ctx, ErrSkippableListTemplate)
}

View File

@ -771,24 +771,42 @@ func (suite *ListsAPIIntgSuite) TestLists_PostList_invalidTemplate() {
listName = testdata.DefaultRestoreConfig("list_api_post_list").Location
)
writer := kjson.NewJsonSerializationWriter()
defer writer.Close()
tests := []struct {
name string
template string
expect assert.ErrorAssertionFunc
}{
{
name: "list with template documentLibrary",
template: DocumentLibraryListTemplateName,
expect: assert.Error,
},
{
name: "list with template webTemplateExtensionsList",
template: WebTemplateExtensionsListTemplateName,
expect: assert.Error,
},
{
name: "list with template sharingLinks",
template: SharingLinksListTemplateName,
expect: assert.Error,
},
}
overrideListInfo := models.NewListInfo()
overrideListInfo.SetTemplate(ptr.To(WebTemplateExtensionsListTemplateName))
for _, test := range tests {
suite.Run(test.name, func() {
t := suite.T()
_, list := getFieldsDataAndList()
list.SetList(overrideListInfo)
err := writer.WriteObjectValue("", list)
require.NoError(t, err)
oldListByteArray, err := writer.GetSerializedContent()
require.NoError(t, err)
_, err = acl.PostList(ctx, siteID, listName, oldListByteArray, fault.New(true))
require.Error(t, err)
assert.Equal(t, ErrSkippableListTemplate.Error(), err.Error())
_, err := acl.PostList(
ctx,
siteID,
listName,
getStoredListBytes(t, test.template),
fault.New(false))
require.Error(t, err)
assert.Equal(t, ErrSkippableListTemplate.Error(), err.Error())
})
}
}
func (suite *ListsAPIIntgSuite) TestLists_DeleteList() {
@ -857,3 +875,22 @@ func getFieldsDataAndList() (map[string]any, *models.List) {
return fieldsData, list
}
func getStoredListBytes(t *testing.T, template string) []byte {
writer := kjson.NewJsonSerializationWriter()
defer writer.Close()
overrideListInfo := models.NewListInfo()
overrideListInfo.SetTemplate(ptr.To(WebTemplateExtensionsListTemplateName))
_, list := getFieldsDataAndList()
list.SetList(overrideListInfo)
err := writer.WriteObjectValue("", list)
require.NoError(t, err)
storedListBytes, err := writer.GetSerializedContent()
require.NoError(t, err)
return storedListBytes
}