Skip to content

Commit d695353

Browse files
update: implemented captcha to turn of bots
1 parent 690bbbf commit d695353

13 files changed

Lines changed: 574 additions & 369 deletions

File tree

.idea/vcs.xml

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/build.gradle

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ android {
6060
def _versionName = versionProperties['versionName']
6161
def tagVersion = Integer.parseInt(versionProperties['tagVersion'])
6262

63-
println(tagVersion)
64-
6563
defaultConfig {
6664
applicationId "com.afkanerd.sw0b"
6765
minSdk 24
@@ -84,6 +82,13 @@ android {
8482
manifestPlaceholders =
8583
['appAuthRedirectScheme': 'oauth.afkanerd.com']
8684

85+
// ...
86+
Properties properties = new Properties()
87+
if (rootProject.file("local.properties").exists()) {
88+
properties.load(rootProject.file("local.properties").newDataInputStream())
89+
}
90+
buildConfigField "String", "RECAPTCHA_KEY", properties.getProperty("recaptcha_key", "\"\"")
91+
8792
}
8893

8994
buildTypes {
@@ -116,6 +121,7 @@ android {
116121
}
117122

118123
compileOptions {
124+
coreLibraryDesugaringEnabled true
119125
sourceCompatibility JavaVersion.VERSION_1_8
120126
targetCompatibility JavaVersion.VERSION_1_8
121127
// kotlinCompilerExtensionVersion compose_compiler
@@ -355,5 +361,8 @@ dependencies {
355361

356362
implementation(libs.coil.compose)
357363
implementation(libs.coil.network.okhttp)
364+
365+
implementation libs.play.services.safetynet
366+
coreLibraryDesugaring libs.desugar.jdk.libs
358367
}
359368

app/src/main/java/com/example/sw0b_001/MainActivity.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ import com.example.sw0b_001.ui.navigation.WelcomeScreen
116116
import com.example.sw0b_001.ui.onboarding.OnboardingInteractive
117117
import com.example.sw0b_001.ui.views.WelcomeMainView
118118
import com.example.sw0b_001.ui.viewModels.OnboardingViewModel
119+
import com.example.sw0b_001.ui.viewModels.VaultsViewModel
119120
import com.example.sw0b_001.ui.views.BottomTabsItems
120121
import com.example.sw0b_001.ui.views.SettingsView
121122
import com.example.sw0b_001.ui.views.compose.ComposerInterface
@@ -139,6 +140,8 @@ class MainActivity : AppCompatActivity() {
139140

140141
var loggedInAlready by mutableStateOf(false)
141142

143+
val vaultViewModel: VaultsViewModel by viewModels()
144+
142145
override fun onCreate(savedInstanceState: Bundle?) {
143146
super.onCreate(savedInstanceState)
144147
enableEdgeToEdge()
@@ -340,20 +343,23 @@ class MainActivity : AppCompatActivity() {
340343
val loginNav: LoginScreen = backEntry.toRoute()
341344
LoginView(
342345
navController = navController,
346+
vaultViewModel = vaultViewModel,
343347
isOnboarding = loginNav.isOnboarding,
344348
)
345349
}
346350
composable<ForgotPasswordScreen> { backEntry ->
347351
val forgotPasswordNav: ForgotPasswordScreen = backEntry.toRoute()
348352
ForgotPasswordView(
349353
navController = navController,
354+
vaultsViewModel = vaultViewModel,
350355
isOnboarding = forgotPasswordNav.isOnboarding,
351356
)
352357
}
353358
composable<CreateAccountScreen> { backEntry ->
354359
val createAccountNav: ForgotPasswordScreen = backEntry.toRoute()
355360
CreateAccountView(
356361
navController = navController,
362+
vaultsViewModel = vaultViewModel,
357363
isOnboarding = createAccountNav.isOnboarding,
358364
)
359365
}
@@ -365,6 +371,7 @@ class MainActivity : AppCompatActivity() {
365371
loginSignupPassword = otpCodeNav.loginSignupPassword,
366372
countryCode = otpCodeNav.countryCode,
367373
otpRequestType = otpCodeNav.otpRequestType,
374+
recaptcha = otpCodeNav.recaptcha,
368375
nextAttemptTimestamp = otpCodeNav.nextAttemptTimestamp,
369376
onCompleteCallback = if(otpCodeNav.isOnboarding)
370377
onboardingViewModel.callback else null,

app/src/main/java/com/example/sw0b_001/data/Vaults.kt

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,14 @@ class Vaults(val context: Context) {
140140
}
141141
}
142142

143-
fun createEntity(context: Context,
144-
phoneNumber: String,
145-
countryCode: String,
146-
password: String,
147-
ownershipResponse: String = "") : Vault.CreateEntityResponse {
143+
fun createEntity(
144+
context: Context,
145+
phoneNumber: String,
146+
countryCode: String,
147+
password: String,
148+
recaptchaToken: String,
149+
ownershipResponse: String = ""
150+
) : Vault.CreateEntityResponse {
148151

149152
val deviceIdPubKey = Cryptography.generateKey(context, DEVICE_ID_KEYSTORE_ALIAS)
150153
val publishPubKey = Cryptography.generateKey(context, Publishers.PUBLISHER_ID_KEYSTORE_ALIAS)
@@ -158,7 +161,6 @@ class Vaults(val context: Context) {
158161
setPassword(password)
159162
setClientPublishPubKey(Base64.encodeToString(publishPubKey, Base64.DEFAULT))
160163
setClientDeviceIdPubKey(Base64.encodeToString(deviceIdPubKey, Base64.DEFAULT))
161-
162164
}.build()
163165

164166
val response = entityStub.createEntity(createEntityRequest1)
@@ -174,19 +176,27 @@ class Vaults(val context: Context) {
174176
return response
175177
}
176178

177-
fun authenticateEntity(context: Context,
178-
phoneNumber: String,
179-
password: String,
180-
ownershipResponse: String = "") : Vault.AuthenticateEntityResponse {
179+
fun authenticateEntity(
180+
context: Context,
181+
phoneNumber: String,
182+
password: String,
183+
recaptchaToken: String,
184+
ownershipResponse: String = ""
185+
) : Vault.AuthenticateEntityResponse {
181186

182-
val deviceIdPubKey = Cryptography.generateKey(context, DEVICE_ID_KEYSTORE_ALIAS)
183-
val publishPubKey = Cryptography.generateKey(context, Publishers.PUBLISHER_ID_KEYSTORE_ALIAS)
187+
val deviceIdPubKey = Cryptography.generateKey(context,
188+
DEVICE_ID_KEYSTORE_ALIAS)
189+
val publishPubKey = Cryptography.generateKey(context,
190+
Publishers.PUBLISHER_ID_KEYSTORE_ALIAS)
184191

185192
val authenticateEntityRequest = Vault.AuthenticateEntityRequest.newBuilder().apply {
186193
setPhoneNumber(phoneNumber)
187194
setPassword(password)
188-
setClientPublishPubKey(Base64.encodeToString(publishPubKey, Base64.DEFAULT))
189-
setClientDeviceIdPubKey(Base64.encodeToString(deviceIdPubKey, Base64.DEFAULT))
195+
setClientPublishPubKey(Base64.encodeToString(publishPubKey,
196+
Base64.DEFAULT))
197+
setClientDeviceIdPubKey(Base64.encodeToString(deviceIdPubKey,
198+
Base64.DEFAULT))
199+
setRecaptchaToken(recaptchaToken)
190200

191201
if(ownershipResponse.isNotBlank()) {
192202
setOwnershipProofResponse(ownershipResponse)
@@ -210,19 +220,27 @@ class Vaults(val context: Context) {
210220
return response
211221
}
212222

213-
fun recoverEntityPassword(context: Context,
214-
phoneNumber: String,
215-
newPassword: String,
216-
ownershipResponse: String? = null) : Vault.ResetPasswordResponse {
223+
fun recoverEntityPassword(
224+
context: Context,
225+
phoneNumber: String,
226+
newPassword: String,
227+
recaptchaToken: String,
228+
ownershipResponse: String? = null
229+
) : Vault.ResetPasswordResponse {
217230

218-
val deviceIdPubKey = Cryptography.generateKey(context, DEVICE_ID_KEYSTORE_ALIAS)
219-
val publishPubKey = Cryptography.generateKey(context, Publishers.PUBLISHER_ID_KEYSTORE_ALIAS)
231+
val deviceIdPubKey = Cryptography.generateKey(context,
232+
DEVICE_ID_KEYSTORE_ALIAS)
233+
val publishPubKey = Cryptography.generateKey(context,
234+
Publishers.PUBLISHER_ID_KEYSTORE_ALIAS)
220235

221236
val resetPasswordRequest = Vault.ResetPasswordRequest.newBuilder().apply {
222237
setPhoneNumber(phoneNumber)
223238
setNewPassword(newPassword)
224-
setClientPublishPubKey(Base64.encodeToString(publishPubKey, Base64.DEFAULT))
225-
setClientDeviceIdPubKey(Base64.encodeToString(deviceIdPubKey, Base64.DEFAULT))
239+
setClientPublishPubKey(Base64.encodeToString(publishPubKey,
240+
Base64.DEFAULT))
241+
setClientDeviceIdPubKey(Base64.encodeToString(deviceIdPubKey,
242+
Base64.DEFAULT))
243+
setRecaptchaToken(recaptchaToken)
226244

227245
ownershipResponse?.let {
228246
setOwnershipProofResponse(ownershipResponse)

app/src/main/java/com/example/sw0b_001/ui/navigation/Screen.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ data class OTPCodeScreen(
3939
val loginSignupPhoneNumber: String,
4040
val loginSignupPassword: String,
4141
val countryCode: String,
42+
val recaptcha: String,
4243
val otpRequestType: OTPCodeVerificationType = OTPCodeVerificationType.AUTHENTICATE,
4344
val nextAttemptTimestamp: Int? = null,
4445
val isOnboarding: Boolean = false
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.example.sw0b_001.ui.viewModels
2+
3+
import android.app.Activity
4+
import androidx.lifecycle.ViewModel
5+
import androidx.lifecycle.viewModelScope
6+
import com.example.sw0b_001.BuildConfig
7+
import com.google.android.gms.safetynet.SafetyNet
8+
import com.google.android.gms.tasks.OnFailureListener
9+
import com.google.android.gms.tasks.OnSuccessListener
10+
import kotlinx.coroutines.launch
11+
import java.util.concurrent.Executor
12+
import java.util.concurrent.Executors
13+
14+
15+
class VaultsViewModel : ViewModel() {
16+
17+
private val executor: Executor = Executors.newSingleThreadExecutor()
18+
19+
fun executeRecaptcha(
20+
activity: Activity,
21+
onFailureCallback: () -> Unit,
22+
onSuccessCallback: (String) -> Unit,
23+
) {
24+
viewModelScope.launch{
25+
SafetyNet.getClient(activity).verifyWithRecaptcha(BuildConfig.RECAPTCHA_KEY)
26+
.addOnSuccessListener(executor, OnSuccessListener { response ->
27+
// Indicates communication with reCAPTCHA service was
28+
// successful.
29+
val userResponseToken = response.tokenResult
30+
if (response.tokenResult?.isNotEmpty() == true) {
31+
onSuccessCallback(userResponseToken.toString())
32+
}
33+
})
34+
.addOnFailureListener(executor, OnFailureListener { e ->
35+
e.printStackTrace()
36+
onFailureCallback()
37+
// if (e is ApiException) {
38+
// // An error occurred when communicating with the
39+
// // reCAPTCHA service. Refer to the status code to
40+
// // handle the error appropriately.
41+
// } else {
42+
// // A different, unknown type of error occurred.
43+
// }
44+
})
45+
}
46+
}
47+
48+
}

app/src/main/java/com/example/sw0b_001/ui/views/AlreadyLoggedInView.kt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,14 @@ fun GetMeOutOfHere(
8686
.fillMaxWidth()
8787
.padding(bottom = 32.dp),
8888
onClick={
89-
Vaults.logout(context) {
90-
Vaults.setGetMeOut(context, false)
91-
CoroutineScope(Dispatchers.Main).launch {
92-
navController.navigate(HomepageScreen) {
93-
popUpTo(0) {
94-
inclusive = true
89+
CoroutineScope(Dispatchers.Default).launch {
90+
Vaults.logout(context) {
91+
Vaults.setGetMeOut(context, false)
92+
CoroutineScope(Dispatchers.Main).launch {
93+
navController.navigate(HomepageScreen) {
94+
popUpTo(0) {
95+
inclusive = true
96+
}
9597
}
9698
}
9799
}

0 commit comments

Comments
 (0)