From 474f07e5cc0166a95aeca5779c3344c4ad5a7060 Mon Sep 17 00:00:00 2001 From: Gilbert Chen Date: Mon, 23 Nov 2020 09:44:10 -0500 Subject: [PATCH] Support GCD impersonation via modified service account file --- src/duplicacy_gcdstorage.go | 29 +++++++++++++++++++++++++---- src/duplicacy_storage_test.go | 4 ++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/duplicacy_gcdstorage.go b/src/duplicacy_gcdstorage.go index 85c4c935..01300202 100644 --- a/src/duplicacy_gcdstorage.go +++ b/src/duplicacy_gcdstorage.go @@ -41,6 +41,7 @@ type GCDStorage struct { backoffs []int // desired backoff time in seconds for each thread attempts []int // number of failed attempts since last success for each thread driveID string // the ID of the shared drive or 'root' (GCDUserDrive) if the user's drive + spaces string // 'appDataFolder' if scope is drive.appdata; 'drive' otherwise createDirectoryLock sync.Mutex isConnected bool @@ -199,7 +200,7 @@ func (storage *GCDStorage) listFiles(threadIndex int, parentID string, listFiles var err error for { - q := storage.service.Files.List().Q(query).Fields("nextPageToken", "files(name, mimeType, id, size)").PageToken(startToken).PageSize(maxCount) + q := storage.service.Files.List().Q(query).Fields("nextPageToken", "files(name, mimeType, id, size)").PageToken(startToken).PageSize(maxCount).Spaces(storage.spaces) if storage.driveID != GCDUserDrive { q = q.DriveId(storage.driveID).IncludeItemsFromAllDrives(true).Corpora("drive").SupportsAllDrives(true) } @@ -231,7 +232,7 @@ func (storage *GCDStorage) listByName(threadIndex int, parentID string, name str for { query := "name = '" + name + "' and '" + parentID + "' in parents and trashed = false " - q := storage.service.Files.List().Q(query).Fields("files(name, mimeType, id, size)") + q := storage.service.Files.List().Q(query).Fields("files(name, mimeType, id, size)").Spaces(storage.spaces) if storage.driveID != GCDUserDrive { q = q.DriveId(storage.driveID).IncludeItemsFromAllDrives(true).Corpora("drive").SupportsAllDrives(true) } @@ -344,11 +345,23 @@ func CreateGCDStorage(tokenFile string, driveID string, storagePath string, thre var tokenSource oauth2.TokenSource + scope := drive.DriveScope + if isServiceAccount { - config, err := google.JWTConfigFromJSON(description, drive.DriveScope) + + if newScope, ok := object["scope"]; ok { + scope = newScope.(string) + } + + config, err := google.JWTConfigFromJSON(description, scope) if err != nil { return nil, err } + + if subject, ok := object["subject"]; ok { + config.Subject = subject.(string) + } + tokenSource = config.TokenSource(ctx) } else { gcdConfig := &GCDConfig{} @@ -398,6 +411,7 @@ func CreateGCDStorage(tokenFile string, driveID string, storagePath string, thre backoffs: make([]int, threads), attempts: make([]int, threads), driveID: driveID, + spaces: "drive", } for i := range storage.backoffs { @@ -405,7 +419,14 @@ func CreateGCDStorage(tokenFile string, driveID string, storagePath string, thre storage.attempts[i] = 0 } - storage.savePathID("", driveID) + + if scope == drive.DriveAppdataScope { + storage.spaces = "appDataFolder" + storage.savePathID("", "appDataFolder") + } else { + storage.savePathID("", driveID) + } + storagePathID, err := storage.getIDFromPath(0, storagePath, true) if err != nil { return nil, err diff --git a/src/duplicacy_storage_test.go b/src/duplicacy_storage_test.go index 43c1c2aa..e7fe5f2d 100644 --- a/src/duplicacy_storage_test.go +++ b/src/duplicacy_storage_test.go @@ -142,6 +142,10 @@ func loadStorage(localStoragePath string, threads int) (Storage, error) { storage, err := CreateGCDStorage(config["token_file"], config["drive"], config["storage_path"], threads) storage.SetDefaultNestingLevels([]int{2, 3}, 2) return storage, err + } else if testStorageName == "gcd-impersonate" { + storage, err := CreateGCDStorage(config["token_file"], config["drive"], config["storage_path"], threads) + storage.SetDefaultNestingLevels([]int{2, 3}, 2) + return storage, err } else if testStorageName == "one" { storage, err := CreateOneDriveStorage(config["token_file"], false, config["storage_path"], threads) storage.SetDefaultNestingLevels([]int{2, 3}, 2)