From 35f74f5ea45ecc563e8de49fda642cf25a31335f Mon Sep 17 00:00:00 2001 From: Philipp Crocoll Date: Wed, 2 Feb 2022 03:50:51 +0100 Subject: [PATCH] add support for Google Drive with restricted scope, closes #622 --- src/Kp2aBusinessLogic/Io/GDriveFileStorage.cs | 16 +++++++++++- .../Resources/Resource.Designer.cs | 14 ++++++++--- .../GoogleDriveAppDataFileStorage.java | 18 ++++++++++++++ ...e.java => GoogleDriveBaseFileStorage.java} | 23 +++++++++--------- .../GoogleDriveFullFileStorage.java | 20 +++++++++++++++ .../javafilestoragetest2/MainActivity.java | 4 +-- .../drawable-mdpi/ic_storage_gdriveKP2A.png | Bin 0 -> 8834 bytes .../drawable-xhdpi/ic_storage_gdriveKP2A.png | Bin 0 -> 12531 bytes .../Resources/values/strings.xml | 2 ++ src/keepass2android/app/App.cs | 2 ++ .../keepass2android-app.csproj | 4 +++ 11 files changed, 85 insertions(+), 18 deletions(-) create mode 100644 src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveAppDataFileStorage.java rename src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/{GoogleDriveFileStorage.java => GoogleDriveBaseFileStorage.java} (98%) create mode 100644 src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveFullFileStorage.java create mode 100644 src/keepass2android/Resources/drawable-mdpi/ic_storage_gdriveKP2A.png create mode 100644 src/keepass2android/Resources/drawable-xhdpi/ic_storage_gdriveKP2A.png diff --git a/src/Kp2aBusinessLogic/Io/GDriveFileStorage.cs b/src/Kp2aBusinessLogic/Io/GDriveFileStorage.cs index 1636e232..9d83c3ba 100644 --- a/src/Kp2aBusinessLogic/Io/GDriveFileStorage.cs +++ b/src/Kp2aBusinessLogic/Io/GDriveFileStorage.cs @@ -17,7 +17,7 @@ namespace keepass2android.Io public class GoogleDriveFileStorage : JavaFileStorage { public GoogleDriveFileStorage(Context ctx, IKp2aApp app) : - base(new Keepass2android.Javafilestorage.GoogleDriveFileStorage(), app) + base(new Keepass2android.Javafilestorage.GoogleDriveFullFileStorage(), app) { } @@ -27,5 +27,19 @@ namespace keepass2android.Io get { return false; } } } + + public class GoogleDriveAppDataFileStorage : JavaFileStorage + { + public GoogleDriveAppDataFileStorage(Context ctx, IKp2aApp app) : + base(new Keepass2android.Javafilestorage.GoogleDriveAppDataFileStorage(), app) + { + } + + + public override bool UserShouldBackup + { + get { return false; } + } + } } #endif \ No newline at end of file diff --git a/src/Kp2aBusinessLogic/Resources/Resource.Designer.cs b/src/Kp2aBusinessLogic/Resources/Resource.Designer.cs index c071c0da..692799c7 100644 --- a/src/Kp2aBusinessLogic/Resources/Resource.Designer.cs +++ b/src/Kp2aBusinessLogic/Resources/Resource.Designer.cs @@ -2998,7 +2998,10 @@ namespace keepass2android public static int config_tooltipAnimTime = 2131230727; // aapt resource value: 0x7F080008 - public static int status_bar_notification_info_maxnum = 2131230728; + public static int google_play_services_version = 2131230728; + + // aapt resource value: 0x7F080009 + public static int status_bar_notification_info_maxnum = 2131230729; static Integer() { @@ -3560,13 +3563,16 @@ namespace keepass2android public static int app_name = 2131492964; // aapt resource value: 0x7F0C0065 - public static int library_name = 2131492965; + public static int common_google_play_services_unknown_issue = 2131492965; // aapt resource value: 0x7F0C0066 - public static int search_menu_title = 2131492966; + public static int library_name = 2131492966; // aapt resource value: 0x7F0C0067 - public static int status_bar_notification_info_overflow = 2131492967; + public static int search_menu_title = 2131492967; + + // aapt resource value: 0x7F0C0068 + public static int status_bar_notification_info_overflow = 2131492968; static String() { diff --git a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveAppDataFileStorage.java b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveAppDataFileStorage.java new file mode 100644 index 00000000..4595d97c --- /dev/null +++ b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveAppDataFileStorage.java @@ -0,0 +1,18 @@ +package keepass2android.javafilestorage; + +import com.google.android.gms.common.Scopes; + +public class GoogleDriveAppDataFileStorage extends GoogleDriveBaseFileStorage +{ + private static final String GDRIVE_PROTOCOL_ID = "gdriveKP2A"; + + @Override + protected String getScopeString() { + return Scopes.DRIVE_FILE; + } + + @Override + public String getProtocolId() { + return GDRIVE_PROTOCOL_ID; + } +} diff --git a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveFileStorage.java b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveBaseFileStorage.java similarity index 98% rename from src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveFileStorage.java rename to src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveBaseFileStorage.java index 1851a579..9cf69bae 100644 --- a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveFileStorage.java +++ b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveBaseFileStorage.java @@ -55,9 +55,9 @@ import com.google.android.gms.tasks.Task; import static android.content.pm.PackageManager.PERMISSION_GRANTED; -public class GoogleDriveFileStorage extends JavaFileStorageBase { +public abstract class GoogleDriveBaseFileStorage extends JavaFileStorageBase { + - private static final String GDRIVE_PROTOCOL_ID = "gdrive"; private static final String FOLDER_MIME_TYPE = "application/vnd.google-apps.folder"; static final int MAGIC_GDRIVE=2082334; static final int REQUEST_ACCOUNT_PICKER = MAGIC_GDRIVE+1; @@ -89,7 +89,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase { public String getRootPathForAccount(String accountName) throws UnsupportedEncodingException { - return GDRIVE_PROTOCOL_ID+"://"+encode(accountName)+"/"; + return getProtocolId()+"://"+encode(accountName)+"/"; } class GDrivePath @@ -276,7 +276,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase { }; - public GoogleDriveFileStorage() + public GoogleDriveBaseFileStorage() { logDebug("Creating GDrive FileStorage."); } @@ -612,7 +612,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase { try { // Signed in successfully GoogleSignInAccount account = completedTask.getResult(ApiException.class); - if (GoogleSignIn.hasPermissions(account, new Scope(Scopes.DRIVE_FULL))) { + if (GoogleSignIn.hasPermissions(account, getScope())) { initializeAccountOrPath(setupAct, account.getAccount().name); return; @@ -851,10 +851,6 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase { } - @Override - public String getProtocolId() { - return GDRIVE_PROTOCOL_ID; - } @Override @@ -882,7 +878,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase { // Configure sign-in to request the user's ID, email address, and basic // profile. ID and basic profile are included in DEFAULT_SIGN_IN. GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) - .requestScopes(new Scope(Scopes.DRIVE_FULL)) + .requestScopes(getScope()) .requestEmail() .build(); // [END configure_signin] @@ -922,10 +918,15 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase { } + protected Scope getScope() { + return new Scope(getScopeString()); + } + + protected abstract String getScopeString(); private GoogleAccountCredential createCredential(Context appContext) { List scopes = new ArrayList(); - scopes.add(DriveScopes.DRIVE); + scopes.add(getScopeString()); GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(appContext, scopes); return credential; } diff --git a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveFullFileStorage.java b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveFullFileStorage.java new file mode 100644 index 00000000..92f1a6fb --- /dev/null +++ b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/GoogleDriveFullFileStorage.java @@ -0,0 +1,20 @@ +package keepass2android.javafilestorage; + +import com.google.android.gms.common.Scopes; +import com.google.android.gms.common.api.Scope; + +public class GoogleDriveFullFileStorage extends GoogleDriveBaseFileStorage +{ + private static final String GDRIVE_PROTOCOL_ID = "gdrive"; + + @Override + protected String getScopeString() { + return Scopes.DRIVE_FULL; + } + + @Override + public String getProtocolId() { + return GDRIVE_PROTOCOL_ID; + } +} + diff --git a/src/java/JavaFileStorageTest-AS/app/src/main/java/com/crocoapps/javafilestoragetest2/MainActivity.java b/src/java/JavaFileStorageTest-AS/app/src/main/java/com/crocoapps/javafilestoragetest2/MainActivity.java index 6f029d9c..23adb14c 100644 --- a/src/java/JavaFileStorageTest-AS/app/src/main/java/com/crocoapps/javafilestoragetest2/MainActivity.java +++ b/src/java/JavaFileStorageTest-AS/app/src/main/java/com/crocoapps/javafilestoragetest2/MainActivity.java @@ -145,7 +145,7 @@ import java.util.ArrayList; import java.util.List; //import keepass2android.javafilestorage.DropboxCloudRailStorage; -import keepass2android.javafilestorage.GoogleDriveFileStorage; +import keepass2android.javafilestorage.GoogleDriveAppDataFileStorage; import keepass2android.javafilestorage.JavaFileStorage; import keepass2android.javafilestorage.JavaFileStorage.FileEntry; import keepass2android.javafilestorage.SftpStorage; @@ -543,7 +543,7 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag //storageToTest = new SkyDriveFileStorage("000000004010C234", appContext); - storageToTest = new GoogleDriveFileStorage(); + storageToTest = new GoogleDriveAppDataFileStorage(); /*storageToTest = new WebDavStorage(new ICertificateErrorHandler() { @Override public boolean onValidationError(String error) { diff --git a/src/keepass2android/Resources/drawable-mdpi/ic_storage_gdriveKP2A.png b/src/keepass2android/Resources/drawable-mdpi/ic_storage_gdriveKP2A.png new file mode 100644 index 0000000000000000000000000000000000000000..d5dea5943d2061f8379234a62348dfc0babdcf43 GIT binary patch literal 8834 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 WEyG$H9^wuxcq$4S@Dropbox (KP2A folder) If you do not want to give KP2A access to your full Dropbox, you may select this option. It will request only access to the folder Apps/Keepass2Android. This is especially suited when creating a new database. If you already have a database, select this option to create the folder, then place your file inside the folder (from your PC) and then select this option again for opening the file. Google Drive + Google Drive (KP2A files) + If you do not want to give KP2A access to your full Google Drive, you may select this option. Note that you need to create a database file first, existing files are not visible to the app. Either choose this option from the Create database screen or, if you already opened a database, by exporting the database choosing this option. PCloud This storage type will only request access to the pCloud folder "Applications/Keepass2Android". If you want to use an existing database from your pCloud account, please make sure the file is placed in this pCloud folder. OneDrive diff --git a/src/keepass2android/app/App.cs b/src/keepass2android/app/App.cs index 56ef1767..24f25efc 100644 --- a/src/keepass2android/app/App.cs +++ b/src/keepass2android/app/App.cs @@ -44,6 +44,7 @@ using keepass2android.addons.OtpKeyProv; using keepass2android.database.edit; using KeePassLib.Interfaces; using KeePassLib.Utility; +using GoogleDriveAppDataFileStorage = keepass2android.Io.GoogleDriveAppDataFileStorage; #if !NoNet #if !EXCLUDE_JAVAFILESTORAGE using Android.Gms.Common; @@ -725,6 +726,7 @@ namespace keepass2android new DropboxFileStorage(LocaleManager.LocalizedAppContext, this), new DropboxAppFolderFileStorage(LocaleManager.LocalizedAppContext, this), GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(LocaleManager.LocalizedAppContext)==ConnectionResult.Success ? new GoogleDriveFileStorage(LocaleManager.LocalizedAppContext, this) : null, + GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(LocaleManager.LocalizedAppContext)==ConnectionResult.Success ? new GoogleDriveAppDataFileStorage(LocaleManager.LocalizedAppContext, this) : null, new OneDriveFileStorage(LocaleManager.LocalizedAppContext, this), new OneDrive2FullFileStorage(), new OneDrive2MyFilesFileStorage(), diff --git a/src/keepass2android/keepass2android-app.csproj b/src/keepass2android/keepass2android-app.csproj index 3eadcb8c..41e6ac8f 100644 --- a/src/keepass2android/keepass2android-app.csproj +++ b/src/keepass2android/keepass2android-app.csproj @@ -474,6 +474,7 @@ + @@ -1100,6 +1101,9 @@ + + +