From f6a17e679f4fac2fda21dc7f64565a0dc4a10ca1 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sat, 27 Jul 2019 22:44:15 +0700 Subject: CLOUD: Ask user to manually enable Storage For more security, newly connected Storage only gets username/used space information and is disabled until user manually presses the button. --- backends/cloud/basestorage.cpp | 22 ++++++++++++++++++++-- backends/cloud/basestorage.h | 12 +++++++++++- backends/cloud/box/boxstorage.cpp | 8 +++++--- backends/cloud/box/boxstorage.h | 2 +- backends/cloud/cloudmanager.cpp | 16 +++++++++++++++- backends/cloud/cloudmanager.h | 6 ++++++ backends/cloud/dropbox/dropboxstorage.cpp | 8 +++++--- backends/cloud/dropbox/dropboxstorage.h | 2 +- backends/cloud/googledrive/googledrivestorage.cpp | 8 +++++--- backends/cloud/googledrive/googledrivestorage.h | 2 +- backends/cloud/id/idstorage.cpp | 4 ++-- backends/cloud/id/idstorage.h | 2 +- backends/cloud/onedrive/onedrivestorage.cpp | 8 +++++--- backends/cloud/onedrive/onedrivestorage.h | 2 +- backends/cloud/storage.cpp | 23 ++++++++++++++++++++++- backends/cloud/storage.h | 13 +++++++++++++ 16 files changed, 114 insertions(+), 24 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/basestorage.cpp b/backends/cloud/basestorage.cpp index ea54a97fd9..074c8596ec 100644 --- a/backends/cloud/basestorage.cpp +++ b/backends/cloud/basestorage.cpp @@ -32,8 +32,10 @@ namespace Cloud { BaseStorage::BaseStorage() {} -BaseStorage::BaseStorage(Common::String token, Common::String refreshToken): - _token(token), _refreshToken(refreshToken) {} +BaseStorage::BaseStorage(Common::String token, Common::String refreshToken, bool enabled): + _token(token), _refreshToken(refreshToken) { + _isEnabled = enabled; +} BaseStorage::~BaseStorage() {} @@ -212,4 +214,20 @@ void BaseStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResponse delete callback; } +void BaseStorage::saveIsEnabledFlag(const Common::String &keyPrefix) const { + ConfMan.set(keyPrefix + "enabled", _isEnabled ? "true" : "false", ConfMan.kCloudDomain); +} + +bool BaseStorage::loadIsEnabledFlag(const Common::String &keyPrefix) { + if (!ConfMan.hasKey(keyPrefix + "enabled", ConfMan.kCloudDomain)) + return false; + + Common::String enabled = ConfMan.get(keyPrefix + "enabled", ConfMan.kCloudDomain); + return (enabled == "true"); +} + +void BaseStorage::removeIsEnabledFlag(const Common::String &keyPrefix) { + ConfMan.removeKey(keyPrefix + "enabled", ConfMan.kCloudDomain); +} + } // End of namespace Cloud diff --git a/backends/cloud/basestorage.h b/backends/cloud/basestorage.h index aae1a6ec2f..de287fcba3 100644 --- a/backends/cloud/basestorage.h +++ b/backends/cloud/basestorage.h @@ -77,9 +77,19 @@ protected: private: void tokenRefreshed(BoolCallback callback, Networking::JsonResponse response); +protected: + /** Helper function to save Storage::_isEnabled into config. */ + void saveIsEnabledFlag(const Common::String &keyPrefix) const; + + /** Helper function to load Storage::_isEnabled value from config. */ + static bool loadIsEnabledFlag(const Common::String &keyPrefix); + + /** Helper function to remove Storage::_isEnabled from config. */ + static void removeIsEnabledFlag(const Common::String &keyPrefix); + public: BaseStorage(); - BaseStorage(Common::String token, Common::String refreshToken); + BaseStorage(Common::String token, Common::String refreshToken, bool enabled = false); virtual ~BaseStorage(); /** diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 13046a08e0..46af2e56be 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -42,8 +42,8 @@ namespace Box { #define BOX_API_FILES_CONTENT "https://api.box.com/2.0/files/%s/content" #define BOX_API_USERS_ME "https://api.box.com/2.0/users/me" -BoxStorage::BoxStorage(Common::String token, Common::String refreshToken): - IdStorage(token, refreshToken) {} +BoxStorage::BoxStorage(Common::String token, Common::String refreshToken, bool enabled): + IdStorage(token, refreshToken, enabled) {} BoxStorage::BoxStorage(Common::String code, Networking::ErrorCallback cb) { getAccessToken(code, cb); @@ -62,6 +62,7 @@ bool BoxStorage::canReuseRefreshToken() { return false; } void BoxStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "access_token", _token, ConfMan.kCloudDomain); ConfMan.set(keyPrefix + "refresh_token", _refreshToken, ConfMan.kCloudDomain); + saveIsEnabledFlag(keyPrefix); } Common::String BoxStorage::name() const { @@ -224,12 +225,13 @@ BoxStorage *BoxStorage::loadFromConfig(Common::String keyPrefix) { Common::String accessToken = ConfMan.get(keyPrefix + "access_token", ConfMan.kCloudDomain); Common::String refreshToken = ConfMan.get(keyPrefix + "refresh_token", ConfMan.kCloudDomain); - return new BoxStorage(accessToken, refreshToken); + return new BoxStorage(accessToken, refreshToken, loadIsEnabledFlag(keyPrefix)); } void BoxStorage::removeFromConfig(Common::String keyPrefix) { ConfMan.removeKey(keyPrefix + "access_token", ConfMan.kCloudDomain); ConfMan.removeKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain); + removeIsEnabledFlag(keyPrefix); } Common::String BoxStorage::getRootDirectoryId() { diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h index ce77192bfa..1916c88449 100644 --- a/backends/cloud/box/boxstorage.h +++ b/backends/cloud/box/boxstorage.h @@ -31,7 +31,7 @@ namespace Box { class BoxStorage: public Id::IdStorage { /** This private constructor is called from loadFromConfig(). */ - BoxStorage(Common::String token, Common::String refreshToken); + BoxStorage(Common::String token, Common::String refreshToken, bool enabled); /** Constructs StorageInfo based on JSON response from cloud. */ void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index a3e9856455..38089db0e9 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -159,7 +159,6 @@ void CloudManager::replaceStorage(Storage *storage, uint32 index) { //do what should be done on first Storage connect if (_activeStorage) { _activeStorage->info(nullptr, nullptr); //automatically calls setStorageUsername() - _activeStorage->syncSaves(nullptr, nullptr); } } @@ -365,6 +364,21 @@ bool CloudManager::canSyncFilename(const Common::String &filename) const { return true; } +bool CloudManager::isStorageEnabled() const { + Storage *storage = getCurrentStorage(); + if (storage) + return storage->isEnabled(); + return false; +} + +void CloudManager::enableStorage() { + Storage *storage = getCurrentStorage(); + if (storage) { + storage->enable(); + save(); + } +} + SavesSyncRequest *CloudManager::syncSaves(Storage::BoolCallback callback, Networking::ErrorCallback errorCallback) { Storage *storage = getCurrentStorage(); if (storage) { diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index ebcc6ea5cf..2d6c0bad43 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -230,6 +230,12 @@ public: /** Returns whether given filename could be uploaded to or downloaded from storage. */ bool canSyncFilename(const Common::String &filename) const; + /** Returns whether current Storage is manually enabled by user (or false, if there is no active Storage). */ + bool isStorageEnabled() const; + + /** Sets Storage::_isEnabled to true and updates the config. */ + void enableStorage(); + /** * Starts saves syncing process in currently active storage if there is any. */ diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 5d8b9e0425..7edc609969 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -40,7 +40,7 @@ namespace Dropbox { #define DROPBOX_API_FILES_DOWNLOAD "https://content.dropboxapi.com/2/files/download" -DropboxStorage::DropboxStorage(Common::String accessToken, bool unused): BaseStorage(accessToken, "") {} +DropboxStorage::DropboxStorage(Common::String accessToken, bool enabled): BaseStorage(accessToken, "", enabled) {} DropboxStorage::DropboxStorage(Common::String code, Networking::ErrorCallback cb): BaseStorage() { getAccessToken(code, cb); @@ -58,6 +58,7 @@ bool DropboxStorage::canReuseRefreshToken() { return false; } void DropboxStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "access_token", _token, ConfMan.kCloudDomain); + saveIsEnabledFlag(keyPrefix); } Common::String DropboxStorage::name() const { @@ -108,12 +109,13 @@ DropboxStorage *DropboxStorage::loadFromConfig(Common::String keyPrefix) { return nullptr; } - Common::String accessToken = ConfMan.get(keyPrefix + "access_token", ConfMan.kCloudDomain); - return new DropboxStorage(accessToken, true); + Common::String accessToken = ConfMan.get(keyPrefix + "access_token", ConfMan.kCloudDomain); + return new DropboxStorage(accessToken, loadIsEnabledFlag(keyPrefix)); } void DropboxStorage::removeFromConfig(Common::String keyPrefix) { ConfMan.removeKey(keyPrefix + "access_token", ConfMan.kCloudDomain); + removeIsEnabledFlag(keyPrefix); } } // End of namespace Dropbox diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 0b76bb5c4a..c6a1374357 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -32,7 +32,7 @@ namespace Dropbox { class DropboxStorage: public Cloud::BaseStorage { /** This private constructor is called from loadFromConfig(). */ - DropboxStorage(Common::String token, bool unused); + DropboxStorage(Common::String token, bool enabled); protected: /** diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index a6e17e6ad3..2049d808c4 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -43,8 +43,8 @@ namespace GoogleDrive { #define GOOGLEDRIVE_API_FILES "https://www.googleapis.com/drive/v3/files" #define GOOGLEDRIVE_API_ABOUT "https://www.googleapis.com/drive/v3/about?fields=storageQuota,user" -GoogleDriveStorage::GoogleDriveStorage(Common::String token, Common::String refreshToken): - IdStorage(token, refreshToken) {} +GoogleDriveStorage::GoogleDriveStorage(Common::String token, Common::String refreshToken, bool enabled): + IdStorage(token, refreshToken, enabled) {} GoogleDriveStorage::GoogleDriveStorage(Common::String code, Networking::ErrorCallback cb) { getAccessToken(code, cb); @@ -63,6 +63,7 @@ bool GoogleDriveStorage::canReuseRefreshToken() { return true; } void GoogleDriveStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "access_token", _token, ConfMan.kCloudDomain); ConfMan.set(keyPrefix + "refresh_token", _refreshToken, ConfMan.kCloudDomain); + saveIsEnabledFlag(keyPrefix); } Common::String GoogleDriveStorage::name() const { @@ -228,12 +229,13 @@ GoogleDriveStorage *GoogleDriveStorage::loadFromConfig(Common::String keyPrefix) Common::String accessToken = ConfMan.get(keyPrefix + "access_token", ConfMan.kCloudDomain); Common::String refreshToken = ConfMan.get(keyPrefix + "refresh_token", ConfMan.kCloudDomain); - return new GoogleDriveStorage(accessToken, refreshToken); + return new GoogleDriveStorage(accessToken, refreshToken, loadIsEnabledFlag(keyPrefix)); } void GoogleDriveStorage::removeFromConfig(Common::String keyPrefix) { ConfMan.removeKey(keyPrefix + "access_token", ConfMan.kCloudDomain); ConfMan.removeKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain); + removeIsEnabledFlag(keyPrefix); } Common::String GoogleDriveStorage::getRootDirectoryId() { diff --git a/backends/cloud/googledrive/googledrivestorage.h b/backends/cloud/googledrive/googledrivestorage.h index db47e7cd3c..792c30a99f 100644 --- a/backends/cloud/googledrive/googledrivestorage.h +++ b/backends/cloud/googledrive/googledrivestorage.h @@ -31,7 +31,7 @@ namespace GoogleDrive { class GoogleDriveStorage: public Id::IdStorage { /** This private constructor is called from loadFromConfig(). */ - GoogleDriveStorage(Common::String token, Common::String refreshToken); + GoogleDriveStorage(Common::String token, Common::String refreshToken, bool enabled); /** Constructs StorageInfo based on JSON response from cloud. */ void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); diff --git a/backends/cloud/id/idstorage.cpp b/backends/cloud/id/idstorage.cpp index dd8805ea9b..78c3facc2c 100644 --- a/backends/cloud/id/idstorage.cpp +++ b/backends/cloud/id/idstorage.cpp @@ -35,8 +35,8 @@ namespace Id { IdStorage::IdStorage() {} -IdStorage::IdStorage(Common::String token, Common::String refreshToken): - BaseStorage(token, refreshToken) {} +IdStorage::IdStorage(Common::String token, Common::String refreshToken, bool enabled): + BaseStorage(token, refreshToken, enabled) {} IdStorage::~IdStorage() {} diff --git a/backends/cloud/id/idstorage.h b/backends/cloud/id/idstorage.h index 35a320284e..26d2618508 100644 --- a/backends/cloud/id/idstorage.h +++ b/backends/cloud/id/idstorage.h @@ -53,7 +53,7 @@ protected: public: IdStorage(); - IdStorage(Common::String token, Common::String refreshToken); + IdStorage(Common::String token, Common::String refreshToken, bool enabled); virtual ~IdStorage(); /** Public Cloud API comes down there. */ diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 6d05d84c39..e7ac5b70f5 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -42,8 +42,8 @@ namespace OneDrive { #define ONEDRIVE_API_SPECIAL_APPROOT_ID "https://graph.microsoft.com/v1.0/drive/special/approot:/" #define ONEDRIVE_API_SPECIAL_APPROOT "https://graph.microsoft.com/v1.0/drive/special/approot" -OneDriveStorage::OneDriveStorage(Common::String token, Common::String refreshToken): - BaseStorage(token, refreshToken) {} +OneDriveStorage::OneDriveStorage(Common::String token, Common::String refreshToken, bool enabled): + BaseStorage(token, refreshToken, enabled) {} OneDriveStorage::OneDriveStorage(Common::String code, Networking::ErrorCallback cb) { getAccessToken(code, cb); @@ -62,6 +62,7 @@ bool OneDriveStorage::canReuseRefreshToken() { return false; } void OneDriveStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "access_token", _token, ConfMan.kCloudDomain); ConfMan.set(keyPrefix + "refresh_token", _refreshToken, ConfMan.kCloudDomain); + saveIsEnabledFlag(keyPrefix); } Common::String OneDriveStorage::name() const { @@ -206,12 +207,13 @@ OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { Common::String accessToken = ConfMan.get(keyPrefix + "access_token", ConfMan.kCloudDomain); Common::String refreshToken = ConfMan.get(keyPrefix + "refresh_token", ConfMan.kCloudDomain); - return new OneDriveStorage(accessToken, refreshToken); + return new OneDriveStorage(accessToken, refreshToken, loadIsEnabledFlag(keyPrefix)); } void OneDriveStorage::removeFromConfig(Common::String keyPrefix) { ConfMan.removeKey(keyPrefix + "access_token", ConfMan.kCloudDomain); ConfMan.removeKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain); + removeIsEnabledFlag(keyPrefix); } } // End of namespace OneDrive diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index cc46772282..edf6a5f53f 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -31,7 +31,7 @@ namespace OneDrive { class OneDriveStorage: public Cloud::BaseStorage { /** This private constructor is called from loadFromConfig(). */ - OneDriveStorage(Common::String token, Common::String refreshToken); + OneDriveStorage(Common::String token, Common::String refreshToken, bool enabled); /** Constructs StorageInfo based on JSON response from cloud. */ void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 3a9ae53a43..ed7f8f0ae7 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -34,10 +34,18 @@ namespace Cloud { Storage::Storage(): _runningRequestsCount(0), _savesSyncRequest(nullptr), _syncRestartRequestsed(false), - _downloadFolderRequest(nullptr) {} + _downloadFolderRequest(nullptr), _isEnabled(false) {} Storage::~Storage() {} +bool Storage::isEnabled() const { + return _isEnabled; +} + +void Storage::enable() { + _isEnabled = true; +} + Networking::ErrorCallback Storage::getErrorPrintingCallback() { return new Common::Callback(this, &Storage::printErrorResponse); } @@ -121,6 +129,12 @@ Networking::Request *Storage::downloadById(Common::String remoteId, Common::Stri } Networking::Request *Storage::downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { + if (!_isEnabled) { + warning("Storage::downloadFolder: cannot be run while Storage is disabled"); + if (errorCallback) + (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "Storage is disabled.", -1)); + return nullptr; + } if (!errorCallback) errorCallback = getErrorPrintingCallback(); return addRequest(new FolderDownloadRequest(this, callback, errorCallback, remotePath, localPath, recursive)); @@ -128,6 +142,13 @@ Networking::Request *Storage::downloadFolder(Common::String remotePath, Common:: SavesSyncRequest *Storage::syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback) { _runningRequestsMutex.lock(); + if (!_isEnabled) { + warning("Storage::syncSaves: cannot be run while Storage is disabled"); + if (errorCallback) + (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "Storage is disabled.", -1)); + _runningRequestsMutex.unlock(); + return nullptr; + } if (_savesSyncRequest) { warning("Storage::syncSaves: there is a sync in progress already"); _syncRestartRequestsed = true; diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index e914834dae..aa6455b841 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -70,6 +70,9 @@ protected: /** FolderDownloadRequest-related */ FolderDownloadRequest *_downloadFolderRequest; + /** Whether user manually enabled the Storage. */ + bool _isEnabled; + /** Returns default error callback (printErrorResponse). */ virtual Networking::ErrorCallback getErrorPrintingCallback(); @@ -115,6 +118,16 @@ public: */ virtual Common::String name() const = 0; + /** + * Return whether Storage has been manually enabled by user. + */ + bool isEnabled() const; + + /** + * Set _isEnabled to true. + */ + void enable(); + /** * Public Cloud API comes down there. * -- cgit v1.2.3