From 4d7d2bac1ef48280ccc898ce57e58253a5fc1d11 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Thu, 25 Aug 2022 21:51:46 +0800 Subject: [PATCH 1/5] Make the server URL configurable, used shared keys for signing --- android/Omnivore/app/build.gradle | 25 +++++++++++++++++-- .../java/app/omnivore/omnivore/Constants.kt | 2 +- .../app/omnivore/omnivore/RESTNetworker.kt | 2 +- .../omnivore/omnivore/ui/auth/GoogleAuth.kt | 11 +++----- .../omnivore/ui/auth/LoginViewModel.kt | 8 +++--- .../omnivore/ui/save/SaveViewModel.kt | 2 +- 6 files changed, 33 insertions(+), 17 deletions(-) diff --git a/android/Omnivore/app/build.gradle b/android/Omnivore/app/build.gradle index cb1022569..ba413cec8 100644 --- a/android/Omnivore/app/build.gradle +++ b/android/Omnivore/app/build.gradle @@ -13,8 +13,8 @@ android { applicationId "app.omnivore.omnivore" minSdk 23 targetSdk 32 - versionCode 1 - versionName "1.0" + versionCode 2 + versionName "0.0.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { @@ -22,9 +22,30 @@ android { } } + signingConfigs{ + release{ + keyAlias 'key0' + storeFile file('external/omnivore-prod.keystore') + storePassword 'omnivore' + } + debug{ + storePassword 'android' + keyAlias 'androiddebugkey' + storeFile file('external/omnivore-demo.keystore') + } + } + buildTypes { + debug{ + signingConfig signingConfigs.debug + buildConfigField("String", "OMNIVORE_API_URL", "\"https://api-demo.omnivore.app\"") + buildConfigField("String", "OMNIVORE_GAUTH_SERVER_CLIENT_ID", "\"267918240109-eu2ar09unac3lqqigluknhk7t0021b54.apps.googleusercontent.com\"") + } release { minifyEnabled false + signingConfig signingConfigs.release + buildConfigField("String", "OMNIVORE_API_URL", "\"https://api-prod.omnivore.app\"") + buildConfigField("String", "OMNIVORE_GAUTH_SERVER_CLIENT_ID", "\"687911924401-lq8j1e97n0sv3khhb8g8n368lk4dqkbp.apps.googleusercontent.com\"") proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Constants.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Constants.kt index db72ef5b7..e4852a6bc 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Constants.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Constants.kt @@ -1,7 +1,7 @@ package app.omnivore.omnivore object Constants { - const val demoProdURL = "https://api-demo.omnivore.app" + const val apiURL = BuildConfig.OMNIVORE_API_URL const val dataStoreName = "omnivore-datastore" } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/RESTNetworker.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/RESTNetworker.kt index c3956f73e..c9e238e67 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/RESTNetworker.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/RESTNetworker.kt @@ -43,7 +43,7 @@ interface AuthProviderLoginSubmit { object RetrofitHelper { fun getInstance(): Retrofit { - return Retrofit.Builder().baseUrl(Constants.demoProdURL) + return Retrofit.Builder().baseUrl(Constants.apiURL) .addConverterFactory(GsonConverterFactory.create()) .build() } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/GoogleAuth.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/GoogleAuth.kt index 874215cff..436bc31c6 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/GoogleAuth.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/GoogleAuth.kt @@ -1,30 +1,27 @@ package app.omnivore.omnivore.ui.auth import android.app.Activity -import android.content.ContentValues -import android.util.Log import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.ActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource +import app.omnivore.omnivore.BuildConfig import app.omnivore.omnivore.R import com.google.android.gms.auth.api.signin.GoogleSignIn import com.google.android.gms.auth.api.signin.GoogleSignInAccount import com.google.android.gms.auth.api.signin.GoogleSignInOptions -import com.google.android.gms.common.api.ApiException -import com.google.android.gms.tasks.OnCompleteListener import com.google.android.gms.tasks.Task @Composable fun GoogleAuthButton(viewModel: LoginViewModel) { val context = LocalContext.current + val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) - .requestIdToken(stringResource(R.string.gcp_id)) -// .requestServerAuthCode(stringResource(R.string.gcp_id), true) + .requestIdToken(BuildConfig.OMNIVORE_GAUTH_SERVER_CLIENT_ID) + .requestEmail() .build() val startForResult = diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/LoginViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/LoginViewModel.kt index 77e3b4533..352281598 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/LoginViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/LoginViewModel.kt @@ -7,10 +7,8 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.* import app.omnivore.omnivore.* -import com.google.android.gms.auth.api.signin.GoogleSignIn import com.google.android.gms.auth.api.signin.GoogleSignInAccount import com.google.android.gms.common.api.ApiException -import com.google.android.gms.tasks.OnCompleteListener import com.google.android.gms.tasks.Task import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.distinctUntilChanged @@ -91,10 +89,10 @@ class LoginViewModel @Inject constructor( Log.d(ContentValues.TAG, "granted Scopes?: ${result.grantedScopes}") val googleIdToken = result.idToken Log.d(ContentValues.TAG, "Google id token?: $googleIdToken") - // TODO: submit id token to backend - // If token is missing then set the error message + // If token is missing then set the error message if (googleIdToken == null) { + errorMessage = "No authentication token found." return } @@ -113,7 +111,7 @@ class LoginViewModel @Inject constructor( if (result.body()?.authToken != null) { datastoreRepo.putString(DatastoreKeys.omnivoreAuthToken, result.body()?.authToken!!) } else { - errorMessage = "Something went wrong. Please check your email/password and try again" + errorMessage = "Something went wrong. Please check your credentials and try again" } if (result.body()?.authCookieString != null) { diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveViewModel.kt index 710554047..4e1acc23c 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveViewModel.kt @@ -47,7 +47,7 @@ class SaveViewModel @Inject constructor( } val apolloClient = ApolloClient.Builder() - .serverUrl("${Constants.demoProdURL}/api/graphql") + .serverUrl("${Constants.apiURL}/api/graphql") .addHttpHeader("Authorization", value = apiKey) .build() From c8b498095cd665356fbf8775883d9ce199a1fa40 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Thu, 25 Aug 2022 21:54:04 +0800 Subject: [PATCH 2/5] Button colour on the share extension --- .../java/app/omnivore/omnivore/ui/save/SaveContent.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveContent.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveContent.kt index 62a355061..710768e67 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveContent.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveContent.kt @@ -8,7 +8,9 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.material.* +import androidx.compose.material.ButtonDefaults import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import app.omnivore.omnivore.ui.save.SaveViewModel import kotlinx.coroutines.launch @@ -32,7 +34,12 @@ fun SaveContent(viewModel: SaveViewModel, modalBottomSheetState: ModalBottomShee coroutineScope.launch { modalBottomSheetState.hide() } - }) { + }, + colors = ButtonDefaults.buttonColors( + contentColor = Color(0xFF3D3D3D), + backgroundColor = Color(0xffffd234) + ) + ) { Text(text = "Dismiss") } } From 0545c29453ca085d56928e228bd7e2b6aa584d17 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Thu, 25 Aug 2022 22:23:55 +0800 Subject: [PATCH 3/5] use properties file for signing info --- android/Omnivore/app/build.gradle | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/android/Omnivore/app/build.gradle b/android/Omnivore/app/build.gradle index ba413cec8..78849006b 100644 --- a/android/Omnivore/app/build.gradle +++ b/android/Omnivore/app/build.gradle @@ -6,6 +6,10 @@ plugins { id 'com.apollographql.apollo3' version '3.5.0' } +def keystorePropertiesFile = rootProject.file("app/external/keystore.properties"); +def keystoreProperties = new Properties() +keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) + android { compileSdk 33 @@ -26,12 +30,14 @@ android { release{ keyAlias 'key0' storeFile file('external/omnivore-prod.keystore') - storePassword 'omnivore' + storePassword keystoreProperties['prodStorePassword'] + keyPassword keystoreProperties['prodKeyPassword'] } debug{ - storePassword 'android' keyAlias 'androiddebugkey' storeFile file('external/omnivore-demo.keystore') + storePassword keystoreProperties['demoStorePassword'] + keyPassword keystoreProperties['demoKeyPassword'] } } From 252bb4b8e1e42ef33649d02078f6b3099495350a Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Thu, 25 Aug 2022 07:53:33 -0700 Subject: [PATCH 4/5] add to android gitignore --- android/Omnivore/app/.gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/android/Omnivore/app/.gitignore b/android/Omnivore/app/.gitignore index 42afabfd2..6a4362e1c 100644 --- a/android/Omnivore/app/.gitignore +++ b/android/Omnivore/app/.gitignore @@ -1 +1,3 @@ -/build \ No newline at end of file +/build +keystore.properties +*.keystore \ No newline at end of file From 826c363f2fa71d8faf6dc2a5d51129c54544464a Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Thu, 25 Aug 2022 08:12:02 -0700 Subject: [PATCH 5/5] sign out of google when tapping logout on android --- .../java/app/omnivore/omnivore/ui/home/HomeView.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt index 11ce48e54..da1c0e4d9 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt @@ -11,12 +11,17 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.navigation.NavHostController import app.omnivore.omnivore.ui.auth.LoginViewModel +import com.google.android.gms.auth.api.signin.GoogleSignIn +import com.google.android.gms.auth.api.signin.GoogleSignInOptions @Composable fun HomeView(viewModel: LoginViewModel) { + val context = LocalContext.current + Column( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, @@ -28,6 +33,13 @@ fun HomeView(viewModel: LoginViewModel) { Text("You have a valid auth token. Nice. Go save something in Chrome!") Button(onClick = { + // Sign out google users + val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .build() + + val googleSignIn = GoogleSignIn.getClient(context, signInOptions) + googleSignIn.signOut() + viewModel.logout() }) { Text(text = "Logout")