Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add recaptcha #99

Merged
merged 3 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ android {
vectorDrawables {
useSupportLibrary = true
}

buildConfigField("String", "RECAPTCHA_API_SITE_KEY", "\"6LfaxOgpAAAAAI3Sj4rtB2oAFjkRJILiGEt-LUsc\"")
}

buildTypes {
Expand Down Expand Up @@ -116,6 +118,7 @@ dependencies {
// Others
implementation(libs.kotlinx.serialization)
implementation(libs.androidx.core.splashscreen)
implementation(libs.recaptcha)

// Test
testImplementation(libs.junit)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
*/
package com.infomaniak.swisstransfer.di

import android.app.Application
import com.infomaniak.multiplatform_swisstransfer.SwissTransferInjection
import com.infomaniak.swisstransfer.ui.MainApplication
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand All @@ -30,6 +32,9 @@ import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
object ApplicationModule {

@Provides
fun providesMainApplication(application: Application) = application as MainApplication

@Provides
@Singleton
fun providesSwissTransferInjection() = SwissTransferInjection()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import android.app.Application
import com.infomaniak.multiplatform_swisstransfer.SwissTransferInjection
import com.infomaniak.swisstransfer.BuildConfig
import com.infomaniak.swisstransfer.ui.utils.AccountUtils
import com.infomaniak.swisstransfer.ui.utils.UploadRecaptcha
import dagger.hilt.android.HiltAndroidApp
import io.sentry.SentryEvent
import io.sentry.SentryOptions
Expand All @@ -36,13 +37,19 @@ class MainApplication : Application() {
@Inject
lateinit var swissTransferInjection: SwissTransferInjection

@Inject
lateinit var uploadRecaptcha: UploadRecaptcha

@Inject
lateinit var globalCoroutineScope: CoroutineScope

override fun onCreate() {
super.onCreate()

configureAccountUtils()
globalCoroutineScope.launch {
AccountUtils.init(swissTransferInjection)
uploadRecaptcha.initializeClient()
}

SentryAndroid.init(this) { options: SentryAndroidOptions ->
// Register the callback as an option
Expand All @@ -52,8 +59,4 @@ class MainApplication : Application() {
}
}
}

private fun configureAccountUtils() {
globalCoroutineScope.launch { AccountUtils.init(swissTransferInjection) }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Infomaniak SwissTransfer - Android
* Copyright (C) 2024 Infomaniak Network SA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.infomaniak.swisstransfer.ui.utils

import android.app.Application
import android.util.Log
import com.google.android.recaptcha.Recaptcha
import com.google.android.recaptcha.RecaptchaAction
import com.google.android.recaptcha.RecaptchaClient
import com.infomaniak.swisstransfer.BuildConfig
import com.infomaniak.swisstransfer.ui.MainApplication
import javax.inject.Inject

/**
* A class responsible for handling reCAPTCHA verification for uploads.
*
* This class uses the Google reCAPTCHA API to verify user actions and prevent abuse.
* It initializes a reCAPTCHA client and provides a method to fetch a reCAPTCHA code.
*
* @property application The application context.
*/
class UploadRecaptcha @Inject constructor(private val application: MainApplication) {

private var client: RecaptchaClient? = null

/**
* Initializes the reCAPTCHA client.
*
* This method should be called before attempting to fetch a reCAPTCHA code.
* It fetches the reCAPTCHA client using the provided API site key.
* If an error occurs during initialization, it logs the error message.
* It MUST be called in the MainApplication.
*/
suspend fun initializeClient() {
runCatching {
client = Recaptcha.fetchClient(application, BuildConfig.RECAPTCHA_API_SITE_KEY)
}.onFailure {
Log.e("Recaptcha", "Getting Recaptcha client failed with an exception", it)
}
}

/**
* Fetches a reCAPTCHA code.
*
* This method executes the reCAPTCHA challenge and retrieves the code.
* The code is then passed to the provided callback function.
*
* @param callback A function that receives the reCAPTCHA code as a string.
* The code may be null if an error occurred.
*/
suspend fun fetchCode(callback: (String?) -> Unit) {
callback(client?.execute(RecaptchaAction.LOGIN)?.getOrNull())
}

companion object {
private const val TAG = "UploadRecaptcha"
}
}
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ serialization = "1.7.1"
swisstransfer = "0.3.0"
sentry = "4.12.0"
sentry-android = "7.15.0"
recaptcha = "18.6.1"

[libraries]
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
Expand All @@ -45,6 +46,7 @@ kotlinx-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-
navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" }
swisstransfer-core = { module = "com.github.Infomaniak.multiplatform-SwissTransfer:STCore", version.ref = "swisstransfer" }
sentry-android = { module = "io.sentry:sentry-android", version.ref = "sentry-android" }
recaptcha = { module = "com.google.android.recaptcha:recaptcha", version.ref = "recaptcha" }
# Tests
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
Expand Down
Loading