enable restore path creation for sharepoint lists (#4922)
Enable restore path creation for sharepoint lists Changes previously approved in: https://github.com/alcionai/corso/pull/4855 #### 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] 🌻 Feature #### 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:
parent
d6e9a2112d
commit
98e8cac374
@ -142,7 +142,8 @@ func makeRestorePathsForEntry(
|
|||||||
// * OneDrive/SharePoint (needs drive information)
|
// * OneDrive/SharePoint (needs drive information)
|
||||||
switch true {
|
switch true {
|
||||||
case ent.Exchange != nil ||
|
case ent.Exchange != nil ||
|
||||||
(ent.Groups != nil && ent.Groups.ItemType == details.GroupsChannelMessage):
|
(ent.Groups != nil && ent.Groups.ItemType == details.GroupsChannelMessage) ||
|
||||||
|
(ent.SharePoint != nil && ent.SharePoint.ItemType == details.SharePointList):
|
||||||
// TODO(ashmrtn): Eventually make Events have it's own function to handle
|
// TODO(ashmrtn): Eventually make Events have it's own function to handle
|
||||||
// setting the restore destination properly.
|
// setting the restore destination properly.
|
||||||
res.RestorePath, err = basicLocationPath(repoRef, locRef)
|
res.RestorePath, err = basicLocationPath(repoRef, locRef)
|
||||||
|
|||||||
@ -50,16 +50,19 @@ func (suite *RestorePathTransformerUnitSuite) TestGetPaths() {
|
|||||||
driveID = "some-drive-id"
|
driveID = "some-drive-id"
|
||||||
siteID = "some-site-id"
|
siteID = "some-site-id"
|
||||||
extraItemName = "some-item"
|
extraItemName = "some-item"
|
||||||
|
listName = "list1"
|
||||||
SharePointRootItemPath = testdata.SharePointRootPath.MustAppend(extraItemName, true)
|
SharePointRootItemPath = testdata.SharePointRootPath.MustAppend(extraItemName, true)
|
||||||
|
SharePointListItemPath = testdata.SharePointListPath.MustAppend(listName, true)
|
||||||
GroupsRootItemPath = testdata.GroupsRootPath.MustAppend(extraItemName, true)
|
GroupsRootItemPath = testdata.GroupsRootPath.MustAppend(extraItemName, true)
|
||||||
)
|
)
|
||||||
|
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
backupVersion int
|
backupVersion int
|
||||||
input []*details.Entry
|
input []*details.Entry
|
||||||
expectErr assert.ErrorAssertionFunc
|
expectErr assert.ErrorAssertionFunc
|
||||||
expected []expectPaths
|
expected []expectPaths
|
||||||
|
isSharepointList bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Groups List Errors v9",
|
name: "Groups List Errors v9",
|
||||||
@ -157,13 +160,13 @@ func (suite *RestorePathTransformerUnitSuite) TestGetPaths() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "SharePoint List Errors",
|
name: "SharePoint List, item in root",
|
||||||
// No version bump for the change so we always have to check for this.
|
// No version bump for the change so we always have to check for this.
|
||||||
backupVersion: version.All8MigrateUserPNToID,
|
backupVersion: version.All8MigrateUserPNToID,
|
||||||
input: []*details.Entry{
|
input: []*details.Entry{
|
||||||
{
|
{
|
||||||
RepoRef: SharePointRootItemPath.RR.String(),
|
RepoRef: SharePointListItemPath.RR.String(),
|
||||||
LocationRef: SharePointRootItemPath.Loc.String(),
|
LocationRef: SharePointListItemPath.Loc.String(),
|
||||||
ItemInfo: details.ItemInfo{
|
ItemInfo: details.ItemInfo{
|
||||||
SharePoint: &details.SharePointInfo{
|
SharePoint: &details.SharePointInfo{
|
||||||
ItemType: details.SharePointList,
|
ItemType: details.SharePointList,
|
||||||
@ -171,7 +174,14 @@ func (suite *RestorePathTransformerUnitSuite) TestGetPaths() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectErr: assert.Error,
|
expected: []expectPaths{
|
||||||
|
{
|
||||||
|
storage: SharePointListItemPath.RR.String(),
|
||||||
|
restore: toRestore(SharePointListItemPath.RR),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectErr: assert.NoError,
|
||||||
|
isSharepointList: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "SharePoint Page Errors",
|
name: "SharePoint Page Errors",
|
||||||
@ -413,12 +423,23 @@ func (suite *RestorePathTransformerUnitSuite) TestGetPaths() {
|
|||||||
|
|
||||||
for _, e := range test.expected {
|
for _, e := range test.expected {
|
||||||
tmp := path.RestorePaths{}
|
tmp := path.RestorePaths{}
|
||||||
p, err := path.FromDataLayerPath(e.storage, true)
|
var p path.Path
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if test.isSharepointList {
|
||||||
|
p, err = path.PrefixOrPathFromDataLayerPath(e.storage, true)
|
||||||
|
} else {
|
||||||
|
p, err = path.FromDataLayerPath(e.storage, true)
|
||||||
|
}
|
||||||
require.NoError(t, err, "parsing expected storage path", clues.ToCore(err))
|
require.NoError(t, err, "parsing expected storage path", clues.ToCore(err))
|
||||||
|
|
||||||
tmp.StoragePath = p
|
tmp.StoragePath = p
|
||||||
|
|
||||||
p, err = path.FromDataLayerPath(e.restore, false)
|
if test.isSharepointList {
|
||||||
|
p, err = path.PrefixOrPathFromDataLayerPath(e.restore, false)
|
||||||
|
} else {
|
||||||
|
p, err = path.FromDataLayerPath(e.restore, false)
|
||||||
|
}
|
||||||
require.NoError(t, err, "parsing expected restore path", clues.ToCore(err))
|
require.NoError(t, err, "parsing expected restore path", clues.ToCore(err))
|
||||||
|
|
||||||
if e.isRestorePrefix {
|
if e.isRestorePrefix {
|
||||||
|
|||||||
57
src/pkg/backup/details/testdata/testdata.go
vendored
57
src/pkg/backup/details/testdata/testdata.go
vendored
@ -16,8 +16,16 @@ import (
|
|||||||
// mustParsePath takes a string representing a resource path and returns a path
|
// mustParsePath takes a string representing a resource path and returns a path
|
||||||
// instance. Panics if the path cannot be parsed. Useful for simple variable
|
// instance. Panics if the path cannot be parsed. Useful for simple variable
|
||||||
// assignments.
|
// assignments.
|
||||||
func mustParsePath(ref string, isItem bool) path.Path {
|
func mustParsePath(ref string, isItem, isSharepointList bool) path.Path {
|
||||||
p, err := path.FromDataLayerPath(ref, isItem)
|
var p path.Path
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if isSharepointList {
|
||||||
|
p, err = path.PrefixOrPathFromDataLayerPath(ref, isItem)
|
||||||
|
} else {
|
||||||
|
p, err = path.FromDataLayerPath(ref, isItem)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -47,7 +55,7 @@ func locFromRepo(rr path.Path, isItem bool) *path.Builder {
|
|||||||
|
|
||||||
if rr.Service() == path.GroupsService {
|
if rr.Service() == path.GroupsService {
|
||||||
loc = loc.PopFront().PopFront().PopFront()
|
loc = loc.PopFront().PopFront().PopFront()
|
||||||
} else if rr.Service() == path.OneDriveService || rr.Category() == path.LibrariesCategory {
|
} else if rr.Service() == path.OneDriveService || rr.Category() == path.LibrariesCategory || rr.Category() == path.ListsCategory {
|
||||||
loc = loc.PopFront()
|
loc = loc.PopFront()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,9 +125,12 @@ func (p repoRefAndLocRef) locationAsRepoRef() path.Path {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustPathRep(ref string, isItem bool) repoRefAndLocRef {
|
func mustPathRep(ref string, isItem, isSharepointList bool) repoRefAndLocRef {
|
||||||
|
var rr path.Path
|
||||||
|
var err error
|
||||||
|
|
||||||
res := repoRefAndLocRef{}
|
res := repoRefAndLocRef{}
|
||||||
tmp := mustParsePath(ref, isItem)
|
tmp := mustParsePath(ref, isItem, isSharepointList)
|
||||||
|
|
||||||
// Now append stuff to the RepoRef elements so we have distinct LocationRef
|
// Now append stuff to the RepoRef elements so we have distinct LocationRef
|
||||||
// and RepoRef elements to simulate using IDs in the path instead of display
|
// and RepoRef elements to simulate using IDs in the path instead of display
|
||||||
@ -133,12 +144,21 @@ func mustPathRep(ref string, isItem bool) repoRefAndLocRef {
|
|||||||
rrPB = rrPB.Append(tmp.Item() + fileSuffix)
|
rrPB = rrPB.Append(tmp.Item() + fileSuffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
rr, err := rrPB.ToDataLayerPath(
|
if isSharepointList {
|
||||||
tmp.Tenant(),
|
rr, err = rrPB.ToDataLayerSharePointListPath(
|
||||||
tmp.ProtectedResource(),
|
tmp.Tenant(),
|
||||||
tmp.Service(),
|
tmp.ProtectedResource(),
|
||||||
tmp.Category(),
|
tmp.Category(),
|
||||||
isItem)
|
isItem)
|
||||||
|
} else {
|
||||||
|
rr, err = rrPB.ToDataLayerPath(
|
||||||
|
tmp.Tenant(),
|
||||||
|
tmp.ProtectedResource(),
|
||||||
|
tmp.Service(),
|
||||||
|
tmp.Category(),
|
||||||
|
isItem)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -166,7 +186,7 @@ var (
|
|||||||
Time3 = time.Date(2023, 9, 21, 10, 0, 0, 0, time.UTC)
|
Time3 = time.Date(2023, 9, 21, 10, 0, 0, 0, time.UTC)
|
||||||
Time4 = time.Date(2023, 10, 21, 10, 0, 0, 0, time.UTC)
|
Time4 = time.Date(2023, 10, 21, 10, 0, 0, 0, time.UTC)
|
||||||
|
|
||||||
ExchangeEmailInboxPath = mustPathRep("tenant-id/exchange/user-id/email/Inbox", false)
|
ExchangeEmailInboxPath = mustPathRep("tenant-id/exchange/user-id/email/Inbox", false, false)
|
||||||
ExchangeEmailBasePath = ExchangeEmailInboxPath.MustAppend("subfolder", false)
|
ExchangeEmailBasePath = ExchangeEmailInboxPath.MustAppend("subfolder", false)
|
||||||
ExchangeEmailBasePath2 = ExchangeEmailInboxPath.MustAppend("othersubfolder/", false)
|
ExchangeEmailBasePath2 = ExchangeEmailInboxPath.MustAppend("othersubfolder/", false)
|
||||||
ExchangeEmailBasePath3 = ExchangeEmailBasePath2.MustAppend("subsubfolder", false)
|
ExchangeEmailBasePath3 = ExchangeEmailBasePath2.MustAppend("subsubfolder", false)
|
||||||
@ -314,7 +334,7 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
ExchangeContactsRootPath = mustPathRep("tenant-id/exchange/user-id/contacts/contacts", false)
|
ExchangeContactsRootPath = mustPathRep("tenant-id/exchange/user-id/contacts/contacts", false, false)
|
||||||
ExchangeContactsBasePath = ExchangeContactsRootPath.MustAppend("contacts", false)
|
ExchangeContactsBasePath = ExchangeContactsRootPath.MustAppend("contacts", false)
|
||||||
ExchangeContactsBasePath2 = ExchangeContactsRootPath.MustAppend("morecontacts", false)
|
ExchangeContactsBasePath2 = ExchangeContactsRootPath.MustAppend("morecontacts", false)
|
||||||
ExchangeContactsItemPath1 = ExchangeContactsBasePath.MustAppend(ItemName1, true)
|
ExchangeContactsItemPath1 = ExchangeContactsBasePath.MustAppend(ItemName1, true)
|
||||||
@ -403,8 +423,8 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
ExchangeEventsBasePath = mustPathRep("tenant-id/exchange/user-id/events/holidays", false)
|
ExchangeEventsBasePath = mustPathRep("tenant-id/exchange/user-id/events/holidays", false, false)
|
||||||
ExchangeEventsBasePath2 = mustPathRep("tenant-id/exchange/user-id/events/moreholidays", false)
|
ExchangeEventsBasePath2 = mustPathRep("tenant-id/exchange/user-id/events/moreholidays", false, false)
|
||||||
ExchangeEventsItemPath1 = ExchangeEventsBasePath.MustAppend(ItemName1, true)
|
ExchangeEventsItemPath1 = ExchangeEventsBasePath.MustAppend(ItemName1, true)
|
||||||
ExchangeEventsItemPath2 = ExchangeEventsBasePath2.MustAppend(ItemName2, true)
|
ExchangeEventsItemPath2 = ExchangeEventsBasePath2.MustAppend(ItemName2, true)
|
||||||
|
|
||||||
@ -507,7 +527,7 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
OneDriveRootPath = mustPathRep("tenant-id/onedrive/user-id/files/drives/foo/root:", false)
|
OneDriveRootPath = mustPathRep("tenant-id/onedrive/user-id/files/drives/foo/root:", false, false)
|
||||||
OneDriveFolderPath = OneDriveRootPath.MustAppend("folder", false)
|
OneDriveFolderPath = OneDriveRootPath.MustAppend("folder", false)
|
||||||
OneDriveBasePath1 = OneDriveFolderPath.MustAppend("a", false)
|
OneDriveBasePath1 = OneDriveFolderPath.MustAppend("a", false)
|
||||||
OneDriveBasePath2 = OneDriveFolderPath.MustAppend("b", false)
|
OneDriveBasePath2 = OneDriveFolderPath.MustAppend("b", false)
|
||||||
@ -732,10 +752,11 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupsRootPath = mustPathRep("tenant-id/groups/group-id/libraries/sites/site-id/drives/foo/root:", false)
|
GroupsRootPath = mustPathRep("tenant-id/groups/group-id/libraries/sites/site-id/drives/foo/root:", false, false)
|
||||||
|
|
||||||
SharePointRootPath = mustPathRep("tenant-id/sharepoint/site-id/libraries/drives/foo/root:", false)
|
SharePointRootPath = mustPathRep("tenant-id/sharepoint/site-id/libraries/drives/foo/root:", false, false)
|
||||||
SharePointLibraryPath = SharePointRootPath.MustAppend("library", false)
|
SharePointLibraryPath = SharePointRootPath.MustAppend("library", false)
|
||||||
|
SharePointListPath = mustPathRep("tenant-id/sharepoint/site-id/lists", false, true)
|
||||||
SharePointBasePath1 = SharePointLibraryPath.MustAppend("a", false)
|
SharePointBasePath1 = SharePointLibraryPath.MustAppend("a", false)
|
||||||
SharePointBasePath2 = SharePointLibraryPath.MustAppend("b", false)
|
SharePointBasePath2 = SharePointLibraryPath.MustAppend("b", false)
|
||||||
|
|
||||||
|
|||||||
@ -355,6 +355,34 @@ func (pb Builder) ToDataLayerSharePointPath(
|
|||||||
return pb.ToDataLayerPath(tenant, site, SharePointService, category, isItem)
|
return pb.ToDataLayerPath(tenant, site, SharePointService, category, isItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pb Builder) ToDataLayerSharePointListPath(
|
||||||
|
tenant, site string,
|
||||||
|
category CategoryType,
|
||||||
|
isItem bool,
|
||||||
|
) (Path, error) {
|
||||||
|
if err := ValidateServiceAndCategory(SharePointService, category); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := verifyInputValues(tenant, site); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
prefixItems := []string{
|
||||||
|
tenant,
|
||||||
|
SharePointService.String(),
|
||||||
|
site,
|
||||||
|
category.String(),
|
||||||
|
}
|
||||||
|
|
||||||
|
return &dataLayerResourcePath{
|
||||||
|
Builder: *pb.withPrefix(prefixItems...),
|
||||||
|
service: SharePointService,
|
||||||
|
category: category,
|
||||||
|
hasItem: isItem,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Stringers and PII Concealer Compliance
|
// Stringers and PII Concealer Compliance
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user