adds ListInfo details to SharepointInfo details (#4916)
adds ListInfo details to SharepointInfo details Changes previously approved in PR: https://github.com/alcionai/corso/pull/4851 #### 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
c3b15a00bd
commit
50fd28aab2
@ -942,7 +942,7 @@ var defaultOneDriveLocationIDer = func(driveID string, elems ...string) details.
|
||||
}
|
||||
|
||||
var defaultSharePointLocationIDer = func(driveID string, elems ...string) details.LocationIDer {
|
||||
return details.NewSharePointLocationIDer(driveID, elems...)
|
||||
return details.NewSharePointLocationIDer(path.LibrariesCategory, driveID, elems...)
|
||||
}
|
||||
|
||||
func (h mockBackupHandler[T]) IsAllPass() bool {
|
||||
|
||||
@ -149,7 +149,8 @@ func (h siteBackupHandler) NewLocationIDer(
|
||||
driveID string,
|
||||
elems ...string,
|
||||
) details.LocationIDer {
|
||||
return details.NewSharePointLocationIDer(driveID, elems...)
|
||||
_, cat := h.ServiceCat()
|
||||
return details.NewSharePointLocationIDer(cat, driveID, elems...)
|
||||
}
|
||||
|
||||
func (h siteBackupHandler) GetItemPermission(
|
||||
|
||||
@ -296,7 +296,7 @@ var defaultOneDriveLocationIDer = func(driveID string, elems ...string) details.
|
||||
}
|
||||
|
||||
var defaultSharePointLocationIDer = func(driveID string, elems ...string) details.LocationIDer {
|
||||
return details.NewSharePointLocationIDer(driveID, elems...)
|
||||
return details.NewSharePointLocationIDer(path.LibrariesCategory, driveID, elems...)
|
||||
}
|
||||
|
||||
func (h BackupHandler[T]) IsAllPass() bool {
|
||||
|
||||
@ -116,7 +116,7 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
|
||||
expectVs: []string{"deadbeef", "sender", "Parent", "subject", nowStr},
|
||||
},
|
||||
{
|
||||
name: "sharepoint info",
|
||||
name: "sharepoint library info",
|
||||
entry: Entry{
|
||||
RepoRef: "reporef",
|
||||
ShortRef: "deadbeef",
|
||||
@ -125,6 +125,7 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
|
||||
ItemInfo: ItemInfo{
|
||||
SharePoint: &SharePointInfo{
|
||||
ItemName: "itemName",
|
||||
ItemType: SharePointLibrary,
|
||||
ParentPath: "parentPath",
|
||||
Size: 1000,
|
||||
WebURL: "https://not.a.real/url",
|
||||
@ -147,6 +148,66 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
|
||||
nowStr,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "sharepoint list info for genericList template",
|
||||
entry: Entry{
|
||||
RepoRef: "reporef",
|
||||
ShortRef: "deadbeef",
|
||||
LocationRef: "locationref",
|
||||
ItemRef: "itemref",
|
||||
ItemInfo: ItemInfo{
|
||||
SharePoint: &SharePointInfo{
|
||||
ItemType: SharePointList,
|
||||
List: &ListInfo{
|
||||
Name: "list1",
|
||||
ItemCount: 50,
|
||||
Template: "genericList",
|
||||
Created: now,
|
||||
Modified: now,
|
||||
WebURL: "https://10rqc2.sharepoint.com/sites/site-4754-small-lists/Lists/list1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectHs: []string{"ID", "List", "Items", "Created", "Modified"},
|
||||
expectVs: []string{
|
||||
"deadbeef",
|
||||
"list1",
|
||||
"50",
|
||||
nowStr,
|
||||
nowStr,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "sharepoint list info for documentLibrary template",
|
||||
entry: Entry{
|
||||
RepoRef: "reporef",
|
||||
ShortRef: "deadbeef",
|
||||
LocationRef: "locationref",
|
||||
ItemRef: "itemref",
|
||||
ItemInfo: ItemInfo{
|
||||
SharePoint: &SharePointInfo{
|
||||
ItemType: SharePointList,
|
||||
List: &ListInfo{
|
||||
Name: "Shared%20Documents",
|
||||
ItemCount: 50,
|
||||
Template: "documentLibrary",
|
||||
Created: now,
|
||||
Modified: now,
|
||||
WebURL: "https://10rqc2.sharepoint.com/sites/site-4754-small-lists/Lists/Shared%20Documents",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectHs: []string{"ID", "List", "Items", "Created", "Modified"},
|
||||
expectVs: []string{
|
||||
"deadbeef",
|
||||
"Shared%20Documents",
|
||||
"50",
|
||||
nowStr,
|
||||
nowStr,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "oneDrive info",
|
||||
entry: Entry{
|
||||
@ -846,6 +907,34 @@ var pathItemsTable = []struct {
|
||||
expectRepoRefs: []string{"abcde", "12345", "foo.meta"},
|
||||
expectLocationRefs: []string{"locationref", "locationref2", "locationref.dirmeta"},
|
||||
},
|
||||
{
|
||||
name: "multiple entries with not recoverables",
|
||||
ents: []Entry{
|
||||
{
|
||||
RepoRef: "abcde",
|
||||
LocationRef: "locationref",
|
||||
},
|
||||
{
|
||||
RepoRef: "foo.meta",
|
||||
LocationRef: "locationref.dirmeta",
|
||||
ItemRef: "itemref.meta",
|
||||
ItemInfo: ItemInfo{
|
||||
SharePoint: &SharePointInfo{ItemType: SharePointList},
|
||||
},
|
||||
},
|
||||
{
|
||||
RepoRef: "invalid-template-list-file",
|
||||
LocationRef: "locationref-invalid-template-list-file",
|
||||
ItemRef: "itemref-template-list-file",
|
||||
ItemInfo: ItemInfo{
|
||||
SharePoint: &SharePointInfo{ItemType: SharePointList},
|
||||
NotRecoverable: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectRepoRefs: []string{"abcde", "foo.meta"},
|
||||
expectLocationRefs: []string{"locationref", "locationref.dirmeta"},
|
||||
},
|
||||
}
|
||||
|
||||
func (suite *DetailsUnitSuite) TestDetailsModel_Path() {
|
||||
@ -1278,11 +1367,15 @@ func (suite *DetailsUnitSuite) TestUnarshalTo() {
|
||||
func (suite *DetailsUnitSuite) TestLocationIDer_FromEntry() {
|
||||
const (
|
||||
rrString = "tenant-id/%s/user-id/%s/drives/drive-id/root:/some/folder/stuff/item"
|
||||
listsRrString = "tenant-id/%s/site-id/%s/lists/list-id/list-id"
|
||||
driveID = "driveID"
|
||||
listID = "listID"
|
||||
|
||||
expectedUniqueLocFmt = "%s/" + driveID + "/root:/some/folder/stuff"
|
||||
expectedExchangeUniqueLocFmt = "%s/root:/some/folder/stuff"
|
||||
expectedDetailsLoc = "root:/some/folder/stuff"
|
||||
expectedListUniqueLocFmt = "%s/" + listID
|
||||
expectedListDetailsLoc = listID
|
||||
)
|
||||
|
||||
table := []struct {
|
||||
@ -1379,6 +1472,21 @@ func (suite *DetailsUnitSuite) TestLocationIDer_FromEntry() {
|
||||
backupVersion: version.OneDrive7LocationRef,
|
||||
expectedErr: require.Error,
|
||||
},
|
||||
{
|
||||
name: "SharePoint List With LocationRef",
|
||||
service: path.SharePointService.String(),
|
||||
category: path.ListsCategory.String(),
|
||||
itemInfo: ItemInfo{
|
||||
SharePoint: &SharePointInfo{
|
||||
ItemType: SharePointList,
|
||||
List: &ListInfo{},
|
||||
},
|
||||
},
|
||||
backupVersion: version.OneDrive7LocationRef,
|
||||
hasLocRef: true,
|
||||
expectedErr: require.NoError,
|
||||
expectedUniqueLoc: fmt.Sprintf(expectedListUniqueLocFmt, path.ListsCategory),
|
||||
},
|
||||
{
|
||||
name: "Exchange Email With LocationRef Old Version",
|
||||
service: path.ExchangeService.String(),
|
||||
@ -1479,13 +1587,23 @@ func (suite *DetailsUnitSuite) TestLocationIDer_FromEntry() {
|
||||
suite.Run(test.name, func() {
|
||||
t := suite.T()
|
||||
|
||||
rr := ""
|
||||
detailsLoc := ""
|
||||
if test.category == path.ListsCategory.String() {
|
||||
rr = fmt.Sprintf(listsRrString, test.service, test.category)
|
||||
detailsLoc = expectedListDetailsLoc
|
||||
} else {
|
||||
rr = fmt.Sprintf(rrString, test.service, test.category)
|
||||
detailsLoc = expectedDetailsLoc
|
||||
}
|
||||
|
||||
entry := Entry{
|
||||
RepoRef: fmt.Sprintf(rrString, test.service, test.category),
|
||||
RepoRef: rr,
|
||||
ItemInfo: test.itemInfo,
|
||||
}
|
||||
|
||||
if test.hasLocRef {
|
||||
entry.LocationRef = expectedDetailsLoc
|
||||
entry.LocationRef = detailsLoc
|
||||
}
|
||||
|
||||
loc, err := entry.ToLocationIDer(test.backupVersion)
|
||||
@ -1502,7 +1620,7 @@ func (suite *DetailsUnitSuite) TestLocationIDer_FromEntry() {
|
||||
"unique location")
|
||||
assert.Equal(
|
||||
t,
|
||||
expectedDetailsLoc,
|
||||
detailsLoc,
|
||||
loc.InDetails().String(),
|
||||
"details location")
|
||||
})
|
||||
|
||||
@ -75,6 +75,7 @@ type ItemInfo struct {
|
||||
Groups *GroupsInfo `json:"groups,omitempty"`
|
||||
// Optional item extension data
|
||||
Extension *ExtensionData `json:"extension,omitempty"`
|
||||
NotRecoverable bool `json:"notRecoverable,omitempty"`
|
||||
}
|
||||
|
||||
// typedInfo should get embedded in each sesrvice type to track
|
||||
|
||||
@ -67,7 +67,9 @@ func (dm DetailsModel) Paths() []string {
|
||||
r := make([]string, 0, len(dm.Entries))
|
||||
|
||||
for _, ent := range dm.Entries {
|
||||
if ent.Folder != nil || ent.isMetaFile() {
|
||||
if ent.Folder != nil ||
|
||||
ent.isMetaFile() ||
|
||||
ent.NotRecoverable {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -85,7 +87,9 @@ func (dm DetailsModel) Items() entrySet {
|
||||
|
||||
for i := 0; i < len(dm.Entries); i++ {
|
||||
ent := dm.Entries[i]
|
||||
if ent.Folder != nil || ent.isMetaFile() {
|
||||
if ent.Folder != nil ||
|
||||
ent.isMetaFile() ||
|
||||
ent.NotRecoverable {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package details
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/alcionai/clues"
|
||||
@ -13,16 +14,24 @@ import (
|
||||
// NewSharePointLocationIDer builds a LocationIDer for the drive and folder
|
||||
// path. The path denoted by the folders should be unique within the drive.
|
||||
func NewSharePointLocationIDer(
|
||||
category path.CategoryType,
|
||||
driveID string,
|
||||
escapedFolders ...string,
|
||||
) uniqueLoc {
|
||||
pb := path.Builder{}.
|
||||
Append(path.LibrariesCategory.String(), driveID).
|
||||
Append(escapedFolders...)
|
||||
pb := path.Builder{}.Append(category.String())
|
||||
prefixElems := 1
|
||||
|
||||
if len(driveID) > 0 { // for library category
|
||||
pb = pb.Append(driveID)
|
||||
|
||||
prefixElems = 2
|
||||
}
|
||||
|
||||
pb = pb.Append(escapedFolders...)
|
||||
|
||||
return uniqueLoc{
|
||||
pb: pb,
|
||||
prefixElems: 2,
|
||||
prefixElems: prefixElems,
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,17 +48,36 @@ type SharePointInfo struct {
|
||||
Size int64 `json:"size,omitempty"`
|
||||
WebURL string `json:"webUrl,omitempty"`
|
||||
SiteID string `json:"siteID,omitempty"`
|
||||
List *ListInfo `json:"list,omitempty"`
|
||||
}
|
||||
|
||||
type ListInfo struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
ItemCount int64 `json:"itemCount,omitempty"`
|
||||
Template string `json:"template,omitempty"`
|
||||
WebURL string `json:"webUrl,omitempty"`
|
||||
Created time.Time `json:"created,omitempty"`
|
||||
Modified time.Time `json:"modified,omitempty"`
|
||||
}
|
||||
|
||||
// Headers returns the human-readable names of properties in a SharePointInfo
|
||||
// for printing out to a terminal in a columnar display.
|
||||
func (i SharePointInfo) Headers() []string {
|
||||
switch i.ItemType {
|
||||
case SharePointLibrary:
|
||||
return []string{"ItemName", "Library", "ParentPath", "Size", "Owner", "Created", "Modified"}
|
||||
case SharePointList:
|
||||
return []string{"List", "Items", "Created", "Modified"}
|
||||
}
|
||||
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// Values returns the values matching the Headers list for printing
|
||||
// out to a terminal in a columnar display.
|
||||
func (i SharePointInfo) Values() []string {
|
||||
switch i.ItemType {
|
||||
case SharePointLibrary:
|
||||
return []string{
|
||||
i.ItemName,
|
||||
i.DriveName,
|
||||
@ -59,6 +87,16 @@ func (i SharePointInfo) Values() []string {
|
||||
dttm.FormatToTabularDisplay(i.Created),
|
||||
dttm.FormatToTabularDisplay(i.Modified),
|
||||
}
|
||||
case SharePointList:
|
||||
return []string{
|
||||
i.List.Name,
|
||||
fmt.Sprintf("%d", i.List.ItemCount),
|
||||
dttm.FormatToTabularDisplay(i.List.Created),
|
||||
dttm.FormatToTabularDisplay(i.List.Modified),
|
||||
}
|
||||
}
|
||||
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func (i *SharePointInfo) UpdateParentPath(newLocPath *path.Builder) {
|
||||
@ -66,11 +104,14 @@ func (i *SharePointInfo) UpdateParentPath(newLocPath *path.Builder) {
|
||||
}
|
||||
|
||||
func (i *SharePointInfo) uniqueLocation(baseLoc *path.Builder) (*uniqueLoc, error) {
|
||||
if len(i.DriveID) == 0 {
|
||||
return nil, clues.New("empty drive ID")
|
||||
}
|
||||
loc := uniqueLoc{}
|
||||
|
||||
loc := NewSharePointLocationIDer(i.DriveID, baseLoc.Elements()...)
|
||||
switch i.ItemType {
|
||||
case SharePointLibrary, OneDriveItem:
|
||||
loc = NewSharePointLocationIDer(path.LibrariesCategory, i.DriveID, baseLoc.Elements()...)
|
||||
case SharePointList:
|
||||
loc = NewSharePointLocationIDer(path.ListsCategory, "", baseLoc.Elements()...)
|
||||
}
|
||||
|
||||
return &loc, nil
|
||||
}
|
||||
@ -78,8 +119,11 @@ func (i *SharePointInfo) uniqueLocation(baseLoc *path.Builder) (*uniqueLoc, erro
|
||||
func (i *SharePointInfo) updateFolder(f *FolderInfo) error {
|
||||
// TODO(ashmrtn): Change to just SharePointLibrary when the code that
|
||||
// generates the item type is fixed.
|
||||
if i.ItemType == OneDriveItem || i.ItemType == SharePointLibrary {
|
||||
switch i.ItemType {
|
||||
case OneDriveItem, SharePointLibrary:
|
||||
return updateFolderWithinDrive(SharePointLibrary, i.DriveName, i.DriveID, f)
|
||||
case SharePointList:
|
||||
return nil
|
||||
}
|
||||
|
||||
return clues.New("unsupported non-SharePoint ItemType").With("item_type", i.ItemType)
|
||||
|
||||
@ -6,12 +6,13 @@ import (
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/common/ptr"
|
||||
"github.com/google/uuid"
|
||||
"github.com/microsoft/kiota-abstractions-go/serialization"
|
||||
kjson "github.com/microsoft/kiota-serialization-json-go"
|
||||
"github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/common/ptr"
|
||||
)
|
||||
|
||||
func ODataErr(code string) *odataerrors.ODataError {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user