corso/src/internal/m365/onedrive_test.go
Abin Simon 214d8a6030
Fixing handling of permissions for external users (#5097)
<!-- PR description-->

---

#### Does this PR need a docs update or release note?

- [x]  Yes, it's included
- [ ] 🕐 Yes, but in a later PR
- [ ]  No

#### Type of change

<!--- Please check the type of change your PR introduces: --->
- [ ] 🌻 Feature
- [x] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Supportability/Tests
- [ ] 💻 CI/Deployment
- [ ] 🧹 Tech Debt/Cleanup

#### Issue(s)

<!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. -->
* fixes https://github.com/alcionai/corso/issues/5046

#### Test Plan

<!-- How will this be tested prior to merging.-->
- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
2024-01-24 19:32:03 +00:00

1407 lines
34 KiB
Go

package m365
import (
"context"
"fmt"
"strings"
"testing"
"github.com/alcionai/clues"
"github.com/microsoftgraph/msgraph-sdk-go/models"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"github.com/alcionai/corso/src/internal/common/ptr"
"github.com/alcionai/corso/src/internal/m365/collection/drive/metadata"
odConsts "github.com/alcionai/corso/src/internal/m365/service/onedrive/consts"
"github.com/alcionai/corso/src/internal/m365/service/onedrive/stub"
m365Stub "github.com/alcionai/corso/src/internal/m365/stub"
"github.com/alcionai/corso/src/internal/tester"
"github.com/alcionai/corso/src/internal/tester/tconfig"
"github.com/alcionai/corso/src/internal/version"
"github.com/alcionai/corso/src/pkg/control"
"github.com/alcionai/corso/src/pkg/control/testdata"
"github.com/alcionai/corso/src/pkg/dttm"
"github.com/alcionai/corso/src/pkg/path"
"github.com/alcionai/corso/src/pkg/services/m365/api"
"github.com/alcionai/corso/src/pkg/services/m365/api/graph"
)
var (
fileName = "test-file.txt"
folderAName = "folder-a"
folderBName = "b"
folderNamedFolder = "folder"
fileAData = []byte(strings.Repeat("a", 33))
fileBData = []byte(strings.Repeat("b", 65))
fileCData = []byte(strings.Repeat("c", 129))
fileDData = []byte(strings.Repeat("d", 257))
fileEData = []byte(strings.Repeat("e", 257))
// Cannot restore owner or empty permissions and so not testing them
writePerm = []string{"write"}
readPerm = []string{"read"}
)
func mustGetDefaultDriveID(
t *testing.T,
ctx context.Context, //revive:disable-line:context-as-argument
ac api.Client,
service path.ServiceType,
resourceOwner string,
) string {
var (
err error
d models.Driveable
)
switch service {
case path.OneDriveService:
d, err = ac.Users().GetDefaultDrive(ctx, resourceOwner)
case path.SharePointService:
d, err = ac.Sites().GetDefaultDrive(ctx, resourceOwner)
default:
assert.FailNowf(t, "unknown service type %s", service.String())
}
if err != nil {
err = graph.Wrap(ctx, err, "retrieving drive")
}
require.NoError(t, err, clues.ToCore(err))
id := ptr.Val(d.GetId())
require.NotEmpty(t, id)
return id
}
type suiteInfo interface {
APIClient() api.Client
Tenant() string
// Returns (username, user ID) for the user. These values are used for
// permissions.
PrimaryUser() (string, string)
SecondaryUser() (string, string)
TertiaryUser() (string, string)
// ResourceOwner returns the resource owner to run the backup/restore
// with. This can be different from the values used for permissions and it can
// also be a site.
ResourceOwner() string
Service() path.ServiceType
}
type oneDriveSuite interface {
tester.Suite
suiteInfo
}
type suiteInfoImpl struct {
ac api.Client
controller *Controller
resourceOwner string
secondaryUser string
secondaryUserID string
service path.ServiceType
tertiaryUser string
tertiaryUserID string
user string
userID string
}
func NewSuiteInfoImpl(
t *testing.T,
ctx context.Context, //revive:disable-line:context-as-argument
resourceOwner string,
service path.ServiceType,
) suiteInfoImpl {
ctrl := newController(ctx, t, path.OneDriveService)
return suiteInfoImpl{
ac: ctrl.AC,
controller: ctrl,
resourceOwner: resourceOwner,
secondaryUser: tconfig.SecondaryM365UserID(t),
service: service,
tertiaryUser: tconfig.TertiaryM365UserID(t),
user: tconfig.M365UserID(t),
}
}
func (si suiteInfoImpl) APIClient() api.Client {
return si.ac
}
func (si suiteInfoImpl) Tenant() string {
return si.controller.tenant
}
func (si suiteInfoImpl) PrimaryUser() (string, string) {
return si.user, si.userID
}
func (si suiteInfoImpl) SecondaryUser() (string, string) {
return si.secondaryUser, si.secondaryUserID
}
func (si suiteInfoImpl) TertiaryUser() (string, string) {
return si.tertiaryUser, si.tertiaryUserID
}
func (si suiteInfoImpl) ResourceOwner() string {
return si.resourceOwner
}
func (si suiteInfoImpl) Service() path.ServiceType {
return si.service
}
// ---------------------------------------------------------------------------
// SharePoint Libraries
// ---------------------------------------------------------------------------
// SharePoint shares most of its libraries implementation with OneDrive so we
// only test simple things here and leave the more extensive testing to
// OneDrive.
type SharePointIntegrationSuite struct {
tester.Suite
suiteInfo
}
func TestSharePointIntegrationSuite(t *testing.T) {
suite.Run(t, &SharePointIntegrationSuite{
Suite: tester.NewIntegrationSuite(
t,
[][]string{tconfig.M365AcctCredEnvs}),
})
}
func (suite *SharePointIntegrationSuite) SetupSuite() {
t := suite.T()
ctx, flush := tester.NewContext(t)
defer flush()
si := NewSuiteInfoImpl(suite.T(), ctx, tconfig.M365SiteID(suite.T()), path.SharePointService)
// users needed for permissions
user, err := si.controller.AC.Users().GetByID(ctx, si.user, api.CallConfig{})
require.NoError(t, err, "fetching user", si.user, clues.ToCore(err))
si.userID = ptr.Val(user.GetId())
secondaryUser, err := si.controller.AC.Users().GetByID(ctx, si.secondaryUser, api.CallConfig{})
require.NoError(t, err, "fetching user", si.secondaryUser, clues.ToCore(err))
si.secondaryUserID = ptr.Val(secondaryUser.GetId())
tertiaryUser, err := si.controller.AC.Users().GetByID(ctx, si.tertiaryUser, api.CallConfig{})
require.NoError(t, err, "fetching user", si.tertiaryUser, clues.ToCore(err))
si.tertiaryUserID = ptr.Val(tertiaryUser.GetId())
suite.suiteInfo = si
}
func (suite *SharePointIntegrationSuite) TestRestoreAndBackup_MultipleFilesAndFolders_NoPermissions() {
testRestoreAndBackupMultipleFilesAndFoldersNoPermissions(suite, version.Backup)
}
// TODO: Re-enable these tests (disabled as it currently acting up CI)
func (suite *SharePointIntegrationSuite) TestPermissionsRestoreAndBackup() {
suite.T().Skip("Temporarily disabled due to CI issues")
testPermissionsRestoreAndBackup(suite, version.Backup)
}
func (suite *SharePointIntegrationSuite) TestRestoreNoPermissionsAndBackup() {
suite.T().Skip("Temporarily disabled due to CI issues")
testRestoreNoPermissionsAndBackup(suite, version.Backup)
}
func (suite *SharePointIntegrationSuite) TestPermissionsInheritanceRestoreAndBackup() {
suite.T().Skip("Temporarily disabled due to CI issues")
testPermissionsInheritanceRestoreAndBackup(suite, version.Backup)
}
func (suite *SharePointIntegrationSuite) TestLinkSharesInheritanceRestoreAndBackup() {
suite.T().Skip("Temporarily disabled due to CI issues")
testLinkSharesInheritanceRestoreAndBackup(suite, version.Backup)
}
func (suite *SharePointIntegrationSuite) TestRestoreFolderNamedFolderRegression() {
// No reason why it couldn't work with previous versions, but this is when it got introduced.
testRestoreFolderNamedFolderRegression(suite, version.All8MigrateUserPNToID)
}
// ---------------------------------------------------------------------------
// OneDrive most recent backup version
// ---------------------------------------------------------------------------
type OneDriveIntegrationSuite struct {
tester.Suite
suiteInfo
}
func TestOneDriveIntegrationSuite(t *testing.T) {
suite.Run(t, &OneDriveIntegrationSuite{
Suite: tester.NewIntegrationSuite(
t,
[][]string{tconfig.M365AcctCredEnvs}),
})
}
func (suite *OneDriveIntegrationSuite) SetupSuite() {
t := suite.T()
ctx, flush := tester.NewContext(t)
defer flush()
si := NewSuiteInfoImpl(t, ctx, tconfig.M365UserID(t), path.OneDriveService)
user, err := si.controller.AC.Users().GetByID(ctx, si.user, api.CallConfig{})
require.NoError(t, err, "fetching user", si.user, clues.ToCore(err))
si.userID = ptr.Val(user.GetId())
secondaryUser, err := si.controller.AC.Users().GetByID(ctx, si.secondaryUser, api.CallConfig{})
require.NoError(t, err, "fetching user", si.secondaryUser, clues.ToCore(err))
si.secondaryUserID = ptr.Val(secondaryUser.GetId())
tertiaryUser, err := si.controller.AC.Users().GetByID(ctx, si.tertiaryUser, api.CallConfig{})
require.NoError(t, err, "fetching user", si.tertiaryUser, clues.ToCore(err))
si.tertiaryUserID = ptr.Val(tertiaryUser.GetId())
suite.suiteInfo = si
}
func (suite *OneDriveIntegrationSuite) TestRestoreAndBackup_MultipleFilesAndFolders_NoPermissions() {
testRestoreAndBackupMultipleFilesAndFoldersNoPermissions(suite, version.Backup)
}
func (suite *OneDriveIntegrationSuite) TestPermissionsRestoreAndBackup() {
testPermissionsRestoreAndBackup(suite, version.Backup)
}
func (suite *OneDriveIntegrationSuite) TestRestoreNoPermissionsAndBackup() {
testRestoreNoPermissionsAndBackup(suite, version.Backup)
}
func (suite *OneDriveIntegrationSuite) TestPermissionsInheritanceRestoreAndBackup() {
testPermissionsInheritanceRestoreAndBackup(suite, version.Backup)
}
func (suite *OneDriveIntegrationSuite) TestLinkSharesInheritanceRestoreAndBackup() {
testLinkSharesInheritanceRestoreAndBackup(suite, version.Backup)
}
func (suite *OneDriveIntegrationSuite) TestRestoreFolderNamedFolderRegression() {
// No reason why it couldn't work with previous versions, but this is when it got introduced.
testRestoreFolderNamedFolderRegression(suite, version.All8MigrateUserPNToID)
}
// ---------------------------------------------------------------------------
// OneDrive regression
// ---------------------------------------------------------------------------
type OneDriveNightlySuite struct {
tester.Suite
suiteInfo
}
func TestOneDriveNightlySuite(t *testing.T) {
suite.Run(t, &OneDriveNightlySuite{
Suite: tester.NewNightlySuite(
t,
[][]string{tconfig.M365AcctCredEnvs}),
})
}
func (suite *OneDriveNightlySuite) SetupSuite() {
t := suite.T()
ctx, flush := tester.NewContext(t)
defer flush()
si := NewSuiteInfoImpl(t, ctx, tconfig.M365UserID(t), path.OneDriveService)
user, err := si.controller.AC.Users().GetByID(ctx, si.user, api.CallConfig{})
require.NoError(t, err, "fetching user", si.user, clues.ToCore(err))
si.userID = ptr.Val(user.GetId())
secondaryUser, err := si.controller.AC.Users().GetByID(ctx, si.secondaryUser, api.CallConfig{})
require.NoError(t, err, "fetching user", si.secondaryUser, clues.ToCore(err))
si.secondaryUserID = ptr.Val(secondaryUser.GetId())
tertiaryUser, err := si.controller.AC.Users().GetByID(ctx, si.tertiaryUser, api.CallConfig{})
require.NoError(t, err, "fetching user", si.tertiaryUser, clues.ToCore(err))
si.tertiaryUserID = ptr.Val(tertiaryUser.GetId())
suite.suiteInfo = si
}
func (suite *OneDriveNightlySuite) TestRestoreAndBackup_MultipleFilesAndFolders_NoPermissions() {
testRestoreAndBackupMultipleFilesAndFoldersNoPermissions(suite, 0)
}
func (suite *OneDriveNightlySuite) TestPermissionsRestoreAndBackup() {
testPermissionsRestoreAndBackup(suite, version.OneDrive1DataAndMetaFiles)
}
func (suite *OneDriveNightlySuite) TestRestoreNoPermissionsAndBackup() {
testRestoreNoPermissionsAndBackup(suite, version.OneDrive1DataAndMetaFiles)
}
func (suite *OneDriveNightlySuite) TestPermissionsInheritanceRestoreAndBackup() {
// No reason why it couldn't work with previous versions, but this is when it got introduced.
testPermissionsInheritanceRestoreAndBackup(suite, version.OneDrive4DirIncludesPermissions)
}
func (suite *OneDriveNightlySuite) TestLinkSharesInheritanceRestoreAndBackup() {
testLinkSharesInheritanceRestoreAndBackup(suite, version.Backup)
}
func (suite *OneDriveNightlySuite) TestRestoreFolderNamedFolderRegression() {
// No reason why it couldn't work with previous versions, but this is when it got introduced.
testRestoreFolderNamedFolderRegression(suite, version.All8MigrateUserPNToID)
}
func testRestoreAndBackupMultipleFilesAndFoldersNoPermissions(
suite oneDriveSuite,
startVersion int,
) {
t := suite.T()
ctx, flush := tester.NewContext(t)
defer flush()
// Get the default drive ID for the test user.
driveID := mustGetDefaultDriveID(
t,
ctx,
suite.APIClient(),
suite.Service(),
suite.ResourceOwner())
rootPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
}
folderAPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderAName,
}
subfolderBPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderAName,
folderBName,
}
subfolderAPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderAName,
folderBName,
folderAName,
}
folderBPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderBName,
}
defaultMetadata := stub.MetaData{SharingMode: metadata.SharingModeInherited}
cols := []stub.ColInfo{
{
PathElements: rootPath,
Meta: defaultMetadata,
Files: []stub.ItemData{
{
Name: fileName,
Data: fileAData,
Meta: defaultMetadata,
},
},
Folders: []stub.ItemData{
{
Name: folderAName,
},
{
Name: folderBName,
},
},
},
{
PathElements: folderAPath,
Meta: defaultMetadata,
Files: []stub.ItemData{
{
Name: fileName,
Data: fileBData,
Meta: defaultMetadata,
},
},
Folders: []stub.ItemData{
{
Name: folderBName,
},
},
},
{
PathElements: subfolderBPath,
Meta: defaultMetadata,
Files: []stub.ItemData{
{
Name: fileName,
Data: fileCData,
Meta: defaultMetadata,
},
},
Folders: []stub.ItemData{
{
Name: folderAName,
},
},
},
{
PathElements: subfolderAPath,
Meta: defaultMetadata,
Files: []stub.ItemData{
{
Name: fileName,
Data: fileDData,
Meta: defaultMetadata,
},
},
},
{
PathElements: folderBPath,
Meta: defaultMetadata,
Files: []stub.ItemData{
{
Name: fileName,
Data: fileEData,
Meta: defaultMetadata,
},
},
},
}
expected, err := stub.DataForInfo(suite.Service(), cols, version.Backup)
require.NoError(suite.T(), err)
for vn := startVersion; vn <= version.Backup; vn++ {
suite.Run(fmt.Sprintf("Version%d", vn), func() {
t := suite.T()
input, err := stub.DataForInfo(suite.Service(), cols, vn)
require.NoError(suite.T(), err)
testData := restoreBackupInfoMultiVersion{
service: suite.Service(),
backupVersion: vn,
collectionsPrevious: input,
collectionsLatest: expected,
}
restoreCfg := testdata.DefaultRestoreConfig("od_restore_and_backup_multi")
restoreCfg.OnCollision = control.Replace
restoreCfg.IncludePermissions = true
opts := control.DefaultOptions()
cfg := m365Stub.ConfigInfo{
Tenant: suite.Tenant(),
ResourceOwners: []string{suite.ResourceOwner()},
Service: testData.service,
Opts: opts,
RestoreCfg: restoreCfg,
}
runRestoreBackupTestVersions(t, testData, cfg)
})
}
}
func testPermissionsRestoreAndBackup(suite oneDriveSuite, startVersion int) {
t := suite.T()
ctx, flush := tester.NewContext(t)
defer flush()
secondaryUserName, secondaryUserID := suite.SecondaryUser()
// Get the default drive ID for the test user.
driveID := mustGetDefaultDriveID(
t,
ctx,
suite.APIClient(),
suite.Service(),
suite.ResourceOwner())
fileName2 := "test-file2.txt"
folderCName := "folder-c"
rootPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
}
folderAPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderAName,
}
folderBPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderBName,
}
// For skipped test
// subfolderAPath := []string{
// odConsts.DrivesPathDir,
// driveID,
// odConsts.RootPathDir,
// folderBName,
// folderAName,
// }
folderCPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderCName,
}
cols := []stub.ColInfo{
{
PathElements: rootPath,
Meta: stub.MetaData{
SharingMode: metadata.SharingModeInherited,
},
Files: []stub.ItemData{
{
// Test restoring a file that doesn't inherit permissions.
Name: fileName,
Data: fileAData,
Meta: stub.MetaData{
Perms: stub.PermData{
User: secondaryUserName,
EntityID: secondaryUserID,
Roles: writePerm,
},
},
},
{
// Test restoring a file that doesn't inherit permissions and has
// no permissions.
Name: fileName2,
Data: fileBData,
Meta: stub.MetaData{
SharingMode: metadata.SharingModeInherited,
},
},
},
Folders: []stub.ItemData{
{
Name: folderBName,
Meta: stub.MetaData{
SharingMode: metadata.SharingModeInherited,
},
},
{
Name: folderAName,
Meta: stub.MetaData{
Perms: stub.PermData{
User: secondaryUserName,
EntityID: secondaryUserID,
Roles: readPerm,
},
},
},
{
Name: folderCName,
Meta: stub.MetaData{
Perms: stub.PermData{
User: secondaryUserName,
EntityID: secondaryUserID,
Roles: readPerm,
},
},
},
},
},
{
PathElements: folderBPath,
Meta: stub.MetaData{
SharingMode: metadata.SharingModeInherited,
},
Files: []stub.ItemData{
{
// Test restoring a file in a non-root folder that doesn't inherit
// permissions.
Name: fileName,
Data: fileBData,
Meta: stub.MetaData{
Perms: stub.PermData{
User: secondaryUserName,
EntityID: secondaryUserID,
Roles: writePerm,
},
},
},
},
Folders: []stub.ItemData{
{
Name: folderAName,
Meta: stub.MetaData{
Perms: stub.PermData{
User: secondaryUserName,
EntityID: secondaryUserID,
Roles: readPerm,
},
},
},
},
},
// TODO: We can't currently support having custom permissions
// with the same set of permissions internally
// {
// // Tests a folder that has permissions with an item in the folder with
// // the same permissions.
// pathElements: subfolderAPath,
// files: []stub.ItemData{
// {
// name: fileName,
// data: fileDData,
// perms: stub.PermData{
// user: secondaryUserName,
// entityID: secondaryUserID,
// roles: readPerm,
// },
// },
// },
// Perms: stub.PermData{
// User: secondaryUserName,
// EntityID: secondaryUserID,
// Roles: readPerm,
// },
// },
{
// Tests a folder that has permissions with an item in the folder with
// the different permissions.
PathElements: folderAPath,
Files: []stub.ItemData{
{
Name: fileName,
Data: fileEData,
Meta: stub.MetaData{
Perms: stub.PermData{
User: secondaryUserName,
EntityID: secondaryUserID,
Roles: writePerm,
},
},
},
},
Meta: stub.MetaData{
Perms: stub.PermData{
User: secondaryUserName,
EntityID: secondaryUserID,
Roles: readPerm,
},
},
},
{
// Tests a folder that has permissions with an item in the folder with
// no permissions.
PathElements: folderCPath,
Files: []stub.ItemData{
{
Name: fileName,
Data: fileAData,
Meta: stub.MetaData{
SharingMode: metadata.SharingModeInherited,
},
},
},
Meta: stub.MetaData{
Perms: stub.PermData{
User: secondaryUserName,
EntityID: secondaryUserID,
Roles: readPerm,
},
},
},
}
expected, err := stub.DataForInfo(suite.Service(), cols, version.Backup)
require.NoError(suite.T(), err)
bss := suite.Service().String()
for vn := startVersion; vn <= version.Backup; vn++ {
suite.Run(fmt.Sprintf("%s-Version%d", bss, vn), func() {
t := suite.T()
// Ideally this can always be true or false and still
// work, but limiting older versions to use emails so as
// to validate that flow as well.
input, err := stub.DataForInfo(suite.Service(), cols, vn)
require.NoError(suite.T(), err)
testData := restoreBackupInfoMultiVersion{
service: suite.Service(),
backupVersion: vn,
collectionsPrevious: input,
collectionsLatest: expected,
}
restoreCfg := testdata.DefaultRestoreConfig("perms_restore_and_backup")
restoreCfg.OnCollision = control.Replace
restoreCfg.IncludePermissions = true
opts := control.DefaultOptions()
cfg := m365Stub.ConfigInfo{
Tenant: suite.Tenant(),
ResourceOwners: []string{suite.ResourceOwner()},
Service: testData.service,
Opts: opts,
RestoreCfg: restoreCfg,
}
runRestoreBackupTestVersions(t, testData, cfg)
})
}
}
func testRestoreNoPermissionsAndBackup(suite oneDriveSuite, startVersion int) {
t := suite.T()
ctx, flush := tester.NewContext(t)
defer flush()
secondaryUserName, secondaryUserID := suite.SecondaryUser()
// Get the default drive ID for the test user.
driveID := mustGetDefaultDriveID(
t,
ctx,
suite.APIClient(),
suite.Service(),
suite.ResourceOwner())
inputCols := []stub.ColInfo{
{
PathElements: []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
},
Files: []stub.ItemData{
{
Name: fileName,
Data: fileAData,
Meta: stub.MetaData{
Perms: stub.PermData{
User: secondaryUserName,
EntityID: secondaryUserID,
Roles: writePerm,
},
SharingMode: metadata.SharingModeCustom,
},
},
},
},
}
expectedCols := []stub.ColInfo{
{
PathElements: []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
},
Files: []stub.ItemData{
{
// No permissions on the output since they weren't restored.
Name: fileName,
Data: fileAData,
},
},
},
}
expected, err := stub.DataForInfo(suite.Service(), expectedCols, version.Backup)
require.NoError(suite.T(), err)
bss := suite.Service().String()
for vn := startVersion; vn <= version.Backup; vn++ {
suite.Run(fmt.Sprintf("%s-Version%d", bss, vn), func() {
t := suite.T()
input, err := stub.DataForInfo(suite.Service(), inputCols, vn)
require.NoError(suite.T(), err)
testData := restoreBackupInfoMultiVersion{
service: suite.Service(),
backupVersion: vn,
collectionsPrevious: input,
collectionsLatest: expected,
}
restoreCfg := testdata.DefaultRestoreConfig("perms_backup_no_restore")
restoreCfg.OnCollision = control.Replace
restoreCfg.IncludePermissions = false
opts := control.DefaultOptions()
cfg := m365Stub.ConfigInfo{
Tenant: suite.Tenant(),
ResourceOwners: []string{suite.ResourceOwner()},
Service: testData.service,
Opts: opts,
RestoreCfg: restoreCfg,
}
runRestoreBackupTestVersions(t, testData, cfg)
})
}
}
// This is similar to TestPermissionsRestoreAndBackup but tests purely
// for inheritance and that too only with newer versions
func testPermissionsInheritanceRestoreAndBackup(suite oneDriveSuite, startVersion int) {
t := suite.T()
ctx, flush := tester.NewContext(t)
defer flush()
secondaryUserName, secondaryUserID := suite.SecondaryUser()
tertiaryUserName, tertiaryUserID := suite.TertiaryUser()
// Get the default drive ID for the test user.
driveID := mustGetDefaultDriveID(
t,
ctx,
suite.APIClient(),
suite.Service(),
suite.ResourceOwner())
folderAName := "custom"
folderBName := "inherited"
folderCName := "empty"
rootPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
}
folderAPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderAName,
}
subfolderAAPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderAName,
folderAName,
}
subfolderABPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderAName,
folderBName,
}
subfolderACPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderAName,
folderCName,
}
fileCustom := stub.ItemData{
Name: "file-custom",
Data: fileAData,
Meta: stub.MetaData{
Perms: stub.PermData{
User: secondaryUserName,
EntityID: secondaryUserID,
Roles: writePerm,
},
SharingMode: metadata.SharingModeCustom,
},
}
fileInherited := stub.ItemData{
Name: "file-inherited",
Data: fileAData,
Meta: stub.MetaData{
SharingMode: metadata.SharingModeInherited,
},
}
fileEmpty := stub.ItemData{
Name: "file-empty",
Data: fileAData,
Meta: stub.MetaData{
SharingMode: metadata.SharingModeCustom,
},
}
// If parent is empty, then empty permissions would be inherited
fileEmptyInherited := stub.ItemData{
Name: "file-empty",
Data: fileAData,
Meta: stub.MetaData{
SharingMode: metadata.SharingModeInherited,
},
}
fileSet := []stub.ItemData{fileCustom, fileInherited, fileEmpty}
fileSetEmpty := []stub.ItemData{fileCustom, fileInherited, fileEmptyInherited}
// Here is what this test is testing
// - custom-permission-folder
// - custom-permission-file
// - inherted-permission-file
// - empty-permission-file
// - custom-permission-folder
// - custom-permission-file
// - inherted-permission-file
// - empty-permission-file
// - inherted-permission-folder
// - custom-permission-file
// - inherted-permission-file
// - empty-permission-file
// - empty-permission-folder
// - custom-permission-file
// - inherted-permission-file
// - empty-permission-file (empty/empty might have interesting behavior)
cols := []stub.ColInfo{
{
PathElements: rootPath,
Files: []stub.ItemData{},
Folders: []stub.ItemData{
{Name: folderAName},
},
Meta: stub.MetaData{
SharingMode: metadata.SharingModeInherited,
},
},
{
PathElements: folderAPath,
Files: fileSet,
Folders: []stub.ItemData{
{Name: folderAName},
{Name: folderBName},
{Name: folderCName},
},
Meta: stub.MetaData{
Perms: stub.PermData{
User: tertiaryUserName,
EntityID: tertiaryUserID,
Roles: readPerm,
},
SharingMode: metadata.SharingModeCustom,
},
},
{
PathElements: subfolderAAPath,
Files: fileSet,
Meta: stub.MetaData{
Perms: stub.PermData{
User: tertiaryUserName,
EntityID: tertiaryUserID,
Roles: writePerm,
},
SharingMode: metadata.SharingModeCustom,
},
},
{
PathElements: subfolderABPath,
Files: fileSet,
Meta: stub.MetaData{
SharingMode: metadata.SharingModeInherited,
},
},
{
PathElements: subfolderACPath,
Files: fileSetEmpty,
Meta: stub.MetaData{
SharingMode: metadata.SharingModeCustom,
},
},
}
expected, err := stub.DataForInfo(suite.Service(), cols, version.Backup)
require.NoError(suite.T(), err)
bss := suite.Service().String()
for vn := startVersion; vn <= version.Backup; vn++ {
suite.Run(fmt.Sprintf("%s-Version%d", bss, vn), func() {
t := suite.T()
// Ideally this can always be true or false and still
// work, but limiting older versions to use emails so as
// to validate that flow as well.
input, err := stub.DataForInfo(suite.Service(), cols, vn)
require.NoError(suite.T(), err)
testData := restoreBackupInfoMultiVersion{
service: suite.Service(),
backupVersion: vn,
collectionsPrevious: input,
collectionsLatest: expected,
}
restoreCfg := testdata.DefaultRestoreConfig("perms_inherit_restore_and_backup")
restoreCfg.OnCollision = control.Replace
restoreCfg.IncludePermissions = true
opts := control.DefaultOptions()
cfg := m365Stub.ConfigInfo{
Tenant: suite.Tenant(),
ResourceOwners: []string{suite.ResourceOwner()},
Service: testData.service,
Opts: opts,
RestoreCfg: restoreCfg,
}
runRestoreBackupTestVersions(t, testData, cfg)
})
}
}
func testLinkSharesInheritanceRestoreAndBackup(suite oneDriveSuite, startVersion int) {
t := suite.T()
ctx, flush := tester.NewContext(t)
defer flush()
secondaryUserName, secondaryUserID := suite.SecondaryUser()
secondaryUser := metadata.Entity{
ID: secondaryUserID,
Email: secondaryUserName,
EntityType: metadata.GV2User,
}
tertiaryUserName, tertiaryUserID := suite.TertiaryUser()
tertiaryUser := metadata.Entity{
ID: tertiaryUserID,
Email: tertiaryUserName,
EntityType: metadata.GV2User,
}
// Get the default drive ID for the test user.
driveID := mustGetDefaultDriveID(
t,
ctx,
suite.APIClient(),
suite.Service(),
suite.ResourceOwner())
folderAName := "custom"
folderBName := "inherited"
folderCName := "empty"
rootPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
}
folderAPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderAName,
}
subfolderAAPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderAName,
folderAName,
}
subfolderABPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderAName,
folderBName,
}
subfolderACPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderAName,
folderCName,
}
fileSet := []stub.ItemData{
{
Name: "file-custom",
Data: fileAData,
Meta: stub.MetaData{
LinkShares: []stub.LinkShareData{
{
Entities: []metadata.Entity{secondaryUser},
Scope: "users",
Type: "edit",
},
},
SharingMode: metadata.SharingModeCustom,
},
},
{
Name: "file-inherited",
Data: fileBData,
Meta: stub.MetaData{
SharingMode: metadata.SharingModeInherited,
},
},
{
Name: "file-empty",
Data: fileCData,
Meta: stub.MetaData{
SharingMode: metadata.SharingModeCustom,
},
},
}
// Here is what this test is testing
// - custom-link-share-folder
// - custom-link-share-file
// - inherted-link-share-file
// - empty-link-share-file
// - custom-link-share-folder
// - custom-link-share-file
// - inherted-link-share-file
// - empty-link-share-file
// - inherted-link-share-folder
// - custom-link-share-file
// - inherted-link-share-file
// - empty-link-share-file
// - empty-link-share-folder
// - custom-link-share-file
// - inherted-link-share-file
// - empty-link-share-file
cols := []stub.ColInfo{
{
PathElements: rootPath,
Files: []stub.ItemData{},
Folders: []stub.ItemData{
{Name: folderAName},
},
},
{
PathElements: folderAPath,
Files: fileSet,
Folders: []stub.ItemData{
{Name: folderAName},
{Name: folderBName},
{Name: folderCName},
},
Meta: stub.MetaData{
LinkShares: []stub.LinkShareData{
{
Entities: []metadata.Entity{tertiaryUser},
Scope: "anonymous",
Type: "edit",
},
},
},
},
{
PathElements: subfolderAAPath,
Files: fileSet,
Meta: stub.MetaData{
LinkShares: []stub.LinkShareData{
{
Entities: []metadata.Entity{tertiaryUser},
Scope: "users",
Type: "edit",
},
},
SharingMode: metadata.SharingModeCustom,
},
},
{
PathElements: subfolderABPath,
Files: fileSet,
Meta: stub.MetaData{
SharingMode: metadata.SharingModeInherited,
},
},
{
PathElements: subfolderACPath,
Files: fileSet,
Meta: stub.MetaData{
SharingMode: metadata.SharingModeCustom,
},
},
}
expected, err := stub.DataForInfo(suite.Service(), cols, version.Backup)
require.NoError(suite.T(), err)
bss := suite.Service().String()
for vn := startVersion; vn <= version.Backup; vn++ {
suite.Run(fmt.Sprintf("%s-Version%d", bss, vn), func() {
t := suite.T()
// Ideally this can always be true or false and still
// work, but limiting older versions to use emails so as
// to validate that flow as well.
input, err := stub.DataForInfo(suite.Service(), cols, vn)
require.NoError(suite.T(), err)
testData := restoreBackupInfoMultiVersion{
service: suite.Service(),
backupVersion: vn,
collectionsPrevious: input,
collectionsLatest: expected,
}
restoreCfg := testdata.DefaultRestoreConfig("linkshares_inherit_restore_and_backup")
restoreCfg.OnCollision = control.Replace
restoreCfg.IncludePermissions = true
opts := control.DefaultOptions()
cfg := m365Stub.ConfigInfo{
Tenant: suite.Tenant(),
ResourceOwners: []string{suite.ResourceOwner()},
Service: testData.service,
Opts: opts,
RestoreCfg: restoreCfg,
}
runRestoreBackupTestVersions(t, testData, cfg)
})
}
}
func testRestoreFolderNamedFolderRegression(
suite oneDriveSuite,
startVersion int,
) {
t := suite.T()
ctx, flush := tester.NewContext(t)
defer flush()
// Get the default drive ID for the test user.
driveID := mustGetDefaultDriveID(
suite.T(),
ctx,
suite.APIClient(),
suite.Service(),
suite.ResourceOwner())
rootPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
}
folderFolderPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderNamedFolder,
}
subfolderPath := []string{
odConsts.DrivesPathDir,
driveID,
odConsts.RootPathDir,
folderNamedFolder,
folderBName,
}
cols := []stub.ColInfo{
{
PathElements: rootPath,
Files: []stub.ItemData{
{
Name: fileName,
Data: fileAData,
},
},
Folders: []stub.ItemData{
{
Name: folderNamedFolder,
},
{
Name: folderBName,
},
},
},
{
PathElements: folderFolderPath,
Files: []stub.ItemData{
{
Name: fileName,
Data: fileBData,
},
},
Folders: []stub.ItemData{
{
Name: folderBName,
},
},
},
{
PathElements: subfolderPath,
Files: []stub.ItemData{
{
Name: fileName,
Data: fileCData,
},
},
Folders: []stub.ItemData{
{
Name: folderNamedFolder,
},
},
},
}
expected, err := stub.DataForInfo(suite.Service(), cols, version.Backup)
require.NoError(suite.T(), err)
bss := suite.Service().String()
for vn := startVersion; vn <= version.Backup; vn++ {
suite.Run(fmt.Sprintf("%s-Version%d", bss, vn), func() {
t := suite.T()
input, err := stub.DataForInfo(suite.Service(), cols, vn)
require.NoError(suite.T(), err)
testData := restoreBackupInfoMultiVersion{
service: suite.Service(),
backupVersion: vn,
collectionsPrevious: input,
collectionsLatest: expected,
}
restoreCfg := control.DefaultRestoreConfig(dttm.SafeForTesting)
restoreCfg.IncludePermissions = true
opts := control.DefaultOptions()
cfg := m365Stub.ConfigInfo{
Tenant: suite.Tenant(),
ResourceOwners: []string{suite.ResourceOwner()},
Service: testData.service,
Opts: opts,
RestoreCfg: restoreCfg,
}
runRestoreTestWithVersion(t, testData, cfg)
})
}
}